???¨¤ JFIF    ?? C    !"$"$?? C  ?? p " ??     ??   ?¨²   ???? (% aA*?XYD?(J??E¡éRE,P€XYae?)(E¡è2€B¡èR£¤ BQ¡è¡é X?)X¡­€¡è? @ .............................................................................................................................................................................. ............................................................................. PK‹¶N]ªàFönn/site-packages/setuptools-41.6.0.dist-info/WHEELnu„[µü¤Wheel-Version: 1.0 Generator: bdist_wheel (0.33.6) Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any PK‹¶N]hBDÜ5Ü50site-packages/setuptools-41.6.0.dist-info/RECORDnu„[µü¤../../../bin/easy_install,sha256=kyVHjd3KmOt_Hd-ehMBXo7pGpLnKgL4ShtrVFRGdt3E,232 ../../../bin/easy_install-3.8,sha256=kyVHjd3KmOt_Hd-ehMBXo7pGpLnKgL4ShtrVFRGdt3E,232 __pycache__/easy_install.cpython-38.pyc,, easy_install.py,sha256=MDC9vt5AxDsXX5qcKlBz2TnW6Tpuv_AobnfhCJ9X3PM,126 pkg_resources/__init__.py,sha256=8L9Xzt6qtgAwlbk95DVBMbFflwoxjIbnikZkRjdJU7U,108349 pkg_resources/__pycache__/__init__.cpython-38.pyc,, pkg_resources/__pycache__/py31compat.cpython-38.pyc,, pkg_resources/_vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pkg_resources/_vendor/__pycache__/__init__.cpython-38.pyc,, pkg_resources/_vendor/__pycache__/appdirs.cpython-38.pyc,, pkg_resources/_vendor/__pycache__/pyparsing.cpython-38.pyc,, pkg_resources/_vendor/__pycache__/six.cpython-38.pyc,, pkg_resources/_vendor/appdirs.py,sha256=C1zpkt179PgsJ4dspL09N-HhOxy6bkTSxUj2_vG6Hkw,24679 pkg_resources/_vendor/packaging/__about__.py,sha256=zkcCPTN_6TcLW0Nrlg0176-R1QQ_WVPTm8sz1R4-HjM,720 pkg_resources/_vendor/packaging/__init__.py,sha256=_vNac5TrzwsrzbOFIbF-5cHqc_Y2aPT2D7zrIR06BOo,513 pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-38.pyc,, pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-38.pyc,, pkg_resources/_vendor/packaging/__pycache__/_compat.cpython-38.pyc,, pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-38.pyc,, pkg_resources/_vendor/packaging/__pycache__/markers.cpython-38.pyc,, pkg_resources/_vendor/packaging/__pycache__/requirements.cpython-38.pyc,, pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-38.pyc,, pkg_resources/_vendor/packaging/__pycache__/utils.cpython-38.pyc,, pkg_resources/_vendor/packaging/__pycache__/version.cpython-38.pyc,, pkg_resources/_vendor/packaging/_compat.py,sha256=Vi_A0rAQeHbU-a9X0tt1yQm9RqkgQbDSxzRw8WlU9kA,860 pkg_resources/_vendor/packaging/_structures.py,sha256=RImECJ4c_wTlaTYYwZYLHEiebDMaAJmK1oPARhw1T5o,1416 pkg_resources/_vendor/packaging/markers.py,sha256=uEcBBtGvzqltgnArqb9c4RrcInXezDLos14zbBHhWJo,8248 pkg_resources/_vendor/packaging/requirements.py,sha256=SikL2UynbsT0qtY9ltqngndha_sfo0w6XGFhAhoSoaQ,4355 pkg_resources/_vendor/packaging/specifiers.py,sha256=SAMRerzO3fK2IkFZCaZkuwZaL_EGqHNOz4pni4vhnN0,28025 pkg_resources/_vendor/packaging/utils.py,sha256=3m6WvPm6NNxE8rkTGmn0r75B_GZSGg7ikafxHsBN1WA,421 pkg_resources/_vendor/packaging/version.py,sha256=OwGnxYfr2ghNzYx59qWIBkrK3SnB6n-Zfd1XaLpnnM0,11556 pkg_resources/_vendor/pyparsing.py,sha256=tmrp-lu-qO1i75ZzIN5A12nKRRD1Cm4Vpk-5LR9rims,232055 pkg_resources/_vendor/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 pkg_resources/extern/__init__.py,sha256=cHiEfHuLmm6rs5Ve_ztBfMI7Lr31vss-D4wkqF5xzlI,2498 pkg_resources/extern/__pycache__/__init__.cpython-38.pyc,, pkg_resources/py31compat.py,sha256=-WQ0e4c3RG_acdhwC3gLiXhP_lg4G5q7XYkZkQg0gxU,558 setuptools-41.6.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 setuptools-41.6.0.dist-info/LICENSE,sha256=wyo6w5WvYyHv0ovnPQagDw22q4h9HCHU_sRhKNIFbVo,1078 setuptools-41.6.0.dist-info/METADATA,sha256=C4M3emJvpj_5ir5cWHN7qwqzqSdoNn90zBzQzCZcfEw,3355 setuptools-41.6.0.dist-info/RECORD,, setuptools-41.6.0.dist-info/WHEEL,sha256=8zNYZbwQSXoB9IfXOjPfeNwvAsALAjffgk27FqvCWbo,110 setuptools-41.6.0.dist-info/dependency_links.txt,sha256=HlkCFkoK5TbZ5EMLbLKYhLcY_E31kBWD8TqW2EgmatQ,239 setuptools-41.6.0.dist-info/entry_points.txt,sha256=t51hYQSHTv2cDVO8fdyd3huPmuBPr2aDcevvakP7lbI,2990 setuptools-41.6.0.dist-info/top_level.txt,sha256=2HUXVVwA4Pff1xgTFr3GsTXXKaPaO6vlG6oNJ_4u4Tg,38 setuptools-41.6.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 setuptools/__init__.py,sha256=WBpCcn2lvdckotabeae1TTYonPOcgCIF3raD2zRWzBc,7283 setuptools/__pycache__/__init__.cpython-38.pyc,, setuptools/__pycache__/_deprecation_warning.cpython-38.pyc,, setuptools/__pycache__/_imp.cpython-38.pyc,, setuptools/__pycache__/archive_util.cpython-38.pyc,, setuptools/__pycache__/build_meta.cpython-38.pyc,, setuptools/__pycache__/config.cpython-38.pyc,, setuptools/__pycache__/dep_util.cpython-38.pyc,, setuptools/__pycache__/depends.cpython-38.pyc,, setuptools/__pycache__/dist.cpython-38.pyc,, setuptools/__pycache__/extension.cpython-38.pyc,, setuptools/__pycache__/glibc.cpython-38.pyc,, setuptools/__pycache__/glob.cpython-38.pyc,, setuptools/__pycache__/launch.cpython-38.pyc,, setuptools/__pycache__/lib2to3_ex.cpython-38.pyc,, setuptools/__pycache__/monkey.cpython-38.pyc,, setuptools/__pycache__/msvc.cpython-38.pyc,, setuptools/__pycache__/namespaces.cpython-38.pyc,, setuptools/__pycache__/package_index.cpython-38.pyc,, setuptools/__pycache__/pep425tags.cpython-38.pyc,, setuptools/__pycache__/py27compat.cpython-38.pyc,, setuptools/__pycache__/py31compat.cpython-38.pyc,, setuptools/__pycache__/py33compat.cpython-38.pyc,, setuptools/__pycache__/py34compat.cpython-38.pyc,, setuptools/__pycache__/sandbox.cpython-38.pyc,, setuptools/__pycache__/site-patch.cpython-38.pyc,, setuptools/__pycache__/ssl_support.cpython-38.pyc,, setuptools/__pycache__/unicode_utils.cpython-38.pyc,, setuptools/__pycache__/version.cpython-38.pyc,, setuptools/__pycache__/wheel.cpython-38.pyc,, setuptools/__pycache__/windows_support.cpython-38.pyc,, setuptools/_deprecation_warning.py,sha256=jU9-dtfv6cKmtQJOXN8nP1mm7gONw5kKEtiPtbwnZyI,218 setuptools/_imp.py,sha256=jloslOkxrTKbobgemfP94YII0nhqiJzE1bRmCTZ1a5I,2223 setuptools/_vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 setuptools/_vendor/__pycache__/__init__.cpython-38.pyc,, setuptools/_vendor/__pycache__/ordered_set.cpython-38.pyc,, setuptools/_vendor/__pycache__/pyparsing.cpython-38.pyc,, setuptools/_vendor/__pycache__/six.cpython-38.pyc,, setuptools/_vendor/ordered_set.py,sha256=dbaCcs27dyN9gnMWGF5nA_BrVn6Q-NrjKYJpV9_fgBs,15130 setuptools/_vendor/packaging/__about__.py,sha256=zkcCPTN_6TcLW0Nrlg0176-R1QQ_WVPTm8sz1R4-HjM,720 setuptools/_vendor/packaging/__init__.py,sha256=_vNac5TrzwsrzbOFIbF-5cHqc_Y2aPT2D7zrIR06BOo,513 setuptools/_vendor/packaging/__pycache__/__about__.cpython-38.pyc,, setuptools/_vendor/packaging/__pycache__/__init__.cpython-38.pyc,, setuptools/_vendor/packaging/__pycache__/_compat.cpython-38.pyc,, setuptools/_vendor/packaging/__pycache__/_structures.cpython-38.pyc,, setuptools/_vendor/packaging/__pycache__/markers.cpython-38.pyc,, setuptools/_vendor/packaging/__pycache__/requirements.cpython-38.pyc,, setuptools/_vendor/packaging/__pycache__/specifiers.cpython-38.pyc,, setuptools/_vendor/packaging/__pycache__/utils.cpython-38.pyc,, setuptools/_vendor/packaging/__pycache__/version.cpython-38.pyc,, setuptools/_vendor/packaging/_compat.py,sha256=Vi_A0rAQeHbU-a9X0tt1yQm9RqkgQbDSxzRw8WlU9kA,860 setuptools/_vendor/packaging/_structures.py,sha256=RImECJ4c_wTlaTYYwZYLHEiebDMaAJmK1oPARhw1T5o,1416 setuptools/_vendor/packaging/markers.py,sha256=Gvpk9EY20yKaMTiKgQZ8yFEEpodqVgVYtfekoic1Yts,8239 setuptools/_vendor/packaging/requirements.py,sha256=t44M2HVWtr8phIz2OhnILzuGT3rTATaovctV1dpnVIg,4343 setuptools/_vendor/packaging/specifiers.py,sha256=SAMRerzO3fK2IkFZCaZkuwZaL_EGqHNOz4pni4vhnN0,28025 setuptools/_vendor/packaging/utils.py,sha256=3m6WvPm6NNxE8rkTGmn0r75B_GZSGg7ikafxHsBN1WA,421 setuptools/_vendor/packaging/version.py,sha256=OwGnxYfr2ghNzYx59qWIBkrK3SnB6n-Zfd1XaLpnnM0,11556 setuptools/_vendor/pyparsing.py,sha256=tmrp-lu-qO1i75ZzIN5A12nKRRD1Cm4Vpk-5LR9rims,232055 setuptools/_vendor/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 setuptools/archive_util.py,sha256=kw8Ib_lKjCcnPKNbS7h8HztRVK0d5RacU3r_KRdVnmM,6592 setuptools/build_meta.py,sha256=-9Nmj9YdbW4zX3TssPJZhsENrTa4fw3k86Jm1cdKMik,9597 setuptools/command/__init__.py,sha256=NWzJ0A1BEengZpVeqUyWLNm2bk4P3F4iL5QUErHy7kA,594 setuptools/command/__pycache__/__init__.cpython-38.pyc,, setuptools/command/__pycache__/alias.cpython-38.pyc,, setuptools/command/__pycache__/bdist_egg.cpython-38.pyc,, setuptools/command/__pycache__/bdist_rpm.cpython-38.pyc,, setuptools/command/__pycache__/bdist_wininst.cpython-38.pyc,, setuptools/command/__pycache__/build_clib.cpython-38.pyc,, setuptools/command/__pycache__/build_ext.cpython-38.pyc,, setuptools/command/__pycache__/build_py.cpython-38.pyc,, setuptools/command/__pycache__/develop.cpython-38.pyc,, setuptools/command/__pycache__/dist_info.cpython-38.pyc,, setuptools/command/__pycache__/easy_install.cpython-38.pyc,, setuptools/command/__pycache__/egg_info.cpython-38.pyc,, setuptools/command/__pycache__/install.cpython-38.pyc,, setuptools/command/__pycache__/install_egg_info.cpython-38.pyc,, setuptools/command/__pycache__/install_lib.cpython-38.pyc,, setuptools/command/__pycache__/install_scripts.cpython-38.pyc,, setuptools/command/__pycache__/py36compat.cpython-38.pyc,, setuptools/command/__pycache__/register.cpython-38.pyc,, setuptools/command/__pycache__/rotate.cpython-38.pyc,, setuptools/command/__pycache__/saveopts.cpython-38.pyc,, setuptools/command/__pycache__/sdist.cpython-38.pyc,, setuptools/command/__pycache__/setopt.cpython-38.pyc,, setuptools/command/__pycache__/test.cpython-38.pyc,, setuptools/command/__pycache__/upload.cpython-38.pyc,, setuptools/command/__pycache__/upload_docs.cpython-38.pyc,, setuptools/command/alias.py,sha256=KjpE0sz_SDIHv3fpZcIQK-sCkJz-SrC6Gmug6b9Nkc8,2426 setuptools/command/bdist_egg.py,sha256=nnfV8Ah8IRC_Ifv5Loa9FdxL66MVbyDXwy-foP810zM,18185 setuptools/command/bdist_rpm.py,sha256=B7l0TnzCGb-0nLlm6rS00jWLkojASwVmdhW2w5Qz_Ak,1508 setuptools/command/bdist_wininst.py,sha256=_6dz3lpB1tY200LxKPLM7qgwTCceOMgaWFF-jW2-pm0,637 setuptools/command/build_clib.py,sha256=bQ9aBr-5ZSO-9fGsGsDLz0mnnFteHUZnftVLkhvHDq0,4484 setuptools/command/build_ext.py,sha256=Ib42YUGksBswm2mL5xmQPF6NeTA6HcqrvAtEgFCv32A,13019 setuptools/command/build_py.py,sha256=yWyYaaS9F3o9JbIczn064A5g1C5_UiKRDxGaTqYbtLE,9596 setuptools/command/develop.py,sha256=MQlnGS6uP19erK2JCNOyQYoYyquk3PADrqrrinqqLtA,8184 setuptools/command/dist_info.py,sha256=5t6kOfrdgALT-P3ogss6PF9k-Leyesueycuk3dUyZnI,960 setuptools/command/easy_install.py,sha256=BLJBFm2-rtp-ZZj0SoN1KAd3GH-LGhKV5MrcgIuFx_8,87453 setuptools/command/egg_info.py,sha256=w73EdxYSOk2gsaAiHGL2dZrCldoPiuRr2eTfqcFvCds,25570 setuptools/command/install.py,sha256=a0EZpL_A866KEdhicTGbuyD_TYl1sykfzdrri-zazT4,4683 setuptools/command/install_egg_info.py,sha256=bMgeIeRiXzQ4DAGPV1328kcjwQjHjOWU4FngAWLV78Q,2203 setuptools/command/install_lib.py,sha256=r5NuasaSxvmIrjgZNj38Iq-1UJG1o1ms7CuHq6MCTbQ,3862 setuptools/command/install_scripts.py,sha256=UD0rEZ6861mTYhIdzcsqKnUl8PozocXWl9VBQ1VTWnc,2439 setuptools/command/launcher manifest.xml,sha256=xlLbjWrB01tKC0-hlVkOKkiSPbzMml2eOPtJ_ucCnbE,628 setuptools/command/py36compat.py,sha256=SzjZcOxF7zdFUT47Zv2n7AM3H8koDys_0OpS-n9gIfc,4986 setuptools/command/register.py,sha256=LO3MvYKPE8dN1m-KkrBRHC68ZFoPvA_vI8Xgp7vv6zI,534 setuptools/command/rotate.py,sha256=co5C1EkI7P0GGT6Tqz-T2SIj2LBJTZXYELpmao6d4KQ,2164 setuptools/command/saveopts.py,sha256=za7QCBcQimKKriWcoCcbhxPjUz30gSB74zuTL47xpP4,658 setuptools/command/sdist.py,sha256=gr5hFrDzUtGfp_0tu0sllzIyr3jMQegIkFmlDauQJxw,7388 setuptools/command/setopt.py,sha256=NTWDyx-gjDF-txf4dO577s7LOzHVoKR0Mq33rFxaRr8,5085 setuptools/command/test.py,sha256=u2kXngIIdSYqtvwFlHiN6Iye1IB4TU6uadB2uiV1szw,9602 setuptools/command/upload.py,sha256=GxtNkIl7SA0r8mACkbDcSCN1m2_WPppK9gZXJmQSiow,6811 setuptools/command/upload_docs.py,sha256=oXiGplM_cUKLwE4CWWw98RzCufAu8tBhMC97GegFcms,7311 setuptools/config.py,sha256=Rek2y8zh67yIc5Rs4biqo63jOwYrvsy5gy8SSDJbWU0,20534 setuptools/dep_util.py,sha256=fgixvC1R7sH3r13ktyf7N0FALoqEXL1cBarmNpSEoWg,935 setuptools/depends.py,sha256=qt2RWllArRvhnm8lxsyRpcthEZYp4GHQgREl1q0LkFw,5517 setuptools/dist.py,sha256=awhNuAZVxwnjntKLjGeUKhSWiCaBsetnPyYQ9LDUUls,50309 setuptools/extension.py,sha256=uc6nHI-MxwmNCNPbUiBnybSyqhpJqjbhvOQ-emdvt_E,1729 setuptools/extern/__init__.py,sha256=4q9gtShB1XFP6CisltsyPqtcfTO6ZM9Lu1QBl3l-qmo,2514 setuptools/extern/__pycache__/__init__.cpython-38.pyc,, setuptools/glibc.py,sha256=X64VvGPL2AbURKwYRsWJOXXGAYOiF_v2qixeTkAULuU,3146 setuptools/glob.py,sha256=o75cHrOxYsvn854thSxE0x9k8JrKDuhP_rRXlVB00Q4,5084 setuptools/launch.py,sha256=sd7ejwhBocCDx_wG9rIs0OaZ8HtmmFU8ZC6IR_S0Lvg,787 setuptools/lib2to3_ex.py,sha256=t5e12hbR2pi9V4ezWDTB4JM-AISUnGOkmcnYHek3xjg,2013 setuptools/monkey.py,sha256=FGc9fffh7gAxMLFmJs2DW_OYWpBjkdbNS2n14UAK4NA,5264 setuptools/msvc.py,sha256=8baJ6aYgCA4TRdWQQi185qB9dnU8FaP4wgpbmd7VODs,46751 setuptools/namespaces.py,sha256=F0Nrbv8KCT2OrO7rwa03om4N4GZKAlnce-rr-cgDQa8,3199 setuptools/package_index.py,sha256=6pb-B1POtHyLycAbkDETk4fO-Qv8_sY-rjTXhUOoh6k,40605 setuptools/pep425tags.py,sha256=o_D_WVeWcXZiI2xjPSg7pouGOvaWRgGRxEDK9DzAXIA,10861 setuptools/py27compat.py,sha256=tvmer0Tn-wk_JummCkoM22UIjpjL-AQ8uUiOaqTs8sI,1496 setuptools/py31compat.py,sha256=h2rtZghOfwoGYd8sQ0-auaKiF3TcL3qX0bX3VessqcE,838 setuptools/py33compat.py,sha256=SMF9Z8wnGicTOkU1uRNwZ_kz5Z_bj29PUBbqdqeeNsc,1330 setuptools/py34compat.py,sha256=KYOd6ybRxjBW8NJmYD8t_UyyVmysppFXqHpFLdslGXU,245 setuptools/sandbox.py,sha256=9UbwfEL5QY436oMI1LtFWohhoZ-UzwHvGyZjUH_qhkw,14276 setuptools/script (dev).tmpl,sha256=RUzQzCQUaXtwdLtYHWYbIQmOaES5Brqq1FvUA_tu-5I,218 setuptools/script.tmpl,sha256=WGTt5piezO27c-Dbx6l5Q4T3Ff20A5z7872hv3aAhYY,138 setuptools/site-patch.py,sha256=OumkIHMuoSenRSW1382kKWI1VAwxNE86E5W8iDd34FY,2302 setuptools/ssl_support.py,sha256=nLjPUBBw7RTTx6O4RJZ5eAMGgjJG8beiDbkFXDZpLuM,8493 setuptools/unicode_utils.py,sha256=NOiZ_5hD72A6w-4wVj8awHFM3n51Kmw1Ic_vx15XFqw,996 setuptools/version.py,sha256=og_cuZQb0QI6ukKZFfZWPlr1HgJBPPn2vO2m_bI9ZTE,144 setuptools/wheel.py,sha256=94uqXsOaKt91d9hW5z6ZppZmNSs_nO66R4uiwhcr4V0,8094 setuptools/windows_support.py,sha256=5GrfqSP2-dLGJoZTq2g6dCKkyQxxa2n5IQiXlJCoYEE,714 PK‹¶N]7Ù_Ýïï>site-packages/setuptools-41.6.0.dist-info/dependency_links.txtnu„[µü¤https://files.pythonhosted.org/packages/source/c/certifi/certifi-2016.9.26.tar.gz#md5=baa81e951a29958563689d868ef1064d https://files.pythonhosted.org/packages/source/w/wincertstore/wincertstore-0.2.zip#md5=ae728f2f007185648d0c7a8679b361e2 PK‹¶N]P׫661site-packages/setuptools-41.6.0.dist-info/LICENSEnu„[µü¤Copyright (C) 2016 Jason R Coombs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PKŒ¶N]�¨ñ® ® :site-packages/setuptools-41.6.0.dist-info/entry_points.txtnu„[µü¤[console_scripts] easy_install = setuptools.command.easy_install:main easy_install-3.8 = setuptools.command.easy_install:main [distutils.commands] alias = setuptools.command.alias:alias bdist_egg = setuptools.command.bdist_egg:bdist_egg bdist_rpm = setuptools.command.bdist_rpm:bdist_rpm bdist_wininst = setuptools.command.bdist_wininst:bdist_wininst build_clib = setuptools.command.build_clib:build_clib build_ext = setuptools.command.build_ext:build_ext build_py = setuptools.command.build_py:build_py develop = setuptools.command.develop:develop dist_info = setuptools.command.dist_info:dist_info easy_install = setuptools.command.easy_install:easy_install egg_info = setuptools.command.egg_info:egg_info install = setuptools.command.install:install install_egg_info = setuptools.command.install_egg_info:install_egg_info install_lib = setuptools.command.install_lib:install_lib install_scripts = setuptools.command.install_scripts:install_scripts register = setuptools.command.register:register rotate = setuptools.command.rotate:rotate saveopts = setuptools.command.saveopts:saveopts sdist = setuptools.command.sdist:sdist setopt = setuptools.command.setopt:setopt test = setuptools.command.test:test upload = setuptools.command.upload:upload upload_docs = setuptools.command.upload_docs:upload_docs [distutils.setup_keywords] convert_2to3_doctests = setuptools.dist:assert_string_list dependency_links = setuptools.dist:assert_string_list eager_resources = setuptools.dist:assert_string_list entry_points = setuptools.dist:check_entry_points exclude_package_data = setuptools.dist:check_package_data extras_require = setuptools.dist:check_extras include_package_data = setuptools.dist:assert_bool install_requires = setuptools.dist:check_requirements namespace_packages = setuptools.dist:check_nsp package_data = setuptools.dist:check_package_data packages = setuptools.dist:check_packages python_requires = setuptools.dist:check_specifier setup_requires = setuptools.dist:check_requirements test_loader = setuptools.dist:check_importable test_runner = setuptools.dist:check_importable test_suite = setuptools.dist:check_test_suite tests_require = setuptools.dist:check_requirements use_2to3 = setuptools.dist:assert_bool use_2to3_exclude_fixers = setuptools.dist:assert_string_list use_2to3_fixers = setuptools.dist:assert_string_list zip_safe = setuptools.dist:assert_bool [egg_info.writers] PKG-INFO = setuptools.command.egg_info:write_pkg_info dependency_links.txt = setuptools.command.egg_info:overwrite_arg depends.txt = setuptools.command.egg_info:warn_depends_obsolete eager_resources.txt = setuptools.command.egg_info:overwrite_arg entry_points.txt = setuptools.command.egg_info:write_entries namespace_packages.txt = setuptools.command.egg_info:overwrite_arg requires.txt = setuptools.command.egg_info:write_requirements top_level.txt = setuptools.command.egg_info:write_toplevel_names [setuptools.installation] eggsecutable = setuptools.command.easy_install:bootstrap PKŒ¶N]“×22site-packages/setuptools-41.6.0.dist-info/zip-safenu„[µü¤ PKŒ¶N]0\‘&&7site-packages/setuptools-41.6.0.dist-info/top_level.txtnu„[µü¤easy_install pkg_resources setuptools PKŒ¶N]²Hlh  2site-packages/setuptools-41.6.0.dist-info/METADATAnu„[µü¤Metadata-Version: 2.1 Name: setuptools Version: 41.6.0 Summary: Easily download, build, install, upgrade, and uninstall Python packages Home-page: https://github.com/pypa/setuptools Author: Python Packaging Authority Author-email: distutils-sig@python.org License: UNKNOWN Project-URL: Documentation, https://setuptools.readthedocs.io/ Keywords: CPAN PyPI distutils eggs package management Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: System :: Archiving :: Packaging Classifier: Topic :: System :: Systems Administration Classifier: Topic :: Utilities Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7 Description-Content-Type: text/x-rst; charset=UTF-8 Provides-Extra: certs Requires-Dist: certifi (==2016.9.26) ; extra == 'certs' Provides-Extra: ssl Requires-Dist: wincertstore (==0.2) ; (sys_platform == "win32") and extra == 'ssl' .. image:: https://img.shields.io/pypi/v/setuptools.svg :target: https://pypi.org/project/setuptools .. image:: https://img.shields.io/readthedocs/setuptools/latest.svg :target: https://setuptools.readthedocs.io .. image:: https://img.shields.io/travis/pypa/setuptools/master.svg?label=Linux%20CI&logo=travis&logoColor=white :target: https://travis-ci.org/pypa/setuptools .. image:: https://img.shields.io/appveyor/ci/pypa/setuptools/master.svg?label=Windows%20CI&logo=appveyor&logoColor=white :target: https://ci.appveyor.com/project/pypa/setuptools/branch/master .. image:: https://img.shields.io/codecov/c/github/pypa/setuptools/master.svg?logo=codecov&logoColor=white :target: https://codecov.io/gh/pypa/setuptools .. image:: https://tidelift.com/badges/github/pypa/setuptools?style=flat :target: https://tidelift.com/subscription/pkg/pypi-setuptools?utm_source=pypi-setuptools&utm_medium=readme .. image:: https://img.shields.io/pypi/pyversions/setuptools.svg See the `Installation Instructions `_ in the Python Packaging User's Guide for instructions on installing, upgrading, and uninstalling Setuptools. Questions and comments should be directed to the `distutils-sig mailing list `_. Bug reports and especially tested patches may be submitted directly to the `bug tracker `_. To report a security vulnerability, please use the `Tidelift security contact `_. Tidelift will coordinate the fix and disclosure. Code of Conduct --------------- Everyone interacting in the setuptools project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the `PyPA Code of Conduct `_. PK�¶N]Ç—Â3site-packages/setuptools-41.6.0.dist-info/INSTALLERnu„[µü¤pip PK޶N]M¸n=§=§'site-packages/pkg_resources/__init__.pynu„[µü¤# coding: utf-8 """ Package resource API -------------------- A resource is a logical file contained within a package, or a logical subdirectory thereof. The package resource API expects resource names to have their path parts separated with ``/``, *not* whatever the local path separator is. Do not use os.path operations to manipulate resource names being passed into the API. The package resource API is designed to work with normal filesystem packages, .egg files, and unpacked .egg files. It can also work in a limited way with .zip files and with custom PEP 302 loaders that support the ``get_data()`` method. """ from __future__ import absolute_import import sys import os import io import time import re import types import zipfile import zipimport import warnings import stat import functools import pkgutil import operator import platform import collections import plistlib import email.parser import errno import tempfile import textwrap import itertools import inspect import ntpath import posixpath from pkgutil import get_importer try: import _imp except ImportError: # Python 3.2 compatibility import imp as _imp try: FileExistsError except NameError: FileExistsError = OSError from pkg_resources.extern import six from pkg_resources.extern.six.moves import urllib, map, filter # capture these to bypass sandboxing from os import utime try: from os import mkdir, rename, unlink WRITE_SUPPORT = True except ImportError: # no write support, probably under GAE WRITE_SUPPORT = False from os import open as os_open from os.path import isdir, split try: import importlib.machinery as importlib_machinery # access attribute to force import under delayed import mechanisms. importlib_machinery.__name__ except ImportError: importlib_machinery = None from . import py31compat from pkg_resources.extern import appdirs from pkg_resources.extern import packaging __import__('pkg_resources.extern.packaging.version') __import__('pkg_resources.extern.packaging.specifiers') __import__('pkg_resources.extern.packaging.requirements') __import__('pkg_resources.extern.packaging.markers') __metaclass__ = type if (3, 0) < sys.version_info < (3, 4): raise RuntimeError("Python 3.4 or later is required") if six.PY2: # Those builtin exceptions are only defined in Python 3 PermissionError = None NotADirectoryError = None # declare some globals that will be defined later to # satisfy the linters. require = None working_set = None add_activation_listener = None resources_stream = None cleanup_resources = None resource_dir = None resource_stream = None set_extraction_path = None resource_isdir = None resource_string = None iter_entry_points = None resource_listdir = None resource_filename = None resource_exists = None _distribution_finders = None _namespace_handlers = None _namespace_packages = None class PEP440Warning(RuntimeWarning): """ Used when there is an issue with a version or specifier not complying with PEP 440. """ def parse_version(v): try: return packaging.version.Version(v) except packaging.version.InvalidVersion: return packaging.version.LegacyVersion(v) _state_vars = {} def _declare_state(vartype, **kw): globals().update(kw) _state_vars.update(dict.fromkeys(kw, vartype)) def __getstate__(): state = {} g = globals() for k, v in _state_vars.items(): state[k] = g['_sget_' + v](g[k]) return state def __setstate__(state): g = globals() for k, v in state.items(): g['_sset_' + _state_vars[k]](k, g[k], v) return state def _sget_dict(val): return val.copy() def _sset_dict(key, ob, state): ob.clear() ob.update(state) def _sget_object(val): return val.__getstate__() def _sset_object(key, ob, state): ob.__setstate__(state) _sget_none = _sset_none = lambda *args: None def get_supported_platform(): """Return this platform's maximum compatible version. distutils.util.get_platform() normally reports the minimum version of Mac OS X that would be required to *use* extensions produced by distutils. But what we want when checking compatibility is to know the version of Mac OS X that we are *running*. To allow usage of packages that explicitly require a newer version of Mac OS X, we must also know the current version of the OS. If this condition occurs for any other platform with a version in its platform strings, this function should be extended accordingly. """ plat = get_build_platform() m = macosVersionString.match(plat) if m is not None and sys.platform == "darwin": try: plat = 'macosx-%s-%s' % ('.'.join(_macosx_vers()[:2]), m.group(3)) except ValueError: # not Mac OS X pass return plat __all__ = [ # Basic resource access and distribution/entry point discovery 'require', 'run_script', 'get_provider', 'get_distribution', 'load_entry_point', 'get_entry_map', 'get_entry_info', 'iter_entry_points', 'resource_string', 'resource_stream', 'resource_filename', 'resource_listdir', 'resource_exists', 'resource_isdir', # Environmental control 'declare_namespace', 'working_set', 'add_activation_listener', 'find_distributions', 'set_extraction_path', 'cleanup_resources', 'get_default_cache', # Primary implementation classes 'Environment', 'WorkingSet', 'ResourceManager', 'Distribution', 'Requirement', 'EntryPoint', # Exceptions 'ResolutionError', 'VersionConflict', 'DistributionNotFound', 'UnknownExtra', 'ExtractionError', # Warnings 'PEP440Warning', # Parsing functions and string utilities 'parse_requirements', 'parse_version', 'safe_name', 'safe_version', 'get_platform', 'compatible_platforms', 'yield_lines', 'split_sections', 'safe_extra', 'to_filename', 'invalid_marker', 'evaluate_marker', # filesystem utilities 'ensure_directory', 'normalize_path', # Distribution "precedence" constants 'EGG_DIST', 'BINARY_DIST', 'SOURCE_DIST', 'CHECKOUT_DIST', 'DEVELOP_DIST', # "Provider" interfaces, implementations, and registration/lookup APIs 'IMetadataProvider', 'IResourceProvider', 'FileMetadata', 'PathMetadata', 'EggMetadata', 'EmptyProvider', 'empty_provider', 'NullProvider', 'EggProvider', 'DefaultProvider', 'ZipProvider', 'register_finder', 'register_namespace_handler', 'register_loader_type', 'fixup_namespace_packages', 'get_importer', # Warnings 'PkgResourcesDeprecationWarning', # Deprecated/backward compatibility only 'run_main', 'AvailableDistributions', ] class ResolutionError(Exception): """Abstract base for dependency resolution errors""" def __repr__(self): return self.__class__.__name__ + repr(self.args) class VersionConflict(ResolutionError): """ An already-installed version conflicts with the requested version. Should be initialized with the installed Distribution and the requested Requirement. """ _template = "{self.dist} is installed but {self.req} is required" @property def dist(self): return self.args[0] @property def req(self): return self.args[1] def report(self): return self._template.format(**locals()) def with_context(self, required_by): """ If required_by is non-empty, return a version of self that is a ContextualVersionConflict. """ if not required_by: return self args = self.args + (required_by,) return ContextualVersionConflict(*args) class ContextualVersionConflict(VersionConflict): """ A VersionConflict that accepts a third parameter, the set of the requirements that required the installed Distribution. """ _template = VersionConflict._template + ' by {self.required_by}' @property def required_by(self): return self.args[2] class DistributionNotFound(ResolutionError): """A requested distribution was not found""" _template = ("The '{self.req}' distribution was not found " "and is required by {self.requirers_str}") @property def req(self): return self.args[0] @property def requirers(self): return self.args[1] @property def requirers_str(self): if not self.requirers: return 'the application' return ', '.join(self.requirers) def report(self): return self._template.format(**locals()) def __str__(self): return self.report() class UnknownExtra(ResolutionError): """Distribution doesn't have an "extra feature" of the given name""" _provider_factories = {} PY_MAJOR = '{}.{}'.format(*sys.version_info) EGG_DIST = 3 BINARY_DIST = 2 SOURCE_DIST = 1 CHECKOUT_DIST = 0 DEVELOP_DIST = -1 def register_loader_type(loader_type, provider_factory): """Register `provider_factory` to make providers for `loader_type` `loader_type` is the type or class of a PEP 302 ``module.__loader__``, and `provider_factory` is a function that, passed a *module* object, returns an ``IResourceProvider`` for that module. """ _provider_factories[loader_type] = provider_factory def get_provider(moduleOrReq): """Return an IResourceProvider for the named module or requirement""" if isinstance(moduleOrReq, Requirement): return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0] try: module = sys.modules[moduleOrReq] except KeyError: __import__(moduleOrReq) module = sys.modules[moduleOrReq] loader = getattr(module, '__loader__', None) return _find_adapter(_provider_factories, loader)(module) def _macosx_vers(_cache=[]): if not _cache: version = platform.mac_ver()[0] # fallback for MacPorts if version == '': plist = '/System/Library/CoreServices/SystemVersion.plist' if os.path.exists(plist): if hasattr(plistlib, 'readPlist'): plist_content = plistlib.readPlist(plist) if 'ProductVersion' in plist_content: version = plist_content['ProductVersion'] _cache.append(version.split('.')) return _cache[0] def _macosx_arch(machine): return {'PowerPC': 'ppc', 'Power_Macintosh': 'ppc'}.get(machine, machine) def get_build_platform(): """Return this platform's string for platform-specific distributions XXX Currently this is the same as ``distutils.util.get_platform()``, but it needs some hacks for Linux and Mac OS X. """ from sysconfig import get_platform plat = get_platform() if sys.platform == "darwin" and not plat.startswith('macosx-'): try: version = _macosx_vers() machine = os.uname()[4].replace(" ", "_") return "macosx-%d.%d-%s" % ( int(version[0]), int(version[1]), _macosx_arch(machine), ) except ValueError: # if someone is running a non-Mac darwin system, this will fall # through to the default implementation pass return plat macosVersionString = re.compile(r"macosx-(\d+)\.(\d+)-(.*)") darwinVersionString = re.compile(r"darwin-(\d+)\.(\d+)\.(\d+)-(.*)") # XXX backward compat get_platform = get_build_platform def compatible_platforms(provided, required): """Can code for the `provided` platform run on the `required` platform? Returns true if either platform is ``None``, or the platforms are equal. XXX Needs compatibility checks for Linux and other unixy OSes. """ if provided is None or required is None or provided == required: # easy case return True # Mac OS X special cases reqMac = macosVersionString.match(required) if reqMac: provMac = macosVersionString.match(provided) # is this a Mac package? if not provMac: # this is backwards compatibility for packages built before # setuptools 0.6. All packages built after this point will # use the new macosx designation. provDarwin = darwinVersionString.match(provided) if provDarwin: dversion = int(provDarwin.group(1)) macosversion = "%s.%s" % (reqMac.group(1), reqMac.group(2)) if dversion == 7 and macosversion >= "10.3" or \ dversion == 8 and macosversion >= "10.4": return True # egg isn't macosx or legacy darwin return False # are they the same major version and machine type? if provMac.group(1) != reqMac.group(1) or \ provMac.group(3) != reqMac.group(3): return False # is the required OS major update >= the provided one? if int(provMac.group(2)) > int(reqMac.group(2)): return False return True # XXX Linux and other platforms' special cases should go here return False def run_script(dist_spec, script_name): """Locate distribution `dist_spec` and run its `script_name` script""" ns = sys._getframe(1).f_globals name = ns['__name__'] ns.clear() ns['__name__'] = name require(dist_spec)[0].run_script(script_name, ns) # backward compatibility run_main = run_script def get_distribution(dist): """Return a current distribution object for a Requirement or string""" if isinstance(dist, six.string_types): dist = Requirement.parse(dist) if isinstance(dist, Requirement): dist = get_provider(dist) if not isinstance(dist, Distribution): raise TypeError("Expected string, Requirement, or Distribution", dist) return dist def load_entry_point(dist, group, name): """Return `name` entry point of `group` for `dist` or raise ImportError""" return get_distribution(dist).load_entry_point(group, name) def get_entry_map(dist, group=None): """Return the entry point map for `group`, or the full entry map""" return get_distribution(dist).get_entry_map(group) def get_entry_info(dist, group, name): """Return the EntryPoint object for `group`+`name`, or ``None``""" return get_distribution(dist).get_entry_info(group, name) class IMetadataProvider: def has_metadata(name): """Does the package's distribution contain the named metadata?""" def get_metadata(name): """The named metadata resource as a string""" def get_metadata_lines(name): """Yield named metadata resource as list of non-blank non-comment lines Leading and trailing whitespace is stripped from each line, and lines with ``#`` as the first non-blank character are omitted.""" def metadata_isdir(name): """Is the named metadata a directory? (like ``os.path.isdir()``)""" def metadata_listdir(name): """List of metadata names in the directory (like ``os.listdir()``)""" def run_script(script_name, namespace): """Execute the named script in the supplied namespace dictionary""" class IResourceProvider(IMetadataProvider): """An object that provides access to package resources""" def get_resource_filename(manager, resource_name): """Return a true filesystem path for `resource_name` `manager` must be an ``IResourceManager``""" def get_resource_stream(manager, resource_name): """Return a readable file-like object for `resource_name` `manager` must be an ``IResourceManager``""" def get_resource_string(manager, resource_name): """Return a string containing the contents of `resource_name` `manager` must be an ``IResourceManager``""" def has_resource(resource_name): """Does the package contain the named resource?""" def resource_isdir(resource_name): """Is the named resource a directory? (like ``os.path.isdir()``)""" def resource_listdir(resource_name): """List of resource names in the directory (like ``os.listdir()``)""" class WorkingSet: """A collection of active distributions on sys.path (or a similar list)""" def __init__(self, entries=None): """Create working set from list of path entries (default=sys.path)""" self.entries = [] self.entry_keys = {} self.by_key = {} self.callbacks = [] if entries is None: entries = sys.path for entry in entries: self.add_entry(entry) @classmethod def _build_master(cls): """ Prepare the master working set. """ ws = cls() try: from __main__ import __requires__ except ImportError: # The main program does not list any requirements return ws # ensure the requirements are met try: ws.require(__requires__) except VersionConflict: return cls._build_from_requirements(__requires__) return ws @classmethod def _build_from_requirements(cls, req_spec): """ Build a working set from a requirement spec. Rewrites sys.path. """ # try it without defaults already on sys.path # by starting with an empty path ws = cls([]) reqs = parse_requirements(req_spec) dists = ws.resolve(reqs, Environment()) for dist in dists: ws.add(dist) # add any missing entries from sys.path for entry in sys.path: if entry not in ws.entries: ws.add_entry(entry) # then copy back to sys.path sys.path[:] = ws.entries return ws def add_entry(self, entry): """Add a path item to ``.entries``, finding any distributions on it ``find_distributions(entry, True)`` is used to find distributions corresponding to the path entry, and they are added. `entry` is always appended to ``.entries``, even if it is already present. (This is because ``sys.path`` can contain the same value more than once, and the ``.entries`` of the ``sys.path`` WorkingSet should always equal ``sys.path``.) """ self.entry_keys.setdefault(entry, []) self.entries.append(entry) for dist in find_distributions(entry, True): self.add(dist, entry, False) def __contains__(self, dist): """True if `dist` is the active distribution for its project""" return self.by_key.get(dist.key) == dist def find(self, req): """Find a distribution matching requirement `req` If there is an active distribution for the requested project, this returns it as long as it meets the version requirement specified by `req`. But, if there is an active distribution for the project and it does *not* meet the `req` requirement, ``VersionConflict`` is raised. If there is no active distribution for the requested project, ``None`` is returned. """ dist = self.by_key.get(req.key) if dist is not None and dist not in req: # XXX add more info raise VersionConflict(dist, req) return dist def iter_entry_points(self, group, name=None): """Yield entry point objects from `group` matching `name` If `name` is None, yields all entry points in `group` from all distributions in the working set, otherwise only ones matching both `group` and `name` are yielded (in distribution order). """ return ( entry for dist in self for entry in dist.get_entry_map(group).values() if name is None or name == entry.name ) def run_script(self, requires, script_name): """Locate distribution for `requires` and run `script_name` script""" ns = sys._getframe(1).f_globals name = ns['__name__'] ns.clear() ns['__name__'] = name self.require(requires)[0].run_script(script_name, ns) def __iter__(self): """Yield distributions for non-duplicate projects in the working set The yield order is the order in which the items' path entries were added to the working set. """ seen = {} for item in self.entries: if item not in self.entry_keys: # workaround a cache issue continue for key in self.entry_keys[item]: if key not in seen: seen[key] = 1 yield self.by_key[key] def add(self, dist, entry=None, insert=True, replace=False): """Add `dist` to working set, associated with `entry` If `entry` is unspecified, it defaults to the ``.location`` of `dist`. On exit from this routine, `entry` is added to the end of the working set's ``.entries`` (if it wasn't already present). `dist` is only added to the working set if it's for a project that doesn't already have a distribution in the set, unless `replace=True`. If it's added, any callbacks registered with the ``subscribe()`` method will be called. """ if insert: dist.insert_on(self.entries, entry, replace=replace) if entry is None: entry = dist.location keys = self.entry_keys.setdefault(entry, []) keys2 = self.entry_keys.setdefault(dist.location, []) if not replace and dist.key in self.by_key: # ignore hidden distros return self.by_key[dist.key] = dist if dist.key not in keys: keys.append(dist.key) if dist.key not in keys2: keys2.append(dist.key) self._added_new(dist) def resolve(self, requirements, env=None, installer=None, replace_conflicting=False, extras=None): """List all distributions needed to (recursively) meet `requirements` `requirements` must be a sequence of ``Requirement`` objects. `env`, if supplied, should be an ``Environment`` instance. If not supplied, it defaults to all distributions available within any entry or distribution in the working set. `installer`, if supplied, will be invoked with each requirement that cannot be met by an already-installed distribution; it should return a ``Distribution`` or ``None``. Unless `replace_conflicting=True`, raises a VersionConflict exception if any requirements are found on the path that have the correct name but the wrong version. Otherwise, if an `installer` is supplied it will be invoked to obtain the correct version of the requirement and activate it. `extras` is a list of the extras to be used with these requirements. This is important because extra requirements may look like `my_req; extra = "my_extra"`, which would otherwise be interpreted as a purely optional requirement. Instead, we want to be able to assert that these requirements are truly required. """ # set up the stack requirements = list(requirements)[::-1] # set of processed requirements processed = {} # key -> dist best = {} to_activate = [] req_extras = _ReqExtras() # Mapping of requirement to set of distributions that required it; # useful for reporting info about conflicts. required_by = collections.defaultdict(set) while requirements: # process dependencies breadth-first req = requirements.pop(0) if req in processed: # Ignore cyclic or redundant dependencies continue if not req_extras.markers_pass(req, extras): continue dist = best.get(req.key) if dist is None: # Find the best distribution and add it to the map dist = self.by_key.get(req.key) if dist is None or (dist not in req and replace_conflicting): ws = self if env is None: if dist is None: env = Environment(self.entries) else: # Use an empty environment and workingset to avoid # any further conflicts with the conflicting # distribution env = Environment([]) ws = WorkingSet([]) dist = best[req.key] = env.best_match( req, ws, installer, replace_conflicting=replace_conflicting ) if dist is None: requirers = required_by.get(req, None) raise DistributionNotFound(req, requirers) to_activate.append(dist) if dist not in req: # Oops, the "best" so far conflicts with a dependency dependent_req = required_by[req] raise VersionConflict(dist, req).with_context(dependent_req) # push the new requirements onto the stack new_requirements = dist.requires(req.extras)[::-1] requirements.extend(new_requirements) # Register the new requirements needed by req for new_requirement in new_requirements: required_by[new_requirement].add(req.project_name) req_extras[new_requirement] = req.extras processed[req] = True # return list of distros to activate return to_activate def find_plugins( self, plugin_env, full_env=None, installer=None, fallback=True): """Find all activatable distributions in `plugin_env` Example usage:: distributions, errors = working_set.find_plugins( Environment(plugin_dirlist) ) # add plugins+libs to sys.path map(working_set.add, distributions) # display errors print('Could not load', errors) The `plugin_env` should be an ``Environment`` instance that contains only distributions that are in the project's "plugin directory" or directories. The `full_env`, if supplied, should be an ``Environment`` contains all currently-available distributions. If `full_env` is not supplied, one is created automatically from the ``WorkingSet`` this method is called on, which will typically mean that every directory on ``sys.path`` will be scanned for distributions. `installer` is a standard installer callback as used by the ``resolve()`` method. The `fallback` flag indicates whether we should attempt to resolve older versions of a plugin if the newest version cannot be resolved. This method returns a 2-tuple: (`distributions`, `error_info`), where `distributions` is a list of the distributions found in `plugin_env` that were loadable, along with any other distributions that are needed to resolve their dependencies. `error_info` is a dictionary mapping unloadable plugin distributions to an exception instance describing the error that occurred. Usually this will be a ``DistributionNotFound`` or ``VersionConflict`` instance. """ plugin_projects = list(plugin_env) # scan project names in alphabetic order plugin_projects.sort() error_info = {} distributions = {} if full_env is None: env = Environment(self.entries) env += plugin_env else: env = full_env + plugin_env shadow_set = self.__class__([]) # put all our entries in shadow_set list(map(shadow_set.add, self)) for project_name in plugin_projects: for dist in plugin_env[project_name]: req = [dist.as_requirement()] try: resolvees = shadow_set.resolve(req, env, installer) except ResolutionError as v: # save error info error_info[dist] = v if fallback: # try the next older version of project continue else: # give up on this project, keep going break else: list(map(shadow_set.add, resolvees)) distributions.update(dict.fromkeys(resolvees)) # success, no need to try any more versions of this project break distributions = list(distributions) distributions.sort() return distributions, error_info def require(self, *requirements): """Ensure that distributions matching `requirements` are activated `requirements` must be a string or a (possibly-nested) sequence thereof, specifying the distributions and versions required. The return value is a sequence of the distributions that needed to be activated to fulfill the requirements; all relevant distributions are included, even if they were already activated in this working set. """ needed = self.resolve(parse_requirements(requirements)) for dist in needed: self.add(dist) return needed def subscribe(self, callback, existing=True): """Invoke `callback` for all distributions If `existing=True` (default), call on all existing ones, as well. """ if callback in self.callbacks: return self.callbacks.append(callback) if not existing: return for dist in self: callback(dist) def _added_new(self, dist): for callback in self.callbacks: callback(dist) def __getstate__(self): return ( self.entries[:], self.entry_keys.copy(), self.by_key.copy(), self.callbacks[:] ) def __setstate__(self, e_k_b_c): entries, keys, by_key, callbacks = e_k_b_c self.entries = entries[:] self.entry_keys = keys.copy() self.by_key = by_key.copy() self.callbacks = callbacks[:] class _ReqExtras(dict): """ Map each requirement to the extras that demanded it. """ def markers_pass(self, req, extras=None): """ Evaluate markers for req against each extra that demanded it. Return False if the req has a marker and fails evaluation. Otherwise, return True. """ extra_evals = ( req.marker.evaluate({'extra': extra}) for extra in self.get(req, ()) + (extras or (None,)) ) return not req.marker or any(extra_evals) class Environment: """Searchable snapshot of distributions on a search path""" def __init__( self, search_path=None, platform=get_supported_platform(), python=PY_MAJOR): """Snapshot distributions available on a search path Any distributions found on `search_path` are added to the environment. `search_path` should be a sequence of ``sys.path`` items. If not supplied, ``sys.path`` is used. `platform` is an optional string specifying the name of the platform that platform-specific distributions must be compatible with. If unspecified, it defaults to the current platform. `python` is an optional string naming the desired version of Python (e.g. ``'3.6'``); it defaults to the current version. You may explicitly set `platform` (and/or `python`) to ``None`` if you wish to map *all* distributions, not just those compatible with the running platform or Python version. """ self._distmap = {} self.platform = platform self.python = python self.scan(search_path) def can_add(self, dist): """Is distribution `dist` acceptable for this environment? The distribution must match the platform and python version requirements specified when this environment was created, or False is returned. """ py_compat = ( self.python is None or dist.py_version is None or dist.py_version == self.python ) return py_compat and compatible_platforms(dist.platform, self.platform) def remove(self, dist): """Remove `dist` from the environment""" self._distmap[dist.key].remove(dist) def scan(self, search_path=None): """Scan `search_path` for distributions usable in this environment Any distributions found are added to the environment. `search_path` should be a sequence of ``sys.path`` items. If not supplied, ``sys.path`` is used. Only distributions conforming to the platform/python version defined at initialization are added. """ if search_path is None: search_path = sys.path for item in search_path: for dist in find_distributions(item): self.add(dist) def __getitem__(self, project_name): """Return a newest-to-oldest list of distributions for `project_name` Uses case-insensitive `project_name` comparison, assuming all the project's distributions use their project's name converted to all lowercase as their key. """ distribution_key = project_name.lower() return self._distmap.get(distribution_key, []) def add(self, dist): """Add `dist` if we ``can_add()`` it and it has not already been added """ if self.can_add(dist) and dist.has_version(): dists = self._distmap.setdefault(dist.key, []) if dist not in dists: dists.append(dist) dists.sort(key=operator.attrgetter('hashcmp'), reverse=True) def best_match( self, req, working_set, installer=None, replace_conflicting=False): """Find distribution best matching `req` and usable on `working_set` This calls the ``find(req)`` method of the `working_set` to see if a suitable distribution is already active. (This may raise ``VersionConflict`` if an unsuitable version of the project is already active in the specified `working_set`.) If a suitable distribution isn't active, this method returns the newest distribution in the environment that meets the ``Requirement`` in `req`. If no suitable distribution is found, and `installer` is supplied, then the result of calling the environment's ``obtain(req, installer)`` method will be returned. """ try: dist = working_set.find(req) except VersionConflict: if not replace_conflicting: raise dist = None if dist is not None: return dist for dist in self[req.key]: if dist in req: return dist # try to download/install return self.obtain(req, installer) def obtain(self, requirement, installer=None): """Obtain a distribution matching `requirement` (e.g. via download) Obtain a distro that matches requirement (e.g. via download). In the base ``Environment`` class, this routine just returns ``installer(requirement)``, unless `installer` is None, in which case None is returned instead. This method is a hook that allows subclasses to attempt other ways of obtaining a distribution before falling back to the `installer` argument.""" if installer is not None: return installer(requirement) def __iter__(self): """Yield the unique project names of the available distributions""" for key in self._distmap.keys(): if self[key]: yield key def __iadd__(self, other): """In-place addition of a distribution or environment""" if isinstance(other, Distribution): self.add(other) elif isinstance(other, Environment): for project in other: for dist in other[project]: self.add(dist) else: raise TypeError("Can't add %r to environment" % (other,)) return self def __add__(self, other): """Add an environment or distribution to an environment""" new = self.__class__([], platform=None, python=None) for env in self, other: new += env return new # XXX backward compatibility AvailableDistributions = Environment class ExtractionError(RuntimeError): """An error occurred extracting a resource The following attributes are available from instances of this exception: manager The resource manager that raised this exception cache_path The base directory for resource extraction original_error The exception instance that caused extraction to fail """ class ResourceManager: """Manage resource extraction and packages""" extraction_path = None def __init__(self): self.cached_files = {} def resource_exists(self, package_or_requirement, resource_name): """Does the named resource exist?""" return get_provider(package_or_requirement).has_resource(resource_name) def resource_isdir(self, package_or_requirement, resource_name): """Is the named resource an existing directory?""" return get_provider(package_or_requirement).resource_isdir( resource_name ) def resource_filename(self, package_or_requirement, resource_name): """Return a true filesystem path for specified resource""" return get_provider(package_or_requirement).get_resource_filename( self, resource_name ) def resource_stream(self, package_or_requirement, resource_name): """Return a readable file-like object for specified resource""" return get_provider(package_or_requirement).get_resource_stream( self, resource_name ) def resource_string(self, package_or_requirement, resource_name): """Return specified resource as a string""" return get_provider(package_or_requirement).get_resource_string( self, resource_name ) def resource_listdir(self, package_or_requirement, resource_name): """List the contents of the named resource directory""" return get_provider(package_or_requirement).resource_listdir( resource_name ) def extraction_error(self): """Give an error message for problems extracting file(s)""" old_exc = sys.exc_info()[1] cache_path = self.extraction_path or get_default_cache() tmpl = textwrap.dedent(""" Can't extract file(s) to egg cache The following error occurred while trying to extract file(s) to the Python egg cache: {old_exc} The Python egg cache directory is currently set to: {cache_path} Perhaps your account does not have write access to this directory? You can change the cache directory by setting the PYTHON_EGG_CACHE environment variable to point to an accessible directory. """).lstrip() err = ExtractionError(tmpl.format(**locals())) err.manager = self err.cache_path = cache_path err.original_error = old_exc raise err def get_cache_path(self, archive_name, names=()): """Return absolute location in cache for `archive_name` and `names` The parent directory of the resulting path will be created if it does not already exist. `archive_name` should be the base filename of the enclosing egg (which may not be the name of the enclosing zipfile!), including its ".egg" extension. `names`, if provided, should be a sequence of path name parts "under" the egg's extraction location. This method should only be called by resource providers that need to obtain an extraction location, and only for names they intend to extract, as it tracks the generated names for possible cleanup later. """ extract_path = self.extraction_path or get_default_cache() target_path = os.path.join(extract_path, archive_name + '-tmp', *names) try: _bypass_ensure_directory(target_path) except Exception: self.extraction_error() self._warn_unsafe_extraction_path(extract_path) self.cached_files[target_path] = 1 return target_path @staticmethod def _warn_unsafe_extraction_path(path): """ If the default extraction path is overridden and set to an insecure location, such as /tmp, it opens up an opportunity for an attacker to replace an extracted file with an unauthorized payload. Warn the user if a known insecure location is used. See Distribute #375 for more details. """ if os.name == 'nt' and not path.startswith(os.environ['windir']): # On Windows, permissions are generally restrictive by default # and temp directories are not writable by other users, so # bypass the warning. return mode = os.stat(path).st_mode if mode & stat.S_IWOTH or mode & stat.S_IWGRP: msg = ( "%s is writable by group/others and vulnerable to attack " "when " "used with get_resource_filename. Consider a more secure " "location (set with .set_extraction_path or the " "PYTHON_EGG_CACHE environment variable)." % path ) warnings.warn(msg, UserWarning) def postprocess(self, tempname, filename): """Perform any platform-specific postprocessing of `tempname` This is where Mac header rewrites should be done; other platforms don't have anything special they should do. Resource providers should call this method ONLY after successfully extracting a compressed resource. They must NOT call it on resources that are already in the filesystem. `tempname` is the current (temporary) name of the file, and `filename` is the name it will be renamed to by the caller after this routine returns. """ if os.name == 'posix': # Make the resource executable mode = ((os.stat(tempname).st_mode) | 0o555) & 0o7777 os.chmod(tempname, mode) def set_extraction_path(self, path): """Set the base path where resources will be extracted to, if needed. If you do not call this routine before any extractions take place, the path defaults to the return value of ``get_default_cache()``. (Which is based on the ``PYTHON_EGG_CACHE`` environment variable, with various platform-specific fallbacks. See that routine's documentation for more details.) Resources are extracted to subdirectories of this path based upon information given by the ``IResourceProvider``. You may set this to a temporary directory, but then you must call ``cleanup_resources()`` to delete the extracted files when done. There is no guarantee that ``cleanup_resources()`` will be able to remove all extracted files. (Note: you may not change the extraction path for a given resource manager once resources have been extracted, unless you first call ``cleanup_resources()``.) """ if self.cached_files: raise ValueError( "Can't change extraction path, files already extracted" ) self.extraction_path = path def cleanup_resources(self, force=False): """ Delete all extracted resource files and directories, returning a list of the file and directory names that could not be successfully removed. This function does not have any concurrency protection, so it should generally only be called when the extraction path is a temporary directory exclusive to a single process. This method is not automatically called; you must call it explicitly or register it as an ``atexit`` function if you wish to ensure cleanup of a temporary directory used for extractions. """ # XXX def get_default_cache(): """ Return the ``PYTHON_EGG_CACHE`` environment variable or a platform-relevant user cache dir for an app named "Python-Eggs". """ return ( os.environ.get('PYTHON_EGG_CACHE') or appdirs.user_cache_dir(appname='Python-Eggs') ) def safe_name(name): """Convert an arbitrary string to a standard distribution name Any runs of non-alphanumeric/. characters are replaced with a single '-'. """ return re.sub('[^A-Za-z0-9.]+', '-', name) def safe_version(version): """ Convert an arbitrary string to a standard version string """ try: # normalize the version return str(packaging.version.Version(version)) except packaging.version.InvalidVersion: version = version.replace(' ', '.') return re.sub('[^A-Za-z0-9.]+', '-', version) def safe_extra(extra): """Convert an arbitrary string to a standard 'extra' name Any runs of non-alphanumeric characters are replaced with a single '_', and the result is always lowercased. """ return re.sub('[^A-Za-z0-9.-]+', '_', extra).lower() def to_filename(name): """Convert a project or version name to its filename-escaped form Any '-' characters are currently replaced with '_'. """ return name.replace('-', '_') def invalid_marker(text): """ Validate text as a PEP 508 environment marker; return an exception if invalid or False otherwise. """ try: evaluate_marker(text) except SyntaxError as e: e.filename = None e.lineno = None return e return False def evaluate_marker(text, extra=None): """ Evaluate a PEP 508 environment marker. Return a boolean indicating the marker result in this environment. Raise SyntaxError if marker is invalid. This implementation uses the 'pyparsing' module. """ try: marker = packaging.markers.Marker(text) return marker.evaluate() except packaging.markers.InvalidMarker as e: raise SyntaxError(e) class NullProvider: """Try to implement resources and metadata for arbitrary PEP 302 loaders""" egg_name = None egg_info = None loader = None def __init__(self, module): self.loader = getattr(module, '__loader__', None) self.module_path = os.path.dirname(getattr(module, '__file__', '')) def get_resource_filename(self, manager, resource_name): return self._fn(self.module_path, resource_name) def get_resource_stream(self, manager, resource_name): return io.BytesIO(self.get_resource_string(manager, resource_name)) def get_resource_string(self, manager, resource_name): return self._get(self._fn(self.module_path, resource_name)) def has_resource(self, resource_name): return self._has(self._fn(self.module_path, resource_name)) def _get_metadata_path(self, name): return self._fn(self.egg_info, name) def has_metadata(self, name): if not self.egg_info: return self.egg_info path = self._get_metadata_path(name) return self._has(path) def get_metadata(self, name): if not self.egg_info: return "" path = self._get_metadata_path(name) value = self._get(path) if six.PY2: return value try: return value.decode('utf-8') except UnicodeDecodeError as exc: # Include the path in the error message to simplify # troubleshooting, and without changing the exception type. exc.reason += ' in {} file at path: {}'.format(name, path) raise def get_metadata_lines(self, name): return yield_lines(self.get_metadata(name)) def resource_isdir(self, resource_name): return self._isdir(self._fn(self.module_path, resource_name)) def metadata_isdir(self, name): return self.egg_info and self._isdir(self._fn(self.egg_info, name)) def resource_listdir(self, resource_name): return self._listdir(self._fn(self.module_path, resource_name)) def metadata_listdir(self, name): if self.egg_info: return self._listdir(self._fn(self.egg_info, name)) return [] def run_script(self, script_name, namespace): script = 'scripts/' + script_name if not self.has_metadata(script): raise ResolutionError( "Script {script!r} not found in metadata at {self.egg_info!r}" .format(**locals()), ) script_text = self.get_metadata(script).replace('\r\n', '\n') script_text = script_text.replace('\r', '\n') script_filename = self._fn(self.egg_info, script) namespace['__file__'] = script_filename if os.path.exists(script_filename): source = open(script_filename).read() code = compile(source, script_filename, 'exec') exec(code, namespace, namespace) else: from linecache import cache cache[script_filename] = ( len(script_text), 0, script_text.split('\n'), script_filename ) script_code = compile(script_text, script_filename, 'exec') exec(script_code, namespace, namespace) def _has(self, path): raise NotImplementedError( "Can't perform this operation for unregistered loader type" ) def _isdir(self, path): raise NotImplementedError( "Can't perform this operation for unregistered loader type" ) def _listdir(self, path): raise NotImplementedError( "Can't perform this operation for unregistered loader type" ) def _fn(self, base, resource_name): self._validate_resource_path(resource_name) if resource_name: return os.path.join(base, *resource_name.split('/')) return base @staticmethod def _validate_resource_path(path): """ Validate the resource paths according to the docs. https://setuptools.readthedocs.io/en/latest/pkg_resources.html#basic-resource-access >>> warned = getfixture('recwarn') >>> warnings.simplefilter('always') >>> vrp = NullProvider._validate_resource_path >>> vrp('foo/bar.txt') >>> bool(warned) False >>> vrp('../foo/bar.txt') >>> bool(warned) True >>> warned.clear() >>> vrp('/foo/bar.txt') >>> bool(warned) True >>> vrp('foo/../../bar.txt') >>> bool(warned) True >>> warned.clear() >>> vrp('foo/f../bar.txt') >>> bool(warned) False Windows path separators are straight-up disallowed. >>> vrp(r'\\foo/bar.txt') Traceback (most recent call last): ... ValueError: Use of .. or absolute path in a resource path \ is not allowed. >>> vrp(r'C:\\foo/bar.txt') Traceback (most recent call last): ... ValueError: Use of .. or absolute path in a resource path \ is not allowed. Blank values are allowed >>> vrp('') >>> bool(warned) False Non-string values are not. >>> vrp(None) Traceback (most recent call last): ... AttributeError: ... """ invalid = ( os.path.pardir in path.split(posixpath.sep) or posixpath.isabs(path) or ntpath.isabs(path) ) if not invalid: return msg = "Use of .. or absolute path in a resource path is not allowed." # Aggressively disallow Windows absolute paths if ntpath.isabs(path) and not posixpath.isabs(path): raise ValueError(msg) # for compatibility, warn; in future # raise ValueError(msg) warnings.warn( msg[:-1] + " and will raise exceptions in a future release.", DeprecationWarning, stacklevel=4, ) def _get(self, path): if hasattr(self.loader, 'get_data'): return self.loader.get_data(path) raise NotImplementedError( "Can't perform this operation for loaders without 'get_data()'" ) register_loader_type(object, NullProvider) class EggProvider(NullProvider): """Provider based on a virtual filesystem""" def __init__(self, module): NullProvider.__init__(self, module) self._setup_prefix() def _setup_prefix(self): # we assume here that our metadata may be nested inside a "basket" # of multiple eggs; that's why we use module_path instead of .archive path = self.module_path old = None while path != old: if _is_egg_path(path): self.egg_name = os.path.basename(path) self.egg_info = os.path.join(path, 'EGG-INFO') self.egg_root = path break old = path path, base = os.path.split(path) class DefaultProvider(EggProvider): """Provides access to package resources in the filesystem""" def _has(self, path): return os.path.exists(path) def _isdir(self, path): return os.path.isdir(path) def _listdir(self, path): return os.listdir(path) def get_resource_stream(self, manager, resource_name): return open(self._fn(self.module_path, resource_name), 'rb') def _get(self, path): with open(path, 'rb') as stream: return stream.read() @classmethod def _register(cls): loader_names = 'SourceFileLoader', 'SourcelessFileLoader', for name in loader_names: loader_cls = getattr(importlib_machinery, name, type(None)) register_loader_type(loader_cls, cls) DefaultProvider._register() class EmptyProvider(NullProvider): """Provider that returns nothing for all requests""" module_path = None _isdir = _has = lambda self, path: False def _get(self, path): return '' def _listdir(self, path): return [] def __init__(self): pass empty_provider = EmptyProvider() class ZipManifests(dict): """ zip manifest builder """ @classmethod def build(cls, path): """ Build a dictionary similar to the zipimport directory caches, except instead of tuples, store ZipInfo objects. Use a platform-specific path separator (os.sep) for the path keys for compatibility with pypy on Windows. """ with zipfile.ZipFile(path) as zfile: items = ( ( name.replace('/', os.sep), zfile.getinfo(name), ) for name in zfile.namelist() ) return dict(items) load = build class MemoizedZipManifests(ZipManifests): """ Memoized zipfile manifests. """ manifest_mod = collections.namedtuple('manifest_mod', 'manifest mtime') def load(self, path): """ Load a manifest at path or return a suitable manifest already loaded. """ path = os.path.normpath(path) mtime = os.stat(path).st_mtime if path not in self or self[path].mtime != mtime: manifest = self.build(path) self[path] = self.manifest_mod(manifest, mtime) return self[path].manifest class ZipProvider(EggProvider): """Resource support for zips and eggs""" eagers = None _zip_manifests = MemoizedZipManifests() def __init__(self, module): EggProvider.__init__(self, module) self.zip_pre = self.loader.archive + os.sep def _zipinfo_name(self, fspath): # Convert a virtual filename (full path to file) into a zipfile subpath # usable with the zipimport directory cache for our target archive fspath = fspath.rstrip(os.sep) if fspath == self.loader.archive: return '' if fspath.startswith(self.zip_pre): return fspath[len(self.zip_pre):] raise AssertionError( "%s is not a subpath of %s" % (fspath, self.zip_pre) ) def _parts(self, zip_path): # Convert a zipfile subpath into an egg-relative path part list. # pseudo-fs path fspath = self.zip_pre + zip_path if fspath.startswith(self.egg_root + os.sep): return fspath[len(self.egg_root) + 1:].split(os.sep) raise AssertionError( "%s is not a subpath of %s" % (fspath, self.egg_root) ) @property def zipinfo(self): return self._zip_manifests.load(self.loader.archive) def get_resource_filename(self, manager, resource_name): if not self.egg_name: raise NotImplementedError( "resource_filename() only supported for .egg, not .zip" ) # no need to lock for extraction, since we use temp names zip_path = self._resource_to_zip(resource_name) eagers = self._get_eager_resources() if '/'.join(self._parts(zip_path)) in eagers: for name in eagers: self._extract_resource(manager, self._eager_to_zip(name)) return self._extract_resource(manager, zip_path) @staticmethod def _get_date_and_size(zip_stat): size = zip_stat.file_size # ymdhms+wday, yday, dst date_time = zip_stat.date_time + (0, 0, -1) # 1980 offset already done timestamp = time.mktime(date_time) return timestamp, size def _extract_resource(self, manager, zip_path): if zip_path in self._index(): for name in self._index()[zip_path]: last = self._extract_resource( manager, os.path.join(zip_path, name) ) # return the extracted directory name return os.path.dirname(last) timestamp, size = self._get_date_and_size(self.zipinfo[zip_path]) if not WRITE_SUPPORT: raise IOError('"os.rename" and "os.unlink" are not supported ' 'on this platform') try: real_path = manager.get_cache_path( self.egg_name, self._parts(zip_path) ) if self._is_current(real_path, zip_path): return real_path outf, tmpnam = _mkstemp( ".$extract", dir=os.path.dirname(real_path), ) os.write(outf, self.loader.get_data(zip_path)) os.close(outf) utime(tmpnam, (timestamp, timestamp)) manager.postprocess(tmpnam, real_path) try: rename(tmpnam, real_path) except os.error: if os.path.isfile(real_path): if self._is_current(real_path, zip_path): # the file became current since it was checked above, # so proceed. return real_path # Windows, del old file and retry elif os.name == 'nt': unlink(real_path) rename(tmpnam, real_path) return real_path raise except os.error: # report a user-friendly error manager.extraction_error() return real_path def _is_current(self, file_path, zip_path): """ Return True if the file_path is current for this zip_path """ timestamp, size = self._get_date_and_size(self.zipinfo[zip_path]) if not os.path.isfile(file_path): return False stat = os.stat(file_path) if stat.st_size != size or stat.st_mtime != timestamp: return False # check that the contents match zip_contents = self.loader.get_data(zip_path) with open(file_path, 'rb') as f: file_contents = f.read() return zip_contents == file_contents def _get_eager_resources(self): if self.eagers is None: eagers = [] for name in ('native_libs.txt', 'eager_resources.txt'): if self.has_metadata(name): eagers.extend(self.get_metadata_lines(name)) self.eagers = eagers return self.eagers def _index(self): try: return self._dirindex except AttributeError: ind = {} for path in self.zipinfo: parts = path.split(os.sep) while parts: parent = os.sep.join(parts[:-1]) if parent in ind: ind[parent].append(parts[-1]) break else: ind[parent] = [parts.pop()] self._dirindex = ind return ind def _has(self, fspath): zip_path = self._zipinfo_name(fspath) return zip_path in self.zipinfo or zip_path in self._index() def _isdir(self, fspath): return self._zipinfo_name(fspath) in self._index() def _listdir(self, fspath): return list(self._index().get(self._zipinfo_name(fspath), ())) def _eager_to_zip(self, resource_name): return self._zipinfo_name(self._fn(self.egg_root, resource_name)) def _resource_to_zip(self, resource_name): return self._zipinfo_name(self._fn(self.module_path, resource_name)) register_loader_type(zipimport.zipimporter, ZipProvider) class FileMetadata(EmptyProvider): """Metadata handler for standalone PKG-INFO files Usage:: metadata = FileMetadata("/path/to/PKG-INFO") This provider rejects all data and metadata requests except for PKG-INFO, which is treated as existing, and will be the contents of the file at the provided location. """ def __init__(self, path): self.path = path def _get_metadata_path(self, name): return self.path def has_metadata(self, name): return name == 'PKG-INFO' and os.path.isfile(self.path) def get_metadata(self, name): if name != 'PKG-INFO': raise KeyError("No metadata except PKG-INFO is available") with io.open(self.path, encoding='utf-8', errors="replace") as f: metadata = f.read() self._warn_on_replacement(metadata) return metadata def _warn_on_replacement(self, metadata): # Python 2.7 compat for: replacement_char = '�' replacement_char = b'\xef\xbf\xbd'.decode('utf-8') if replacement_char in metadata: tmpl = "{self.path} could not be properly decoded in UTF-8" msg = tmpl.format(**locals()) warnings.warn(msg) def get_metadata_lines(self, name): return yield_lines(self.get_metadata(name)) class PathMetadata(DefaultProvider): """Metadata provider for egg directories Usage:: # Development eggs: egg_info = "/path/to/PackageName.egg-info" base_dir = os.path.dirname(egg_info) metadata = PathMetadata(base_dir, egg_info) dist_name = os.path.splitext(os.path.basename(egg_info))[0] dist = Distribution(basedir, project_name=dist_name, metadata=metadata) # Unpacked egg directories: egg_path = "/path/to/PackageName-ver-pyver-etc.egg" metadata = PathMetadata(egg_path, os.path.join(egg_path,'EGG-INFO')) dist = Distribution.from_filename(egg_path, metadata=metadata) """ def __init__(self, path, egg_info): self.module_path = path self.egg_info = egg_info class EggMetadata(ZipProvider): """Metadata provider for .egg files""" def __init__(self, importer): """Create a metadata provider from a zipimporter""" self.zip_pre = importer.archive + os.sep self.loader = importer if importer.prefix: self.module_path = os.path.join(importer.archive, importer.prefix) else: self.module_path = importer.archive self._setup_prefix() _declare_state('dict', _distribution_finders={}) def register_finder(importer_type, distribution_finder): """Register `distribution_finder` to find distributions in sys.path items `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item handler), and `distribution_finder` is a callable that, passed a path item and the importer instance, yields ``Distribution`` instances found on that path item. See ``pkg_resources.find_on_path`` for an example.""" _distribution_finders[importer_type] = distribution_finder def find_distributions(path_item, only=False): """Yield distributions accessible via `path_item`""" importer = get_importer(path_item) finder = _find_adapter(_distribution_finders, importer) return finder(importer, path_item, only) def find_eggs_in_zip(importer, path_item, only=False): """ Find eggs in zip files; possibly multiple nested eggs. """ if importer.archive.endswith('.whl'): # wheels are not supported with this finder # they don't have PKG-INFO metadata, and won't ever contain eggs return metadata = EggMetadata(importer) if metadata.has_metadata('PKG-INFO'): yield Distribution.from_filename(path_item, metadata=metadata) if only: # don't yield nested distros return for subitem in metadata.resource_listdir(''): if _is_egg_path(subitem): subpath = os.path.join(path_item, subitem) dists = find_eggs_in_zip(zipimport.zipimporter(subpath), subpath) for dist in dists: yield dist elif subitem.lower().endswith('.dist-info'): subpath = os.path.join(path_item, subitem) submeta = EggMetadata(zipimport.zipimporter(subpath)) submeta.egg_info = subpath yield Distribution.from_location(path_item, subitem, submeta) register_finder(zipimport.zipimporter, find_eggs_in_zip) def find_nothing(importer, path_item, only=False): return () register_finder(object, find_nothing) def _by_version_descending(names): """ Given a list of filenames, return them in descending order by version number. >>> names = 'bar', 'foo', 'Python-2.7.10.egg', 'Python-2.7.2.egg' >>> _by_version_descending(names) ['Python-2.7.10.egg', 'Python-2.7.2.egg', 'foo', 'bar'] >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.egg' >>> _by_version_descending(names) ['Setuptools-1.2.3.egg', 'Setuptools-1.2.3b1.egg'] >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.post1.egg' >>> _by_version_descending(names) ['Setuptools-1.2.3.post1.egg', 'Setuptools-1.2.3b1.egg'] """ def _by_version(name): """ Parse each component of the filename """ name, ext = os.path.splitext(name) parts = itertools.chain(name.split('-'), [ext]) return [packaging.version.parse(part) for part in parts] return sorted(names, key=_by_version, reverse=True) def find_on_path(importer, path_item, only=False): """Yield distributions accessible on a sys.path directory""" path_item = _normalize_cached(path_item) if _is_unpacked_egg(path_item): yield Distribution.from_filename( path_item, metadata=PathMetadata( path_item, os.path.join(path_item, 'EGG-INFO') ) ) return entries = safe_listdir(path_item) # for performance, before sorting by version, # screen entries for only those that will yield # distributions filtered = ( entry for entry in entries if dist_factory(path_item, entry, only) ) # scan for .egg and .egg-info in directory path_item_entries = _by_version_descending(filtered) for entry in path_item_entries: fullpath = os.path.join(path_item, entry) factory = dist_factory(path_item, entry, only) for dist in factory(fullpath): yield dist def dist_factory(path_item, entry, only): """ Return a dist_factory for a path_item and entry """ lower = entry.lower() is_meta = any(map(lower.endswith, ('.egg-info', '.dist-info'))) return ( distributions_from_metadata if is_meta else find_distributions if not only and _is_egg_path(entry) else resolve_egg_link if not only and lower.endswith('.egg-link') else NoDists() ) class NoDists: """ >>> bool(NoDists()) False >>> list(NoDists()('anything')) [] """ def __bool__(self): return False if six.PY2: __nonzero__ = __bool__ def __call__(self, fullpath): return iter(()) def safe_listdir(path): """ Attempt to list contents of path, but suppress some exceptions. """ try: return os.listdir(path) except (PermissionError, NotADirectoryError): pass except OSError as e: # Ignore the directory if does not exist, not a directory or # permission denied ignorable = ( e.errno in (errno.ENOTDIR, errno.EACCES, errno.ENOENT) # Python 2 on Windows needs to be handled this way :( or getattr(e, "winerror", None) == 267 ) if not ignorable: raise return () def distributions_from_metadata(path): root = os.path.dirname(path) if os.path.isdir(path): if len(os.listdir(path)) == 0: # empty metadata dir; skip return metadata = PathMetadata(root, path) else: metadata = FileMetadata(path) entry = os.path.basename(path) yield Distribution.from_location( root, entry, metadata, precedence=DEVELOP_DIST, ) def non_empty_lines(path): """ Yield non-empty lines from file at path """ with open(path) as f: for line in f: line = line.strip() if line: yield line def resolve_egg_link(path): """ Given a path to an .egg-link, resolve distributions present in the referenced path. """ referenced_paths = non_empty_lines(path) resolved_paths = ( os.path.join(os.path.dirname(path), ref) for ref in referenced_paths ) dist_groups = map(find_distributions, resolved_paths) return next(dist_groups, ()) register_finder(pkgutil.ImpImporter, find_on_path) if hasattr(importlib_machinery, 'FileFinder'): register_finder(importlib_machinery.FileFinder, find_on_path) _declare_state('dict', _namespace_handlers={}) _declare_state('dict', _namespace_packages={}) def register_namespace_handler(importer_type, namespace_handler): """Register `namespace_handler` to declare namespace packages `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item handler), and `namespace_handler` is a callable like this:: def namespace_handler(importer, path_entry, moduleName, module): # return a path_entry to use for child packages Namespace handlers are only called if the importer object has already agreed that it can handle the relevant path item, and they should only return a subpath if the module __path__ does not already contain an equivalent subpath. For an example namespace handler, see ``pkg_resources.file_ns_handler``. """ _namespace_handlers[importer_type] = namespace_handler def _handle_ns(packageName, path_item): """Ensure that named package includes a subpath of path_item (if needed)""" importer = get_importer(path_item) if importer is None: return None # capture warnings due to #1111 with warnings.catch_warnings(): warnings.simplefilter("ignore") loader = importer.find_module(packageName) if loader is None: return None module = sys.modules.get(packageName) if module is None: module = sys.modules[packageName] = types.ModuleType(packageName) module.__path__ = [] _set_parent_ns(packageName) elif not hasattr(module, '__path__'): raise TypeError("Not a package:", packageName) handler = _find_adapter(_namespace_handlers, importer) subpath = handler(importer, path_item, packageName, module) if subpath is not None: path = module.__path__ path.append(subpath) loader.load_module(packageName) _rebuild_mod_path(path, packageName, module) return subpath def _rebuild_mod_path(orig_path, package_name, module): """ Rebuild module.__path__ ensuring that all entries are ordered corresponding to their sys.path order """ sys_path = [_normalize_cached(p) for p in sys.path] def safe_sys_path_index(entry): """ Workaround for #520 and #513. """ try: return sys_path.index(entry) except ValueError: return float('inf') def position_in_sys_path(path): """ Return the ordinal of the path based on its position in sys.path """ path_parts = path.split(os.sep) module_parts = package_name.count('.') + 1 parts = path_parts[:-module_parts] return safe_sys_path_index(_normalize_cached(os.sep.join(parts))) new_path = sorted(orig_path, key=position_in_sys_path) new_path = [_normalize_cached(p) for p in new_path] if isinstance(module.__path__, list): module.__path__[:] = new_path else: module.__path__ = new_path def declare_namespace(packageName): """Declare that package 'packageName' is a namespace package""" _imp.acquire_lock() try: if packageName in _namespace_packages: return path = sys.path parent, _, _ = packageName.rpartition('.') if parent: declare_namespace(parent) if parent not in _namespace_packages: __import__(parent) try: path = sys.modules[parent].__path__ except AttributeError: raise TypeError("Not a package:", parent) # Track what packages are namespaces, so when new path items are added, # they can be updated _namespace_packages.setdefault(parent or None, []).append(packageName) _namespace_packages.setdefault(packageName, []) for path_item in path: # Ensure all the parent's path items are reflected in the child, # if they apply _handle_ns(packageName, path_item) finally: _imp.release_lock() def fixup_namespace_packages(path_item, parent=None): """Ensure that previously-declared namespace packages include path_item""" _imp.acquire_lock() try: for package in _namespace_packages.get(parent, ()): subpath = _handle_ns(package, path_item) if subpath: fixup_namespace_packages(subpath, package) finally: _imp.release_lock() def file_ns_handler(importer, path_item, packageName, module): """Compute an ns-package subpath for a filesystem or zipfile importer""" subpath = os.path.join(path_item, packageName.split('.')[-1]) normalized = _normalize_cached(subpath) for item in module.__path__: if _normalize_cached(item) == normalized: break else: # Only return the path if it's not already there return subpath register_namespace_handler(pkgutil.ImpImporter, file_ns_handler) register_namespace_handler(zipimport.zipimporter, file_ns_handler) if hasattr(importlib_machinery, 'FileFinder'): register_namespace_handler(importlib_machinery.FileFinder, file_ns_handler) def null_ns_handler(importer, path_item, packageName, module): return None register_namespace_handler(object, null_ns_handler) def normalize_path(filename): """Normalize a file/dir name for comparison purposes""" return os.path.normcase(os.path.realpath(os.path.normpath(_cygwin_patch(filename)))) def _cygwin_patch(filename): # pragma: nocover """ Contrary to POSIX 2008, on Cygwin, getcwd (3) contains symlink components. Using os.path.abspath() works around this limitation. A fix in os.getcwd() would probably better, in Cygwin even more so, except that this seems to be by design... """ return os.path.abspath(filename) if sys.platform == 'cygwin' else filename def _normalize_cached(filename, _cache={}): try: return _cache[filename] except KeyError: _cache[filename] = result = normalize_path(filename) return result def _is_egg_path(path): """ Determine if given path appears to be an egg. """ return path.lower().endswith('.egg') def _is_unpacked_egg(path): """ Determine if given path appears to be an unpacked egg. """ return ( _is_egg_path(path) and os.path.isfile(os.path.join(path, 'EGG-INFO', 'PKG-INFO')) ) def _set_parent_ns(packageName): parts = packageName.split('.') name = parts.pop() if parts: parent = '.'.join(parts) setattr(sys.modules[parent], name, sys.modules[packageName]) def yield_lines(strs): """Yield non-empty/non-comment lines of a string or sequence""" if isinstance(strs, six.string_types): for s in strs.splitlines(): s = s.strip() # skip blank lines/comments if s and not s.startswith('#'): yield s else: for ss in strs: for s in yield_lines(ss): yield s MODULE = re.compile(r"\w+(\.\w+)*$").match EGG_NAME = re.compile( r""" (?P[^-]+) ( -(?P[^-]+) ( -py(?P[^-]+) ( -(?P.+) )? )? )? """, re.VERBOSE | re.IGNORECASE, ).match class EntryPoint: """Object representing an advertised importable object""" def __init__(self, name, module_name, attrs=(), extras=(), dist=None): if not MODULE(module_name): raise ValueError("Invalid module name", module_name) self.name = name self.module_name = module_name self.attrs = tuple(attrs) self.extras = tuple(extras) self.dist = dist def __str__(self): s = "%s = %s" % (self.name, self.module_name) if self.attrs: s += ':' + '.'.join(self.attrs) if self.extras: s += ' [%s]' % ','.join(self.extras) return s def __repr__(self): return "EntryPoint.parse(%r)" % str(self) def load(self, require=True, *args, **kwargs): """ Require packages for this EntryPoint, then resolve it. """ if not require or args or kwargs: warnings.warn( "Parameters to load are deprecated. Call .resolve and " ".require separately.", PkgResourcesDeprecationWarning, stacklevel=2, ) if require: self.require(*args, **kwargs) return self.resolve() def resolve(self): """ Resolve the entry point from its module and attrs. """ module = __import__(self.module_name, fromlist=['__name__'], level=0) try: return functools.reduce(getattr, self.attrs, module) except AttributeError as exc: raise ImportError(str(exc)) def require(self, env=None, installer=None): if self.extras and not self.dist: raise UnknownExtra("Can't require() without a distribution", self) # Get the requirements for this entry point with all its extras and # then resolve them. We have to pass `extras` along when resolving so # that the working set knows what extras we want. Otherwise, for # dist-info distributions, the working set will assume that the # requirements for that extra are purely optional and skip over them. reqs = self.dist.requires(self.extras) items = working_set.resolve(reqs, env, installer, extras=self.extras) list(map(working_set.add, items)) pattern = re.compile( r'\s*' r'(?P.+?)\s*' r'=\s*' r'(?P[\w.]+)\s*' r'(:\s*(?P[\w.]+))?\s*' r'(?P\[.*\])?\s*$' ) @classmethod def parse(cls, src, dist=None): """Parse a single entry point from string `src` Entry point syntax follows the form:: name = some.module:some.attr [extra1, extra2] The entry name and module name are required, but the ``:attrs`` and ``[extras]`` parts are optional """ m = cls.pattern.match(src) if not m: msg = "EntryPoint must be in 'name=module:attrs [extras]' format" raise ValueError(msg, src) res = m.groupdict() extras = cls._parse_extras(res['extras']) attrs = res['attr'].split('.') if res['attr'] else () return cls(res['name'], res['module'], attrs, extras, dist) @classmethod def _parse_extras(cls, extras_spec): if not extras_spec: return () req = Requirement.parse('x' + extras_spec) if req.specs: raise ValueError() return req.extras @classmethod def parse_group(cls, group, lines, dist=None): """Parse an entry point group""" if not MODULE(group): raise ValueError("Invalid group name", group) this = {} for line in yield_lines(lines): ep = cls.parse(line, dist) if ep.name in this: raise ValueError("Duplicate entry point", group, ep.name) this[ep.name] = ep return this @classmethod def parse_map(cls, data, dist=None): """Parse a map of entry point groups""" if isinstance(data, dict): data = data.items() else: data = split_sections(data) maps = {} for group, lines in data: if group is None: if not lines: continue raise ValueError("Entry points must be listed in groups") group = group.strip() if group in maps: raise ValueError("Duplicate group name", group) maps[group] = cls.parse_group(group, lines, dist) return maps def _remove_md5_fragment(location): if not location: return '' parsed = urllib.parse.urlparse(location) if parsed[-1].startswith('md5='): return urllib.parse.urlunparse(parsed[:-1] + ('',)) return location def _version_from_file(lines): """ Given an iterable of lines from a Metadata file, return the value of the Version field, if present, or None otherwise. """ def is_version_line(line): return line.lower().startswith('version:') version_lines = filter(is_version_line, lines) line = next(iter(version_lines), '') _, _, value = line.partition(':') return safe_version(value.strip()) or None class Distribution: """Wrap an actual or potential sys.path entry w/metadata""" PKG_INFO = 'PKG-INFO' def __init__( self, location=None, metadata=None, project_name=None, version=None, py_version=PY_MAJOR, platform=None, precedence=EGG_DIST): self.project_name = safe_name(project_name or 'Unknown') if version is not None: self._version = safe_version(version) self.py_version = py_version self.platform = platform self.location = location self.precedence = precedence self._provider = metadata or empty_provider @classmethod def from_location(cls, location, basename, metadata=None, **kw): project_name, version, py_version, platform = [None] * 4 basename, ext = os.path.splitext(basename) if ext.lower() in _distributionImpl: cls = _distributionImpl[ext.lower()] match = EGG_NAME(basename) if match: project_name, version, py_version, platform = match.group( 'name', 'ver', 'pyver', 'plat' ) return cls( location, metadata, project_name=project_name, version=version, py_version=py_version, platform=platform, **kw )._reload_version() def _reload_version(self): return self @property def hashcmp(self): return ( self.parsed_version, self.precedence, self.key, _remove_md5_fragment(self.location), self.py_version or '', self.platform or '', ) def __hash__(self): return hash(self.hashcmp) def __lt__(self, other): return self.hashcmp < other.hashcmp def __le__(self, other): return self.hashcmp <= other.hashcmp def __gt__(self, other): return self.hashcmp > other.hashcmp def __ge__(self, other): return self.hashcmp >= other.hashcmp def __eq__(self, other): if not isinstance(other, self.__class__): # It's not a Distribution, so they are not equal return False return self.hashcmp == other.hashcmp def __ne__(self, other): return not self == other # These properties have to be lazy so that we don't have to load any # metadata until/unless it's actually needed. (i.e., some distributions # may not know their name or version without loading PKG-INFO) @property def key(self): try: return self._key except AttributeError: self._key = key = self.project_name.lower() return key @property def parsed_version(self): if not hasattr(self, "_parsed_version"): self._parsed_version = parse_version(self.version) return self._parsed_version def _warn_legacy_version(self): LV = packaging.version.LegacyVersion is_legacy = isinstance(self._parsed_version, LV) if not is_legacy: return # While an empty version is technically a legacy version and # is not a valid PEP 440 version, it's also unlikely to # actually come from someone and instead it is more likely that # it comes from setuptools attempting to parse a filename and # including it in the list. So for that we'll gate this warning # on if the version is anything at all or not. if not self.version: return tmpl = textwrap.dedent(""" '{project_name} ({version})' is being parsed as a legacy, non PEP 440, version. You may find odd behavior and sort order. In particular it will be sorted as less than 0.0. It is recommended to migrate to PEP 440 compatible versions. """).strip().replace('\n', ' ') warnings.warn(tmpl.format(**vars(self)), PEP440Warning) @property def version(self): try: return self._version except AttributeError: version = self._get_version() if version is None: path = self._get_metadata_path_for_display(self.PKG_INFO) msg = ( "Missing 'Version:' header and/or {} file at path: {}" ).format(self.PKG_INFO, path) raise ValueError(msg, self) return version @property def _dep_map(self): """ A map of extra to its list of (direct) requirements for this distribution, including the null extra. """ try: return self.__dep_map except AttributeError: self.__dep_map = self._filter_extras(self._build_dep_map()) return self.__dep_map @staticmethod def _filter_extras(dm): """ Given a mapping of extras to dependencies, strip off environment markers and filter out any dependencies not matching the markers. """ for extra in list(filter(None, dm)): new_extra = extra reqs = dm.pop(extra) new_extra, _, marker = extra.partition(':') fails_marker = marker and ( invalid_marker(marker) or not evaluate_marker(marker) ) if fails_marker: reqs = [] new_extra = safe_extra(new_extra) or None dm.setdefault(new_extra, []).extend(reqs) return dm def _build_dep_map(self): dm = {} for name in 'requires.txt', 'depends.txt': for extra, reqs in split_sections(self._get_metadata(name)): dm.setdefault(extra, []).extend(parse_requirements(reqs)) return dm def requires(self, extras=()): """List of Requirements needed for this distro if `extras` are used""" dm = self._dep_map deps = [] deps.extend(dm.get(None, ())) for ext in extras: try: deps.extend(dm[safe_extra(ext)]) except KeyError: raise UnknownExtra( "%s has no such extra feature %r" % (self, ext) ) return deps def _get_metadata_path_for_display(self, name): """ Return the path to the given metadata file, if available. """ try: # We need to access _get_metadata_path() on the provider object # directly rather than through this class's __getattr__() # since _get_metadata_path() is marked private. path = self._provider._get_metadata_path(name) # Handle exceptions e.g. in case the distribution's metadata # provider doesn't support _get_metadata_path(). except Exception: return '[could not detect]' return path def _get_metadata(self, name): if self.has_metadata(name): for line in self.get_metadata_lines(name): yield line def _get_version(self): lines = self._get_metadata(self.PKG_INFO) version = _version_from_file(lines) return version def activate(self, path=None, replace=False): """Ensure distribution is importable on `path` (default=sys.path)""" if path is None: path = sys.path self.insert_on(path, replace=replace) if path is sys.path: fixup_namespace_packages(self.location) for pkg in self._get_metadata('namespace_packages.txt'): if pkg in sys.modules: declare_namespace(pkg) def egg_name(self): """Return what this distribution's standard .egg filename should be""" filename = "%s-%s-py%s" % ( to_filename(self.project_name), to_filename(self.version), self.py_version or PY_MAJOR ) if self.platform: filename += '-' + self.platform return filename def __repr__(self): if self.location: return "%s (%s)" % (self, self.location) else: return str(self) def __str__(self): try: version = getattr(self, 'version', None) except ValueError: version = None version = version or "[unknown version]" return "%s %s" % (self.project_name, version) def __getattr__(self, attr): """Delegate all unrecognized public attributes to .metadata provider""" if attr.startswith('_'): raise AttributeError(attr) return getattr(self._provider, attr) def __dir__(self): return list( set(super(Distribution, self).__dir__()) | set( attr for attr in self._provider.__dir__() if not attr.startswith('_') ) ) if not hasattr(object, '__dir__'): # python 2.7 not supported del __dir__ @classmethod def from_filename(cls, filename, metadata=None, **kw): return cls.from_location( _normalize_cached(filename), os.path.basename(filename), metadata, **kw ) def as_requirement(self): """Return a ``Requirement`` that matches this distribution exactly""" if isinstance(self.parsed_version, packaging.version.Version): spec = "%s==%s" % (self.project_name, self.parsed_version) else: spec = "%s===%s" % (self.project_name, self.parsed_version) return Requirement.parse(spec) def load_entry_point(self, group, name): """Return the `name` entry point of `group` or raise ImportError""" ep = self.get_entry_info(group, name) if ep is None: raise ImportError("Entry point %r not found" % ((group, name),)) return ep.load() def get_entry_map(self, group=None): """Return the entry point map for `group`, or the full entry map""" try: ep_map = self._ep_map except AttributeError: ep_map = self._ep_map = EntryPoint.parse_map( self._get_metadata('entry_points.txt'), self ) if group is not None: return ep_map.get(group, {}) return ep_map def get_entry_info(self, group, name): """Return the EntryPoint object for `group`+`name`, or ``None``""" return self.get_entry_map(group).get(name) def insert_on(self, path, loc=None, replace=False): """Ensure self.location is on path If replace=False (default): - If location is already in path anywhere, do nothing. - Else: - If it's an egg and its parent directory is on path, insert just ahead of the parent. - Else: add to the end of path. If replace=True: - If location is already on path anywhere (not eggs) or higher priority than its parent (eggs) do nothing. - Else: - If it's an egg and its parent directory is on path, insert just ahead of the parent, removing any lower-priority entries. - Else: add it to the front of path. """ loc = loc or self.location if not loc: return nloc = _normalize_cached(loc) bdir = os.path.dirname(nloc) npath = [(p and _normalize_cached(p) or p) for p in path] for p, item in enumerate(npath): if item == nloc: if replace: break else: # don't modify path (even removing duplicates) if # found and not replace return elif item == bdir and self.precedence == EGG_DIST: # if it's an .egg, give it precedence over its directory # UNLESS it's already been added to sys.path and replace=False if (not replace) and nloc in npath[p:]: return if path is sys.path: self.check_version_conflict() path.insert(p, loc) npath.insert(p, nloc) break else: if path is sys.path: self.check_version_conflict() if replace: path.insert(0, loc) else: path.append(loc) return # p is the spot where we found or inserted loc; now remove duplicates while True: try: np = npath.index(nloc, p + 1) except ValueError: break else: del npath[np], path[np] # ha! p = np return def check_version_conflict(self): if self.key == 'setuptools': # ignore the inevitable setuptools self-conflicts :( return nsp = dict.fromkeys(self._get_metadata('namespace_packages.txt')) loc = normalize_path(self.location) for modname in self._get_metadata('top_level.txt'): if (modname not in sys.modules or modname in nsp or modname in _namespace_packages): continue if modname in ('pkg_resources', 'setuptools', 'site'): continue fn = getattr(sys.modules[modname], '__file__', None) if fn and (normalize_path(fn).startswith(loc) or fn.startswith(self.location)): continue issue_warning( "Module %s was already imported from %s, but %s is being added" " to sys.path" % (modname, fn, self.location), ) def has_version(self): try: self.version except ValueError: issue_warning("Unbuilt egg for " + repr(self)) return False return True def clone(self, **kw): """Copy this distribution, substituting in any changed keyword args""" names = 'project_name version py_version platform location precedence' for attr in names.split(): kw.setdefault(attr, getattr(self, attr, None)) kw.setdefault('metadata', self._provider) return self.__class__(**kw) @property def extras(self): return [dep for dep in self._dep_map if dep] class EggInfoDistribution(Distribution): def _reload_version(self): """ Packages installed by distutils (e.g. numpy or scipy), which uses an old safe_version, and so their version numbers can get mangled when converted to filenames (e.g., 1.11.0.dev0+2329eae to 1.11.0.dev0_2329eae). These distributions will not be parsed properly downstream by Distribution and safe_version, so take an extra step and try to get the version number from the metadata file itself instead of the filename. """ md_version = self._get_version() if md_version: self._version = md_version return self class DistInfoDistribution(Distribution): """ Wrap an actual or potential sys.path entry w/metadata, .dist-info style. """ PKG_INFO = 'METADATA' EQEQ = re.compile(r"([\(,])\s*(\d.*?)\s*([,\)])") @property def _parsed_pkg_info(self): """Parse and cache metadata""" try: return self._pkg_info except AttributeError: metadata = self.get_metadata(self.PKG_INFO) self._pkg_info = email.parser.Parser().parsestr(metadata) return self._pkg_info @property def _dep_map(self): try: return self.__dep_map except AttributeError: self.__dep_map = self._compute_dependencies() return self.__dep_map def _compute_dependencies(self): """Recompute this distribution's dependencies.""" dm = self.__dep_map = {None: []} reqs = [] # Including any condition expressions for req in self._parsed_pkg_info.get_all('Requires-Dist') or []: reqs.extend(parse_requirements(req)) def reqs_for_extra(extra): for req in reqs: if not req.marker or req.marker.evaluate({'extra': extra}): yield req common = frozenset(reqs_for_extra(None)) dm[None].extend(common) for extra in self._parsed_pkg_info.get_all('Provides-Extra') or []: s_extra = safe_extra(extra.strip()) dm[s_extra] = list(frozenset(reqs_for_extra(extra)) - common) return dm _distributionImpl = { '.egg': Distribution, '.egg-info': EggInfoDistribution, '.dist-info': DistInfoDistribution, } def issue_warning(*args, **kw): level = 1 g = globals() try: # find the first stack frame that is *not* code in # the pkg_resources module, to use for the warning while sys._getframe(level).f_globals is g: level += 1 except ValueError: pass warnings.warn(stacklevel=level + 1, *args, **kw) class RequirementParseError(ValueError): def __str__(self): return ' '.join(self.args) def parse_requirements(strs): """Yield ``Requirement`` objects for each specification in `strs` `strs` must be a string, or a (possibly-nested) iterable thereof. """ # create a steppable iterator, so we can handle \-continuations lines = iter(yield_lines(strs)) for line in lines: # Drop comments -- a hash without a space may be in a URL. if ' #' in line: line = line[:line.find(' #')] # If there is a line continuation, drop it, and append the next line. if line.endswith('\\'): line = line[:-2].strip() try: line += next(lines) except StopIteration: return yield Requirement(line) class Requirement(packaging.requirements.Requirement): def __init__(self, requirement_string): """DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!""" try: super(Requirement, self).__init__(requirement_string) except packaging.requirements.InvalidRequirement as e: raise RequirementParseError(str(e)) self.unsafe_name = self.name project_name = safe_name(self.name) self.project_name, self.key = project_name, project_name.lower() self.specs = [ (spec.operator, spec.version) for spec in self.specifier] self.extras = tuple(map(safe_extra, self.extras)) self.hashCmp = ( self.key, self.url, self.specifier, frozenset(self.extras), str(self.marker) if self.marker else None, ) self.__hash = hash(self.hashCmp) def __eq__(self, other): return ( isinstance(other, Requirement) and self.hashCmp == other.hashCmp ) def __ne__(self, other): return not self == other def __contains__(self, item): if isinstance(item, Distribution): if item.key != self.key: return False item = item.version # Allow prereleases always in order to match the previous behavior of # this method. In the future this should be smarter and follow PEP 440 # more accurately. return self.specifier.contains(item, prereleases=True) def __hash__(self): return self.__hash def __repr__(self): return "Requirement.parse(%r)" % str(self) @staticmethod def parse(s): req, = parse_requirements(s) return req def _always_object(classes): """ Ensure object appears in the mro even for old-style classes. """ if object not in classes: return classes + (object,) return classes def _find_adapter(registry, ob): """Return an adapter factory for `ob` from `registry`""" types = _always_object(inspect.getmro(getattr(ob, '__class__', type(ob)))) for t in types: if t in registry: return registry[t] def ensure_directory(path): """Ensure that the parent directory of `path` exists""" dirname = os.path.dirname(path) py31compat.makedirs(dirname, exist_ok=True) def _bypass_ensure_directory(path): """Sandbox-bypassing version of ensure_directory()""" if not WRITE_SUPPORT: raise IOError('"os.mkdir" not supported on this platform.') dirname, filename = split(path) if dirname and filename and not isdir(dirname): _bypass_ensure_directory(dirname) try: mkdir(dirname, 0o755) except FileExistsError: pass def split_sections(s): """Split a string or iterable thereof into (section, content) pairs Each ``section`` is a stripped version of the section header ("[section]") and each ``content`` is a list of stripped lines excluding blank lines and comment-only lines. If there are any such lines before the first section header, they're returned in a first ``section`` of ``None``. """ section = None content = [] for line in yield_lines(s): if line.startswith("["): if line.endswith("]"): if section or content: yield section, content section = line[1:-1].strip() content = [] else: raise ValueError("Invalid section heading", line) else: content.append(line) # wrap up last segment yield section, content def _mkstemp(*args, **kw): old_open = os.open try: # temporarily bypass sandboxing os.open = os_open return tempfile.mkstemp(*args, **kw) finally: # and then put it back os.open = old_open # Silence the PEP440Warning by default, so that end users don't get hit by it # randomly just because they use pkg_resources. We want to append the rule # because we want earlier uses of filterwarnings to take precedence over this # one. warnings.filterwarnings("ignore", category=PEP440Warning, append=True) # from jaraco.functools 1.3 def _call_aside(f, *args, **kwargs): f(*args, **kwargs) return f @_call_aside def _initialize(g=globals()): "Set up global resource manager (deliberately not state-saved)" manager = ResourceManager() g['_manager'] = manager g.update( (name, getattr(manager, name)) for name in dir(manager) if not name.startswith('_') ) @_call_aside def _initialize_master_working_set(): """ Prepare the master working set and make the ``require()`` API available. This function has explicit effects on the global state of pkg_resources. It is intended to be invoked once at the initialization of this module. Invocation by other packages is unsupported and done at their own risk. """ working_set = WorkingSet._build_master() _declare_state('object', working_set=working_set) require = working_set.require iter_entry_points = working_set.iter_entry_points add_activation_listener = working_set.subscribe run_script = working_set.run_script # backward compatibility run_main = run_script # Activate all distributions already on sys.path with replace=False and # ensure that all distributions added to the working set in the future # (e.g. by calling ``require()``) will get activated as well, # with higher priority (replace=True). tuple( dist.activate(replace=False) for dist in working_set ) add_activation_listener( lambda dist: dist.activate(replace=True), existing=False, ) working_set.entries = [] # match order list(map(working_set.add_entry, sys.path)) globals().update(locals()) class PkgResourcesDeprecationWarning(Warning): """ Base class for warning about deprecations in ``pkg_resources`` This class is not derived from ``DeprecationWarning``, and as such is visible by default. """ PK‘¶N]\0÷[ˆˆEsite-packages/pkg_resources/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤U âQab=§ãG@s¢dZddlmZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlmZz ddlZWnek �rddlZYnXze Wne!k �r*e"Z YnXddl#m$Z$ddl%m&Z&m'Z'm(Z(ddlm)Z)zddlm*Z*m+Z+m,Z,d Z-Wnek �rŽd Z-YnXdd lm.Z/dd l0m1Z1m2Z2zddl3m4Z5e5j6Wnek �rÜdZ5YnXd dl7m8Z8ddl#m9Z9ddl#m:Z:e;dƒe;dƒe;dƒe;dƒek�r@dk�rLnne?dƒ‚e$j@�r\dZAdZBdZCdZDdZEdZFdZGdZHdZIdZJdZKdZLdZMdZNdZOdZPdZQdZRdZSGdd„deTƒZUdd„ZViZWdd„ZXdd„ZYd d!„ZZd"d#„Z[d$d%„Z\d&d'„Z]d(d)„Z^d*d+„Z_Z`d,d-„Zad.d/d0d1d2d3d4d5d6d7d8d9d:d;dd?d@dAdBdCdDdEdFdGdHdIdJdKdLdMddNddOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcdddedfdgdhdidjdkdldmdndodpdqdrgGZbGdsdI„dIecƒZdGdtdJ„dJedƒZeGdudv„dveeƒZfGdwdK„dKedƒZgGdxdL„dLedƒZhiZidyjjej>ŽZkdzZld{Zmd ZndZod|Zpd}dm„Zqd~d0„Zrgfdd€„Zsd�d‚„Ztdƒd„„Zue vd…¡Zwe vd†¡ZxeuZyd‡dR„Zzdˆd/„Z{e{Z|d‰d1„Z}dŠd2„Z~�dd‹d3„ZdŒd4„Z€Gd�d`„d`ƒZ�GdŽda„dae�ƒZ‚Gd�dD„dDƒZƒGd�d‘„d‘e„ƒZ…Gd’dC„dCƒZ†e†Z‡Gd“dM„dMe?ƒZˆGd”dE„dEƒZ‰d•dB„ZŠd–dO„Z‹d—dP„ZŒd˜dU„Z�d™dV„ZŽdšdW„Z��dd›dX„Z�Gdœdg„dgƒZ‘eqe’e‘ƒGd�dh„dhe‘ƒZ“Gdždi„die“ƒZ”e” •¡GdŸde„dee‘ƒZ–e–ƒZ—Gd d¡„d¡e„ƒZ˜Gd¢d£„d£e˜ƒZ™Gd¤dj„dje“ƒZšeqe j›ešƒGd¥db„dbe–ƒZœGd¦dc„dce”ƒZ�Gd§dd„ddešƒZžeXd¨id©�dªdk„ZŸ�dd«d?„Z �dd¬d­„Z¡eŸe j›e¡ƒ�dd®d¯„Z¢eŸe’e¢ƒd°d±„Z£�dd²d³„Z¤d´dµ„Z¥Gd¶d·„d·ƒZ¦d¸d¹„Z§dºd»„Z¨d¼d½„Z©d¾d¿„ZªeŸej«e¤ƒe¬e5dÀƒ�r°eŸe5j­e¤ƒeXd¨idÁ�eXd¨idÂ�dÃdl„Z®dÄdÅ„Z¯dÆdÇ„Z°dÈd<„Z±�ddÉdn„Z²dÊdË„Z³e®ej«e³ƒe®e j›e³ƒe¬e5dÀƒ�r,e®e5j­e³ƒdÌdÍ„Z´e®e’e´ƒdÎdZ„ZµdÏdЄZ¶ifdÑdÒ„Z·dÓdÔ„Z¸dÕdÖ„Z¹d×dØ„ZºdÙdS„Z»e vdÚ¡j¼Z½e vdÛej¾ej¿B¡j¼ZÀGdÜdH„dHƒZÁdÝdÞ„ZÂdßdà„ZÃGdádF„dFƒZÄGdâdã„dãeăZÅGdädå„dåeăZÆeÄeÅeÆdæœZÇdçdè„ZÈGdédê„dêeɃZÊdëdN„ZËGdìdG„dGe:jÌj̓ZÍdídî„ZÎdïdð„ZÏdñdY„ZÐdòdó„ZÑdôdT„ZÒdõdö„ZÓe jÔd÷eUd dø�dùdú„ZÕeÕeÖƒfdûdü„ƒZ×eÕdýdþ„ƒZØGdÿdp„dpeÙƒZÚdS(aZ Package resource API -------------------- A resource is a logical file contained within a package, or a logical subdirectory thereof. The package resource API expects resource names to have their path parts separated with ``/``, *not* whatever the local path separator is. Do not use os.path operations to manipulate resource names being passed into the API. The package resource API is designed to work with normal filesystem packages, .egg files, and unpacked .egg files. It can also work in a limited way with .zip files and with custom PEP 302 loaders that support the ``get_data()`` method. é)Úabsolute_importN)Ú get_importer)Úsix)ÚurllibÚmapÚfilter)Úutime)ÚmkdirÚrenameÚunlinkTF)Úopen)ÚisdirÚsplité)Ú py31compat)Úappdirs)Ú packagingz&pkg_resources.extern.packaging.versionz)pkg_resources.extern.packaging.specifiersz+pkg_resources.extern.packaging.requirementsz&pkg_resources.extern.packaging.markers)ér)rézPython 3.4 or later is requiredc@seZdZdZdS)Ú PEP440Warningza Used when there is an issue with a version or specifier not complying with PEP 440. N©Ú__name__Ú __module__Ú __qualname__Ú__doc__©rrú:/usr/lib/python3.8/site-packages/pkg_resources/__init__.pyrxsrcCs8ztj |¡WStjjk r2tj |¡YSXdS©N)rÚversionÚVersionÚInvalidVersionÚ LegacyVersion)ÚvrrrÚ parse_versionsr#cKs"tƒ |¡t t ||¡¡dSr)ÚglobalsÚupdateÚ _state_varsÚdictÚfromkeys)ZvartypeÚkwrrrÚ_declare_state‰s r*cCs8i}tƒ}t ¡D] \}}|d|||ƒ||<q|S)NZ_sget_)r$r&Úitems©ÚstateÚgÚkr"rrrÚ __getstate__Žs r0cCs8tƒ}| ¡D]$\}}|dt|||||ƒq|S)NZ_sset_)r$r+r&r,rrrÚ __setstate__–sr1cCs| ¡Sr)Úcopy©ÚvalrrrÚ _sget_dict�sr5cCs| ¡| |¡dSr)Úclearr%©ÚkeyÚobr-rrrÚ _sset_dict¡sr:cCs| ¡Sr)r0r3rrrÚ _sget_object¦sr;cCs| |¡dSr)r1r7rrrÚ _sset_objectªsr<cGsdSrr©ÚargsrrrÚ®ór?cCsbtƒ}t |¡}|dk r^tjdkr^z&dd tƒdd…¡| d¡f}Wntk r\YnX|S)aZReturn this platform's maximum compatible version. distutils.util.get_platform() normally reports the minimum version of Mac OS X that would be required to *use* extensions produced by distutils. But what we want when checking compatibility is to know the version of Mac OS X that we are *running*. To allow usage of packages that explicitly require a newer version of Mac OS X, we must also know the current version of the OS. If this condition occurs for any other platform with a version in its platform strings, this function should be extended accordingly. NÚdarwinz macosx-%s-%sÚ.ér) Úget_build_platformÚmacosVersionStringÚmatchÚsysÚplatformÚjoinÚ _macosx_versÚgroupÚ ValueError)ÚplatÚmrrrÚget_supported_platform±s  &rOÚrequireÚ run_scriptÚ get_providerÚget_distributionÚload_entry_pointÚ get_entry_mapÚget_entry_infoÚiter_entry_pointsÚresource_stringÚresource_streamÚresource_filenameÚresource_listdirÚresource_existsÚresource_isdirÚdeclare_namespaceÚ working_setÚadd_activation_listenerÚfind_distributionsÚset_extraction_pathÚcleanup_resourcesÚget_default_cacheÚ EnvironmentÚ WorkingSetÚResourceManagerÚ DistributionÚ RequirementÚ EntryPointÚResolutionErrorÚVersionConflictÚDistributionNotFoundÚ UnknownExtraÚExtractionErrorÚparse_requirementsÚ safe_nameÚ safe_versionÚ get_platformÚcompatible_platformsÚ yield_linesÚsplit_sectionsÚ safe_extraÚ to_filenameÚinvalid_markerÚevaluate_markerÚensure_directoryÚnormalize_pathÚEGG_DISTÚ BINARY_DISTÚ SOURCE_DISTÚ CHECKOUT_DISTÚ DEVELOP_DISTÚIMetadataProviderÚIResourceProviderÚ FileMetadataÚ PathMetadataÚ EggMetadataÚ EmptyProviderÚempty_providerÚ NullProviderÚ EggProviderÚDefaultProviderÚ ZipProviderÚregister_finderÚregister_namespace_handlerÚregister_loader_typeÚfixup_namespace_packagesrÚPkgResourcesDeprecationWarningÚrun_mainÚAvailableDistributionsc@seZdZdZdd„ZdS)rkz.Abstract base for dependency resolution errorscCs|jjt|jƒSr)Ú __class__rÚreprr>©ÚselfrrrÚ__repr__þszResolutionError.__repr__N)rrrrr˜rrrrrkûsc@s<eZdZdZdZedd„ƒZedd„ƒZdd„Zd d „Z d S) rlzª An already-installed version conflicts with the requested version. Should be initialized with the installed Distribution and the requested Requirement. z3{self.dist} is installed but {self.req} is requiredcCs |jdS©Nrr=r–rrrÚdist szVersionConflict.distcCs |jdS©Nrr=r–rrrÚreqszVersionConflict.reqcCs|jjftƒŽSr©Ú _templateÚformatÚlocalsr–rrrÚreportszVersionConflict.reportcCs|s|S|j|f}t|ŽS)zt If required_by is non-empty, return a version of self that is a ContextualVersionConflict. )r>ÚContextualVersionConflict)r—Ú required_byr>rrrÚ with_contexts zVersionConflict.with_contextN) rrrrržÚpropertyršrœr¡r¤rrrrrls  c@s&eZdZdZejdZedd„ƒZdS)r¢z… A VersionConflict that accepts a third parameter, the set of the requirements that required the installed Distribution. z by {self.required_by}cCs |jdS)NrCr=r–rrrr£*sz%ContextualVersionConflict.required_byN)rrrrrlržr¥r£rrrrr¢"s r¢c@sHeZdZdZdZedd„ƒZedd„ƒZedd„ƒZd d „Z d d „Z d S)rmz&A requested distribution was not foundzSThe '{self.req}' distribution was not found and is required by {self.requirers_str}cCs |jdSr™r=r–rrrrœ5szDistributionNotFound.reqcCs |jdSr›r=r–rrrÚ requirers9szDistributionNotFound.requirerscCs|js dSd |j¡S)Nzthe applicationz, )r¦rIr–rrrÚ requirers_str=sz"DistributionNotFound.requirers_strcCs|jjftƒŽSrr�r–rrrr¡CszDistributionNotFound.reportcCs| ¡Sr)r¡r–rrrÚ__str__FszDistributionNotFound.__str__N) rrrrržr¥rœr¦r§r¡r¨rrrrrm/s   c@seZdZdZdS)rnz>Distribution doesn't have an "extra feature" of the given nameNrrrrrrnJsz{}.{}rrCéÿÿÿÿcCs |t|<dS)aRegister `provider_factory` to make providers for `loader_type` `loader_type` is the type or class of a PEP 302 ``module.__loader__``, and `provider_factory` is a function that, passed a *module* object, returns an ``IResourceProvider`` for that module. N)Ú_provider_factories)Z loader_typeZprovider_factoryrrrr�XscCstt|tƒr$t |¡p"tt|ƒƒdSztj|}Wn&tk rXt |ƒtj|}YnXt |ddƒ}t t |ƒ|ƒS)z?Return an IResourceProvider for the named module or requirementrÚ __loader__N) Ú isinstancerir_ÚfindrPÚstrrGÚmodulesÚKeyErrorÚ __import__ÚgetattrÚ _find_adapterrª)Z moduleOrReqÚmoduleÚloaderrrrrRbs  cCsd|s\t ¡d}|dkrLd}tj |¡rLttdƒrLt |¡}d|krL|d}| |  d¡¡|dS)NrÚz0/System/Library/CoreServices/SystemVersion.plistÚ readPlistZProductVersionrB) rHZmac_verÚosÚpathÚexistsÚhasattrÚplistlibr·Úappendr)Ú_cacherZplistZ plist_contentrrrrJos    rJcCsdddœ ||¡S)NZppc)ZPowerPCZPower_Macintosh)Úget)ÚmachinerrrÚ _macosx_archsrÁcCs~ddlm}|ƒ}tjdkrz| d¡szz>tƒ}t ¡d dd¡}dt |dƒt |d ƒt |ƒfWSt k rxYnX|S) zÄReturn this platform's string for platform-specific distributions XXX Currently this is the same as ``distutils.util.get_platform()``, but it needs some hacks for Linux and Mac OS X. r)rsrAzmacosx-rú Ú_zmacosx-%d.%d-%sr) Z sysconfigrsrGrHÚ startswithrJr¸ÚunameÚreplaceÚintrÁrL)rsrMrrÀrrrrDƒs  þrDzmacosx-(\d+)\.(\d+)-(.*)zdarwin-(\d+)\.(\d+)\.(\d+)-(.*)cCsè|dks|dks||krdSt |¡}|rät |¡}|s”t |¡}|r�t| d¡ƒ}d| d¡| d¡f}|dkr||dksŒ|dkr�|d kr�dSd S| d¡| d¡ks¼| d ¡| d ¡krÀd St| d¡ƒt| d¡ƒkràd SdSd S) zÛCan code for the `provided` platform run on the `required` platform? Returns true if either platform is ``None``, or the platforms are equal. XXX Needs compatibility checks for Linux and other unixy OSes. NTrz%s.%srCéz10.3éz10.4Fr)rErFÚdarwinVersionStringrÇrK)ZprovidedZrequiredZreqMacZprovMacZ provDarwinZdversionZ macosversionrrrrt¡s2   ÿÿÿcCs<t d¡j}|d}| ¡||d<t|ƒd ||¡dS)z@Locate distribution `dist_spec` and run its `script_name` scriptrrrN©rGÚ _getframeÚ f_globalsr6rPrQ)Z dist_specÚ script_nameÚnsÚnamerrrrQÏs  cCs@t|tjƒrt |¡}t|tƒr(t|ƒ}t|tƒsIs the named metadata a directory? (like ``os.path.isdir()``)NrrØrrrÚmetadata_isdirsz IMetadataProvider.metadata_isdircCsdS)z?List of metadata names in the directory (like ``os.listdir()``)NrrØrrrÚmetadata_listdirsz"IMetadataProvider.metadata_listdircCsdS)z=Execute the named script in the supplied namespace dictionaryNr)rÎÚ namespacerrrrQ szIMetadataProvider.run_scriptN) rrrrÙrÚrÛrÜrÝrQrrrrr‚ös c@s@eZdZdZdd„Zdd„Zdd„Zdd „Zd d „Zd d „Z dS)rƒz3An object that provides access to package resourcescCsdS)zdReturn a true filesystem path for `resource_name` `manager` must be an ``IResourceManager``Nr©ÚmanagerÚ resource_namerrrÚget_resource_filenamesz'IResourceProvider.get_resource_filenamecCsdS)ziReturn a readable file-like object for `resource_name` `manager` must be an ``IResourceManager``NrrßrrrÚget_resource_streamsz%IResourceProvider.get_resource_streamcCsdS)zmReturn a string containing the contents of `resource_name` `manager` must be an ``IResourceManager``NrrßrrrÚget_resource_stringsz%IResourceProvider.get_resource_stringcCsdS)z,Does the package contain the named resource?Nr©rárrrÚ has_resourceszIResourceProvider.has_resourcecCsdS)z>Is the named resource a directory? (like ``os.path.isdir()``)Nrrårrrr]"sz IResourceProvider.resource_isdircCsdS)z?List of resource names in the directory (like ``os.listdir()``)Nrrårrrr[%sz"IResourceProvider.resource_listdirN) rrrrrârãrärær]r[rrrrrƒ sc@s¬eZdZdZd'dd„Zedd„ƒZedd„ƒZd d „Zd d „Z d d„Z d(dd„Z dd„Z dd„Z d)dd„Zd*dd„Zd+dd„Zdd„Zd,dd „Zd!d"„Zd#d$„Zd%d&„ZdS)-rfzDA collection of active distributions on sys.path (or a similar list)NcCs>g|_i|_i|_g|_|dkr&tj}|D]}| |¡q*dS)z?Create working set from list of path entries (default=sys.path)N)ÚentriesÚ entry_keysÚby_keyÚ callbacksrGr¹Ú add_entry)r—rçÚentryrrrÚ__init__,szWorkingSet.__init__cCsb|ƒ}zddlm}Wntk r.|YSXz| |¡Wntk r\| |¡YSX|S)z1 Prepare the master working set. r)Ú __requires__)Ú__main__rîÚ ImportErrorrPrlÚ_build_from_requirements)ÚclsÚwsrîrrrÚ _build_master9s zWorkingSet._build_mastercCsf|gƒ}t|ƒ}| |tƒ¡}|D]}| |¡q"tjD]}||jkr8| |¡q8|jtjdd…<|S)zQ Build a working set from a requirement spec. Rewrites sys.path. N)rpÚresolvereÚaddrGr¹rçrë)ròZreq_specróÚreqsÚdistsršrìrrrrñMs    z#WorkingSet._build_from_requirementscCs<|j |g¡|j |¡t|dƒD]}| ||d¡q$dS)aÝAdd a path item to ``.entries``, finding any distributions on it ``find_distributions(entry, True)`` is used to find distributions corresponding to the path entry, and they are added. `entry` is always appended to ``.entries``, even if it is already present. (This is because ``sys.path`` can contain the same value more than once, and the ``.entries`` of the ``sys.path`` WorkingSet should always equal ``sys.path``.) TFN)rèÚ setdefaultrçr½rarö)r—rìršrrrrëcs  zWorkingSet.add_entrycCs|j |j¡|kS)z9True if `dist` is the active distribution for its project)rér¿r8©r—ršrrrÚ __contains__rszWorkingSet.__contains__cCs,|j |j¡}|dk r(||kr(t||ƒ‚|S)aÐFind a distribution matching requirement `req` If there is an active distribution for the requested project, this returns it as long as it meets the version requirement specified by `req`. But, if there is an active distribution for the project and it does *not* meet the `req` requirement, ``VersionConflict`` is raised. If there is no active distribution for the requested project, ``None`` is returned. N)rér¿r8rl)r—rœršrrrr­vs  zWorkingSet.findcs‡‡fdd„|DƒS)aYield entry point objects from `group` matching `name` If `name` is None, yields all entry points in `group` from all distributions in the working set, otherwise only ones matching both `group` and `name` are yielded (in distribution order). c3s8|]0}| ˆ¡ ¡D]}ˆdks*ˆ|jkr|VqqdSr)rUÚvaluesrÐ)Ú.0ršrì©rKrÐrrÚ �s  ýz/WorkingSet.iter_entry_points..r©r—rKrÐrrþrrW†s þzWorkingSet.iter_entry_pointscCs>t d¡j}|d}| ¡||d<| |¡d ||¡dS)z?Locate distribution for `requires` and run `script_name` scriptrrrNrË)r—ÚrequiresrÎrÏrÐrrrrQ”s  zWorkingSet.run_scriptccsLi}|jD]<}||jkrq |j|D] }||kr$d||<|j|Vq$q dS)z¸Yield distributions for non-duplicate projects in the working set The yield order is the order in which the items' path entries were added to the working set. rN)rçrèré)r—ÚseenÚitemr8rrrÚ__iter__œs  zWorkingSet.__iter__TFcCsœ|r|j|j||d�|dkr$|j}|j |g¡}|j |jg¡}|sV|j|jkrVdS||j|j<|j|krx| |j¡|j|krŽ| |j¡| |¡dS)aAdd `dist` to working set, associated with `entry` If `entry` is unspecified, it defaults to the ``.location`` of `dist`. On exit from this routine, `entry` is added to the end of the working set's ``.entries`` (if it wasn't already present). `dist` is only added to the working set if it's for a project that doesn't already have a distribution in the set, unless `replace=True`. If it's added, any callbacks registered with the ``subscribe()`` method will be called. ©rÆN) Ú insert_onrçÚlocationrèrùr8rér½Ú _added_new)r—ršrìÚinsertrÆÚkeysZkeys2rrrrö­s      zWorkingSet.addcCsxt|ƒddd…}i}i}g}tƒ} t t¡} |�rt| d¡} | |krHq.|  | |¡sVq.| | j¡} | dk�r|j  | j¡} | dksŽ| | krø|rø|} |dkr¾| dkr®t |j ƒ}nt gƒ}t gƒ} |j | | ||d�} || j<| dkrø|  | d¡}t| |ƒ‚| | ¡| | k�r$| | }t| | ƒ |¡‚|  | j¡ddd…}| |¡|D] }| | | j¡| j| |<�qHd|| <q.|S)aÎList all distributions needed to (recursively) meet `requirements` `requirements` must be a sequence of ``Requirement`` objects. `env`, if supplied, should be an ``Environment`` instance. If not supplied, it defaults to all distributions available within any entry or distribution in the working set. `installer`, if supplied, will be invoked with each requirement that cannot be met by an already-installed distribution; it should return a ``Distribution`` or ``None``. Unless `replace_conflicting=True`, raises a VersionConflict exception if any requirements are found on the path that have the correct name but the wrong version. Otherwise, if an `installer` is supplied it will be invoked to obtain the correct version of the requirement and activate it. `extras` is a list of the extras to be used with these requirements. This is important because extra requirements may look like `my_req; extra = "my_extra"`, which would otherwise be interpreted as a purely optional requirement. Instead, we want to be able to assert that these requirements are truly required. Nr©r)Úreplace_conflictingT)ÚlistÚ _ReqExtrasÚ collectionsÚ defaultdictÚsetÚpopÚ markers_passr¿r8rérerçrfÚ best_matchrmr½rlr¤rÚextrasÚextendröÚ project_name)r—Ú requirementsÚenvÚ installerr rZ processedZbestZ to_activateZ req_extrasr£rœršrór¦Z dependent_reqZnew_requirementsZnew_requirementrrrrõËsT      þ      zWorkingSet.resolvec Cs t|ƒ}| ¡i}i}|dkr4t|jƒ}||7}n||}| g¡} tt| j|ƒƒ|D]–} || D]ˆ} |  ¡g} z|  | ||¡} WnBt k rÈ}z$||| <|r®WY¢qfn WY¢qZW5d}~XYqfXtt| j| ƒƒ|  t   | ¡¡qZqfqZt|ƒ}| ¡||fS)asFind all activatable distributions in `plugin_env` Example usage:: distributions, errors = working_set.find_plugins( Environment(plugin_dirlist) ) # add plugins+libs to sys.path map(working_set.add, distributions) # display errors print('Could not load', errors) The `plugin_env` should be an ``Environment`` instance that contains only distributions that are in the project's "plugin directory" or directories. The `full_env`, if supplied, should be an ``Environment`` contains all currently-available distributions. If `full_env` is not supplied, one is created automatically from the ``WorkingSet`` this method is called on, which will typically mean that every directory on ``sys.path`` will be scanned for distributions. `installer` is a standard installer callback as used by the ``resolve()`` method. The `fallback` flag indicates whether we should attempt to resolve older versions of a plugin if the newest version cannot be resolved. This method returns a 2-tuple: (`distributions`, `error_info`), where `distributions` is a list of the distributions found in `plugin_env` that were loadable, along with any other distributions that are needed to resolve their dependencies. `error_info` is a dictionary mapping unloadable plugin distributions to an exception instance describing the error that occurred. Usually this will be a ``DistributionNotFound`` or ``VersionConflict`` instance. N) r Úsortrerçr”rröÚas_requirementrõrkr%r'r()r—Z plugin_envZfull_envrZfallbackZplugin_projectsZ error_infoZ distributionsrZ shadow_setrršrœZ resolveesr"rrrÚ find_plugins's4$      zWorkingSet.find_pluginscGs&| t|ƒ¡}|D]}| |¡q|S)a¾Ensure that distributions matching `requirements` are activated `requirements` must be a string or a (possibly-nested) sequence thereof, specifying the distributions and versions required. The return value is a sequence of the distributions that needed to be activated to fulfill the requirements; all relevant distributions are included, even if they were already activated in this working set. )rõrprö)r—rZneededršrrrrP{s  zWorkingSet.requirecCs8||jkrdS|j |¡|s"dS|D] }||ƒq&dS)zƒInvoke `callback` for all distributions If `existing=True` (default), call on all existing ones, as well. N)rêr½)r—ÚcallbackÚexistingršrrrÚ subscribe‹s  zWorkingSet.subscribecCs|jD] }||ƒqdSr)rê)r—ršrrrrr™s zWorkingSet._added_newcCs,|jdd…|j ¡|j ¡|jdd…fSr)rçrèr2rérêr–rrrr0�s   þzWorkingSet.__getstate__cCs@|\}}}}|dd…|_| ¡|_| ¡|_|dd…|_dSr)rçr2rèrérê)r—Ze_k_b_crçr rérêrrrr1£s    zWorkingSet.__setstate__)N)N)NTF)NNFN)NNT)T)rrrrríÚ classmethodrôrñrërûr­rWrQrrörõrrPrrr0r1rrrrrf)s4     ÿ ]ÿ T c@seZdZdZddd„ZdS)r z> Map each requirement to the extras that demanded it. Ncs2‡fdd„| ˆd¡|pdDƒ}ˆj p0t|ƒS)z» Evaluate markers for req against each extra that demanded it. Return False if the req has a marker and fails evaluation. Otherwise, return True. c3s|]}ˆj d|i¡VqdS)ÚextraN©ÚmarkerÚevaluate)rýr!©rœrrrÿ¸sÿz*_ReqExtras.markers_pass..rr)r¿r#Úany)r—rœrZ extra_evalsrr%rr°s þz_ReqExtras.markers_pass)N)rrrrrrrrrr «sr c@sxeZdZdZdeƒefdd„Zdd„Zdd„Zdd d „Z d d „Z d d„Z ddd„Z ddd„Z dd„Zdd„Zdd„ZdS)rez5Searchable snapshot of distributions on a search pathNcCs i|_||_||_| |¡dS)a!Snapshot distributions available on a search path Any distributions found on `search_path` are added to the environment. `search_path` should be a sequence of ``sys.path`` items. If not supplied, ``sys.path`` is used. `platform` is an optional string specifying the name of the platform that platform-specific distributions must be compatible with. If unspecified, it defaults to the current platform. `python` is an optional string naming the desired version of Python (e.g. ``'3.6'``); it defaults to the current version. You may explicitly set `platform` (and/or `python`) to ``None`` if you wish to map *all* distributions, not just those compatible with the running platform or Python version. N)Ú_distmaprHÚpythonÚscan)r—Ú search_pathrHr(rrrríÂszEnvironment.__init__cCs2|jdkp|jdkp|j|jk}|o0t|j|jƒS)zåIs distribution `dist` acceptable for this environment? The distribution must match the platform and python version requirements specified when this environment was created, or False is returned. N)r(Ú py_versionrtrH)r—ršZ py_compatrrrÚcan_addÚs  ÿ ýzEnvironment.can_addcCs|j|j |¡dS)z"Remove `dist` from the environmentN)r'r8Úremoverúrrrr-èszEnvironment.removecCs4|dkrtj}|D]}t|ƒD]}| |¡qqdS)adScan `search_path` for distributions usable in this environment Any distributions found are added to the environment. `search_path` should be a sequence of ``sys.path`` items. If not supplied, ``sys.path`` is used. Only distributions conforming to the platform/python version defined at initialization are added. N)rGr¹rarö)r—r*rršrrrr)ìs  zEnvironment.scancCs| ¡}|j |g¡S)aReturn a newest-to-oldest list of distributions for `project_name` Uses case-insensitive `project_name` comparison, assuming all the project's distributions use their project's name converted to all lowercase as their key. )Úlowerr'r¿)r—rZdistribution_keyrrrÚ __getitem__ûszEnvironment.__getitem__cCsL| |¡rH| ¡rH|j |jg¡}||krH| |¡|jt d¡dd�dS)zLAdd `dist` if we ``can_add()`` it and it has not already been added ÚhashcmpT©r8ÚreverseN) r,Ú has_versionr'rùr8r½rÚoperatorÚ attrgetter)r—ršrørrrrös  zEnvironment.addFcCsfz| |¡}Wntk r,|s$‚d}YnX|dk r:|S||jD]}||krD|SqD| ||¡S)a¸Find distribution best matching `req` and usable on `working_set` This calls the ``find(req)`` method of the `working_set` to see if a suitable distribution is already active. (This may raise ``VersionConflict`` if an unsuitable version of the project is already active in the specified `working_set`.) If a suitable distribution isn't active, this method returns the newest distribution in the environment that meets the ``Requirement`` in `req`. If no suitable distribution is found, and `installer` is supplied, then the result of calling the environment's ``obtain(req, installer)`` method will be returned. N)r­rlr8Úobtain)r—rœr_rr ršrrrrs  zEnvironment.best_matchcCs|dk r||ƒSdS)aÞObtain a distribution matching `requirement` (e.g. via download) Obtain a distro that matches requirement (e.g. via download). In the base ``Environment`` class, this routine just returns ``installer(requirement)``, unless `installer` is None, in which case None is returned instead. This method is a hook that allows subclasses to attempt other ways of obtaining a distribution before falling back to the `installer` argument.Nr)r—Z requirementrrrrr6+s zEnvironment.obtainccs"|j ¡D]}||r |Vq dS)z=Yield the unique project names of the available distributionsN)r'r ©r—r8rrrr7szEnvironment.__iter__cCsVt|tƒr| |¡n)r—Z archive_nameÚnamesZ extract_pathZ target_pathrrrÚget_cache_pathªs    zResourceManager.get_cache_pathcCsVtjdkr| tjd¡sdSt |¡j}|tj@s>|tj@rRd|}t  |t ¡dS)aN If the default extraction path is overridden and set to an insecure location, such as /tmp, it opens up an opportunity for an attacker to replace an extracted file with an unauthorized payload. Warn the user if a known insecure location is used. See Distribute #375 for more details. ÚntZwindirNzË%s is writable by group/others and vulnerable to attack when used with get_resource_filename. Consider a more secure location (set with .set_extraction_path or the PYTHON_EGG_CACHE environment variable).) r¸rÐrÄÚenvironÚstatÚst_modeÚS_IWOTHÚS_IWGRPÚwarningsÚwarnÚ UserWarning)r¹ÚmodeÚmsgrrrrLÃs  üÿz,ResourceManager._warn_unsafe_extraction_pathcCs.tjdkr*t |¡jdBd@}t ||¡dS)a4Perform any platform-specific postprocessing of `tempname` This is where Mac header rewrites should be done; other platforms don't have anything special they should do. Resource providers should call this method ONLY after successfully extracting a compressed resource. They must NOT call it on resources that are already in the filesystem. `tempname` is the current (temporary) name of the file, and `filename` is the name it will be renamed to by the caller after this routine returns. ÚposiximiÿN)r¸rÐrQrRÚchmod)r—ZtempnameÚfilenamerXrrrÚ postprocessÝs zResourceManager.postprocesscCs|jrtdƒ‚||_dS)aÒSet the base path where resources will be extracted to, if needed. If you do not call this routine before any extractions take place, the path defaults to the return value of ``get_default_cache()``. (Which is based on the ``PYTHON_EGG_CACHE`` environment variable, with various platform-specific fallbacks. See that routine's documentation for more details.) Resources are extracted to subdirectories of this path based upon information given by the ``IResourceProvider``. You may set this to a temporary directory, but then you must call ``cleanup_resources()`` to delete the extracted files when done. There is no guarantee that ``cleanup_resources()`` will be able to remove all extracted files. (Note: you may not change the extraction path for a given resource manager once resources have been extracted, unless you first call ``cleanup_resources()``.) z5Can't change extraction path, files already extractedN)r>rLrA©r—r¹rrrrbñs ÿz#ResourceManager.set_extraction_pathFcCsdS)aB Delete all extracted resource files and directories, returning a list of the file and directory names that could not be successfully removed. This function does not have any concurrency protection, so it should generally only be called when the extraction path is a temporary directory exclusive to a single process. This method is not automatically called; you must call it explicitly or register it as an ``atexit`` function if you wish to ensure cleanup of a temporary directory used for extractions. Nr)r—Úforcerrrrc sz!ResourceManager.cleanup_resources)r)F)rrrrrArír\r]rZrYrXr[rIrNÚ staticmethodrLr]rbrcrrrrrges   cCstj d¡ptjdd�S)zŒ Return the ``PYTHON_EGG_CACHE`` environment variable or a platform-relevant user cache dir for an app named "Python-Eggs". ZPYTHON_EGG_CACHEz Python-Eggs)Zappname)r¸rPr¿rZuser_cache_dirrrrrrds  þcCst dd|¡S)z�Convert an arbitrary string to a standard distribution name Any runs of non-alphanumeric/. characters are replaced with a single '-'. ú[^A-Za-z0-9.]+ú-)ÚreÚsubrØrrrrq%scCsJzttj |¡ƒWStjjk rD| dd¡}t dd|¡YSXdS)zB Convert an arbitrary string to a standard version string rÂrBrarbN)r®rrrr rÆrcrd)rrrrrr-s  cCst dd|¡ ¡S)z±Convert an arbitrary string to a standard 'extra' name Any runs of non-alphanumeric characters are replaced with a single '_', and the result is always lowercased. z[^A-Za-z0-9.-]+rÃ)rcrdr.)r!rrrrw9scCs | dd¡S)z|Convert a project or version name to its filename-escaped form Any '-' characters are currently replaced with '_'. rbrÃrrØrrrrxBsc CsHz t|ƒWn6tk rB}zd|_d|_|WY¢Sd}~XYnXdS)zo Validate text as a PEP 508 environment marker; return an exception if invalid or False otherwise. NF)rzÚ SyntaxErrorr\Úlineno)ÚtextÚerrrryJs c CsJztj |¡}| ¡WStjjk rD}z t|ƒ‚W5d}~XYnXdS)zÙ Evaluate a PEP 508 environment marker. Return a boolean indicating the marker result in this environment. Raise SyntaxError if marker is invalid. This implementation uses the 'pyparsing' module. N)rZmarkersZMarkerr$Z InvalidMarkerre)rgr!r#rhrrrrzXs   c@sÀeZdZdZdZdZdZdd„Zdd„Zdd„Z d d „Z d d „Z d d„Z dd„Z dd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd „Zd!d"„Zd#d$„Zd%d&„Zed'd(„ƒZd)d*„ZdS)+r‰zETry to implement resources and metadata for arbitrary PEP 302 loadersNcCs(t|ddƒ|_tj t|ddƒ¡|_dS)Nr«Ú__file__r¶)r²rµr¸r¹ÚdirnameÚ module_path©r—r´rrrrínszNullProvider.__init__cCs| |j|¡Sr)Ú_fnrk©r—ràrárrrrârsz"NullProvider.get_resource_filenamecCst | ||¡¡Sr)ÚioÚBytesIOrärnrrrrãusz NullProvider.get_resource_streamcCs| | |j|¡¡Sr)Ú_getrmrkrnrrrräxsz NullProvider.get_resource_stringcCs| | |j|¡¡Sr)Ú_hasrmrk©r—rárrrræ{szNullProvider.has_resourcecCs| |j|¡Sr)rmÚegg_info©r—rÐrrrÚ_get_metadata_path~szNullProvider._get_metadata_pathcCs |js |jS| |¡}| |¡Sr)rtrvrr©r—rÐr¹rrrrÙ�s zNullProvider.has_metadatac Cst|js dS| |¡}| |¡}tjr(|Sz | d¡WStk rn}z|jd ||¡7_‚W5d}~XYnXdS)Nr¶úutf-8z in {} file at path: {}) rtrvrqrÚPY2ÚdecodeÚUnicodeDecodeErrorÚreasonrŸ)r—rÐr¹ÚvalueÚexcrrrrÚˆs   zNullProvider.get_metadatacCst| |¡ƒSr©rurÚrurrrrÛ—szNullProvider.get_metadata_linescCs| | |j|¡¡Sr)Ú_isdirrmrkrsrrrr]šszNullProvider.resource_isdircCs|jo| | |j|¡¡Sr)rtr€rmrurrrrÜ�szNullProvider.metadata_isdircCs| | |j|¡¡Sr)Ú_listdirrmrkrsrrrr[ szNullProvider.resource_listdircCs|jr| | |j|¡¡SgSr)rtr�rmrurrrrÝ£szNullProvider.metadata_listdirc CsÌd|}| |¡s$tdjftƒŽƒ‚| |¡ dd¡}| dd¡}| |j|¡}||d<tj   |¡rŠt |ƒ  ¡}t ||dƒ}t|||ƒn>dd lm}t|ƒd| d¡|f||<t ||dƒ} t| ||ƒdS) Nzscripts/z') # => <script> do_nasty_stuff() </script> # sanitize_html('Click here for $100') # => Click here for $100 def sanitize_token(self, token): # accommodate filters which use token_type differently token_type = token["type"] if token_type in ("StartTag", "EndTag", "EmptyTag"): name = token["name"] namespace = token["namespace"] if ((namespace, name) in self.allowed_elements or (namespace is None and (namespaces["html"], name) in self.allowed_elements)): return self.allowed_token(token) else: return self.disallowed_token(token) elif token_type == "Comment": pass else: return token def allowed_token(self, token): if "data" in token: attrs = token["data"] attr_names = set(attrs.keys()) # Remove forbidden attributes for to_remove in (attr_names - self.allowed_attributes): del token["data"][to_remove] attr_names.remove(to_remove) # Remove attributes with disallowed URL values for attr in (attr_names & self.attr_val_is_uri): assert attr in attrs # I don't have a clue where this regexp comes from or why it matches those # characters, nor why we call unescape. I just know it's always been here. # Should you be worried by this comment in a sanitizer? Yes. On the other hand, all # this will do is remove *more* than it otherwise would. val_unescaped = re.sub("[`\x00-\x20\x7f-\xa0\\s]+", '', unescape(attrs[attr])).lower() # remove replacement characters from unescaped characters val_unescaped = val_unescaped.replace("\ufffd", "") try: uri = urlparse.urlparse(val_unescaped) except ValueError: uri = None del attrs[attr] if uri and uri.scheme: if uri.scheme not in self.allowed_protocols: del attrs[attr] if uri.scheme == 'data': m = data_content_type.match(uri.path) if not m: del attrs[attr] elif m.group('content_type') not in self.allowed_content_types: del attrs[attr] for attr in self.svg_attr_val_allows_ref: if attr in attrs: attrs[attr] = re.sub(r'url\s*\(\s*[^#\s][^)]+?\)', ' ', unescape(attrs[attr])) if (token["name"] in self.svg_allow_local_href and (namespaces['xlink'], 'href') in attrs and re.search(r'^\s*[^#\s].*', attrs[(namespaces['xlink'], 'href')])): del attrs[(namespaces['xlink'], 'href')] if (None, 'style') in attrs: attrs[(None, 'style')] = self.sanitize_css(attrs[(None, 'style')]) token["data"] = attrs return token def disallowed_token(self, token): token_type = token["type"] if token_type == "EndTag": token["data"] = "" % token["name"] elif token["data"]: assert token_type in ("StartTag", "EmptyTag") attrs = [] for (ns, name), v in token["data"].items(): attrs.append(' %s="%s"' % (name if ns is None else "%s:%s" % (prefixes[ns], name), escape(v))) token["data"] = "<%s%s>" % (token["name"], ''.join(attrs)) else: token["data"] = "<%s>" % token["name"] if token.get("selfClosing"): token["data"] = token["data"][:-1] + "/>" token["type"] = "Characters" del token["name"] return token def sanitize_css(self, style): # disallow urls style = re.compile(r'url\s*\(\s*[^\s)]+?\s*\)\s*').sub(' ', style) # gauntlet if not re.match(r"""^([:,;#%.\sa-zA-Z0-9!]|\w-\w|'[\s\w]+'|"[\s\w]+"|\([\d,\s]+\))*$""", style): return '' if not re.match(r"^\s*([-\w]+\s*:[^:;]*(;\s*|$))*$", style): return '' clean = [] for prop, value in re.findall(r"([-\w]+)\s*:\s*([^:;]*)", style): if not value: continue if prop.lower() in self.allowed_css_properties: clean.append(prop + ': ' + value + ';') elif prop.split('-')[0].lower() in ['background', 'border', 'margin', 'padding']: for keyword in value.split(): if keyword not in self.allowed_css_keywords and \ not re.match(r"^(#[0-9a-fA-F]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|\d{0,2}\.?\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\))?)$", keyword): # noqa break else: clean.append(prop + ': ' + value + ';') elif prop.lower() in self.allowed_svg_properties: clean.append(prop + ': ' + value + ';') return ' '.join(clean) PKÒ¶N]6site-packages/pip/_vendor/html5lib/filters/__init__.pynu„[µü¤PKÒ¶N]Y±Èâbsite-packages/pip/_vendor/html5lib/filters/__pycache__/alphabeticalattributes.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.e—ã@sJddlmZmZmZddlmZddlmZdd„ZGdd„dej ƒZ d S) é)Úabsolute_importÚdivisionÚunicode_literalsé)Úbase)Ú OrderedDictcCs|ddpd|ddfS)zùReturn an appropriate key for an attribute for sorting Attributes have a namespace that can be either ``None`` or a string. We can't compare the two because they're different types, so we convert ``None`` to an empty string first. rÚr©)Úattrr r úW/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.pyÚ _attr_keysr c@seZdZdZdd„ZdS)ÚFilterz$Alphabetizes attributes for elementsccs\tj |¡D]J}|ddkrPtƒ}t|d ¡td�D]\}}|||<q6||d<|Vq dS)NÚtype)ZStartTagZEmptyTagÚdata)Úkey)rr Ú__iter__rÚsortedÚitemsr )ÚselfÚtokenZattrsÚnameÚvaluer r r rs  ÿ zFilter.__iter__N)Ú__name__Ú __module__Ú __qualname__Ú__doc__rr r r r r sr N) Z __future__rrrrrÚ collectionsrr r r r r r Ús   PKÒ¶N]õÃã·BBPsite-packages/pip/_vendor/html5lib/filters/__pycache__/base.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.eã@s(ddlmZmZmZGdd„deƒZdS)é)Úabsolute_importÚdivisionÚunicode_literalsc@s$eZdZdd„Zdd„Zdd„ZdS)ÚFiltercCs ||_dS©N)Úsource)Úselfr©r úE/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/filters/base.pyÚ__init__szFilter.__init__cCs t|jƒSr)Úiterr)rr r r Ú__iter__szFilter.__iter__cCs t|j|ƒSr)Úgetattrr)rÚnamer r r Ú __getattr__ szFilter.__getattr__N)Ú__name__Ú __module__Ú __qualname__r r rr r r r rsrN)Z __future__rrrÚobjectrr r r r ÚsPKÒ¶N][@!¤¤Tsite-packages/pip/_vendor/html5lib/filters/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.eã@sdS)N©rrrúI/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/filters/__init__.pyÚóPKÒ¶N]=ÙÖb�?�?Osite-packages/pip/_vendor/html5lib/filters/__pycache__/sanitizer.cpython-38.pycnu„[µü¤U ÀÒ.eˆfãD@s> ddlmZmZmZddlZddlmZmZddlm Z ddl m Z ddl mZmZd gZeed d fed d fed d fed dfed dfed dfed dfed dfed dfed dfed dfed dfed dfed dfed dfed dfed dfed dfed dfed dfed dfed d fed d!fed d"fed d#fed d$fed d%fed d&fed d'fed d(fed d)fed d*fed d+fed d,fed d-fed d.fed d/fed d0fed d1fed d2fed d3fed d4fed d5fed d6fed d7fed d8fed d9fed d:fed d;fed dfed d?fed d@fed dAfed dBfed dCfed dDfed dEfed dFfed dGfed dHfed dIfed dJfed dKfed dLfed dMfed dNfed dOfed dPfed dQfed dRfed dSfed dTfed dUfed dVfed dWfed dXfed dYfed dZfed d[fed d\fed d]fed d^fed d_fed d`fed dafed dbfed dcfed ddfed defed dffed dgfed dhfed difed djfed dkfed dlfed dmfedndofedndpfedndqfedndrfedndsfedndtfedndufedndvfedndwfedndxfedndyfedndzfednd{fednd|fednd}fednd~fedndfednd€fednd�fednd‚fedndƒfednd„fednd…fednd†fednd‡fedndˆfednd‰fedŠd fedŠd‹fedŠdŒfedŠd�fedŠdŽfedŠd�fedŠd�fedŠd‘fedŠd’fedŠd“fedŠd”fedŠd•fedŠd–fedŠd—fedŠd˜fedŠd™fedŠdšfedŠd›fedŠdœfedŠd�fedŠdžfedŠdŸfedŠd fedŠd¡fedŠd¢fedŠd£fedŠd¤fedŠd¥fedŠd¦fedŠdŠfedŠd§fedŠd¨fedŠd©fedŠdªfedŠd«ff¡ƒZed¬d­d®d¯d°d±d²d³d´dµd¶d·d¸d¹dºd»d¼d½d¾d¿dÀdÁdÂdÃdÄdÅdÆdÇdÈdÉdÊdËdÌdÍdÎdÏdÐdÑdÒdÓdÔdÕdÖd×dØdÙdÚdÛdÜdÝdÞdßdàdádâdãdädådædçdèdédêdëdìdídîdïdðdñdòdódôdõdöd÷dødùdúdûdüdýdþdÿ�d�d�d�d�d�d�d�d�d�d �d �d �d �d �d�d�d�d�d�d�d�d�d�d�d�d�d�d�d�d�d�d�d �d!�d"�d#�d$�d%�d&�d'�d(�d)�d*�d+�d,�d-�d.�d/�d0�d1�d2�d3�d4�d5�d6�d7e�d8�d9f�d:d±�d;�d;�d;�d<�d=�d>�d?�d@�dA�dB�dC�dD�dE�dFdâdæ�dG�dH�dI�dJ�dK�dK�dL�dM�dN�dO�dO�dO�dP�dQ�d�dR�dS�dT�dU�dV�d6�d6e�dW�dXfe�dW�dYfe�dW�dZf�d[�d\�d]�d^�d_�d`�da�db�dc�dd�de�df�dg�dhdÉ�didË�dj�dk�dl�dm�dn�do�dp�dq�d@�drdÞ�ds�dt�du�dv�dw�dx�dy�dz�d{�d|�d}�d~�d�d€�d��d‚�dƒdæ�d„�d…dî�d†�d‡�dˆ�d‰�dŠdô�d‹�dŒ�d��dŽ�d��d��d‘dý�d�d�d’�d“�d”�d•�d–�d—�d˜�d™�dš�d›�dœ�d��dž�dŸ�d �d¡�d¢�d£�d¤�d¥�d¦�d§�d¨�d©�dª�d«�d¬�d­�d®�d¯�d°�d±�d²�d³�d´�dµ�d¶�d·�d(�d¸�d¹�dº�d,�d»�d¼�d½�d¾�d¿�dÀ�dÁ�dÂ�dÃ�dÄ�dÅ�d6�dÆ�dÇ�dÈ�dÉ�dÊe�dW�dËfe�dW�dÌfe�dW�dXfe�dW�dÍfe�dW�dYfe�dWd©fe�dW�dZfe�d8�dÎfe�d8�d9fe�d8�dÏf�dÐ�dÑ�dÒ�dÓ�fCƒZedê�d!dÈd°dö�d d¶dÕdÜdü�d e�dW�dXfe�d8�dÎff ƒZe�dÔƒZe�dÕƒZe�dÖƒZe�d׃Ze�d؃Ze�dÙƒZe�dÚƒZe �dÛej¡ZG�dÜd „d e jƒZdS(Ýé)Úabsolute_importÚdivisionÚunicode_literalsN)ÚescapeÚunescape)Ú urllib_parseé)Úbaseé)Ú namespacesÚprefixesÚFilterÚhtmlÚaÚabbrZacronymZaddressZareaZarticleZasideZaudioÚbZbigZ blockquoteÚbrZbuttonZcanvasZcaptionÚcenterÚciteÚcodeÚcolZcolgroupZcommandZdatagridZdatalistZddÚdelZdetailsZdfnZdialogÚdirZdivZdlZdtZemz event-sourceZfieldsetZ figcaptionZfigureZfooterÚfontÚformÚheaderZh1Zh2Zh3Zh4Zh5Zh6ZhrÚiZimgÚinputZinsZkeygenZkbdÚlabelZlegendZliÚmÚmapZmenuZmeterZmulticolZnavZnextidZolÚoutputZoptgroupZoptionÚpZpreZprogressÚqÚsZsampZsectionZselectZsmallZsoundÚsourceZspacerÚspanZstrikeZstrongÚsubZsupÚtableZtbodyZtdZtextareaÚtimeZtfootZthZtheadZtrZttÚuZulÚvarZvideoZmathmlZmactionZmathZmerrorZmfracÚmiZ mmultiscriptsZmnÚmoZmoverZmpaddedZmphantomZ mprescriptsZmrootZmrowZmspaceZmsqrtZmstyleZmsubZmsubsupZmsupZmtableZmtdZmtextZmtrZmunderZ munderoverÚnoneZsvgÚanimateÚ animateColorÚ animateMotionÚanimateTransformZclipPathZcircleZdefsZdescZellipsez font-facezfont-face-namez font-face-srcÚgZglyphZhkernÚlinearGradientÚlineÚmarkerZmetadataz missing-glyphZmpathÚpathZpolygonZpolylineÚradialGradientZrectÚsetÚstopZswitchÚtextÚtitleZtspanÚuse)Nr)NZaccept)Nzaccept-charset)NZ accesskey)NÚaction)NZalign)NZalt)NZ autocomplete)NZ autofocus)NZaxis)NÚ background)NZbalance)NZbgcolor)NZ bgproperties)NÚborder)NZ bordercolor)NZbordercolordark)NZbordercolorlight)NZ bottompadding)NZ cellpadding)NZ cellspacing)NZch)NZ challenge)NÚchar)NZcharoff)NZchoff)NÚcharset)NÚchecked)Nr)NÚclass)NÚclear)NÚcolor)NZcols)NZcolspan)NZcompact)NZcontenteditable)NZcontrols)NZcoords)NÚdata)NZdatafld)NZ datapagesize)NZdatasrc)NZdatetime)NÚdefault)NZdelay)Nr)NZdisabled)NZ draggable)NZdynsrc)NZenctype)NÚend)NZface)NÚfor)Nr)NÚframe)NZ galleryimg)NZgutter)NZheaders)NÚheight)NZ hidefocus)NZhidden)NZhigh)NÚhref)NZhreflang)NZhspace)NZicon)NÚid)NZ inputmode)NZismap)NZkeytype)Nr)NZ leftspacing)NÚlang)NÚlist)NZlongdesc)NZloop)NZ loopcount)NZloopend)NZ loopstart)NZlow)NZlowsrc)NÚmax)NZ maxlength)NZmedia)NÚmethod)NÚmin)NZmultiple)NÚname)NZnohref)NZnoshade)NÚnowrap)NÚopen)NZoptimum©NÚpattern)NZping)Nz point-size)NZposter)NZpqg)NZpreload)NÚprompt)NZ radiogroup)NÚreadonly)NZrel)Nz repeat-max)Nz repeat-min)NÚreplace)NZrequired)NZrev)NZ rightspacing)NZrows)NZrowspan)NZrules)NZscope)NZselected)NÚshape)NÚsize)Nr&)NÚsrc)NÚstart)NÚstep©NÚstyle)NZsummary)NÚsuppress)NZtabindex)NÚtarget)NÚtemplate)Nr<)NZ toppadding)NÚtype)NZ unselectable)NZusemap)NÚurn)NZvalign)NÚvalue)NZvariable)NÚvolume)NZvspace)NZvrml)NÚwidth)NZwrapZxmlrO)NZ actiontype)NZ columnalign)NZ columnlines)NZ columnspacing)NZ columnspan)NÚdepth)NÚdisplay)NZ displaystyle)NZ equalcolumns)NZ equalrows)NZfence)NZ fontstyle)NZ fontweight)NZ linethickness)NZlspace)NZmathbackground)NZ mathcolor)NZ mathvariant)NÚmaxsize)NZminsize)NÚother)NZrowalign)NZrowlines)NZ rowspacing)NZrspace)NZ scriptlevel)NZ selection)NZ separator)NZstretchyÚxlinkrMZshowrf)Nz accent-height)NÚ accumulate)NZadditive)NZ alphabetic)Nz arabic-form)NZascent)NZ attributeName)NZ attributeType)NZ baseProfile)NZbbox)NZbegin)NZby)NZcalcMode)Nz cap-height©Nz clip-path)Nzcolor-rendering)NZcontent)NZcx)NZcy)NÚd)NZdx)NZdy)NZdescent)NZdur©NÚfill)Nú fill-opacity)Nú fill-rule)Nú font-family)Nú font-size)Nz font-stretch)Nú font-style)Nú font-variant)Nú font-weight)NÚfrom)NZfx)NZfy)NZg1)NZg2)Nz glyph-name)NZ gradientUnits)NZhanging)Nz horiz-adv-x)Nzhoriz-origin-x)NZ ideographic)NÚk)NZ keyPoints)NZ keySplines)NZkeyTimes©Nz marker-end©Nz marker-mid©Nz marker-start)NZ markerHeight)NZ markerUnits)NZ markerWidth)NZ mathematical)NÚoffset)NZopacity)NZorient)NÚorigin)Nzoverline-position)Nzoverline-thickness)Nzpanose-1)Nr7)NZ pathLength)NZpoints)NZpreserveAspectRatio)NÚr)NZrefX)NZrefY)NZ repeatCount)NZ repeatDur)NZrequiredExtensions)NZrequiredFeatures)NZrestart)NÚrotate)NÚrx)NZry)NZslope)NZstemh)NZstemv)Nz stop-color)Nz stop-opacity)Nzstrikethrough-position)Nzstrikethrough-thickness©NÚstroke)Nzstroke-dasharray)Nzstroke-dashoffset)Nústroke-linecap)Nústroke-linejoin)Nzstroke-miterlimit)Nústroke-opacity)Nú stroke-width)NZsystemLanguage)Nz text-anchor)NÚto)NZ transform)NZu1)NZu2)Nzunderline-position)Nzunderline-thickness)NZunicode)Nz unicode-range)Nz units-per-em)NÚvalues)NÚversion)NZviewBox)NZ visibility)NZwidths)NÚx)Nzx-height)NZx1)NZx2ZactuateZarcroleZroler Zspace)NÚy)NZy1)NZy2)NZ zoomAndPan) rq)Nz color-profile©NÚcursorrs©NÚfilter)Nr6r€rr~)NÚmaskr†))NZaltGlyph)Nr/)Nr0)Nr1)Nr2r‘)NZfeImager“)Nr4rW)Nr8)NZtextpath)NZtref)Nr9)Nr=).Zazimuthzbackground-colorzborder-bottom-colorzborder-collapsez border-colorzborder-left-colorzborder-right-colorzborder-top-colorrErFr’Ú directionrlZ elevationÚfloatrrwrxryrzr{rLzletter-spacingz line-heightZoverflowÚpausez pause-afterz pause-beforeZpitchz pitch-rangeZrichnessZspeakz speak-headerz speak-numeralzspeak-punctuationz speech-rateZstressz text-alignztext-decorationz text-indentz unicode-bidizvertical-alignz voice-familyriz white-spacerj)'ÚautoZaquaZblackÚblockZblueZboldZbothZbottomZbrownrZcollapseZdashedZdottedZfuchsiaZgrayZgreenz !importantZitalicÚleftZlimeZmaroonZmediumr.ZnavyZnormalrUZoliveZpointerZpurpleZredÚrightZsolidZsilverZtealÚtopZ transparentZ underlineZwhiteZyellow)rtrurvr‡r‹rˆr‰rŠ)Zed2kZftpZhttpZhttpsZircZmailtoZnewsZgopherZnntpZtelnetZwebcalZxmppZcalltoZfeedrgZaimZrsyncÚtagZsshZsftpZrtspZafsrG)z image/pngz image/jpegz image/gifz image/webpz image/bmpz text/plainaL ^ # Match a content type / (?P[-a-zA-Z0-9.]+/[-a-zA-Z0-9.]+) # Match any character set and encoding (?:(?:;charset=(?:[-a-zA-Z0-9]+)(?:;(?:base64))?) |(?:;(?:base64))?(?:;charset=(?:[-a-zA-Z0-9]+))?) # Assume the rest is data ,.* $ c s^eZdZdZeeeeee e e e e f ‡fdd„ Zdd„Zdd„Zdd „Zd d „Zd d „Z‡ZS)r zISanitizes token stream of XHTML+MathML+SVG and of inline style attributesc sPtt|ƒ |¡||_||_||_||_||_||_||_ | |_ | |_ | |_ dS)aSCreates a Filter :arg allowed_elements: set of elements to allow--everything else will be escaped :arg allowed_attributes: set of attributes to allow in elements--everything else will be stripped :arg allowed_css_properties: set of CSS properties to allow--everything else will be stripped :arg allowed_css_keywords: set of CSS keywords to allow--everything else will be stripped :arg allowed_svg_properties: set of SVG properties to allow--everything else will be removed :arg allowed_protocols: set of allowed protocols for URIs :arg allowed_content_types: set of allowed content types for ``data`` URIs. :arg attr_val_is_uri: set of attributes that have URI values--values that have a scheme not listed in ``allowed_protocols`` are removed :arg svg_attr_val_allows_ref: set of SVG attributes that can have references :arg svg_allow_local_href: set of SVG elements that can have local hrefs--these are removed N) Úsuperr Ú__init__Úallowed_elementsÚallowed_attributesÚallowed_css_propertiesÚallowed_css_keywordsÚallowed_svg_propertiesÚallowed_protocolsÚallowed_content_typesÚattr_val_is_uriÚsvg_attr_val_allows_refÚsvg_allow_local_href) Úselfr%r¡r¢r£r¤r¥r¦r§r¨r©rª©Ú __class__©úJ/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/filters/sanitizer.pyr Ås+zFilter.__init__ccs*tj |¡D]}| |¡}|r |Vq dS)N)r r Ú__iter__Úsanitize_token)r«Útokenr®r®r¯r°üs zFilter.__iter__cCsp|d}|dkr^|d}|d}||f|jksH|dkrRtd|f|jkrR| |¡S| |¡Sn|dkrhn|SdS)Nrf)ÚStartTagÚEndTagÚEmptyTagrTÚ namespacerÚComment)r¡r Ú allowed_tokenÚdisallowed_token)r«r²Ú token_typerTr¶r®r®r¯r± sÿþ  zFilter.sanitize_tokenc Csªd|k�r¦|d}t| ¡ƒ}||jD]}|d|=| |¡q(||j@D]¸}||ks\t‚t ddt||ƒ¡  ¡}|  dd¡}zt   |¡}Wnt k r®d}||=YnX|rL|j rL|j |jkrÌ||=|j dkrLt |j¡}|sî||=qL| d¡|jkrL||=qL|jD]*}||k�r t ddt||ƒ¡||<�q |d|jk�r‚td d f|k�r‚t d |td d f¡�r‚|td d f=d |k�rž| |d ¡|d <||d<|S) NrGu [`- - \s]+Úu�Z content_typezurl\s*\(\s*[^#\s][^)]+?\)ú rTrorMz ^\s*[^#\s].*ra)r9Úkeysr¢Úremover¨ÚAssertionErrorÚrer'rÚlowerr[ÚurlparseÚ ValueErrorZschemer¦Údata_content_typeÚmatchr7Úgroupr§r©rªr ÚsearchÚ sanitize_css) r«r²ÚattrsZ attr_namesZ to_removeÚattrZ val_unescapedZurirr®r®r¯r¸sX      ÿ         þ ÿÿÿ zFilter.allowed_tokencCsâ|d}|dkr"d|d|d<nŒ|drž|dks6t‚g}|d ¡D]:\\}}}| d|dkrd|ndt||ft|ƒf¡qFd |dd  |¡f|d<nd |d|d<| d ¡rÐ|ddd …d|d<d|d<|d=|S)Nrfr´zrTrG)r³rµz %s="%s"z%s:%sz<%s%s>r»z<%s>Z selfClosingéÿÿÿÿz/>Z Characters)r¿ÚitemsÚappendr rÚjoinÚget)r«r²rºrÉÚnsrTÚvr®r®r¯r¹Qs 0 zFilter.disallowed_tokencCsüt d¡ d|¡}t d|¡s"dSt d|¡s2dSg}t d|¡D]®\}}|sPqB| ¡|jkrv| |d|d¡qB| d ¡d  ¡d krÌ| ¡D]}||j kr”t d |¡s”qðq”| |d|d¡qB| ¡|j krB| |d|d¡qBd  |¡S) Nzurl\s*\(\s*[^\s)]+?\s*\)\s*r¼z@^([:,;#%.\sa-zA-Z0-9!]|\w-\w|'[\s\w]+'|"[\s\w]+"|\([\d,\s]+\))*$r»z ^\s*([-\w]+\s*:[^:;]*(;\s*|$))*$z([-\w]+)\s*:\s*([^:;]*)z: ú;ú-r)r?r@ZmarginZpaddingz_^(#[0-9a-fA-F]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|\d{0,2}\.?\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\))?)$) rÀÚcompiler'rÅÚfindallrÁr£rÍÚsplitr¤r¥rÎ)r«rbZcleanZproprhÚkeywordr®r®r¯rÈes*     ÿzFilter.sanitize_css)Ú__name__Ú __module__Ú __qualname__Ú__doc__r¡r¢r£r¤r¥r¦r§r¨r©rªr r°r±r¸r¹rÈÚ __classcell__r®r®r¬r¯r Ãs"õ72) Z __future__rrrrÀZxml.sax.saxutilsrrZpip._vendor.six.movesrrÂr»r Z constantsr r Ú__all__Ú frozensetr¡r¢r¨r©rªr£r¤r¥r¦r§rÔÚVERBOSErÄr r®r®r®r¯Ús                                                                                                                                                                   €ß% €€ºKó   1 *   õPKÒ¶N]õÃã·BBJsite-packages/pip/_vendor/html5lib/filters/__pycache__/base.cpython-38.pycnu„[µü¤U ÀÒ.eã@s(ddlmZmZmZGdd„deƒZdS)é)Úabsolute_importÚdivisionÚunicode_literalsc@s$eZdZdd„Zdd„Zdd„ZdS)ÚFiltercCs ||_dS©N)Úsource)Úselfr©r úE/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/filters/base.pyÚ__init__szFilter.__init__cCs t|jƒSr)Úiterr)rr r r Ú__iter__szFilter.__iter__cCs t|j|ƒSr)Úgetattrr)rÚnamer r r Ú __getattr__ szFilter.__getattr__N)Ú__name__Ú __module__Ú __qualname__r r rr r r r rsrN)Z __future__rrrÚobjectrr r r r ÚsPKÒ¶N]@áÖ¯& & Jsite-packages/pip/_vendor/html5lib/filters/__pycache__/lint.cpython-38.pycnu„[µü¤U ÀÒ.e;ã@shddlmZmZmZddlmZddlmZddlm Z m Z ddlm Z d  e ¡Z Gd d „d ej ƒZ d S) é)Úabsolute_importÚdivisionÚunicode_literals)Ú text_typeé)Úbaseé)Ú namespacesÚ voidElements)ÚspaceCharactersÚcs*eZdZdZd‡fdd„ Zdd„Z‡ZS)ÚFilterzgLints the token stream for errors If it finds any errors, it'll raise an ``AssertionError``. Tcstt|ƒ |¡||_dS)z•Creates a Filter :arg source: the source token stream :arg require_matching_tags: whether or not to require matching tags N)Úsuperr Ú__init__Úrequire_matching_tags)ÚselfÚsourcer©Ú __class__©úE/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/filters/lint.pyrszFilter.__init__c csDg}tj |¡D�],}|d}|dk�rF|d}|d}|dksNt|tƒsNt‚|dksZt‚t|tƒsht‚|dkstt‚t|dtƒs†t‚|r–|tdkr¬|tkr¬|dks¸t‚n |d ks¸t‚|d krÔ|j rÔ|  ||f¡|d  ¡D]`\\}}}|dk�st|tƒ�st‚|dk�st‚t|tƒ�s$t‚|dk�s2t‚t|tƒsàt‚qà�nò|d k�r|d}|d}|dk�szt|tƒ�szt‚|dk�sˆt‚t|tƒ�s˜t‚|dk�s¦t‚|�rº|tdk�rÜ|tk�rÜd �sþtd d |iƒ‚n"|j �r8|  ¡}|||fk�s8t‚�n6|dk�r(|d}t|tƒ�s8t‚�n|dk�rx|d}t|tƒ�sJt‚|dk�sXt‚|dk�r8|  t¡dk�s8t‚nÀ|dk�râ|d}|dk�s¤t|tƒ�s¤t‚|ddk�sÂt|tƒ�sÂt‚|ddk�s8t|tƒ�s8t‚nV|dk�rt|dtƒ�s8t‚n6|dk�r"t|dtƒ�s8t‚nd �s8tdd|iƒ‚|VqdS)NÚtype)ÚStartTagÚEmptyTagÚ namespaceÚnamer ÚdataZhtmlrrZEndTagFz.Void element reported as EndTag token: %(tag)sÚtagÚComment)Z CharactersÚSpaceCharactersrZDoctypeZpublicIdZsystemIdZEntityZSerializerErrorzUnknown token type: %(type)s)rr Ú__iter__Ú isinstancerÚAssertionErrorÚdictr r rÚappendÚitemsÚpopÚstripr ) rZ open_elementsÚtokenrrrÚvalueÚstartrrrrr sl            zFilter.__iter__)T)Ú__name__Ú __module__Ú __qualname__Ú__doc__rr Ú __classcell__rrrrr s r N)Z __future__rrrZpip._vendor.sixrr rZ constantsr r r Újoinr rrrrÚs     PKÒ¶N]<„çQ§ § Rsite-packages/pip/_vendor/html5lib/filters/__pycache__/optionaltags.cpython-38.pycnu„[µü¤U ÀÒ.e\)ã@s6ddlmZmZmZddlmZGdd„dejƒZdS)é)Úabsolute_importÚdivisionÚunicode_literalsé)Úbasec@s0eZdZdZdd„Zdd„Zdd„Zdd „Zd S) ÚFilterz+Removes optional tags from the token streamccsHd}}|jD] }|dk r&|||fV|}|}q|dk rD||dfVdS)N)Úsource)ÚselfZ previous1Z previous2Útoken©r úM/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/filters/optionaltags.pyÚsliders  z Filter.sliderccsp| ¡D]b\}}}|d}|dkrD|ds<| |d||¡sj|Vq|dkrd| |d|¡sj|Vq|VqdS)NÚtypeÚStartTagÚdataÚnameÚEndTag)r Úis_optional_startÚis_optional_end)r Úpreviousr Únextrr r r Ú__iter__sÿzFilter.__iter__cCsÞ|r |dpd}|dkr |dkS|dkrJ|dkr4dS|dkrÚ|ddkSn�|d krx|dkr^d S|d krr|dd kSdSnb|d krš|dkr”|ddkSd Sn@|dkrÚ|d krÖ|rÊ|ddkrÊ|ddkrÊd S|ddkSd Sd S)NrÚhtml©ÚCommentZSpaceCharactersÚhead©rZEmptyTagTrrÚbodyFr)ZscriptZstyleÚcolgroupÚcolÚtbody)r ÚtheadÚtfootÚtrr )r Útagnamerrrr r r rs6   ÿ zFilter.is_optional_startcCs|r |dpd}|dkr |dkS|dkrP|dkr<|d|kS|dkpJ|dkS�n¬|dkrŒ|dkrl|ddkS|d kr„|dkp‚|dkSd S�np|d kr¼|d kr¨|dd kS|dkp¶|dkS�n@|dkrì|dkrØ|ddkS|dkpæ|dkS�n|dk�r |dk�r |ddkS|dk�p|dkSnÜ|dk�rT|dk�r8d S|dk�rN|ddkSdSn¨|dk�r–|dk�rt|ddkS|dk�r�|dk�pŽ|dkSd Snf|dk�rÊ|dk�r¶|ddkS|dk�pÆ|dkSn2|dk�rü|dk�rê|ddkS|dk�pú|dkSd S)Nr)rrrr)ZliÚoptgroupr#rrr)ZdtÚddr&FÚpr)ZaddressZarticleZasideZ blockquoteZdatagridZdialogÚdirZdivZdlZfieldsetZfooterZformZh1Zh2Zh3Zh4Zh5Zh6ÚheaderZhrZmenuZnavZolr'ZpreZsectionÚtableZulÚoption)r+r%)ZrtZrprT)r!r )r r"r r")ZtdZthr )r r$rrr r r rXs\                     zFilter.is_optional_endN)Ú__name__Ú __module__Ú __qualname__Ú__doc__r rrrr r r r rs   9rN)Z __future__rrrÚrrr r r r Ús PKÒ¶N]<„çQ§ § Xsite-packages/pip/_vendor/html5lib/filters/__pycache__/optionaltags.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.e\)ã@s6ddlmZmZmZddlmZGdd„dejƒZdS)é)Úabsolute_importÚdivisionÚunicode_literalsé)Úbasec@s0eZdZdZdd„Zdd„Zdd„Zdd „Zd S) ÚFilterz+Removes optional tags from the token streamccsHd}}|jD] }|dk r&|||fV|}|}q|dk rD||dfVdS)N)Úsource)ÚselfZ previous1Z previous2Útoken©r úM/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/filters/optionaltags.pyÚsliders  z Filter.sliderccsp| ¡D]b\}}}|d}|dkrD|ds<| |d||¡sj|Vq|dkrd| |d|¡sj|Vq|VqdS)NÚtypeÚStartTagÚdataÚnameÚEndTag)r Úis_optional_startÚis_optional_end)r Úpreviousr Únextrr r r Ú__iter__sÿzFilter.__iter__cCsÞ|r |dpd}|dkr |dkS|dkrJ|dkr4dS|dkrÚ|ddkSn�|d krx|dkr^d S|d krr|dd kSdSnb|d krš|dkr”|ddkSd Sn@|dkrÚ|d krÖ|rÊ|ddkrÊ|ddkrÊd S|ddkSd Sd S)NrÚhtml©ÚCommentZSpaceCharactersÚhead©rZEmptyTagTrrÚbodyFr)ZscriptZstyleÚcolgroupÚcolÚtbody)r ÚtheadÚtfootÚtrr )r Útagnamerrrr r r rs6   ÿ zFilter.is_optional_startcCs|r |dpd}|dkr |dkS|dkrP|dkr<|d|kS|dkpJ|dkS�n¬|dkrŒ|dkrl|ddkS|d kr„|dkp‚|dkSd S�np|d kr¼|d kr¨|dd kS|dkp¶|dkS�n@|dkrì|dkrØ|ddkS|dkpæ|dkS�n|dk�r |dk�r |ddkS|dk�p|dkSnÜ|dk�rT|dk�r8d S|dk�rN|ddkSdSn¨|dk�r–|dk�rt|ddkS|dk�r�|dk�pŽ|dkSd Snf|dk�rÊ|dk�r¶|ddkS|dk�pÆ|dkSn2|dk�rü|dk�rê|ddkS|dk�pú|dkSd S)Nr)rrrr)ZliÚoptgroupr#rrr)ZdtÚddr&FÚpr)ZaddressZarticleZasideZ blockquoteZdatagridZdialogÚdirZdivZdlZfieldsetZfooterZformZh1Zh2Zh3Zh4Zh5Zh6ÚheaderZhrZmenuZnavZolr'ZpreZsectionÚtableZulÚoption)r+r%)ZrtZrprT)r!r )r r"r r")ZtdZthr )r r$rrr r r rXs\                     zFilter.is_optional_endN)Ú__name__Ú __module__Ú __qualname__Ú__doc__r rrrr r r r rs   9rN)Z __future__rrrÚrrr r r r Ús PKÒ¶N]my00_site-packages/pip/_vendor/html5lib/filters/__pycache__/inject_meta_charset.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.e� ã@s6ddlmZmZmZddlmZGdd„dejƒZdS)é)Úabsolute_importÚdivisionÚunicode_literalsé)Úbasec@s eZdZdZdd„Zdd„ZdS)ÚFilterz=Injects ```` tag into head of documentcCstj ||¡||_dS)ztCreates a Filter :arg source: the source token stream :arg encoding: the encoding to set N)rrÚ__init__Úencoding)ÚselfÚsourcer ©r úT/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.pyrszFilter.__init__c csÒd}|jdk}g}tj |¡D�]¬}|d}|dkrL|d ¡dkrHd}�nd|dk�rJ|d ¡dkrød }|d  ¡D]X\\}}} |dk rŽqvqv| ¡d kr¶|j|d ||f<d }qöqv|d krv|  ¡dkrvd }qv|röd|d kröd|j|d d<d }nP|d ¡dk�r°|�s°dd|d dœVddd|jidœVdddœVd }qnf|dk�r°|d ¡dk�r°|�r°| d¡V|�s’ddd|jidœV|�r¨| d¡V�q’d }d}|dk�rÆ| |¡q|VqdS)NZpre_headÚtypeZStartTagÚnameÚheadZin_headZEmptyTagÚmetaFÚdataÚcharsetTz http-equivz content-type)NZcontentztext/html; charset=%s)rrr)NrZEndTag)rrrZ post_head)r rrÚ__iter__ÚlowerÚitemsÚpopÚappend) r ÚstateZ meta_foundZpendingÚtokenrZhas_http_equiv_content_typeÚ namespacerÚvaluer r r rs^   ÿÿ   ÿ  zFilter.__iter__N)Ú__name__Ú __module__Ú __qualname__Ú__doc__rrr r r r rs rN)Z __future__rrrÚrrr r r r Ús PKÒ¶N]Z½†44Psite-packages/pip/_vendor/html5lib/filters/__pycache__/whitespace.cpython-38.pycnu„[µü¤U ÀÒ.e¾ã@snddlmZmZmZddlZddlmZddlmZm Z d  e ¡Z e  de ¡Z Gd d „d ej ƒZ d d „ZdS) é)Úabsolute_importÚdivisionÚunicode_literalsNé)Úbaseé)ÚrcdataElementsÚspaceCharactersÚz[%s]+c@s,eZdZdZeddgeeƒƒZdd„ZdS)ÚFilterzACollapses whitespace except in pre, textarea, and script elementsZpreZtextareaccsœd}tj |¡D]†}|d}|dkr@|s6|d|jkr@|d7}nP|dkrV|rV|d8}n:|st|dkrt|drtd |d<n|s�|d kr�t|dƒ|d<|VqdS) NrÚtypeZStartTagÚnamerZEndTagZSpaceCharactersÚdataú Z Characters)rr Ú__iter__ÚspacePreserveElementsÚcollapse_spaces)ÚselfZpreserveÚtokenr ©rúK/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/filters/whitespace.pyrs ÿ ÿ     zFilter.__iter__N) Ú__name__Ú __module__Ú __qualname__Ú__doc__Ú frozensetÚlistrrrrrrrr sr cCs t d|¡S)Nr)Ú SPACES_REGEXÚsub)Útextrrrr%sr)Z __future__rrrÚrer rZ constantsrr ÚjoinÚcompilerr rrrrrÚs  PKÒ¶N]¼¦‘nP?P?Usite-packages/pip/_vendor/html5lib/filters/__pycache__/sanitizer.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.eˆfãD@s> ddlmZmZmZddlZddlmZmZddlm Z ddl m Z ddl mZmZd gZeed d fed d fed d fed dfed dfed dfed dfed dfed dfed dfed dfed dfed dfed dfed dfed dfed dfed dfed dfed dfed dfed d fed d!fed d"fed d#fed d$fed d%fed d&fed d'fed d(fed d)fed d*fed d+fed d,fed d-fed d.fed d/fed d0fed d1fed d2fed d3fed d4fed d5fed d6fed d7fed d8fed d9fed d:fed d;fed dfed d?fed d@fed dAfed dBfed dCfed dDfed dEfed dFfed dGfed dHfed dIfed dJfed dKfed dLfed dMfed dNfed dOfed dPfed dQfed dRfed dSfed dTfed dUfed dVfed dWfed dXfed dYfed dZfed d[fed d\fed d]fed d^fed d_fed d`fed dafed dbfed dcfed ddfed defed dffed dgfed dhfed difed djfed dkfed dlfed dmfedndofedndpfedndqfedndrfedndsfedndtfedndufedndvfedndwfedndxfedndyfedndzfednd{fednd|fednd}fednd~fedndfednd€fednd�fednd‚fedndƒfednd„fednd…fednd†fednd‡fedndˆfednd‰fedŠd fedŠd‹fedŠdŒfedŠd�fedŠdŽfedŠd�fedŠd�fedŠd‘fedŠd’fedŠd“fedŠd”fedŠd•fedŠd–fedŠd—fedŠd˜fedŠd™fedŠdšfedŠd›fedŠdœfedŠd�fedŠdžfedŠdŸfedŠd fedŠd¡fedŠd¢fedŠd£fedŠd¤fedŠd¥fedŠd¦fedŠdŠfedŠd§fedŠd¨fedŠd©fedŠdªfedŠd«ff¡ƒZed¬d­d®d¯d°d±d²d³d´dµd¶d·d¸d¹dºd»d¼d½d¾d¿dÀdÁdÂdÃdÄdÅdÆdÇdÈdÉdÊdËdÌdÍdÎdÏdÐdÑdÒdÓdÔdÕdÖd×dØdÙdÚdÛdÜdÝdÞdßdàdádâdãdädådædçdèdédêdëdìdídîdïdðdñdòdódôdõdöd÷dødùdúdûdüdýdþdÿ�d�d�d�d�d�d�d�d�d�d �d �d �d �d �d�d�d�d�d�d�d�d�d�d�d�d�d�d�d�d�d�d�d �d!�d"�d#�d$�d%�d&�d'�d(�d)�d*�d+�d,�d-�d.�d/�d0�d1�d2�d3�d4�d5�d6�d7e�d8�d9f�d:d±�d;�d;�d;�d<�d=�d>�d?�d@�dA�dB�dC�dD�dE�dFdâdæ�dG�dH�dI�dJ�dK�dK�dL�dM�dN�dO�dO�dO�dP�dQ�d�dR�dS�dT�dU�dV�d6�d6e�dW�dXfe�dW�dYfe�dW�dZf�d[�d\�d]�d^�d_�d`�da�db�dc�dd�de�df�dg�dhdÉ�didË�dj�dk�dl�dm�dn�do�dp�dq�d@�drdÞ�ds�dt�du�dv�dw�dx�dy�dz�d{�d|�d}�d~�d�d€�d��d‚�dƒdæ�d„�d…dî�d†�d‡�dˆ�d‰�dŠdô�d‹�dŒ�d��dŽ�d��d��d‘dý�d�d�d’�d“�d”�d•�d–�d—�d˜�d™�dš�d›�dœ�d��dž�dŸ�d �d¡�d¢�d£�d¤�d¥�d¦�d§�d¨�d©�dª�d«�d¬�d­�d®�d¯�d°�d±�d²�d³�d´�dµ�d¶�d·�d(�d¸�d¹�dº�d,�d»�d¼�d½�d¾�d¿�dÀ�dÁ�dÂ�dÃ�dÄ�dÅ�d6�dÆ�dÇ�dÈ�dÉ�dÊe�dW�dËfe�dW�dÌfe�dW�dXfe�dW�dÍfe�dW�dYfe�dWd©fe�dW�dZfe�d8�dÎfe�d8�d9fe�d8�dÏf�dÐ�dÑ�dÒ�dÓ�fCƒZedê�d!dÈd°dö�d d¶dÕdÜdü�d e�dW�dXfe�d8�dÎff ƒZe�dÔƒZe�dÕƒZe�dÖƒZe�d׃Ze�d؃Ze�dÙƒZe�dÚƒZe �dÛej¡ZG�dÜd „d e jƒZdS(Ýé)Úabsolute_importÚdivisionÚunicode_literalsN)ÚescapeÚunescape)Ú urllib_parseé)Úbaseé)Ú namespacesÚprefixesÚFilterÚhtmlÚaÚabbrZacronymZaddressZareaZarticleZasideZaudioÚbZbigZ blockquoteÚbrZbuttonZcanvasZcaptionÚcenterÚciteÚcodeÚcolZcolgroupZcommandZdatagridZdatalistZddÚdelZdetailsZdfnZdialogÚdirZdivZdlZdtZemz event-sourceZfieldsetZ figcaptionZfigureZfooterÚfontÚformÚheaderZh1Zh2Zh3Zh4Zh5Zh6ZhrÚiZimgÚinputZinsZkeygenZkbdÚlabelZlegendZliÚmÚmapZmenuZmeterZmulticolZnavZnextidZolÚoutputZoptgroupZoptionÚpZpreZprogressÚqÚsZsampZsectionZselectZsmallZsoundÚsourceZspacerÚspanZstrikeZstrongÚsubZsupÚtableZtbodyZtdZtextareaÚtimeZtfootZthZtheadZtrZttÚuZulÚvarZvideoZmathmlZmactionZmathZmerrorZmfracÚmiZ mmultiscriptsZmnÚmoZmoverZmpaddedZmphantomZ mprescriptsZmrootZmrowZmspaceZmsqrtZmstyleZmsubZmsubsupZmsupZmtableZmtdZmtextZmtrZmunderZ munderoverÚnoneZsvgÚanimateÚ animateColorÚ animateMotionÚanimateTransformZclipPathZcircleZdefsZdescZellipsez font-facezfont-face-namez font-face-srcÚgZglyphZhkernÚlinearGradientÚlineÚmarkerZmetadataz missing-glyphZmpathÚpathZpolygonZpolylineÚradialGradientZrectÚsetÚstopZswitchÚtextÚtitleZtspanÚuse)Nr)NZaccept)Nzaccept-charset)NZ accesskey)NÚaction)NZalign)NZalt)NZ autocomplete)NZ autofocus)NZaxis)NÚ background)NZbalance)NZbgcolor)NZ bgproperties)NÚborder)NZ bordercolor)NZbordercolordark)NZbordercolorlight)NZ bottompadding)NZ cellpadding)NZ cellspacing)NZch)NZ challenge)NÚchar)NZcharoff)NZchoff)NÚcharset)NÚchecked)Nr)NÚclass)NÚclear)NÚcolor)NZcols)NZcolspan)NZcompact)NZcontenteditable)NZcontrols)NZcoords)NÚdata)NZdatafld)NZ datapagesize)NZdatasrc)NZdatetime)NÚdefault)NZdelay)Nr)NZdisabled)NZ draggable)NZdynsrc)NZenctype)NÚend)NZface)NÚfor)Nr)NÚframe)NZ galleryimg)NZgutter)NZheaders)NÚheight)NZ hidefocus)NZhidden)NZhigh)NÚhref)NZhreflang)NZhspace)NZicon)NÚid)NZ inputmode)NZismap)NZkeytype)Nr)NZ leftspacing)NÚlang)NÚlist)NZlongdesc)NZloop)NZ loopcount)NZloopend)NZ loopstart)NZlow)NZlowsrc)NÚmax)NZ maxlength)NZmedia)NÚmethod)NÚmin)NZmultiple)NÚname)NZnohref)NZnoshade)NÚnowrap)NÚopen)NZoptimum©NÚpattern)NZping)Nz point-size)NZposter)NZpqg)NZpreload)NÚprompt)NZ radiogroup)NÚreadonly)NZrel)Nz repeat-max)Nz repeat-min)NÚreplace)NZrequired)NZrev)NZ rightspacing)NZrows)NZrowspan)NZrules)NZscope)NZselected)NÚshape)NÚsize)Nr&)NÚsrc)NÚstart)NÚstep©NÚstyle)NZsummary)NÚsuppress)NZtabindex)NÚtarget)NÚtemplate)Nr<)NZ toppadding)NÚtype)NZ unselectable)NZusemap)NÚurn)NZvalign)NÚvalue)NZvariable)NÚvolume)NZvspace)NZvrml)NÚwidth)NZwrapZxmlrO)NZ actiontype)NZ columnalign)NZ columnlines)NZ columnspacing)NZ columnspan)NÚdepth)NÚdisplay)NZ displaystyle)NZ equalcolumns)NZ equalrows)NZfence)NZ fontstyle)NZ fontweight)NZ linethickness)NZlspace)NZmathbackground)NZ mathcolor)NZ mathvariant)NÚmaxsize)NZminsize)NÚother)NZrowalign)NZrowlines)NZ rowspacing)NZrspace)NZ scriptlevel)NZ selection)NZ separator)NZstretchyÚxlinkrMZshowrf)Nz accent-height)NÚ accumulate)NZadditive)NZ alphabetic)Nz arabic-form)NZascent)NZ attributeName)NZ attributeType)NZ baseProfile)NZbbox)NZbegin)NZby)NZcalcMode)Nz cap-height©Nz clip-path)Nzcolor-rendering)NZcontent)NZcx)NZcy)NÚd)NZdx)NZdy)NZdescent)NZdur©NÚfill)Nú fill-opacity)Nú fill-rule)Nú font-family)Nú font-size)Nz font-stretch)Nú font-style)Nú font-variant)Nú font-weight)NÚfrom)NZfx)NZfy)NZg1)NZg2)Nz glyph-name)NZ gradientUnits)NZhanging)Nz horiz-adv-x)Nzhoriz-origin-x)NZ ideographic)NÚk)NZ keyPoints)NZ keySplines)NZkeyTimes©Nz marker-end©Nz marker-mid©Nz marker-start)NZ markerHeight)NZ markerUnits)NZ markerWidth)NZ mathematical)NÚoffset)NZopacity)NZorient)NÚorigin)Nzoverline-position)Nzoverline-thickness)Nzpanose-1)Nr7)NZ pathLength)NZpoints)NZpreserveAspectRatio)NÚr)NZrefX)NZrefY)NZ repeatCount)NZ repeatDur)NZrequiredExtensions)NZrequiredFeatures)NZrestart)NÚrotate)NÚrx)NZry)NZslope)NZstemh)NZstemv)Nz stop-color)Nz stop-opacity)Nzstrikethrough-position)Nzstrikethrough-thickness©NÚstroke)Nzstroke-dasharray)Nzstroke-dashoffset)Nústroke-linecap)Nústroke-linejoin)Nzstroke-miterlimit)Nústroke-opacity)Nú stroke-width)NZsystemLanguage)Nz text-anchor)NÚto)NZ transform)NZu1)NZu2)Nzunderline-position)Nzunderline-thickness)NZunicode)Nz unicode-range)Nz units-per-em)NÚvalues)NÚversion)NZviewBox)NZ visibility)NZwidths)NÚx)Nzx-height)NZx1)NZx2ZactuateZarcroleZroler Zspace)NÚy)NZy1)NZy2)NZ zoomAndPan) rq)Nz color-profile©NÚcursorrs©NÚfilter)Nr6r€rr~)NÚmaskr†))NZaltGlyph)Nr/)Nr0)Nr1)Nr2r‘)NZfeImager“)Nr4rW)Nr8)NZtextpath)NZtref)Nr9)Nr=).Zazimuthzbackground-colorzborder-bottom-colorzborder-collapsez border-colorzborder-left-colorzborder-right-colorzborder-top-colorrErFr’Ú directionrlZ elevationÚfloatrrwrxryrzr{rLzletter-spacingz line-heightZoverflowÚpausez pause-afterz pause-beforeZpitchz pitch-rangeZrichnessZspeakz speak-headerz speak-numeralzspeak-punctuationz speech-rateZstressz text-alignztext-decorationz text-indentz unicode-bidizvertical-alignz voice-familyriz white-spacerj)'ÚautoZaquaZblackÚblockZblueZboldZbothZbottomZbrownrZcollapseZdashedZdottedZfuchsiaZgrayZgreenz !importantZitalicÚleftZlimeZmaroonZmediumr.ZnavyZnormalrUZoliveZpointerZpurpleZredÚrightZsolidZsilverZtealÚtopZ transparentZ underlineZwhiteZyellow)rtrurvr‡r‹rˆr‰rŠ)Zed2kZftpZhttpZhttpsZircZmailtoZnewsZgopherZnntpZtelnetZwebcalZxmppZcalltoZfeedrgZaimZrsyncÚtagZsshZsftpZrtspZafsrG)z image/pngz image/jpegz image/gifz image/webpz image/bmpz text/plainaL ^ # Match a content type / (?P[-a-zA-Z0-9.]+/[-a-zA-Z0-9.]+) # Match any character set and encoding (?:(?:;charset=(?:[-a-zA-Z0-9]+)(?:;(?:base64))?) |(?:;(?:base64))?(?:;charset=(?:[-a-zA-Z0-9]+))?) # Assume the rest is data ,.* $ c s^eZdZdZeeeeee e e e e f ‡fdd„ Zdd„Zdd„Zdd „Zd d „Zd d „Z‡ZS)r zISanitizes token stream of XHTML+MathML+SVG and of inline style attributesc sPtt|ƒ |¡||_||_||_||_||_||_||_ | |_ | |_ | |_ dS)aSCreates a Filter :arg allowed_elements: set of elements to allow--everything else will be escaped :arg allowed_attributes: set of attributes to allow in elements--everything else will be stripped :arg allowed_css_properties: set of CSS properties to allow--everything else will be stripped :arg allowed_css_keywords: set of CSS keywords to allow--everything else will be stripped :arg allowed_svg_properties: set of SVG properties to allow--everything else will be removed :arg allowed_protocols: set of allowed protocols for URIs :arg allowed_content_types: set of allowed content types for ``data`` URIs. :arg attr_val_is_uri: set of attributes that have URI values--values that have a scheme not listed in ``allowed_protocols`` are removed :arg svg_attr_val_allows_ref: set of SVG attributes that can have references :arg svg_allow_local_href: set of SVG elements that can have local hrefs--these are removed N) Úsuperr Ú__init__Úallowed_elementsÚallowed_attributesÚallowed_css_propertiesÚallowed_css_keywordsÚallowed_svg_propertiesÚallowed_protocolsÚallowed_content_typesÚattr_val_is_uriÚsvg_attr_val_allows_refÚsvg_allow_local_href) Úselfr%r¡r¢r£r¤r¥r¦r§r¨r©rª©Ú __class__©úJ/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/filters/sanitizer.pyr Ås+zFilter.__init__ccs*tj |¡D]}| |¡}|r |Vq dS)N)r r Ú__iter__Úsanitize_token)r«Útokenr®r®r¯r°üs zFilter.__iter__cCsp|d}|dkr^|d}|d}||f|jksH|dkrRtd|f|jkrR| |¡S| |¡Sn|dkrhn|SdS)Nrf)ZStartTagÚEndTagZEmptyTagrTÚ namespacerÚComment)r¡r Ú allowed_tokenÚdisallowed_token)r«r²Ú token_typerTr´r®r®r¯r± sÿþ  zFilter.sanitize_tokenc Csžd|k�rš|d}t| ¡ƒ}||jD]}|d|=| |¡q(||j@D]¬}t ddt||ƒ¡ ¡}|  dd¡}zt   |¡}Wnt k r¢d}||=YnX|rL|j rL|j |j krÀ||=|j dkrLt |j¡}|sâ||=qL| d¡|jkrL||=qL|jD]*}||k�rt ddt||ƒ¡||<�q|d|jk�rvtd d f|k�rvt d |td d f¡�rv|td d f=d |k�r’| |d ¡|d <||d<|S) NrGu [`- - \s]+Úu�Z content_typezurl\s*\(\s*[^#\s][^)]+?\)ú rTrorMz ^\s*[^#\s].*ra)r9Úkeysr¢Úremover¨Úrer'rÚlowerr[ÚurlparseÚ ValueErrorZschemer¦Údata_content_typeÚmatchr7Úgroupr§r©rªr ÚsearchÚ sanitize_css) r«r²ÚattrsZ attr_namesZ to_removeÚattrZ val_unescapedZurirr®r®r¯r¶sV     ÿ         þ ÿÿÿ zFilter.allowed_tokencCsÖ|d}|dkr"d|d|d<n€|dr’g}|d ¡D]:\\}}}| d|dkrX|ndt||ft|ƒf¡q:d|dd  |¡f|d<nd |d|d<| d ¡rÄ|ddd …d |d<d|d<|d=|S)Nrfr³zrTrGz %s="%s"z%s:%sz<%s%s>r¹z<%s>Z selfClosingéÿÿÿÿz/>Z Characters)ÚitemsÚappendr rÚjoinÚget)r«r²r¸rÆÚnsrTÚvr®r®r¯r·Qs0 zFilter.disallowed_tokencCsüt d¡ d|¡}t d|¡s"dSt d|¡s2dSg}t d|¡D]®\}}|sPqB| ¡|jkrv| |d|d¡qB| d ¡d  ¡d krÌ| ¡D]}||j kr”t d |¡s”qðq”| |d|d¡qB| ¡|j krB| |d|d¡qBd  |¡S) Nzurl\s*\(\s*[^\s)]+?\s*\)\s*rºz@^([:,;#%.\sa-zA-Z0-9!]|\w-\w|'[\s\w]+'|"[\s\w]+"|\([\d,\s]+\))*$r¹z ^\s*([-\w]+\s*:[^:;]*(;\s*|$))*$z([-\w]+)\s*:\s*([^:;]*)z: ú;ú-r)r?r@ZmarginZpaddingz_^(#[0-9a-fA-F]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|\d{0,2}\.?\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\))?)$) r½Úcompiler'rÂÚfindallr¾r£rÊÚsplitr¤r¥rË)r«rbZcleanZproprhÚkeywordr®r®r¯rÅes*     ÿzFilter.sanitize_css)Ú__name__Ú __module__Ú __qualname__Ú__doc__r¡r¢r£r¤r¥r¦r§r¨r©rªr r°r±r¶r·rÅÚ __classcell__r®r®r¬r¯r Ãs"õ72) Z __future__rrrr½Zxml.sax.saxutilsrrZpip._vendor.six.movesrr¿r¹r Z constantsr r Ú__all__Ú frozensetr¡r¢r¨r©rªr£r¤r¥r¦r§rÑÚVERBOSErÁr r®r®r®r¯Ús                                                                                                                                                                   €ß% €€ºKó   1 *   õPKÒ¶N][@!¤¤Nsite-packages/pip/_vendor/html5lib/filters/__pycache__/__init__.cpython-38.pycnu„[µü¤U ÀÒ.eã@sdS)N©rrrúI/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/filters/__init__.pyÚóPKÒ¶N]my00Ysite-packages/pip/_vendor/html5lib/filters/__pycache__/inject_meta_charset.cpython-38.pycnu„[µü¤U ÀÒ.e� ã@s6ddlmZmZmZddlmZGdd„dejƒZdS)é)Úabsolute_importÚdivisionÚunicode_literalsé)Úbasec@s eZdZdZdd„Zdd„ZdS)ÚFilterz=Injects ```` tag into head of documentcCstj ||¡||_dS)ztCreates a Filter :arg source: the source token stream :arg encoding: the encoding to set N)rrÚ__init__Úencoding)ÚselfÚsourcer ©r úT/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.pyrszFilter.__init__c csÒd}|jdk}g}tj |¡D�]¬}|d}|dkrL|d ¡dkrHd}�nd|dk�rJ|d ¡dkrød }|d  ¡D]X\\}}} |dk rŽqvqv| ¡d kr¶|j|d ||f<d }qöqv|d krv|  ¡dkrvd }qv|röd|d kröd|j|d d<d }nP|d ¡dk�r°|�s°dd|d dœVddd|jidœVdddœVd }qnf|dk�r°|d ¡dk�r°|�r°| d¡V|�s’ddd|jidœV|�r¨| d¡V�q’d }d}|dk�rÆ| |¡q|VqdS)NZpre_headÚtypeZStartTagÚnameÚheadZin_headZEmptyTagÚmetaFÚdataÚcharsetTz http-equivz content-type)NZcontentztext/html; charset=%s)rrr)NrZEndTag)rrrZ post_head)r rrÚ__iter__ÚlowerÚitemsÚpopÚappend) r ÚstateZ meta_foundZpendingÚtokenrZhas_http_equiv_content_typeÚ namespacerÚvaluer r r rs^   ÿÿ   ÿ  zFilter.__iter__N)Ú__name__Ú __module__Ú __qualname__Ú__doc__rrr r r r rs rN)Z __future__rrrÚrrr r r r Ús PKÒ¶N]Y±Èâ\site-packages/pip/_vendor/html5lib/filters/__pycache__/alphabeticalattributes.cpython-38.pycnu„[µü¤U ÀÒ.e—ã@sJddlmZmZmZddlmZddlmZdd„ZGdd„dej ƒZ d S) é)Úabsolute_importÚdivisionÚunicode_literalsé)Úbase)Ú OrderedDictcCs|ddpd|ddfS)zùReturn an appropriate key for an attribute for sorting Attributes have a namespace that can be either ``None`` or a string. We can't compare the two because they're different types, so we convert ``None`` to an empty string first. rÚr©)Úattrr r úW/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.pyÚ _attr_keysr c@seZdZdZdd„ZdS)ÚFilterz$Alphabetizes attributes for elementsccs\tj |¡D]J}|ddkrPtƒ}t|d ¡td�D]\}}|||<q6||d<|Vq dS)NÚtype)ZStartTagZEmptyTagÚdata)Úkey)rr Ú__iter__rÚsortedÚitemsr )ÚselfÚtokenZattrsÚnameÚvaluer r r rs  ÿ zFilter.__iter__N)Ú__name__Ú __module__Ú __qualname__Ú__doc__rr r r r r sr N) Z __future__rrrrrÚ collectionsrr r r r r r Ús   PKÒ¶N]ƒTS‚EEPsite-packages/pip/_vendor/html5lib/filters/__pycache__/lint.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.e;ã@shddlmZmZmZddlmZddlmZddlm Z m Z ddlm Z d  e ¡Z Gd d „d ej ƒZ d S) é)Úabsolute_importÚdivisionÚunicode_literals)Ú text_typeé)Úbaseé)Ú namespacesÚ voidElements)ÚspaceCharactersÚcs*eZdZdZd‡fdd„ Zdd„Z‡ZS)ÚFilterzgLints the token stream for errors If it finds any errors, it'll raise an ``AssertionError``. Tcstt|ƒ |¡||_dS)z•Creates a Filter :arg source: the source token stream :arg require_matching_tags: whether or not to require matching tags N)Úsuperr Ú__init__Úrequire_matching_tags)ÚselfÚsourcer©Ú __class__©úE/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/filters/lint.pyrszFilter.__init__c cs.g}tj |¡D�]}|d}|dkrˆ|d}|d}|rF|tdkrP|tkrPn|dkrl|jrl| ||f¡|d ¡D] \\}}}qxnš|dkrÊ|d}|d}|r°|tdkrº|tkrºn|jrÈ| ¡}nX|d krÜ|d}nF|d krö|d}|d krôn,|d k�r |d}n|d k�rn |dk�r"n|VqdS)NÚtype)ÚStartTagZEmptyTagÚ namespaceÚnameZhtmlrÚdataZEndTagÚComment)Z CharactersÚSpaceCharactersrZDoctypeZEntityZSerializerError) rr Ú__iter__r r rÚappendÚitemsÚpop) rZ open_elementsÚtokenrrrÚvalueÚstartrrrrrsF   zFilter.__iter__)T)Ú__name__Ú __module__Ú __qualname__Ú__doc__rrÚ __classcell__rrrrr s r N)Z __future__rrrZpip._vendor.sixrr rZ constantsr r r Újoinr rrrrÚs     PKÒ¶N]Z½†44Vsite-packages/pip/_vendor/html5lib/filters/__pycache__/whitespace.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.e¾ã@snddlmZmZmZddlZddlmZddlmZm Z d  e ¡Z e  de ¡Z Gd d „d ej ƒZ d d „ZdS) é)Úabsolute_importÚdivisionÚunicode_literalsNé)Úbaseé)ÚrcdataElementsÚspaceCharactersÚz[%s]+c@s,eZdZdZeddgeeƒƒZdd„ZdS)ÚFilterzACollapses whitespace except in pre, textarea, and script elementsZpreZtextareaccsœd}tj |¡D]†}|d}|dkr@|s6|d|jkr@|d7}nP|dkrV|rV|d8}n:|st|dkrt|drtd |d<n|s�|d kr�t|dƒ|d<|VqdS) NrÚtypeZStartTagÚnamerZEndTagZSpaceCharactersÚdataú Z Characters)rr Ú__iter__ÚspacePreserveElementsÚcollapse_spaces)ÚselfZpreserveÚtokenr ©rúK/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/filters/whitespace.pyrs ÿ ÿ     zFilter.__iter__N) Ú__name__Ú __module__Ú __qualname__Ú__doc__Ú frozensetÚlistrrrrrrrr sr cCs t d|¡S)Nr)Ú SPACES_REGEXÚsub)Útextrrrr%sr)Z __future__rrrÚrer rZ constantsrr ÚjoinÚcompilerr rrrrrÚs  PKÒ¶N]óÀ?� � Asite-packages/pip/_vendor/html5lib/filters/inject_meta_charset.pynu„[µü¤from __future__ import absolute_import, division, unicode_literals from . import base class Filter(base.Filter): """Injects ```` tag into head of document""" def __init__(self, source, encoding): """Creates a Filter :arg source: the source token stream :arg encoding: the encoding to set """ base.Filter.__init__(self, source) self.encoding = encoding def __iter__(self): state = "pre_head" meta_found = (self.encoding is None) pending = [] for token in base.Filter.__iter__(self): type = token["type"] if type == "StartTag": if token["name"].lower() == "head": state = "in_head" elif type == "EmptyTag": if token["name"].lower() == "meta": # replace charset with actual encoding has_http_equiv_content_type = False for (namespace, name), value in token["data"].items(): if namespace is not None: continue elif name.lower() == 'charset': token["data"][(namespace, name)] = self.encoding meta_found = True break elif name == 'http-equiv' and value.lower() == 'content-type': has_http_equiv_content_type = True else: if has_http_equiv_content_type and (None, "content") in token["data"]: token["data"][(None, "content")] = 'text/html; charset=%s' % self.encoding meta_found = True elif token["name"].lower() == "head" and not meta_found: # insert meta into empty head yield {"type": "StartTag", "name": "head", "data": token["data"]} yield {"type": "EmptyTag", "name": "meta", "data": {(None, "charset"): self.encoding}} yield {"type": "EndTag", "name": "head"} meta_found = True continue elif type == "EndTag": if token["name"].lower() == "head" and pending: # insert meta into head (if necessary) and flush pending queue yield pending.pop(0) if not meta_found: yield {"type": "EmptyTag", "name": "meta", "data": {(None, "charset"): self.encoding}} while pending: yield pending.pop(0) meta_found = True state = "post_head" if state == "in_head": pending.append(token) else: yield token PKÒ¶N]"€ûÄ2site-packages/pip/_vendor/html5lib/filters/base.pynu„[µü¤from __future__ import absolute_import, division, unicode_literals class Filter(object): def __init__(self, source): self.source = source def __iter__(self): return iter(self.source) def __getattr__(self, name): return getattr(self.source, name) PKÒ¶N]uš*\)\):site-packages/pip/_vendor/html5lib/filters/optionaltags.pynu„[µü¤from __future__ import absolute_import, division, unicode_literals from . import base class Filter(base.Filter): """Removes optional tags from the token stream""" def slider(self): previous1 = previous2 = None for token in self.source: if previous1 is not None: yield previous2, previous1, token previous2 = previous1 previous1 = token if previous1 is not None: yield previous2, previous1, None def __iter__(self): for previous, token, next in self.slider(): type = token["type"] if type == "StartTag": if (token["data"] or not self.is_optional_start(token["name"], previous, next)): yield token elif type == "EndTag": if not self.is_optional_end(token["name"], next): yield token else: yield token def is_optional_start(self, tagname, previous, next): type = next and next["type"] or None if tagname in 'html': # An html element's start tag may be omitted if the first thing # inside the html element is not a space character or a comment. return type not in ("Comment", "SpaceCharacters") elif tagname == 'head': # A head element's start tag may be omitted if the first thing # inside the head element is an element. # XXX: we also omit the start tag if the head element is empty if type in ("StartTag", "EmptyTag"): return True elif type == "EndTag": return next["name"] == "head" elif tagname == 'body': # A body element's start tag may be omitted if the first thing # inside the body element is not a space character or a comment, # except if the first thing inside the body element is a script # or style element and the node immediately preceding the body # element is a head element whose end tag has been omitted. if type in ("Comment", "SpaceCharacters"): return False elif type == "StartTag": # XXX: we do not look at the preceding event, so we never omit # the body element's start tag if it's followed by a script or # a style element. return next["name"] not in ('script', 'style') else: return True elif tagname == 'colgroup': # A colgroup element's start tag may be omitted if the first thing # inside the colgroup element is a col element, and if the element # is not immediately preceded by another colgroup element whose # end tag has been omitted. if type in ("StartTag", "EmptyTag"): # XXX: we do not look at the preceding event, so instead we never # omit the colgroup element's end tag when it is immediately # followed by another colgroup element. See is_optional_end. return next["name"] == "col" else: return False elif tagname == 'tbody': # A tbody element's start tag may be omitted if the first thing # inside the tbody element is a tr element, and if the element is # not immediately preceded by a tbody, thead, or tfoot element # whose end tag has been omitted. if type == "StartTag": # omit the thead and tfoot elements' end tag when they are # immediately followed by a tbody element. See is_optional_end. if previous and previous['type'] == 'EndTag' and \ previous['name'] in ('tbody', 'thead', 'tfoot'): return False return next["name"] == 'tr' else: return False return False def is_optional_end(self, tagname, next): type = next and next["type"] or None if tagname in ('html', 'head', 'body'): # An html element's end tag may be omitted if the html element # is not immediately followed by a space character or a comment. return type not in ("Comment", "SpaceCharacters") elif tagname in ('li', 'optgroup', 'tr'): # A li element's end tag may be omitted if the li element is # immediately followed by another li element or if there is # no more content in the parent element. # An optgroup element's end tag may be omitted if the optgroup # element is immediately followed by another optgroup element, # or if there is no more content in the parent element. # A tr element's end tag may be omitted if the tr element is # immediately followed by another tr element, or if there is # no more content in the parent element. if type == "StartTag": return next["name"] == tagname else: return type == "EndTag" or type is None elif tagname in ('dt', 'dd'): # A dt element's end tag may be omitted if the dt element is # immediately followed by another dt element or a dd element. # A dd element's end tag may be omitted if the dd element is # immediately followed by another dd element or a dt element, # or if there is no more content in the parent element. if type == "StartTag": return next["name"] in ('dt', 'dd') elif tagname == 'dd': return type == "EndTag" or type is None else: return False elif tagname == 'p': # A p element's end tag may be omitted if the p element is # immediately followed by an address, article, aside, # blockquote, datagrid, dialog, dir, div, dl, fieldset, # footer, form, h1, h2, h3, h4, h5, h6, header, hr, menu, # nav, ol, p, pre, section, table, or ul, element, or if # there is no more content in the parent element. if type in ("StartTag", "EmptyTag"): return next["name"] in ('address', 'article', 'aside', 'blockquote', 'datagrid', 'dialog', 'dir', 'div', 'dl', 'fieldset', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hr', 'menu', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'ul') else: return type == "EndTag" or type is None elif tagname == 'option': # An option element's end tag may be omitted if the option # element is immediately followed by another option element, # or if it is immediately followed by an optgroup # element, or if there is no more content in the parent # element. if type == "StartTag": return next["name"] in ('option', 'optgroup') else: return type == "EndTag" or type is None elif tagname in ('rt', 'rp'): # An rt element's end tag may be omitted if the rt element is # immediately followed by an rt or rp element, or if there is # no more content in the parent element. # An rp element's end tag may be omitted if the rp element is # immediately followed by an rt or rp element, or if there is # no more content in the parent element. if type == "StartTag": return next["name"] in ('rt', 'rp') else: return type == "EndTag" or type is None elif tagname == 'colgroup': # A colgroup element's end tag may be omitted if the colgroup # element is not immediately followed by a space character or # a comment. if type in ("Comment", "SpaceCharacters"): return False elif type == "StartTag": # XXX: we also look for an immediately following colgroup # element. See is_optional_start. return next["name"] != 'colgroup' else: return True elif tagname in ('thead', 'tbody'): # A thead element's end tag may be omitted if the thead element # is immediately followed by a tbody or tfoot element. # A tbody element's end tag may be omitted if the tbody element # is immediately followed by a tbody or tfoot element, or if # there is no more content in the parent element. # A tfoot element's end tag may be omitted if the tfoot element # is immediately followed by a tbody element, or if there is no # more content in the parent element. # XXX: we never omit the end tag when the following element is # a tbody. See is_optional_start. if type == "StartTag": return next["name"] in ['tbody', 'tfoot'] elif tagname == 'tbody': return type == "EndTag" or type is None else: return False elif tagname == 'tfoot': # A tfoot element's end tag may be omitted if the tfoot element # is immediately followed by a tbody element, or if there is no # more content in the parent element. # XXX: we never omit the end tag when the following element is # a tbody. See is_optional_start. if type == "StartTag": return next["name"] == 'tbody' else: return type == "EndTag" or type is None elif tagname in ('td', 'th'): # A td element's end tag may be omitted if the td element is # immediately followed by a td or th element, or if there is # no more content in the parent element. # A th element's end tag may be omitted if the th element is # immediately followed by a td or th element, or if there is # no more content in the parent element. if type == "StartTag": return next["name"] in ('td', 'th') else: return type == "EndTag" or type is None return False PKÒ¶N]`rÿ¾¾8site-packages/pip/_vendor/html5lib/filters/whitespace.pynu„[µü¤from __future__ import absolute_import, division, unicode_literals import re from . import base from ..constants import rcdataElements, spaceCharacters spaceCharacters = "".join(spaceCharacters) SPACES_REGEX = re.compile("[%s]+" % spaceCharacters) class Filter(base.Filter): """Collapses whitespace except in pre, textarea, and script elements""" spacePreserveElements = frozenset(["pre", "textarea"] + list(rcdataElements)) def __iter__(self): preserve = 0 for token in base.Filter.__iter__(self): type = token["type"] if type == "StartTag" \ and (preserve or token["name"] in self.spacePreserveElements): preserve += 1 elif type == "EndTag" and preserve: preserve -= 1 elif not preserve and type == "SpaceCharacters" and token["data"]: # Test on token["data"] above to not introduce spaces where there were not token["data"] = " " elif not preserve and type == "Characters": token["data"] = collapse_spaces(token["data"]) yield token def collapse_spaces(text): return SPACES_REGEX.sub(' ', text) PKÒ¶N]’Ñd ;;2site-packages/pip/_vendor/html5lib/filters/lint.pynu„[µü¤from __future__ import absolute_import, division, unicode_literals from pip._vendor.six import text_type from . import base from ..constants import namespaces, voidElements from ..constants import spaceCharacters spaceCharacters = "".join(spaceCharacters) class Filter(base.Filter): """Lints the token stream for errors If it finds any errors, it'll raise an ``AssertionError``. """ def __init__(self, source, require_matching_tags=True): """Creates a Filter :arg source: the source token stream :arg require_matching_tags: whether or not to require matching tags """ super(Filter, self).__init__(source) self.require_matching_tags = require_matching_tags def __iter__(self): open_elements = [] for token in base.Filter.__iter__(self): type = token["type"] if type in ("StartTag", "EmptyTag"): namespace = token["namespace"] name = token["name"] assert namespace is None or isinstance(namespace, text_type) assert namespace != "" assert isinstance(name, text_type) assert name != "" assert isinstance(token["data"], dict) if (not namespace or namespace == namespaces["html"]) and name in voidElements: assert type == "EmptyTag" else: assert type == "StartTag" if type == "StartTag" and self.require_matching_tags: open_elements.append((namespace, name)) for (namespace, name), value in token["data"].items(): assert namespace is None or isinstance(namespace, text_type) assert namespace != "" assert isinstance(name, text_type) assert name != "" assert isinstance(value, text_type) elif type == "EndTag": namespace = token["namespace"] name = token["name"] assert namespace is None or isinstance(namespace, text_type) assert namespace != "" assert isinstance(name, text_type) assert name != "" if (not namespace or namespace == namespaces["html"]) and name in voidElements: assert False, "Void element reported as EndTag token: %(tag)s" % {"tag": name} elif self.require_matching_tags: start = open_elements.pop() assert start == (namespace, name) elif type == "Comment": data = token["data"] assert isinstance(data, text_type) elif type in ("Characters", "SpaceCharacters"): data = token["data"] assert isinstance(data, text_type) assert data != "" if type == "SpaceCharacters": assert data.strip(spaceCharacters) == "" elif type == "Doctype": name = token["name"] assert name is None or isinstance(name, text_type) assert token["publicId"] is None or isinstance(name, text_type) assert token["systemId"] is None or isinstance(name, text_type) elif type == "Entity": assert isinstance(token["name"], text_type) elif type == "SerializerError": assert isinstance(token["data"], text_type) else: assert False, "Unknown token type: %(type)s" % {"type": type} yield token PKÒ¶N]€°——Dsite-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.pynu„[µü¤from __future__ import absolute_import, division, unicode_literals from . import base from collections import OrderedDict def _attr_key(attr): """Return an appropriate key for an attribute for sorting Attributes have a namespace that can be either ``None`` or a string. We can't compare the two because they're different types, so we convert ``None`` to an empty string first. """ return (attr[0][0] or ''), attr[0][1] class Filter(base.Filter): """Alphabetizes attributes for elements""" def __iter__(self): for token in base.Filter.__iter__(self): if token["type"] in ("StartTag", "EmptyTag"): attrs = OrderedDict() for name, value in sorted(token["data"].items(), key=_attr_key): attrs[name] = value token["data"] = attrs yield token PKÒ¶N]P§±Ý"Ý"6site-packages/pip/_vendor/html5lib/treebuilders/dom.pynu„[µü¤from __future__ import absolute_import, division, unicode_literals try: from collections.abc import MutableMapping except ImportError: # Python 2.7 from collections import MutableMapping from xml.dom import minidom, Node import weakref from . import base from .. import constants from ..constants import namespaces from .._utils import moduleFactoryFactory def getDomBuilder(DomImplementation): Dom = DomImplementation class AttrList(MutableMapping): def __init__(self, element): self.element = element def __iter__(self): return iter(self.element.attributes.keys()) def __setitem__(self, name, value): if isinstance(name, tuple): raise NotImplementedError else: attr = self.element.ownerDocument.createAttribute(name) attr.value = value self.element.attributes[name] = attr def __len__(self): return len(self.element.attributes) def items(self): return list(self.element.attributes.items()) def values(self): return list(self.element.attributes.values()) def __getitem__(self, name): if isinstance(name, tuple): raise NotImplementedError else: return self.element.attributes[name].value def __delitem__(self, name): if isinstance(name, tuple): raise NotImplementedError else: del self.element.attributes[name] class NodeBuilder(base.Node): def __init__(self, element): base.Node.__init__(self, element.nodeName) self.element = element namespace = property(lambda self: hasattr(self.element, "namespaceURI") and self.element.namespaceURI or None) def appendChild(self, node): node.parent = self self.element.appendChild(node.element) def insertText(self, data, insertBefore=None): text = self.element.ownerDocument.createTextNode(data) if insertBefore: self.element.insertBefore(text, insertBefore.element) else: self.element.appendChild(text) def insertBefore(self, node, refNode): self.element.insertBefore(node.element, refNode.element) node.parent = self def removeChild(self, node): if node.element.parentNode == self.element: self.element.removeChild(node.element) node.parent = None def reparentChildren(self, newParent): while self.element.hasChildNodes(): child = self.element.firstChild self.element.removeChild(child) newParent.element.appendChild(child) self.childNodes = [] def getAttributes(self): return AttrList(self.element) def setAttributes(self, attributes): if attributes: for name, value in list(attributes.items()): if isinstance(name, tuple): if name[0] is not None: qualifiedName = (name[0] + ":" + name[1]) else: qualifiedName = name[1] self.element.setAttributeNS(name[2], qualifiedName, value) else: self.element.setAttribute( name, value) attributes = property(getAttributes, setAttributes) def cloneNode(self): return NodeBuilder(self.element.cloneNode(False)) def hasContent(self): return self.element.hasChildNodes() def getNameTuple(self): if self.namespace is None: return namespaces["html"], self.name else: return self.namespace, self.name nameTuple = property(getNameTuple) class TreeBuilder(base.TreeBuilder): # pylint:disable=unused-variable def documentClass(self): self.dom = Dom.getDOMImplementation().createDocument(None, None, None) return weakref.proxy(self) def insertDoctype(self, token): name = token["name"] publicId = token["publicId"] systemId = token["systemId"] domimpl = Dom.getDOMImplementation() doctype = domimpl.createDocumentType(name, publicId, systemId) self.document.appendChild(NodeBuilder(doctype)) if Dom == minidom: doctype.ownerDocument = self.dom def elementClass(self, name, namespace=None): if namespace is None and self.defaultNamespace is None: node = self.dom.createElement(name) else: node = self.dom.createElementNS(namespace, name) return NodeBuilder(node) def commentClass(self, data): return NodeBuilder(self.dom.createComment(data)) def fragmentClass(self): return NodeBuilder(self.dom.createDocumentFragment()) def appendChild(self, node): self.dom.appendChild(node.element) def testSerializer(self, element): return testSerializer(element) def getDocument(self): return self.dom def getFragment(self): return base.TreeBuilder.getFragment(self).element def insertText(self, data, parent=None): data = data if parent != self: base.TreeBuilder.insertText(self, data, parent) else: # HACK: allow text nodes as children of the document node if hasattr(self.dom, '_child_node_types'): # pylint:disable=protected-access if Node.TEXT_NODE not in self.dom._child_node_types: self.dom._child_node_types = list(self.dom._child_node_types) self.dom._child_node_types.append(Node.TEXT_NODE) self.dom.appendChild(self.dom.createTextNode(data)) implementation = DomImplementation name = None def testSerializer(element): element.normalize() rv = [] def serializeElement(element, indent=0): if element.nodeType == Node.DOCUMENT_TYPE_NODE: if element.name: if element.publicId or element.systemId: publicId = element.publicId or "" systemId = element.systemId or "" rv.append("""|%s""" % (' ' * indent, element.name, publicId, systemId)) else: rv.append("|%s" % (' ' * indent, element.name)) else: rv.append("|%s" % (' ' * indent,)) elif element.nodeType == Node.DOCUMENT_NODE: rv.append("#document") elif element.nodeType == Node.DOCUMENT_FRAGMENT_NODE: rv.append("#document-fragment") elif element.nodeType == Node.COMMENT_NODE: rv.append("|%s" % (' ' * indent, element.nodeValue)) elif element.nodeType == Node.TEXT_NODE: rv.append("|%s\"%s\"" % (' ' * indent, element.nodeValue)) else: if (hasattr(element, "namespaceURI") and element.namespaceURI is not None): name = "%s %s" % (constants.prefixes[element.namespaceURI], element.nodeName) else: name = element.nodeName rv.append("|%s<%s>" % (' ' * indent, name)) if element.hasAttributes(): attributes = [] for i in range(len(element.attributes)): attr = element.attributes.item(i) name = attr.nodeName value = attr.value ns = attr.namespaceURI if ns: name = "%s %s" % (constants.prefixes[ns], attr.localName) else: name = attr.nodeName attributes.append((name, value)) for name, value in sorted(attributes): rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value)) indent += 2 for child in element.childNodes: serializeElement(child, indent) serializeElement(element, 0) return "\n".join(rv) return locals() # The actual means to get a module! getDomModule = moduleFactoryFactory(getDomBuilder) PKÒ¶N]eÛkL;site-packages/pip/_vendor/html5lib/treebuilders/__init__.pynu„[µü¤"""A collection of modules for building different kinds of trees from HTML documents. To create a treebuilder for a new type of tree, you need to do implement several things: 1. A set of classes for various types of elements: Document, Doctype, Comment, Element. These must implement the interface of ``base.treebuilders.Node`` (although comment nodes have a different signature for their constructor, see ``treebuilders.etree.Comment``) Textual content may also be implemented as another node type, or not, as your tree implementation requires. 2. A treebuilder object (called ``TreeBuilder`` by convention) that inherits from ``treebuilders.base.TreeBuilder``. This has 4 required attributes: * ``documentClass`` - the class to use for the bottommost node of a document * ``elementClass`` - the class to use for HTML Elements * ``commentClass`` - the class to use for comments * ``doctypeClass`` - the class to use for doctypes It also has one required method: * ``getDocument`` - Returns the root node of the complete document tree 3. If you wish to run the unit tests, you must also create a ``testSerializer`` method on your treebuilder which accepts a node and returns a string containing Node and its children serialized according to the format used in the unittests """ from __future__ import absolute_import, division, unicode_literals from .._utils import default_etree treeBuilderCache = {} def getTreeBuilder(treeType, implementation=None, **kwargs): """Get a TreeBuilder class for various types of trees with built-in support :arg treeType: the name of the tree type required (case-insensitive). Supported values are: * "dom" - A generic builder for DOM implementations, defaulting to a xml.dom.minidom based implementation. * "etree" - A generic builder for tree implementations exposing an ElementTree-like interface, defaulting to xml.etree.cElementTree if available and xml.etree.ElementTree if not. * "lxml" - A etree-based builder for lxml.etree, handling limitations of lxml's implementation. :arg implementation: (Currently applies to the "etree" and "dom" tree types). A module implementing the tree type e.g. xml.etree.ElementTree or xml.etree.cElementTree. :arg kwargs: Any additional options to pass to the TreeBuilder when creating it. Example: >>> from html5lib.treebuilders import getTreeBuilder >>> builder = getTreeBuilder('etree') """ treeType = treeType.lower() if treeType not in treeBuilderCache: if treeType == "dom": from . import dom # Come up with a sane default (pref. from the stdlib) if implementation is None: from xml.dom import minidom implementation = minidom # NEVER cache here, caching is done in the dom submodule return dom.getDomModule(implementation, **kwargs).TreeBuilder elif treeType == "lxml": from . import etree_lxml treeBuilderCache[treeType] = etree_lxml.TreeBuilder elif treeType == "etree": from . import etree if implementation is None: implementation = default_etree # NEVER cache here, caching is done in the etree submodule return etree.getETreeModule(implementation, **kwargs).TreeBuilder else: raise ValueError("""Unrecognised treebuilder "%s" """ % treeType) return treeBuilderCache.get(treeType) PKÒ¶N]Çä�..Usite-packages/pip/_vendor/html5lib/treebuilders/__pycache__/etree_lxml.cpython-38.pycnu„[µü¤U ÀÒ.e*7ã@sØdZddlmZmZmZddlZddlZddlZddlm Z ddl m Z ddlm Z dd lm Z dd lmZddlm Z d Ze d ¡Ze  d ¡jZGdd„deƒZGdd„deƒZdd„Zdd„ZGdd„de jƒZdS)aÃModule for supporting the lxml.etree library. The idea here is to use as much of the native library as possible, without using fragile hacks like custom element names that break between releases. The downside of this is that we cannot represent all possible trees; specifically the following are known to cause problems: Text or comments as siblings of the root element Docypes with no name When any of these things occur, we emit a DataLossWarning é)Úabsolute_importÚdivisionÚunicode_literalsNé)Úbaseé)ÚDataLossWarning)Ú constants)Úetree)Ú _ihatexmlTz {([^}]*)}(.*)Zasdc@seZdZdd„ZdS)Ú DocumentTypecCs||_||_||_dS©N)ÚnameÚpublicIdÚsystemId)Úselfrrr©rúP/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.pyÚ__init__#szDocumentType.__init__N)Ú__name__Ú __module__Ú __qualname__rrrrrr "sr c@s,eZdZdd„Zdd„Zdd„ZeeƒZdS)ÚDocumentcCsd|_g|_dSr )Ú _elementTreeÚ _childNodes©rrrrr*szDocument.__init__cCs|j ¡ |j¡dSr )rÚgetrootZaddnextÚ_element©rÚelementrrrÚ appendChild.szDocument.appendChildcCs|jSr )rrrrrÚ_getChildNodes1szDocument._getChildNodesN)rrrrr r!ÚpropertyZ childNodesrrrrr)srcs6g‰tjdd�‰d‡‡‡fdd„ ‰ˆ|dƒd ˆ¡S)NT©ZpreventDoubleDashCommentsrc s,t|dƒ�s,t|dƒrºˆ d¡|jjrz|jjsF|jjsFd|jj}nd|jj|jj|jjf}ˆ dd|d|f¡| ¡}| ¡dk r˜| ¡}q‚|dk r¸ˆ||dƒ|  ¡}q˜nnt |t ƒsÐt |t ƒ�rt |t ƒsìt jd dksìt‚ˆ d d||f¡n$ˆ d ¡|D]}ˆ||dƒ�q�nü|jtk�r€ˆ d d||jf¡t|d ƒ�r(|j�r(ˆ d d||jf¡�n¨t |tjƒ�s’t‚tj |j¡}|dk �rè| d¡}| d¡}tj|}ˆ dd||ˆ |¡f¡nˆ dd|ˆ |j¡f¡t|dƒ�r¶g}|j ¡D]d\} } t | ¡}|dk �rj| ¡\}} ˆ | ¡} tj|}d|| f} n ˆ | ¡} | | | f¡�q t |ƒD]&\} } ˆ dd|d| | f¡�qŽ|j�rÚˆ d d|d|jf¡|d7}|D]} ˆ| |ƒ�qæt|d ƒ�r(|j�r(ˆ d d|d|jf¡dS)NÚtagrz #documentú zz|%s%sú rrz|%s"%s"z#document-fragmentz|%sÚtailrz |%s<%s %s>z|%s<%s>Úattribz%s %sz |%s%s="%s")!ÚhasattrÚappendÚdocinfoÚ internalDTDZ public_idZ system_urlÚ root_namerZ getpreviousZgetnextÚ isinstanceÚstrÚbytesÚsysÚ version_infoÚAssertionErrorr$Ú comment_typeÚtextr'r Z_ElementÚetree_buildersÚ tag_regexpÚmatchÚgroupr ÚprefixesÚ fromXmlNamer(ÚitemsÚgroupsÚsorted) rÚindentÚdtd_strZ next_elementZnsmatchÚnsr$ÚprefixÚ attributesrÚvalueZ attr_stringÚchild©Ú infosetFilterÚrvÚserializeElementrrrI;s|   ÿý         ÿ   ÿ        z(testSerializer..serializeElementÚ )r)r Ú InfosetFilterÚjoin©rrrFrÚtestSerializer7s  F rNcs$g‰‡‡fdd„‰ˆ|ƒd ˆ¡S)z4Serialize an element and its child nodes to a stringcst|dƒsH|jjr:|jjr$|jj}n d|jj}ˆ |¡ˆ| ¡ƒnœ|jtkrfˆ d|j f¡n~|j s€ˆ d|jf¡n.d  dd„|j   ¡Dƒ¡}ˆ d|j|f¡|j rÀˆ |j ¡|D] }ˆ|ƒqĈ d |jf¡t|d ƒ�r|j �rˆ |j ¡dS) Nr$r%z z<%s>r&cSsg|]\}}d||f‘qS)z%s="%s"r)Ú.0rrDrrrÚ œsÿz6tostring..serializeElement..z<%s %s>zr')r)r+r,Údoctyper-r*rr$r4r5r(rLr<r')rr@ÚattrrE©rHrIrrrIŠs,      ÿ  z"tostring..serializeElementÚ)rLrMrrSrÚtostring†s rUcszeZdZeZeZdZdZeZ e Z ddd„Z dd„Z dd„Zd d „Zd d „Zd d„Zddd„Zd‡fdd„ Zdd„Z‡ZS)Ú TreeBuilderNFcsŠtjt|d�‰tjdd�‰|_||_G‡fdd„dtƒ‰G‡‡‡fdd„dˆjƒ}G‡‡fdd „d ˆj ƒ}||_ ||_ t j  ||¡dS) N)ÚfullTreeTr#cs&eZdZd‡fdd„ Z‡fdd„ZdS)z(TreeBuilder.__init__..AttributesNcsr|dkr i}||_t ||¡| ¡D]F\}}t|tƒrTd|dˆ |d¡f}n ˆ |¡}||jjj|<q&dS©Nú{%s}%srr)rÚdictrr<r.ÚtupleÚcoerceAttributer()rrrDÚkeyr©rGrrr½s   z1TreeBuilder.__init__..Attributes.__init__csPt |||¡t|tƒr4d|dˆ |d¡f}n ˆ |¡}||jjj|<dSrX)rZÚ __setitem__r.r[r\rr()rr]rDrr^rrr_És   z4TreeBuilder.__init__..Attributes.__setitem__)N)rrrrr_rr^rrÚ Attributes¼s r`csxeZdZ‡‡‡fdd„Z‡fdd„Z‡fdd„ZeeeƒZdd„Z‡fd d „Z eee ƒZ d‡‡fd d „ Z ‡fdd„Z d S)z%TreeBuilder.__init__..Elementcs*ˆ |¡}ˆjj|||d�ˆ|ƒ|_dS)N)Ú namespace)Ú coerceElementÚElementrÚ _attributes)rrra©r`ÚbuilderrGrrrÒs z.TreeBuilder.__init__..Element.__init__cs$ˆ |¡|_| |j|j¡|j_dSr )rbÚ_nameZ _getETreeTagZ _namespacerr$)rrr^rrÚ_setName×s  ÿz.TreeBuilder.__init__..Element._setNamecs ˆ |j¡Sr )r;rgrr^rrÚ_getNameÜsz.TreeBuilder.__init__..Element._getNamecSs|jSr ©rdrrrrÚ_getAttributesász4TreeBuilder.__init__..Element._getAttributescsˆ||ƒ|_dSr rj)rrC)r`rrÚ_setAttributesäsz4TreeBuilder.__init__..Element._setAttributesNcsˆ |¡}ˆj |||¡dSr )ZcoerceCharactersrcÚ insertText)rÚdataZ insertBefore©rfrGrrrmés z0TreeBuilder.__init__..Element.insertTextcsˆj ||¡dSr )rcr )rrE)rfrrr ísz1TreeBuilder.__init__..Element.appendChild)N) rrrrrhrir"rrkrlrCrmr rrerrrcÑs     rccs8eZdZ‡‡fdd„Z‡fdd„Zdd„ZeeeƒZdS)z%TreeBuilder.__init__..Commentcsˆ |¡}ˆj ||¡dSr )Ú coerceCommentÚCommentr©rrnrorrrñs z.TreeBuilder.__init__..Comment.__init__csˆ |¡}||j_dSr )rprr5rrr^rrÚ_setDataõs z.TreeBuilder.__init__..Comment._setDatacSs|jjSr )rr5rrrrÚ_getDataùsz.TreeBuilder.__init__..Comment._getDataN)rrrrrsrtr"rnrrorrrqðs rq)r6ZgetETreeModuler r rKrGÚnamespaceHTMLElementsrZrcrqÚ elementClassÚ commentClassrrVr)rrurWrcrqrrerr·szTreeBuilder.__init__cCs$tj |¡|j|_g|_d|_dSr )rrVÚresetÚinsertCommentInitialÚ insertCommentÚinitial_commentsrQrrrrrxs zTreeBuilder.resetcCst|ƒSr )rNrrrrrN szTreeBuilder.testSerializercCstr |jjS|jj ¡SdSr )rWÚdocumentrrrrrrÚ getDocument szTreeBuilder.getDocumentcCsFg}|jdj}|jr"| |j¡| t|ƒ¡|jrB| |j¡|S)Nr)Ú openElementsrr5r*ÚextendÚlistr')rZfragmentrrrrÚ getFragments   zTreeBuilder.getFragmentcCsh|d}|d}|d}|s0t dt¡d|_n4|j |¡}||krPt dt¡| |||¡}||_dS)Nrrrz#lxml cannot represent empty doctypez%lxml cannot represent non-xml doctype)ÚwarningsÚwarnrrQrGrbÚ doctypeClass)rÚtokenrrrZ coercedNamerQrrrÚ insertDoctypes   zTreeBuilder.insertDoctypecCs6|dks||jkst‚|jjdks&t‚|j |¡dSr )r|r3rr{r*©rrnÚparentrrrry,sz TreeBuilder.insertCommentInitialcsB||jkr,|jj ¡djtkr,t dt¡tt |ƒ  ||¡dS)Néÿÿÿÿz@lxml cannot represent adjacent comments beyond the root elements) r|rrr$r4r‚rƒrÚsuperrVrzr‡©Ú __class__rrÚinsertCommentMain1s  ÿ zTreeBuilder.insertCommentMainc Cs´d}|jrô|jjst‚|d|jj7}|jjdk s>|jjdk rÐ|d|j |jjpRd¡7}|jjrÈ|jj}| d¡dkrž| d¡dkržt  dt ¡|  dd¡}| d¡dkrº|d |7}qÐ|d |7}n|d 7}|d 7}|jj|d krôt  dt ¡|d7}t   |¡}|jD] }| |d¡}| |j¡�q | ¡|_| ¡|j_|d }| d|j¡}|dk�rj|} n d||f} | |_| ||¡} || _|jj | ¡|j | ¡|j|_dS)NrTz rzGlxml cannot represent doctype with a different name to the root elementz$rnrarY)rQrr3rrrGZ coercePubidÚfindr‚rƒrÚreplacer Z fromstringr{rwZ addpreviousrÚ documentClassr|Z getroottreerÚgetZdefaultNamespacer$rvrr*r~r�rz) rr…ZdocStrZsysidÚrootÚ comment_tokenZcommentrraZ etree_tagZ root_elementrrrÚ insertRoot7sP   ÿÿ           zTreeBuilder.insertRoot)F)N)N)rrrrr“r r„rvrwZ fragmentClassr ÚimplementationrrxrNr}r�r†ryr�r—Ú __classcell__rrr‹rrV¯s L  rV)Ú__doc__Z __future__rrrr‚Úrer1rTrr rr r6r Z lxml.etreerWÚcompiler7rqr$r4Úobjectr rrNrUrVrrrrÚs$         O)PKÒ¶N]—¶Ï—G-G-[site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/etree_lxml.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.e*7ã@sØdZddlmZmZmZddlZddlZddlZddlm Z ddl m Z ddlm Z dd lm Z dd lmZddlm Z d Ze d ¡Ze  d ¡jZGdd„deƒZGdd„deƒZdd„Zdd„ZGdd„de jƒZdS)aÃModule for supporting the lxml.etree library. The idea here is to use as much of the native library as possible, without using fragile hacks like custom element names that break between releases. The downside of this is that we cannot represent all possible trees; specifically the following are known to cause problems: Text or comments as siblings of the root element Docypes with no name When any of these things occur, we emit a DataLossWarning é)Úabsolute_importÚdivisionÚunicode_literalsNé)Úbaseé)ÚDataLossWarning)Ú constants)Úetree)Ú _ihatexmlTz {([^}]*)}(.*)Zasdc@seZdZdd„ZdS)Ú DocumentTypecCs||_||_||_dS©N)ÚnameÚpublicIdÚsystemId)Úselfrrr©rúP/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.pyÚ__init__#szDocumentType.__init__N)Ú__name__Ú __module__Ú __qualname__rrrrrr "sr c@s,eZdZdd„Zdd„Zdd„ZeeƒZdS)ÚDocumentcCsd|_g|_dSr )Ú _elementTreeÚ _childNodes©rrrrr*szDocument.__init__cCs|j ¡ |j¡dSr )rÚgetrootZaddnextÚ_element©rÚelementrrrÚ appendChild.szDocument.appendChildcCs|jSr )rrrrrÚ_getChildNodes1szDocument._getChildNodesN)rrrrr r!ÚpropertyZ childNodesrrrrr)srcs6g‰tjdd�‰d‡‡‡fdd„ ‰ˆ|dƒd ˆ¡S)NT©ZpreventDoubleDashCommentsrc sút|dƒ�s t|dƒrºˆ d¡|jjrz|jjsF|jjsFd|jj}nd|jj|jj|jjf}ˆ dd|d|f¡| ¡}| ¡dk r˜| ¡}q‚|dk r¸ˆ||dƒ|  ¡}q˜nNt |t ƒsÎt |t ƒr戠d d||f¡n"ˆ d ¡|D]}ˆ||dƒqô�nê|j tk�r`ˆ d d||jf¡t|d ƒ�rö|j�röˆ d d||jf¡�n–tj |j ¡}|dk �r¶| d ¡}| d¡}tj|}ˆ dd||ˆ |¡f¡nˆ dd|ˆ |j ¡f¡t|dƒ�r„g}|j ¡D]d\} } t | ¡}|dk �r8| ¡\}} ˆ | ¡} tj|}d|| f} n ˆ | ¡} | | | f¡�qît|ƒD]&\} } ˆ dd|d| | f¡�q\|j�r¨ˆ d d|d|jf¡|d7}|D]} ˆ| |ƒ�q´t|d ƒ�rö|j�röˆ d d|d|jf¡dS)NÚtagrz #documentú zz|%s%sú rz|%s"%s"z#document-fragmentz|%sÚtailrz |%s<%s %s>z|%s<%s>Úattribz%s %sz |%s%s="%s")ÚhasattrÚappendÚdocinfoÚ internalDTDZ public_idZ system_urlÚ root_namerZ getpreviousZgetnextÚ isinstanceÚstrÚbytesr$Ú comment_typeÚtextr'Úetree_buildersÚ tag_regexpÚmatchÚgroupr ÚprefixesÚ fromXmlNamer(ÚitemsÚgroupsÚsorted) rÚindentÚdtd_strZ next_elementZnsmatchÚnsr$ÚprefixÚ attributesrÚvalueZ attr_stringÚchild©Ú infosetFilterÚrvÚserializeElementrrrF;sx   ÿý         ÿ   ÿ        z(testSerializer..serializeElementÚ )r)r Ú InfosetFilterÚjoin©rrrCrÚtestSerializer7s  F rKcs$g‰‡‡fdd„‰ˆ|ƒd ˆ¡S)z4Serialize an element and its child nodes to a stringcst|dƒsH|jjr:|jjr$|jj}n d|jj}ˆ |¡ˆ| ¡ƒnœ|jtkrfˆ d|j f¡n~|j s€ˆ d|jf¡n.d  dd„|j   ¡Dƒ¡}ˆ d|j|f¡|j rÀˆ |j ¡|D] }ˆ|ƒqĈ d |jf¡t|d ƒ�r|j �rˆ |j ¡dS) Nr$r%z z<%s>r&cSsg|]\}}d||f‘qS)z%s="%s"r)Ú.0rrArrrÚ œsÿz6tostring..serializeElement..z<%s %s>zr')r)r+r,Údoctyper-r*rr$r1r2r(rIr9r')rr=ÚattrrB©rErFrrrFŠs,      ÿ  z"tostring..serializeElementÚ)rIrJrrPrÚtostring†s rRcszeZdZeZeZdZdZeZ e Z ddd„Z dd„Z dd„Zd d „Zd d „Zd d„Zddd„Zd‡fdd„ Zdd„Z‡ZS)Ú TreeBuilderNFcsŠtjt|d�‰tjdd�‰|_||_G‡fdd„dtƒ‰G‡‡‡fdd„dˆjƒ}G‡‡fdd „d ˆj ƒ}||_ ||_ t j  ||¡dS) N)ÚfullTreeTr#cs&eZdZd‡fdd„ Z‡fdd„ZdS)z(TreeBuilder.__init__..AttributesNcsr|dkr i}||_t ||¡| ¡D]F\}}t|tƒrTd|dˆ |d¡f}n ˆ |¡}||jjj|<q&dS©Nú{%s}%srr)rÚdictrr9r.ÚtupleÚcoerceAttributer()rrrAÚkeyr©rDrrr½s   z1TreeBuilder.__init__..Attributes.__init__csPt |||¡t|tƒr4d|dˆ |d¡f}n ˆ |¡}||jjj|<dSrU)rWÚ __setitem__r.rXrYrr()rrZrArr[rrr\És   z4TreeBuilder.__init__..Attributes.__setitem__)N)rrrrr\rr[rrÚ Attributes¼s r]csxeZdZ‡‡‡fdd„Z‡fdd„Z‡fdd„ZeeeƒZdd„Z‡fd d „Z eee ƒZ d‡‡fd d „ Z ‡fdd„Z d S)z%TreeBuilder.__init__..Elementcs*ˆ |¡}ˆjj|||d�ˆ|ƒ|_dS)N)Ú namespace)Ú coerceElementÚElementrÚ _attributes)rrr^©r]ÚbuilderrDrrrÒs z.TreeBuilder.__init__..Element.__init__cs$ˆ |¡|_| |j|j¡|j_dSr )r_Ú_nameZ _getETreeTagZ _namespacerr$)rrr[rrÚ_setName×s  ÿz.TreeBuilder.__init__..Element._setNamecs ˆ |j¡Sr )r8rdrr[rrÚ_getNameÜsz.TreeBuilder.__init__..Element._getNamecSs|jSr ©rarrrrÚ_getAttributesász4TreeBuilder.__init__..Element._getAttributescsˆ||ƒ|_dSr rg)rr@)r]rrÚ_setAttributesäsz4TreeBuilder.__init__..Element._setAttributesNcsˆ |¡}ˆj |||¡dSr )ZcoerceCharactersr`Ú insertText)rÚdataZ insertBefore©rcrDrrrjés z0TreeBuilder.__init__..Element.insertTextcsˆj ||¡dSr )r`r )rrB)rcrrr ísz1TreeBuilder.__init__..Element.appendChild)N) rrrrrerfr"rrhrir@rjr rrbrrr`Ñs     r`cs8eZdZ‡‡fdd„Z‡fdd„Zdd„ZeeeƒZdS)z%TreeBuilder.__init__..Commentcsˆ |¡}ˆj ||¡dSr )Ú coerceCommentÚCommentr©rrkrlrrrñs z.TreeBuilder.__init__..Comment.__init__csˆ |¡}||j_dSr )rmrr2ror[rrÚ_setDataõs z.TreeBuilder.__init__..Comment._setDatacSs|jjSr )rr2rrrrÚ_getDataùsz.TreeBuilder.__init__..Comment._getDataN)rrrrrprqr"rkrrlrrrnðs rn)r3ZgetETreeModuler r rHrDÚnamespaceHTMLElementsrWr`rnÚ elementClassÚ commentClassrrSr)rrrrTr`rnrrbrr·szTreeBuilder.__init__cCs$tj |¡|j|_g|_d|_dSr )rrSÚresetÚinsertCommentInitialÚ insertCommentÚinitial_commentsrNrrrrrus zTreeBuilder.resetcCst|ƒSr )rKrrrrrK szTreeBuilder.testSerializercCstr |jjS|jj ¡SdSr )rTÚdocumentrrrrrrÚ getDocument szTreeBuilder.getDocumentcCsFg}|jdj}|jr"| |j¡| t|ƒ¡|jrB| |j¡|S)Nr)Ú openElementsrr2r*ÚextendÚlistr')rZfragmentrrrrÚ getFragments   zTreeBuilder.getFragmentcCsh|d}|d}|d}|s0t dt¡d|_n4|j |¡}||krPt dt¡| |||¡}||_dS)Nrrrz#lxml cannot represent empty doctypez%lxml cannot represent non-xml doctype)ÚwarningsÚwarnrrNrDr_Ú doctypeClass)rÚtokenrrrZ coercedNamerNrrrÚ insertDoctypes   zTreeBuilder.insertDoctypecCs|j |¡dSr )rxr*©rrkÚparentrrrrv,sz TreeBuilder.insertCommentInitialcsB||jkr,|jj ¡djtkr,t dt¡tt |ƒ  ||¡dS)Néÿÿÿÿz@lxml cannot represent adjacent comments beyond the root elements) ryrrr$r1rr€rÚsuperrSrwr„©Ú __class__rrÚinsertCommentMain1s  ÿ zTreeBuilder.insertCommentMainc Cs¨d}|jrè|d|jj7}|jjdk s2|jjdk rÄ|d|j |jjpFd¡7}|jjr¼|jj}| d¡dkr’| d¡dkr’t dt ¡|  dd¡}| d¡dkr®|d |7}qÄ|d |7}n|d 7}|d 7}|jj|d krèt dt ¡|d7}t   |¡}|j D] }| |d¡}| |j¡�q| ¡|_| ¡|j_|d }| d|j¡}|dk�r^|} n d||f} | |_| ||¡} || _|jj | ¡|j | ¡|j|_dS)NrQz rzGlxml cannot represent doctype with a different name to the root elementz$rkr^rV)rNrrrrDZ coercePubidÚfindrr€rÚreplacer Z fromstringrxrtZ addpreviousrÚ documentClassryZ getroottreerÚgetZdefaultNamespacer$rsrr*r{rŠrw) rr‚ZdocStrZsysidÚrootÚ comment_tokenZcommentrr^Z etree_tagZ root_elementrrrÚ insertRoot7sN  ÿÿ           zTreeBuilder.insertRoot)F)N)N)rrrrr�r r�rsrtZ fragmentClassr ÚimplementationrrurKrzr~rƒrvrŠr”Ú __classcell__rrrˆrrS¯s L  rS)Ú__doc__Z __future__rrrrÚreÚsysrQrr rr r3r Z lxml.etreerTÚcompiler4rnr$r1Úobjectr rrKrRrSrrrrÚs$         O)PKÒ¶N]�ä'Í$Í$Nsite-packages/pip/_vendor/html5lib/treebuilders/__pycache__/dom.cpython-38.pycnu„[µü¤U ÀÒ.eÝ"ã@s¢ddlmZmZmZzddlmZWn ek rDddlmZYnXddlm Z m Z ddl Z ddl m Z ddl mZdd lmZdd lmZd d „ZeeƒZdS) é)Úabsolute_importÚdivisionÚunicode_literals)ÚMutableMapping)ÚminidomÚNodeNé)Úbaseé)Ú constants)Ú namespaces)ÚmoduleFactoryFactorycsVˆ‰Gdd„dtƒ‰G‡‡fdd„dtjƒ‰G‡‡‡‡fdd„dtjƒ}dd„‰tƒS) Nc@sLeZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dS)zgetDomBuilder..AttrListcSs ||_dS©N©Úelement©Úselfr©rúI/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treebuilders/dom.pyÚ__init__sz(getDomBuilder..AttrList.__init__cSst|jj ¡ƒSr)ÚiterrÚ attributesÚkeys©rrrrÚ__iter__sz(getDomBuilder..AttrList.__iter__cSs4t|tƒrt‚n |jj |¡}||_||jj|<dSr)Ú isinstanceÚtupleÚNotImplementedErrorrÚ ownerDocumentZcreateAttributeÚvaluer)rÚnamerÚattrrrrÚ __setitem__s  z+getDomBuilder..AttrList.__setitem__cSs t|jjƒSr)ÚlenrrrrrrÚ__len__#sz'getDomBuilder..AttrList.__len__cSst|jj ¡ƒSr)ÚlistrrÚitemsrrrrr&&sz%getDomBuilder..AttrList.itemscSst|jj ¡ƒSr)r%rrÚvaluesrrrrr')sz&getDomBuilder..AttrList.valuescSs"t|tƒrt‚n|jj|jSdSr)rrrrrr©rr rrrÚ __getitem__,s z+getDomBuilder..AttrList.__getitem__cSst|tƒrt‚n |jj|=dSr)rrrrrr(rrrÚ __delitem__2s z+getDomBuilder..AttrList.__delitem__N) Ú__name__Ú __module__Ú __qualname__rrr"r$r&r'r)r*rrrrÚAttrListsr.csŒeZdZdd„Zedd„ƒZdd„Zddd „Zd d „Zd d „Z dd„Z ‡fdd„Z dd„Z ee e ƒZ ‡fdd„Zdd„Zdd„ZeeƒZdS)z"getDomBuilder..NodeBuildercSstj ||j¡||_dSr)r rrÚnodeNamerrrrrr9sz+getDomBuilder..NodeBuilder.__init__cSst|jdƒr|jjpdS)NÚ namespaceURI)Úhasattrrr0rrrrÚ=s ÿz+getDomBuilder..NodeBuilder.cSs||_|j |j¡dSr)ÚparentrÚ appendChild©rÚnoderrrr4@sz.getDomBuilder..NodeBuilder.appendChildNcSs4|jj |¡}|r$|j ||j¡n |j |¡dSr)rrÚcreateTextNodeÚ insertBeforer4)rÚdatar8ÚtextrrrÚ insertTextDsz-getDomBuilder..NodeBuilder.insertTextcSs|j |j|j¡||_dSr)rr8r3)rr6ZrefNoderrrr8Ksz/getDomBuilder..NodeBuilder.insertBeforecSs&|jj|jkr|j |j¡d|_dSr)rZ parentNodeÚ removeChildr3r5rrrr<Osz.getDomBuilder..NodeBuilder.removeChildcSs6|j ¡r,|jj}|j |¡|j |¡qg|_dSr)rÚ hasChildNodesZ firstChildr<r4Ú childNodes)rZ newParentÚchildrrrÚreparentChildrenTs   z3getDomBuilder..NodeBuilder.reparentChildrencs ˆ|jƒSrrr)r.rrÚ getAttributes[sz0getDomBuilder..NodeBuilder.getAttributescSsv|rrt| ¡ƒD]`\}}t|tƒrb|ddk rD|dd|d}n|d}|j |d||¡q|j ||¡qdS)Nrú:rr )r%r&rrrZsetAttributeNSZ setAttribute)rrr rZ qualifiedNamerrrÚ setAttributes^s  ÿÿz0getDomBuilder..NodeBuilder.setAttributescsˆ|j d¡ƒS)NF)rÚ cloneNoder©Ú NodeBuilderrrrDmsz,getDomBuilder..NodeBuilder.cloneNodecSs |j ¡Sr)rr=rrrrÚ hasContentpsz-getDomBuilder..NodeBuilder.hasContentcSs(|jdkrtd|jfS|j|jfSdS)NZhtml)Ú namespacer r rrrrÚ getNameTupless z/getDomBuilder..NodeBuilder.getNameTuple)N)r+r,r-rÚpropertyrHr4r;r8r<r@rArCrrDrGrIZ nameTupler)r.rFrrrF8s     rFcs‚eZdZ‡fdd„Z‡‡fdd„Zd‡fdd„ Z‡fdd „Z‡fd d „Zd d „Z‡fdd„Z dd„Z dd„Z ddd„Z ”Z dZdS)z"getDomBuilder..TreeBuildercsˆ ¡ ddd¡|_t |¡Sr)ÚgetDOMImplementationZcreateDocumentÚdomÚweakrefÚproxyr)ÚDomrrÚ documentClass|sz0getDomBuilder..TreeBuilder.documentClasscsR|d}|d}|d}ˆ ¡}| |||¡}|j ˆ|ƒ¡ˆtkrN|j|_dS)Nr ÚpublicIdÚsystemId)rKZcreateDocumentTypeZdocumentr4rrLr)rÚtokenr rQrRZdomimplZdoctype)rOrFrrÚ insertDoctype€sz0getDomBuilder..TreeBuilder.insertDoctypeNcs6|dkr |jdkr |j |¡}n|j ||¡}ˆ|ƒSr)ZdefaultNamespacerLZ createElementZcreateElementNS)rr rHr6rErrÚ elementClass‹sz/getDomBuilder..TreeBuilder.elementClasscsˆ|j |¡ƒSr)rLZ createComment)rr9rErrÚ commentClass“sz/getDomBuilder..TreeBuilder.commentClasscsˆ|j ¡ƒSr)rLZcreateDocumentFragmentrrErrÚ fragmentClass–sz0getDomBuilder..TreeBuilder.fragmentClasscSs|j |j¡dSr)rLr4rr5rrrr4™sz.getDomBuilder..TreeBuilder.appendChildcsˆ|ƒSrrr)ÚtestSerializerrrrXœsz1getDomBuilder..TreeBuilder.testSerializercSs|jSr)rLrrrrÚ getDocumentŸsz.getDomBuilder..TreeBuilder.getDocumentcSstj |¡jSr)r Ú TreeBuilderÚ getFragmentrrrrrr[¢sz.getDomBuilder..TreeBuilder.getFragmentcSsp|}||krtj |||¡nNt|jdƒrXtj|jjkrXt|jjƒ|j_|jj  tj¡|j  |j  |¡¡dS)NÚ_child_node_types) r rZr;r1rLrÚ TEXT_NODEr\r%Úappendr4r7)rr9r3rrrr;¥s z-getDomBuilder..TreeBuilder.insertText)N)N)r+r,r-rPrTrUrVrWr4rXrYr[r;Úimplementationr r)rOÚDomImplementationrFrXrrrZ{s      rZcs0| ¡g‰d‡‡fdd„ ‰ˆ|dƒd ˆ¡S)Nrc s|jtjkr‚|jrj|js|jrP|jp&d}|jp0d}ˆ dd||j||f¡q~ˆ dd||jf¡nˆ dd|f¡�nr|jtjkrœˆ d¡�nX|jtjkr¶ˆ d¡�n>|jtj krÞˆ dd||j f¡�n|jtj k�rˆ d d||j f¡nît |d ƒ�r6|j dk �r6d tj|j |jf}n|j}ˆ d d||f¡| ¡�rôg}tt|jƒƒD]T}|j |¡}|j}|j}|j } | �r¬d tj| |jf}n|j}| ||f¡�qnt|ƒD]&\}}ˆ d d|d||f¡�qÌ|d7}|jD]} ˆ| |ƒ�qdS)NÚz|%sú z|%sz|%sz #documentz#document-fragmentz|%sz|%s"%s"r0z%s %sz|%s<%s>z |%s%s="%s"r )ZnodeTyperZDOCUMENT_TYPE_NODEr rQrRr^Z DOCUMENT_NODEZDOCUMENT_FRAGMENT_NODEZ COMMENT_NODEZ nodeValuer]r1r0r Úprefixesr/Z hasAttributesÚranger#rÚitemrZ localNameÚsortedr>) rÚindentrQrRr rÚir!rÚnsr?©ÚrvÚserializeElementrrrl¹sT    ÿ    ÿ ÿ    z?getDomBuilder..testSerializer..serializeElementÚ )r)Z normalizeÚjoinrrrjrrXµs . z%getDomBuilder..testSerializer)rr rrZÚlocals)r`rZr)r.rOr`rFrXrÚ getDomBuilders $C:6rp)Z __future__rrrZcollections.abcrÚ ImportErrorÚ collectionsZxml.domrrrMrar r r Z_utilsr rpZ getDomModulerrrrÚs    _PKÒ¶N]�ä'Í$Í$Tsite-packages/pip/_vendor/html5lib/treebuilders/__pycache__/dom.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.eÝ"ã@s¢ddlmZmZmZzddlmZWn ek rDddlmZYnXddlm Z m Z ddl Z ddl m Z ddl mZdd lmZdd lmZd d „ZeeƒZdS) é)Úabsolute_importÚdivisionÚunicode_literals)ÚMutableMapping)ÚminidomÚNodeNé)Úbaseé)Ú constants)Ú namespaces)ÚmoduleFactoryFactorycsVˆ‰Gdd„dtƒ‰G‡‡fdd„dtjƒ‰G‡‡‡‡fdd„dtjƒ}dd„‰tƒS) Nc@sLeZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dS)zgetDomBuilder..AttrListcSs ||_dS©N©Úelement©Úselfr©rúI/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treebuilders/dom.pyÚ__init__sz(getDomBuilder..AttrList.__init__cSst|jj ¡ƒSr)ÚiterrÚ attributesÚkeys©rrrrÚ__iter__sz(getDomBuilder..AttrList.__iter__cSs4t|tƒrt‚n |jj |¡}||_||jj|<dSr)Ú isinstanceÚtupleÚNotImplementedErrorrÚ ownerDocumentZcreateAttributeÚvaluer)rÚnamerÚattrrrrÚ __setitem__s  z+getDomBuilder..AttrList.__setitem__cSs t|jjƒSr)ÚlenrrrrrrÚ__len__#sz'getDomBuilder..AttrList.__len__cSst|jj ¡ƒSr)ÚlistrrÚitemsrrrrr&&sz%getDomBuilder..AttrList.itemscSst|jj ¡ƒSr)r%rrÚvaluesrrrrr')sz&getDomBuilder..AttrList.valuescSs"t|tƒrt‚n|jj|jSdSr)rrrrrr©rr rrrÚ __getitem__,s z+getDomBuilder..AttrList.__getitem__cSst|tƒrt‚n |jj|=dSr)rrrrrr(rrrÚ __delitem__2s z+getDomBuilder..AttrList.__delitem__N) Ú__name__Ú __module__Ú __qualname__rrr"r$r&r'r)r*rrrrÚAttrListsr.csŒeZdZdd„Zedd„ƒZdd„Zddd „Zd d „Zd d „Z dd„Z ‡fdd„Z dd„Z ee e ƒZ ‡fdd„Zdd„Zdd„ZeeƒZdS)z"getDomBuilder..NodeBuildercSstj ||j¡||_dSr)r rrÚnodeNamerrrrrr9sz+getDomBuilder..NodeBuilder.__init__cSst|jdƒr|jjpdS)NÚ namespaceURI)Úhasattrrr0rrrrÚ=s ÿz+getDomBuilder..NodeBuilder.cSs||_|j |j¡dSr)ÚparentrÚ appendChild©rÚnoderrrr4@sz.getDomBuilder..NodeBuilder.appendChildNcSs4|jj |¡}|r$|j ||j¡n |j |¡dSr)rrÚcreateTextNodeÚ insertBeforer4)rÚdatar8ÚtextrrrÚ insertTextDsz-getDomBuilder..NodeBuilder.insertTextcSs|j |j|j¡||_dSr)rr8r3)rr6ZrefNoderrrr8Ksz/getDomBuilder..NodeBuilder.insertBeforecSs&|jj|jkr|j |j¡d|_dSr)rZ parentNodeÚ removeChildr3r5rrrr<Osz.getDomBuilder..NodeBuilder.removeChildcSs6|j ¡r,|jj}|j |¡|j |¡qg|_dSr)rÚ hasChildNodesZ firstChildr<r4Ú childNodes)rZ newParentÚchildrrrÚreparentChildrenTs   z3getDomBuilder..NodeBuilder.reparentChildrencs ˆ|jƒSrrr)r.rrÚ getAttributes[sz0getDomBuilder..NodeBuilder.getAttributescSsv|rrt| ¡ƒD]`\}}t|tƒrb|ddk rD|dd|d}n|d}|j |d||¡q|j ||¡qdS)Nrú:rr )r%r&rrrZsetAttributeNSZ setAttribute)rrr rZ qualifiedNamerrrÚ setAttributes^s  ÿÿz0getDomBuilder..NodeBuilder.setAttributescsˆ|j d¡ƒS)NF)rÚ cloneNoder©Ú NodeBuilderrrrDmsz,getDomBuilder..NodeBuilder.cloneNodecSs |j ¡Sr)rr=rrrrÚ hasContentpsz-getDomBuilder..NodeBuilder.hasContentcSs(|jdkrtd|jfS|j|jfSdS)NZhtml)Ú namespacer r rrrrÚ getNameTupless z/getDomBuilder..NodeBuilder.getNameTuple)N)r+r,r-rÚpropertyrHr4r;r8r<r@rArCrrDrGrIZ nameTupler)r.rFrrrF8s     rFcs‚eZdZ‡fdd„Z‡‡fdd„Zd‡fdd„ Z‡fdd „Z‡fd d „Zd d „Z‡fdd„Z dd„Z dd„Z ddd„Z ”Z dZdS)z"getDomBuilder..TreeBuildercsˆ ¡ ddd¡|_t |¡Sr)ÚgetDOMImplementationZcreateDocumentÚdomÚweakrefÚproxyr)ÚDomrrÚ documentClass|sz0getDomBuilder..TreeBuilder.documentClasscsR|d}|d}|d}ˆ ¡}| |||¡}|j ˆ|ƒ¡ˆtkrN|j|_dS)Nr ÚpublicIdÚsystemId)rKZcreateDocumentTypeZdocumentr4rrLr)rÚtokenr rQrRZdomimplZdoctype)rOrFrrÚ insertDoctype€sz0getDomBuilder..TreeBuilder.insertDoctypeNcs6|dkr |jdkr |j |¡}n|j ||¡}ˆ|ƒSr)ZdefaultNamespacerLZ createElementZcreateElementNS)rr rHr6rErrÚ elementClass‹sz/getDomBuilder..TreeBuilder.elementClasscsˆ|j |¡ƒSr)rLZ createComment)rr9rErrÚ commentClass“sz/getDomBuilder..TreeBuilder.commentClasscsˆ|j ¡ƒSr)rLZcreateDocumentFragmentrrErrÚ fragmentClass–sz0getDomBuilder..TreeBuilder.fragmentClasscSs|j |j¡dSr)rLr4rr5rrrr4™sz.getDomBuilder..TreeBuilder.appendChildcsˆ|ƒSrrr)ÚtestSerializerrrrXœsz1getDomBuilder..TreeBuilder.testSerializercSs|jSr)rLrrrrÚ getDocumentŸsz.getDomBuilder..TreeBuilder.getDocumentcSstj |¡jSr)r Ú TreeBuilderÚ getFragmentrrrrrr[¢sz.getDomBuilder..TreeBuilder.getFragmentcSsp|}||krtj |||¡nNt|jdƒrXtj|jjkrXt|jjƒ|j_|jj  tj¡|j  |j  |¡¡dS)NÚ_child_node_types) r rZr;r1rLrÚ TEXT_NODEr\r%Úappendr4r7)rr9r3rrrr;¥s z-getDomBuilder..TreeBuilder.insertText)N)N)r+r,r-rPrTrUrVrWr4rXrYr[r;Úimplementationr r)rOÚDomImplementationrFrXrrrZ{s      rZcs0| ¡g‰d‡‡fdd„ ‰ˆ|dƒd ˆ¡S)Nrc s|jtjkr‚|jrj|js|jrP|jp&d}|jp0d}ˆ dd||j||f¡q~ˆ dd||jf¡nˆ dd|f¡�nr|jtjkrœˆ d¡�nX|jtjkr¶ˆ d¡�n>|jtj krÞˆ dd||j f¡�n|jtj k�rˆ d d||j f¡nît |d ƒ�r6|j dk �r6d tj|j |jf}n|j}ˆ d d||f¡| ¡�rôg}tt|jƒƒD]T}|j |¡}|j}|j}|j } | �r¬d tj| |jf}n|j}| ||f¡�qnt|ƒD]&\}}ˆ d d|d||f¡�qÌ|d7}|jD]} ˆ| |ƒ�qdS)NÚz|%sú z|%sz|%sz #documentz#document-fragmentz|%sz|%s"%s"r0z%s %sz|%s<%s>z |%s%s="%s"r )ZnodeTyperZDOCUMENT_TYPE_NODEr rQrRr^Z DOCUMENT_NODEZDOCUMENT_FRAGMENT_NODEZ COMMENT_NODEZ nodeValuer]r1r0r Úprefixesr/Z hasAttributesÚranger#rÚitemrZ localNameÚsortedr>) rÚindentrQrRr rÚir!rÚnsr?©ÚrvÚserializeElementrrrl¹sT    ÿ    ÿ ÿ    z?getDomBuilder..testSerializer..serializeElementÚ )r)Z normalizeÚjoinrrrjrrXµs . z%getDomBuilder..testSerializer)rr rrZÚlocals)r`rZr)r.rOr`rFrXrÚ getDomBuilders $C:6rp)Z __future__rrrZcollections.abcrÚ ImportErrorÚ collectionsZxml.domrrrMrar r r Z_utilsr rpZ getDomModulerrrrÚs    _PKÒ¶N]£64Ä+Ä+Usite-packages/pip/_vendor/html5lib/treebuilders/__pycache__/base.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.eó8ã@súddlmZmZmZddlmZddlmZmZm Z dZ e eƒdfe ee e ddfgƒBƒdfe ee e dd fe dd fgƒBƒdfe e ddfe dd fgƒdfe e dd fe dd fgƒdfdœZ Gdd„deƒZGdd„deƒZGdd„deƒZdS)é)Úabsolute_importÚdivisionÚunicode_literals)Ú text_typeé)ÚscopingElementsÚtableInsertModeElementsÚ namespacesNFÚhtmlÚbuttonZolZulÚtableÚoptgroupÚoptionT)Nr Úlistr Zselectc@sbeZdZdZdd„Zdd„Zdd„Zdd „Zdd d „Zd d„Z dd„Z dd„Z dd„Z dd„Z d S)ÚNodezRepresents an item in the treecCs(||_d|_d|_i|_g|_g|_dS)zRCreates a Node :arg name: The tag name associated with the node N)ÚnameÚparentÚvalueÚ attributesÚ childNodesZ_flags)Úselfr©rúJ/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treebuilders/base.pyÚ__init__s z Node.__init__cCs:d dd„|j ¡Dƒ¡}|r,d|j|fSd|jSdS)Nú cSsg|]\}}d||f‘qS)z%s="%s"r)Ú.0rrrrrÚ .sÿz Node.__str__..z<%s %s>ú<%s>)ÚjoinrÚitemsr)rZ attributesStrrrrÚ__str__-s  þz Node.__str__cCs d|jS)Nr)r©rrrrÚ__repr__6sz Node.__repr__cCst‚dS)z[Insert node as a child of the current node :arg node: the node to insert N©ÚNotImplementedError©rÚnoderrrÚ appendChild9szNode.appendChildNcCst‚dS)aBInsert data as text in the current node, positioned before the start of node insertBefore or to the end of the node's text. :arg data: the data to insert :arg insertBefore: True if you want to insert the text before the node and False if you want to insert it after the node Nr#)rÚdataÚ insertBeforerrrÚ insertTextAs zNode.insertTextcCst‚dS)aInsert node as a child of the current node, before refNode in the list of child nodes. Raises ValueError if refNode is not a child of the current node :arg node: the node to insert :arg refNode: the child node to insert the node before Nr#)rr&ZrefNoderrrr)Ms zNode.insertBeforecCst‚dS)zhRemove node from the children of the current node :arg node: the child node to remove Nr#r%rrrÚ removeChildYszNode.removeChildcCs |jD]}| |¡qg|_dS)zôMove all the children of the current node to newParent. This is needed so that trees that don't store text as nodes move the text in the correct way :arg newParent: the node to move all this node's children to N)rr')rZ newParentZchildrrrÚreparentChildrenas  zNode.reparentChildrencCst‚dS)zŠReturn a shallow copy of the current node i.e. a node with the same name and attributes but with no parent or child nodes Nr#r!rrrÚ cloneNodenszNode.cloneNodecCst‚dS)zFReturn true if the node has children or text, false otherwise Nr#r!rrrÚ hasContenttszNode.hasContent)N)Ú__name__Ú __module__Ú __qualname__Ú__doc__rr r"r'r*r)r+r,r-r.rrrrrs    rc@seZdZdd„Zdd„ZdS)ÚActiveFormattingElementscCsfd}|tkrV|ddd…D]:}|tkr*qV| ||¡r>|d7}|dkr| |¡qVqt ||¡dS)Nréÿÿÿÿéé)ÚMarkerÚ nodesEqualÚremoverÚappend)rr&Z equalCountÚelementrrrr:{s  zActiveFormattingElements.appendcCs$|j|jksdS|j|jks dSdS)NFT)Ú nameTupler)rZnode1Znode2rrrr8ˆs   z#ActiveFormattingElements.nodesEqualN)r/r0r1r:r8rrrrr3zs r3c@sÖeZdZdZdZdZdZdZdZdd„Z dd„Z d+dd„Z d d „Z d d „Z d d„Zdd„Zdd„Zd,dd„Zdd„Zdd„Zdd„ZeeeƒZdd„Zdd„Zd-dd „Zd!d"„Zd.d#d$„Zd%d&„Zd'd(„Zd)d*„ZdS)/Ú TreeBuilderaBase treebuilder implementation * documentClass - the class to use for the bottommost node of a document * elementClass - the class to use for HTML Elements * commentClass - the class to use for comments * doctypeClass - the class to use for doctypes NcCs|r d|_nd|_| ¡dS)zmCreate a TreeBuilder :arg namespaceHTMLElements: whether or not to namespace HTML elements zhttp://www.w3.org/1999/xhtmlN)ÚdefaultNamespaceÚreset)rZnamespaceHTMLElementsrrrr¬szTreeBuilder.__init__cCs.g|_tƒ|_d|_d|_d|_| ¡|_dS)NF)Ú openElementsr3ÚactiveFormattingElementsZ headPointerZ formPointerÚinsertFromTableÚ documentClassÚdocumentr!rrrr?¸s zTreeBuilder.resetcCs~t|dƒ}|s$t|tƒr$td|f}t|\}}t|jƒD]>}|rP||krPdS|sd|j|krddS||j|kAr:dSq:dS)Nr<r TF)ÚhasattrÚ isinstancerr ÚlistElementsMapÚreversedr@r<)rÚtargetZvariantZ exactNodeZ listElementsÚinvertr&rrrÚelementInScopeÄs     zTreeBuilder.elementInScopecCsÀ|js dSt|jƒd}|j|}|tks4||jkr8dS|tkrl||jkrl|dkrXd}ql|d8}|j|}q8|d7}|j|}| ¡}| d|j|j|jdœ¡}||j|<||jdkrlq¼qldS)Nr5rr4ZStartTag)ÚtyperÚ namespacer() rAÚlenr7r@r-Ú insertElementrrMr)rÚiÚentryZcloner;rrrÚ#reconstructActiveFormattingElementsÚs.   ý z/TreeBuilder.reconstructActiveFormattingElementscCs(|j ¡}|jr$|tkr$|j ¡}q dS©N)rAÚpopr7)rrQrrrÚclearActiveFormattingElementss z)TreeBuilder.clearActiveFormattingElementscCs:|jddd…D]$}|tkr"q6q|j|kr|SqdS)zšCheck if an element exists between the end of the active formatting elements and the last marker. If it does, return it, else return falseNr4F)rAr7r)rrÚitemrrrÚ!elementInActiveFormattingElements s   z-TreeBuilder.elementInActiveFormattingElementscCs&| |¡}|j |¡|j |¡dSrS)Ú createElementr@r:rDr')rÚtokenr;rrrÚ insertRoots  zTreeBuilder.insertRootcCs6|d}|d}|d}| |||¡}|j |¡dS)NrÚpublicIdÚsystemId)Ú doctypeClassrDr')rrYrr[r\ZdoctyperrrÚ insertDoctype s zTreeBuilder.insertDoctypecCs*|dkr|jd}| | |d¡¡dS)Nr4r()r@r'Ú commentClass)rrYrrrrÚ insertComment(s zTreeBuilder.insertCommentcCs0|d}| d|j¡}| ||¡}|d|_|S)z.Create an element but don't insert it anywhererrMr()Úgetr>Ú elementClassr©rrYrrMr;rrrrX-s   zTreeBuilder.createElementcCs|jSrS)Ú_insertFromTabler!rrrÚ_getInsertFromTable5szTreeBuilder._getInsertFromTablecCs ||_|r|j|_n|j|_dS)zsSwitch the function used to insert an element from the normal one to the misnested table one and back againN)rdÚinsertElementTablerOÚinsertElementNormal)rrrrrÚ_setInsertFromTable8s zTreeBuilder._setInsertFromTablecCsL|d}| d|j¡}| ||¡}|d|_|jd |¡|j |¡|S)NrrMr(r4)rar>rbrr@r'r:rcrrrrgCs   zTreeBuilder.insertElementNormalcCs`| |¡}|jdjtkr$| |¡S| ¡\}}|dkrD| |¡n | ||¡|j |¡|S)z-Create an element and insert it into the treer4N) rXr@rrrgÚgetTableMisnestedNodePositionr'r)r:)rrYr;rr)rrrrfMs      zTreeBuilder.insertElementTablecCsV|dkr|jd}|jr.|jr:|jdjtkr:| |¡n| ¡\}}| ||¡dS)zInsert text data.Nr4)r@rBrrr*ri)rr(rr)rrrr*]s   ÿÿ  zTreeBuilder.insertTextcCstd}d}d}|jddd…D]}|jdkr|}q4q|rb|jrJ|j}|}ql|j|j |¡d}n |jd}||fS)zsGet the foster parent element, and sibling to insert before (or None) when inserting a misnested table nodeNr4r r5r)r@rrÚindex)rZ lastTableZ fosterParentr)Zelmrrrrils  ÿ z)TreeBuilder.getTableMisnestedNodePositioncCs8|jdj}|tdƒkr4||kr4|j ¡| |¡dS)Nr4)ZddZdtZlirr ÚpZrpZrt)r@rÚ frozensetrTÚgenerateImpliedEndTags)rÚexcluderrrrrm†s   ÿ z"TreeBuilder.generateImpliedEndTagscCs|jS)zReturn the final tree)rDr!rrrÚ getDocument�szTreeBuilder.getDocumentcCs| ¡}|jd |¡|S)zReturn the final fragmentr)Ú fragmentClassr@r,)rZfragmentrrrÚ getFragment”szTreeBuilder.getFragmentcCst‚dS)z‰Serialize the subtree of node in the format required by unit tests :arg node: the node from which to start serializing Nr#r%rrrÚtestSerializer›szTreeBuilder.testSerializer)N)N)N)N)r/r0r1r2rCrbr_r]rprr?rKrRrUrWrZr^r`rXrerhÚpropertyrBrgrfr*rirmrorqrrrrrrr=’s6   .     r=)Z __future__rrrZpip._vendor.sixrZ constantsrrr r7rlÚsetrGÚobjectrrr3r=rrrrÚs0   ÿÿ  ÿÿ  ÿÿù cPKÒ¶N]‹ÙÔÐØ Ø Ysite-packages/pip/_vendor/html5lib/treebuilders/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.eã@s6dZddlmZmZmZddlmZiZddd„ZdS) a)A collection of modules for building different kinds of trees from HTML documents. To create a treebuilder for a new type of tree, you need to do implement several things: 1. A set of classes for various types of elements: Document, Doctype, Comment, Element. These must implement the interface of ``base.treebuilders.Node`` (although comment nodes have a different signature for their constructor, see ``treebuilders.etree.Comment``) Textual content may also be implemented as another node type, or not, as your tree implementation requires. 2. A treebuilder object (called ``TreeBuilder`` by convention) that inherits from ``treebuilders.base.TreeBuilder``. This has 4 required attributes: * ``documentClass`` - the class to use for the bottommost node of a document * ``elementClass`` - the class to use for HTML Elements * ``commentClass`` - the class to use for comments * ``doctypeClass`` - the class to use for doctypes It also has one required method: * ``getDocument`` - Returns the root node of the complete document tree 3. If you wish to run the unit tests, you must also create a ``testSerializer`` method on your treebuilder which accepts a node and returns a string containing Node and its children serialized according to the format used in the unittests é)Úabsolute_importÚdivisionÚunicode_literalsé)Ú default_etreeNcKs²| ¡}|tkr¨|dkrLddlm}|dkr>> from html5lib.treebuilders import getTreeBuilder >>> builder = getTreeBuilder('etree') Údomé)rNr)ÚminidomZlxml)Ú etree_lxmlÚetree)r zUnrecognised treebuilder "%s" )ÚlowerÚtreeBuilderCacheÚrZxml.domr Z getDomModuleZ TreeBuilderr r rZgetETreeModuleÚ ValueErrorÚget)ZtreeTypeÚimplementationÚkwargsrr r r ©rúN/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treebuilders/__init__.pyÚgetTreeBuilder's$      r)N) Ú__doc__Z __future__rrrZ_utilsrr rrrrrÚs PKÒ¶N]tÅ™æ2,2,Osite-packages/pip/_vendor/html5lib/treebuilders/__pycache__/base.cpython-38.pycnu„[µü¤U ÀÒ.eó8ã@súddlmZmZmZddlmZddlmZmZm Z dZ e eƒdfe ee e ddfgƒBƒdfe ee e dd fe dd fgƒBƒdfe e ddfe dd fgƒdfe e dd fe dd fgƒdfdœZ Gdd„deƒZGdd„deƒZGdd„deƒZdS)é)Úabsolute_importÚdivisionÚunicode_literals)Ú text_typeé)ÚscopingElementsÚtableInsertModeElementsÚ namespacesNFÚhtmlÚbuttonZolZulÚtableÚoptgroupÚoptionT)Nr Úlistr Zselectc@sbeZdZdZdd„Zdd„Zdd„Zdd „Zdd d „Zd d„Z dd„Z dd„Z dd„Z dd„Z d S)ÚNodezRepresents an item in the treecCs(||_d|_d|_i|_g|_g|_dS)zRCreates a Node :arg name: The tag name associated with the node N)ÚnameÚparentÚvalueÚ attributesÚ childNodesZ_flags)Úselfr©rúJ/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treebuilders/base.pyÚ__init__s z Node.__init__cCs:d dd„|j ¡Dƒ¡}|r,d|j|fSd|jSdS)Nú cSsg|]\}}d||f‘qS)z%s="%s"r)Ú.0rrrrrÚ .sÿz Node.__str__..z<%s %s>ú<%s>)ÚjoinrÚitemsr)rZ attributesStrrrrÚ__str__-s  þz Node.__str__cCs d|jS)Nr)r©rrrrÚ__repr__6sz Node.__repr__cCst‚dS)z[Insert node as a child of the current node :arg node: the node to insert N©ÚNotImplementedError©rÚnoderrrÚ appendChild9szNode.appendChildNcCst‚dS)aBInsert data as text in the current node, positioned before the start of node insertBefore or to the end of the node's text. :arg data: the data to insert :arg insertBefore: True if you want to insert the text before the node and False if you want to insert it after the node Nr#)rÚdataÚ insertBeforerrrÚ insertTextAs zNode.insertTextcCst‚dS)aInsert node as a child of the current node, before refNode in the list of child nodes. Raises ValueError if refNode is not a child of the current node :arg node: the node to insert :arg refNode: the child node to insert the node before Nr#)rr&ZrefNoderrrr)Ms zNode.insertBeforecCst‚dS)zhRemove node from the children of the current node :arg node: the child node to remove Nr#r%rrrÚ removeChildYszNode.removeChildcCs |jD]}| |¡qg|_dS)zôMove all the children of the current node to newParent. This is needed so that trees that don't store text as nodes move the text in the correct way :arg newParent: the node to move all this node's children to N)rr')rZ newParentZchildrrrÚreparentChildrenas  zNode.reparentChildrencCst‚dS)zŠReturn a shallow copy of the current node i.e. a node with the same name and attributes but with no parent or child nodes Nr#r!rrrÚ cloneNodenszNode.cloneNodecCst‚dS)zFReturn true if the node has children or text, false otherwise Nr#r!rrrÚ hasContenttszNode.hasContent)N)Ú__name__Ú __module__Ú __qualname__Ú__doc__rr r"r'r*r)r+r,r-r.rrrrrs    rc@seZdZdd„Zdd„ZdS)ÚActiveFormattingElementscCsfd}|tkrV|ddd…D]:}|tkr*qV| ||¡r>|d7}|dkr| |¡qVqt ||¡dS)Nréÿÿÿÿéé)ÚMarkerÚ nodesEqualÚremoverÚappend)rr&Z equalCountÚelementrrrr:{s  zActiveFormattingElements.appendcCs$|j|jksdS|j|jks dSdS)NFT)Ú nameTupler)rZnode1Znode2rrrr8ˆs   z#ActiveFormattingElements.nodesEqualN)r/r0r1r:r8rrrrr3zs r3c@sÖeZdZdZdZdZdZdZdZdd„Z dd„Z d+dd„Z d d „Z d d „Z d d„Zdd„Zdd„Zd,dd„Zdd„Zdd„Zdd„ZeeeƒZdd„Zdd„Zd-dd „Zd!d"„Zd.d#d$„Zd%d&„Zd'd(„Zd)d*„ZdS)/Ú TreeBuilderaBase treebuilder implementation * documentClass - the class to use for the bottommost node of a document * elementClass - the class to use for HTML Elements * commentClass - the class to use for comments * doctypeClass - the class to use for doctypes NcCs|r d|_nd|_| ¡dS)zmCreate a TreeBuilder :arg namespaceHTMLElements: whether or not to namespace HTML elements zhttp://www.w3.org/1999/xhtmlN)ÚdefaultNamespaceÚreset)rZnamespaceHTMLElementsrrrr¬szTreeBuilder.__init__cCs.g|_tƒ|_d|_d|_d|_| ¡|_dS)NF)Ú openElementsr3ÚactiveFormattingElementsZ headPointerZ formPointerÚinsertFromTableÚ documentClassÚdocumentr!rrrr?¸s zTreeBuilder.resetcCs”t|dƒ}|s2t|tƒr$td|f}t|tƒs2t‚t|\}}t|jƒD]>}|r^||kr^dS|sr|j |krrdS||j |kArHdSqHds�t‚dS)Nr<r TF) ÚhasattrÚ isinstancerr ÚtupleÚAssertionErrorÚlistElementsMapÚreversedr@r<)rÚtargetZvariantZ exactNodeZ listElementsÚinvertr&rrrÚelementInScopeÄs     zTreeBuilder.elementInScopecCsÀ|js dSt|jƒd}|j|}|tks4||jkr8dS|tkrl||jkrl|dkrXd}ql|d8}|j|}q8|d7}|j|}| ¡}| d|j|j|jdœ¡}||j|<||jdkrlq¼qldS)Nr5rr4ZStartTag)ÚtyperÚ namespacer() rAÚlenr7r@r-Ú insertElementrrOr)rÚiÚentryZcloner;rrrÚ#reconstructActiveFormattingElementsÚs.   ý z/TreeBuilder.reconstructActiveFormattingElementscCs(|j ¡}|jr$|tkr$|j ¡}q dS©N)rAÚpopr7)rrSrrrÚclearActiveFormattingElementss z)TreeBuilder.clearActiveFormattingElementscCs:|jddd…D]$}|tkr"q6q|j|kr|SqdS)zšCheck if an element exists between the end of the active formatting elements and the last marker. If it does, return it, else return falseNr4F)rAr7r)rrÚitemrrrÚ!elementInActiveFormattingElements s   z-TreeBuilder.elementInActiveFormattingElementscCs&| |¡}|j |¡|j |¡dSrU)Ú createElementr@r:rDr')rÚtokenr;rrrÚ insertRoots  zTreeBuilder.insertRootcCs6|d}|d}|d}| |||¡}|j |¡dS)NrÚpublicIdÚsystemId)Ú doctypeClassrDr')rr[rr]r^ZdoctyperrrÚ insertDoctype s zTreeBuilder.insertDoctypecCs*|dkr|jd}| | |d¡¡dS)Nr4r()r@r'Ú commentClass)rr[rrrrÚ insertComment(s zTreeBuilder.insertCommentcCs0|d}| d|j¡}| ||¡}|d|_|S)z.Create an element but don't insert it anywhererrOr()Úgetr>Ú elementClassr©rr[rrOr;rrrrZ-s   zTreeBuilder.createElementcCs|jSrU)Ú_insertFromTabler!rrrÚ_getInsertFromTable5szTreeBuilder._getInsertFromTablecCs ||_|r|j|_n|j|_dS)zsSwitch the function used to insert an element from the normal one to the misnested table one and back againN)rfÚinsertElementTablerQÚinsertElementNormal)rrrrrÚ_setInsertFromTable8s zTreeBuilder._setInsertFromTablecCsb|d}t|tƒstd|ƒ‚| d|j¡}| ||¡}|d|_|jd |¡|j  |¡|S)NrzElement %s not unicoderOr(r4) rFrrHrcr>rdrr@r'r:rerrrriCs   zTreeBuilder.insertElementNormalcCs`| |¡}|jdjtkr$| |¡S| ¡\}}|dkrD| |¡n | ||¡|j |¡|S)z-Create an element and insert it into the treer4N) rZr@rrriÚgetTableMisnestedNodePositionr'r)r:)rr[r;rr)rrrrhMs      zTreeBuilder.insertElementTablecCsV|dkr|jd}|jr.|jr:|jdjtkr:| |¡n| ¡\}}| ||¡dS)zInsert text data.Nr4)r@rBrrr*rk)rr(rr)rrrr*]s   ÿÿ  zTreeBuilder.insertTextcCstd}d}d}|jddd…D]}|jdkr|}q4q|rb|jrJ|j}|}ql|j|j |¡d}n |jd}||fS)zsGet the foster parent element, and sibling to insert before (or None) when inserting a misnested table nodeNr4r r5r)r@rrÚindex)rZ lastTableZ fosterParentr)Zelmrrrrkls  ÿ z)TreeBuilder.getTableMisnestedNodePositioncCs8|jdj}|tdƒkr4||kr4|j ¡| |¡dS)Nr4)ZddZdtZlirr ÚpZrpZrt)r@rÚ frozensetrVÚgenerateImpliedEndTags)rÚexcluderrrrro†s   ÿ z"TreeBuilder.generateImpliedEndTagscCs|jS)zReturn the final tree)rDr!rrrÚ getDocument�szTreeBuilder.getDocumentcCs| ¡}|jd |¡|S)zReturn the final fragmentr)Ú fragmentClassr@r,)rZfragmentrrrÚ getFragment”szTreeBuilder.getFragmentcCst‚dS)z‰Serialize the subtree of node in the format required by unit tests :arg node: the node from which to start serializing Nr#r%rrrÚtestSerializer›szTreeBuilder.testSerializer)N)N)N)N)r/r0r1r2rCrdrar_rrrr?rMrTrWrYr\r`rbrZrgrjÚpropertyrBrirhr*rkrorqrsrtrrrrr=’s6   .     r=)Z __future__rrrZpip._vendor.sixrZ constantsrrr r7rnÚsetrIÚobjectrrr3r=rrrrÚs0   ÿÿ  ÿÿ  ÿÿù cPKÒ¶N]‹ÙÔÐØ Ø Ssite-packages/pip/_vendor/html5lib/treebuilders/__pycache__/__init__.cpython-38.pycnu„[µü¤U ÀÒ.eã@s6dZddlmZmZmZddlmZiZddd„ZdS) a)A collection of modules for building different kinds of trees from HTML documents. To create a treebuilder for a new type of tree, you need to do implement several things: 1. A set of classes for various types of elements: Document, Doctype, Comment, Element. These must implement the interface of ``base.treebuilders.Node`` (although comment nodes have a different signature for their constructor, see ``treebuilders.etree.Comment``) Textual content may also be implemented as another node type, or not, as your tree implementation requires. 2. A treebuilder object (called ``TreeBuilder`` by convention) that inherits from ``treebuilders.base.TreeBuilder``. This has 4 required attributes: * ``documentClass`` - the class to use for the bottommost node of a document * ``elementClass`` - the class to use for HTML Elements * ``commentClass`` - the class to use for comments * ``doctypeClass`` - the class to use for doctypes It also has one required method: * ``getDocument`` - Returns the root node of the complete document tree 3. If you wish to run the unit tests, you must also create a ``testSerializer`` method on your treebuilder which accepts a node and returns a string containing Node and its children serialized according to the format used in the unittests é)Úabsolute_importÚdivisionÚunicode_literalsé)Ú default_etreeNcKs²| ¡}|tkr¨|dkrLddlm}|dkr>> from html5lib.treebuilders import getTreeBuilder >>> builder = getTreeBuilder('etree') Údomé)rNr)ÚminidomZlxml)Ú etree_lxmlÚetree)r zUnrecognised treebuilder "%s" )ÚlowerÚtreeBuilderCacheÚrZxml.domr Z getDomModuleZ TreeBuilderr r rZgetETreeModuleÚ ValueErrorÚget)ZtreeTypeÚimplementationÚkwargsrr r r ©rúN/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treebuilders/__init__.pyÚgetTreeBuilder's$      r)N) Ú__doc__Z __future__rrrZ_utilsrr rrrrrÚs PKÒ¶N]óÜøÐ·-·-Vsite-packages/pip/_vendor/html5lib/treebuilders/__pycache__/etree.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.eÜ1ã@s„ddlmZmZmZddlmZddlZddlmZddlm Z ddlm Z dd l m Z dd l m Z e d ¡Zdd d„Ze eƒZdS)é)Úabsolute_importÚdivisionÚunicode_literals)Ú text_typeNé)Úbaseé)Ú _ihatexml)Ú constants)Ú namespaces)ÚmoduleFactoryFactoryz {([^}]*)}(.*)Fc sºˆ‰ˆ d¡j‰G‡fdd„dtjƒ‰G‡fdd„dˆƒ‰G‡fdd„dˆƒ‰G‡fdd „d ˆƒ‰G‡fd d „d ˆƒ‰‡fd d „‰ ‡‡fdd„}G‡‡‡‡‡‡‡‡ fdd„dtjƒ}tƒS)NZasdcsÄeZdZd$‡fdd„ Zdd„Zdd„Zdd „ZeeeƒZd d „Z d d „Z ee e ƒZ dd„Z dd„Z ee e ƒZdd„Zdd„ZeeeƒZdd„Zdd„Zdd„Zdd„Zd%dd„Zd d!„Zd"d#„ZdS)&z getETreeBuilder..ElementNcs^||_||_ˆ | ||¡¡|_|dkr:td|jf|_n|j|jf|_d|_g|_g|_ dS)NÚhtml) Ú_nameÚ _namespaceÚElementÚ _getETreeTagÚ_elementr Z nameTupleÚparentÚ _childNodesÚ_flags)ÚselfÚnameÚ namespace©Ú ElementTree©úK/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treebuilders/etree.pyÚ__init__s ÿz)getETreeBuilder..Element.__init__cSs|dkr|}n d||f}|S)Nú{%s}%sr)rrrZ etree_tagrrrr#s z-getETreeBuilder..Element._getETreeTagcSs||_| |j|j¡|j_dS©N)rrrrÚtag)rrrrrÚ_setName*sz)getETreeBuilder..Element._setNamecSs|jSr)r©rrrrÚ_getName.sz)getETreeBuilder..Element._getNamecSs||_| |j|j¡|j_dSr)rrrrr )rrrrrÚ _setNamespace3sz.getETreeBuilder..Element._setNamespacecSs|jSr)rr"rrrÚ _getNamespace7sz.getETreeBuilder..Element._getNamespacecSs|jjSr)rÚattribr"rrrÚ_getAttributes<sz/getETreeBuilder..Element._getAttributescSsht|jj ¡ƒD]}|jj|=q| ¡D]:\}}t|tƒrPd|d|df}n|}|j ||¡q(dS)Nrrr)Úlistrr&ÚkeysÚitemsÚ isinstanceÚtupleÚset)rÚ attributesÚkeyÚvaluerrrrÚ_setAttributes?s  z/getETreeBuilder..Element._setAttributescSs|jSr)rr"rrrÚ_getChildNodesMsz/getETreeBuilder..Element._getChildNodescSs*|jdd…=g|_|D]}| |¡qdSr)rrZ insertChild)rr0ÚelementrrrÚ_setChildNodesPs z/getETreeBuilder..Element._setChildNodescSst|jjpt|jƒƒS)z,Return true if the node has children or text)ÚboolrÚtextÚlenr"rrrÚ hasContentXsz+getETreeBuilder..Element.hasContentcSs$|j |¡|j |j¡||_dSr)rÚappendrr©rÚnoderrrÚ appendChild\s z,getETreeBuilder..Element.appendChildcSs,t|jƒ |j¡}|j ||j¡||_dSr)r(rÚindexÚinsertr)rr;ZrefNoder=rrrÚ insertBeforeasz-getETreeBuilder..Element.insertBeforecSs$|j |¡|j |j¡d|_dSr)rÚremoverrr:rrrÚ removeChildfs z,getETreeBuilder..Element.removeChildcSsÞt|jƒs,|jjsd|j_|jj|7_n®|dkrb|jdjsLd|jd_|jdj|7_nxt|jƒ}| |j¡}|dkrº|j|djs d|j|d_|j|dj|7_n |jjsÊd|j_|jj|7_dS)NÚéÿÿÿÿrr)r7rr6Útailr(r=)rÚdatar?Zchildrenr=rrrÚ insertTextks"     z+getETreeBuilder..Element.insertTextcSs4t|ƒ|j|jƒ}|j ¡D]\}}||j|<q|Sr)Útyperrr.r*)rr3rr0rrrÚ cloneNode‚s z*getETreeBuilder..Element.cloneNodecSsl|jr"|jdjj|jj7_n0|jjs2d|j_|jjdk rR|jj|jj7_d|j_tj ||¡dS)NrCrB)Ú childNodesrrDr6rÚNodeÚreparentChildren)rZ newParentrrrrKˆs z1getETreeBuilder..Element.reparentChildren)N)N)Ú__name__Ú __module__Ú __qualname__rrr!r#Úpropertyrr$r%rr'r1r.r2r4rIr8r<r?rArFrHrKrrrrrs*      rcs2eZdZ‡fdd„Zdd„Zdd„ZeeeƒZdS)z getETreeBuilder..Commentcs"ˆ |¡|_d|_g|_g|_dSr)ÚCommentrrrr)rrErrrr”s z)getETreeBuilder..Comment.__init__cSs|jjSr©rr6r"rrrÚ_getDataœsz)getETreeBuilder..Comment._getDatacSs ||j_dSrrQ©rr0rrrÚ_setDataŸsz)getETreeBuilder..Comment._setDataN)rLrMrNrrRrTrOrErrrrrP“s rPcsLeZdZ‡fdd„Zdd„Zdd„ZeeeƒZdd„Zd d „Z eee ƒZ d S) z%getETreeBuilder..DocumentTypecs$ˆ |d¡||j_||_||_dS)Nú )rrr6ÚpublicIdÚsystemId)rrrVrW©rrrr¥s z.getETreeBuilder..DocumentType.__init__cSs|j dd¡S)NrVrB©rÚgetr"rrrÚ _getPublicId«sz2getETreeBuilder..DocumentType._getPublicIdcSs|dk r|j d|¡dS)NrV©rr-rSrrrÚ _setPublicId®sz2getETreeBuilder..DocumentType._setPublicIdcSs|j dd¡S)NrWrBrYr"rrrÚ _getSystemId´sz2getETreeBuilder..DocumentType._getSystemIdcSs|dk r|j d|¡dS)NrWr\rSrrrÚ _setSystemId·sz2getETreeBuilder..DocumentType._setSystemIdN) rLrMrNrr[r]rOrVr^r_rWrrXrrÚ DocumentType¤s  r`cseZdZ‡fdd„ZdS)z!getETreeBuilder..Documentcsˆ |d¡dS)NÚ DOCUMENT_ROOT©rr"rXrrr¾sz*getETreeBuilder..Document.__init__N©rLrMrNrrrXrrÚDocument½srdcseZdZ‡fdd„ZdS)z)getETreeBuilder..DocumentFragmentcsˆ |d¡dS)NZDOCUMENT_FRAGMENTrbr"rXrrrÂsz2getETreeBuilder..DocumentFragment.__init__NrcrrXrrÚDocumentFragmentÁsrecs*g‰d‡‡‡fdd„ ‰ˆ|dƒd ˆ¡S)Nrc snt|dƒs| ¡}|jdkrz| d¡s0| d¡rd| d¡pú raz #documentz|%s"%s"ú rúDocument node cannot have tailr&ú$Document node cannot have attributesz|%sz%s %sz|%s<%s>z |%s%s="%s")ÚhasattrÚgetrootr rZr9r6rDÚ TypeErrorr7r&Ú tag_regexpÚmatchÚgroupsr Úprefixesr*Úsorted) r3ÚindentrVrWZnsmatchrÚnsÚprefixr.r0Z attr_stringÚchild)ÚElementTreeCommentTypeÚrvÚserializeElementrrrxÈs\   ÿ                 zAgetETreeBuilder..testSerializer..serializeElementÚ )r)Újoin©r3)rv)rwrxrÚtestSerializerÅs7 z'getETreeBuilder..testSerializercs2g‰t ¡‰‡‡‡‡‡fdd„‰ˆ|ƒd ˆ¡S)z4Serialize an element and its child nodes to a stringcs¢t|ˆjƒr| ¡}|jdkr|| d¡s2| d¡rf| d¡p>d}| d¡pLd}ˆ d|j||f¡nˆ d|jf¡�n|jdkrÞ|jdk rœˆ |j¡|jdk r®tdƒ‚t |d ƒrÊt |j ƒrÊtd ƒ‚|D] }ˆ|ƒqÎn¬|jˆkrüˆ d |jf¡nŽ|j �sˆ d ˆ  |j¡f¡n2d   ‡fdd„|j  ¡Dƒ¡}ˆ d|j|f¡|j�rdˆ |j¡|D]}ˆ|ƒ�qhˆ d|jf¡|j�ržˆ |j¡dS)NrUrVrWrBzrfrarhr&riz z<%s>rgcs"g|]\}}dˆ |¡|f‘qS)z%s="%s")Ú fromXmlName)Ú.0rr0)ÚfilterrrÚ &s þÿzOgetETreeBuilder..tostring..serializeElement..z<%s %s>z)r+rrkr rZr9r6rDrlrjr7r&r}rzr*)r3rVrWruÚattr)rrvrrwrxrrrxsD   ÿ      þ  z;getETreeBuilder..tostring..serializeElementrB)r Z InfosetFilterrzr{)rrv)rrwrxrÚtostrings -z!getETreeBuilder..tostringcsDeZdZ”Z”Z”Z”Z”Z”Z‡fdd„Z ‡fdd„Z dd„Z dS)z$getETreeBuilder..TreeBuildercsˆ|ƒSrr)rr3)r|rrr|Asz3getETreeBuilder..TreeBuilder.testSerializercs<ˆr |jjS|jdk r*|jj d|j¡S|jj d¡SdS)Nz{%s}htmlr )ZdocumentrZdefaultNamespaceÚfindr")ÚfullTreerrÚ getDocumentDs ÿz0getETreeBuilder..TreeBuilder.getDocumentcSstj |¡jSr)rÚ TreeBuilderÚ getFragmentrr"rrrr‡Nsz0getETreeBuilder..TreeBuilder.getFragmentN) rLrMrNZ documentClassZ doctypeClassZ elementClassZ commentClassZ fragmentClassÚimplementationr|r…r‡r)rPrdrer`rÚElementTreeImplementationr„r|rrr†9s  r†)rPr rrJr†Úlocals)r‰r„r‚r†r) rPrdrer`rrrvr‰r„r|rÚgetETreeBuilders ~ >6$r‹)F)Z __future__rrrZpip._vendor.sixrÚrerBrr r r Z_utilsr Úcompilermr‹ZgetETreeModulerrrrÚs        EPKÒ¶N]wý . .Psite-packages/pip/_vendor/html5lib/treebuilders/__pycache__/etree.cpython-38.pycnu„[µü¤U ÀÒ.eÜ1ã@s„ddlmZmZmZddlmZddlZddlmZddlm Z ddlm Z dd l m Z dd l m Z e d ¡Zdd d„Ze eƒZdS)é)Úabsolute_importÚdivisionÚunicode_literals)Ú text_typeNé)Úbaseé)Ú _ihatexml)Ú constants)Ú namespaces)ÚmoduleFactoryFactoryz {([^}]*)}(.*)Fc sºˆ‰ˆ d¡j‰G‡fdd„dtjƒ‰G‡fdd„dˆƒ‰G‡fdd„dˆƒ‰G‡fdd „d ˆƒ‰G‡fd d „d ˆƒ‰‡fd d „‰ ‡‡fdd„}G‡‡‡‡‡‡‡‡ fdd„dtjƒ}tƒS)NZasdcsÄeZdZd$‡fdd„ Zdd„Zdd„Zdd „ZeeeƒZd d „Z d d „Z ee e ƒZ dd„Z dd„Z ee e ƒZdd„Zdd„ZeeeƒZdd„Zdd„Zdd„Zdd„Zd%dd„Zd d!„Zd"d#„ZdS)&z getETreeBuilder..ElementNcs^||_||_ˆ | ||¡¡|_|dkr:td|jf|_n|j|jf|_d|_g|_g|_ dS)NÚhtml) Ú_nameÚ _namespaceÚElementÚ _getETreeTagÚ_elementr Z nameTupleÚparentÚ _childNodesÚ_flags)ÚselfÚnameÚ namespace©Ú ElementTree©úK/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treebuilders/etree.pyÚ__init__s ÿz)getETreeBuilder..Element.__init__cSs|dkr|}n d||f}|S)Nú{%s}%sr)rrrZ etree_tagrrrr#s z-getETreeBuilder..Element._getETreeTagcSs||_| |j|j¡|j_dS©N)rrrrÚtag)rrrrrÚ_setName*sz)getETreeBuilder..Element._setNamecSs|jSr)r©rrrrÚ_getName.sz)getETreeBuilder..Element._getNamecSs||_| |j|j¡|j_dSr)rrrrr )rrrrrÚ _setNamespace3sz.getETreeBuilder..Element._setNamespacecSs|jSr)rr"rrrÚ _getNamespace7sz.getETreeBuilder..Element._getNamespacecSs|jjSr)rÚattribr"rrrÚ_getAttributes<sz/getETreeBuilder..Element._getAttributescSsht|jj ¡ƒD]}|jj|=q| ¡D]:\}}t|tƒrPd|d|df}n|}|j ||¡q(dS)Nrrr)Úlistrr&ÚkeysÚitemsÚ isinstanceÚtupleÚset)rÚ attributesÚkeyÚvaluerrrrÚ_setAttributes?s  z/getETreeBuilder..Element._setAttributescSs|jSr)rr"rrrÚ_getChildNodesMsz/getETreeBuilder..Element._getChildNodescSs*|jdd…=g|_|D]}| |¡qdSr)rrZ insertChild)rr0ÚelementrrrÚ_setChildNodesPs z/getETreeBuilder..Element._setChildNodescSst|jjpt|jƒƒS)z,Return true if the node has children or text)ÚboolrÚtextÚlenr"rrrÚ hasContentXsz+getETreeBuilder..Element.hasContentcSs$|j |¡|j |j¡||_dSr)rÚappendrr©rÚnoderrrÚ appendChild\s z,getETreeBuilder..Element.appendChildcSs,t|jƒ |j¡}|j ||j¡||_dSr)r(rÚindexÚinsertr)rr;ZrefNoder=rrrÚ insertBeforeasz-getETreeBuilder..Element.insertBeforecSs$|j |¡|j |j¡d|_dSr)rÚremoverrr:rrrÚ removeChildfs z,getETreeBuilder..Element.removeChildcSsÞt|jƒs,|jjsd|j_|jj|7_n®|dkrb|jdjsLd|jd_|jdj|7_nxt|jƒ}| |j¡}|dkrº|j|djs d|j|d_|j|dj|7_n |jjsÊd|j_|jj|7_dS)NÚéÿÿÿÿrr)r7rr6Útailr(r=)rÚdatar?Zchildrenr=rrrÚ insertTextks"     z+getETreeBuilder..Element.insertTextcSs4t|ƒ|j|jƒ}|j ¡D]\}}||j|<q|Sr)Útyperrr.r*)rr3rr0rrrÚ cloneNode‚s z*getETreeBuilder..Element.cloneNodecSsl|jr"|jdjj|jj7_n0|jjs2d|j_|jjdk rR|jj|jj7_d|j_tj ||¡dS)NrCrB)Ú childNodesrrDr6rÚNodeÚreparentChildren)rZ newParentrrrrKˆs z1getETreeBuilder..Element.reparentChildren)N)N)Ú__name__Ú __module__Ú __qualname__rrr!r#Úpropertyrr$r%rr'r1r.r2r4rIr8r<r?rArFrHrKrrrrrs*      rcs2eZdZ‡fdd„Zdd„Zdd„ZeeeƒZdS)z getETreeBuilder..Commentcs"ˆ |¡|_d|_g|_g|_dSr)ÚCommentrrrr)rrErrrr”s z)getETreeBuilder..Comment.__init__cSs|jjSr©rr6r"rrrÚ_getDataœsz)getETreeBuilder..Comment._getDatacSs ||j_dSrrQ©rr0rrrÚ_setDataŸsz)getETreeBuilder..Comment._setDataN)rLrMrNrrRrTrOrErrrrrP“s rPcsLeZdZ‡fdd„Zdd„Zdd„ZeeeƒZdd„Zd d „Z eee ƒZ d S) z%getETreeBuilder..DocumentTypecs$ˆ |d¡||j_||_||_dS)Nú )rrr6ÚpublicIdÚsystemId)rrrVrW©rrrr¥s z.getETreeBuilder..DocumentType.__init__cSs|j dd¡S)NrVrB©rÚgetr"rrrÚ _getPublicId«sz2getETreeBuilder..DocumentType._getPublicIdcSs|dk r|j d|¡dS)NrV©rr-rSrrrÚ _setPublicId®sz2getETreeBuilder..DocumentType._setPublicIdcSs|j dd¡S)NrWrBrYr"rrrÚ _getSystemId´sz2getETreeBuilder..DocumentType._getSystemIdcSs|dk r|j d|¡dS)NrWr\rSrrrÚ _setSystemId·sz2getETreeBuilder..DocumentType._setSystemIdN) rLrMrNrr[r]rOrVr^r_rWrrXrrÚ DocumentType¤s  r`cseZdZ‡fdd„ZdS)z!getETreeBuilder..Documentcsˆ |d¡dS)NÚ DOCUMENT_ROOT©rr"rXrrr¾sz*getETreeBuilder..Document.__init__N©rLrMrNrrrXrrÚDocument½srdcseZdZ‡fdd„ZdS)z)getETreeBuilder..DocumentFragmentcsˆ |d¡dS)NZDOCUMENT_FRAGMENTrbr"rXrrrÂsz2getETreeBuilder..DocumentFragment.__init__NrcrrXrrÚDocumentFragmentÁsrecs*g‰d‡‡‡fdd„ ‰ˆ|dƒd ˆ¡S)Nrc s”t|dƒs| ¡}|jdkrz| d¡s0| d¡rd| d¡pú raz #documentz|%s"%s"ú rúDocument node cannot have tailr&ú$Document node cannot have attributesz|%szExpected unicode, got %s, %sz%s %sz|%s<%s>z |%s%s="%s")ÚhasattrÚgetrootr rZr9r6rDÚ TypeErrorr7r&r+rÚAssertionErrorrGÚ tag_regexpÚmatchÚgroupsr Úprefixesr*Úsorted) r3ÚindentrVrWZnsmatchrÚnsÚprefixr.r0Z attr_stringÚchild)ÚElementTreeCommentTypeÚrvÚserializeElementrrryÈsb   ÿ      ÿ           zAgetETreeBuilder..testSerializer..serializeElementÚ )r)Újoin©r3)rw)rxryrÚtestSerializerÅs7 z'getETreeBuilder..testSerializercs2g‰t ¡‰‡‡‡‡‡fdd„‰ˆ|ƒd ˆ¡S)z4Serialize an element and its child nodes to a stringcs¢t|ˆjƒr| ¡}|jdkr|| d¡s2| d¡rf| d¡p>d}| d¡pLd}ˆ d|j||f¡nˆ d|jf¡�n|jdkrÞ|jdk rœˆ |j¡|jdk r®tdƒ‚t |d ƒrÊt |j ƒrÊtd ƒ‚|D] }ˆ|ƒqÎn¬|jˆkrüˆ d |jf¡nŽ|j �sˆ d ˆ  |j¡f¡n2d   ‡fdd„|j  ¡Dƒ¡}ˆ d|j|f¡|j�rdˆ |j¡|D]}ˆ|ƒ�qhˆ d|jf¡|j�ržˆ |j¡dS)NrUrVrWrBzrfrarhr&riz z<%s>rgcs"g|]\}}dˆ |¡|f‘qS)z%s="%s")Ú fromXmlName)Ú.0rr0)ÚfilterrrÚ &s þÿzOgetETreeBuilder..tostring..serializeElement..z<%s %s>z)r+rrkr rZr9r6rDrlrjr7r&r~r{r*)r3rVrWrvÚattr)rrwr€rxryrrrysD   ÿ      þ  z;getETreeBuilder..tostring..serializeElementrB)r Z InfosetFilterr{r|)rrw)r€rxryrÚtostrings -z!getETreeBuilder..tostringcsDeZdZ”Z”Z”Z”Z”Z”Z‡fdd„Z ‡fdd„Z dd„Z dS)z$getETreeBuilder..TreeBuildercsˆ|ƒSrr)rr3)r}rrr}Asz3getETreeBuilder..TreeBuilder.testSerializercs<ˆr |jjS|jdk r*|jj d|j¡S|jj d¡SdS)Nz{%s}htmlr )ZdocumentrZdefaultNamespaceÚfindr")ÚfullTreerrÚ getDocumentDs ÿz0getETreeBuilder..TreeBuilder.getDocumentcSstj |¡jSr)rÚ TreeBuilderÚ getFragmentrr"rrrrˆNsz0getETreeBuilder..TreeBuilder.getFragmentN) rLrMrNZ documentClassZ doctypeClassZ elementClassZ commentClassZ fragmentClassÚimplementationr}r†rˆr)rPrdrer`rÚElementTreeImplementationr…r}rrr‡9s  r‡)rPr rrJr‡Úlocals)rŠr…rƒr‡r) rPrdrer`rrrwrŠr…r}rÚgetETreeBuilders ~ >6$rŒ)F)Z __future__rrrZpip._vendor.sixrÚrerBrr r r Z_utilsr ÚcompilernrŒZgetETreeModulerrrrÚs        EPKÒ¶N]¡}—ðÜ1Ü18site-packages/pip/_vendor/html5lib/treebuilders/etree.pynu„[µü¤from __future__ import absolute_import, division, unicode_literals # pylint:disable=protected-access from pip._vendor.six import text_type import re from . import base from .. import _ihatexml from .. import constants from ..constants import namespaces from .._utils import moduleFactoryFactory tag_regexp = re.compile("{([^}]*)}(.*)") def getETreeBuilder(ElementTreeImplementation, fullTree=False): ElementTree = ElementTreeImplementation ElementTreeCommentType = ElementTree.Comment("asd").tag class Element(base.Node): def __init__(self, name, namespace=None): self._name = name self._namespace = namespace self._element = ElementTree.Element(self._getETreeTag(name, namespace)) if namespace is None: self.nameTuple = namespaces["html"], self._name else: self.nameTuple = self._namespace, self._name self.parent = None self._childNodes = [] self._flags = [] def _getETreeTag(self, name, namespace): if namespace is None: etree_tag = name else: etree_tag = "{%s}%s" % (namespace, name) return etree_tag def _setName(self, name): self._name = name self._element.tag = self._getETreeTag(self._name, self._namespace) def _getName(self): return self._name name = property(_getName, _setName) def _setNamespace(self, namespace): self._namespace = namespace self._element.tag = self._getETreeTag(self._name, self._namespace) def _getNamespace(self): return self._namespace namespace = property(_getNamespace, _setNamespace) def _getAttributes(self): return self._element.attrib def _setAttributes(self, attributes): # Delete existing attributes first # XXX - there may be a better way to do this... for key in list(self._element.attrib.keys()): del self._element.attrib[key] for key, value in attributes.items(): if isinstance(key, tuple): name = "{%s}%s" % (key[2], key[1]) else: name = key self._element.set(name, value) attributes = property(_getAttributes, _setAttributes) def _getChildNodes(self): return self._childNodes def _setChildNodes(self, value): del self._element[:] self._childNodes = [] for element in value: self.insertChild(element) childNodes = property(_getChildNodes, _setChildNodes) def hasContent(self): """Return true if the node has children or text""" return bool(self._element.text or len(self._element)) def appendChild(self, node): self._childNodes.append(node) self._element.append(node._element) node.parent = self def insertBefore(self, node, refNode): index = list(self._element).index(refNode._element) self._element.insert(index, node._element) node.parent = self def removeChild(self, node): self._childNodes.remove(node) self._element.remove(node._element) node.parent = None def insertText(self, data, insertBefore=None): if not(len(self._element)): if not self._element.text: self._element.text = "" self._element.text += data elif insertBefore is None: # Insert the text as the tail of the last child element if not self._element[-1].tail: self._element[-1].tail = "" self._element[-1].tail += data else: # Insert the text before the specified node children = list(self._element) index = children.index(insertBefore._element) if index > 0: if not self._element[index - 1].tail: self._element[index - 1].tail = "" self._element[index - 1].tail += data else: if not self._element.text: self._element.text = "" self._element.text += data def cloneNode(self): element = type(self)(self.name, self.namespace) for name, value in self.attributes.items(): element.attributes[name] = value return element def reparentChildren(self, newParent): if newParent.childNodes: newParent.childNodes[-1]._element.tail += self._element.text else: if not newParent._element.text: newParent._element.text = "" if self._element.text is not None: newParent._element.text += self._element.text self._element.text = "" base.Node.reparentChildren(self, newParent) class Comment(Element): def __init__(self, data): # Use the superclass constructor to set all properties on the # wrapper element self._element = ElementTree.Comment(data) self.parent = None self._childNodes = [] self._flags = [] def _getData(self): return self._element.text def _setData(self, value): self._element.text = value data = property(_getData, _setData) class DocumentType(Element): def __init__(self, name, publicId, systemId): Element.__init__(self, "") self._element.text = name self.publicId = publicId self.systemId = systemId def _getPublicId(self): return self._element.get("publicId", "") def _setPublicId(self, value): if value is not None: self._element.set("publicId", value) publicId = property(_getPublicId, _setPublicId) def _getSystemId(self): return self._element.get("systemId", "") def _setSystemId(self, value): if value is not None: self._element.set("systemId", value) systemId = property(_getSystemId, _setSystemId) class Document(Element): def __init__(self): Element.__init__(self, "DOCUMENT_ROOT") class DocumentFragment(Element): def __init__(self): Element.__init__(self, "DOCUMENT_FRAGMENT") def testSerializer(element): rv = [] def serializeElement(element, indent=0): if not(hasattr(element, "tag")): element = element.getroot() if element.tag == "": if element.get("publicId") or element.get("systemId"): publicId = element.get("publicId") or "" systemId = element.get("systemId") or "" rv.append("""""" % (element.text, publicId, systemId)) else: rv.append("" % (element.text,)) elif element.tag == "DOCUMENT_ROOT": rv.append("#document") if element.text is not None: rv.append("|%s\"%s\"" % (' ' * (indent + 2), element.text)) if element.tail is not None: raise TypeError("Document node cannot have tail") if hasattr(element, "attrib") and len(element.attrib): raise TypeError("Document node cannot have attributes") elif element.tag == ElementTreeCommentType: rv.append("|%s" % (' ' * indent, element.text)) else: assert isinstance(element.tag, text_type), \ "Expected unicode, got %s, %s" % (type(element.tag), element.tag) nsmatch = tag_regexp.match(element.tag) if nsmatch is None: name = element.tag else: ns, name = nsmatch.groups() prefix = constants.prefixes[ns] name = "%s %s" % (prefix, name) rv.append("|%s<%s>" % (' ' * indent, name)) if hasattr(element, "attrib"): attributes = [] for name, value in element.attrib.items(): nsmatch = tag_regexp.match(name) if nsmatch is not None: ns, name = nsmatch.groups() prefix = constants.prefixes[ns] attr_string = "%s %s" % (prefix, name) else: attr_string = name attributes.append((attr_string, value)) for name, value in sorted(attributes): rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value)) if element.text: rv.append("|%s\"%s\"" % (' ' * (indent + 2), element.text)) indent += 2 for child in element: serializeElement(child, indent) if element.tail: rv.append("|%s\"%s\"" % (' ' * (indent - 2), element.tail)) serializeElement(element, 0) return "\n".join(rv) def tostring(element): # pylint:disable=unused-variable """Serialize an element and its child nodes to a string""" rv = [] filter = _ihatexml.InfosetFilter() def serializeElement(element): if isinstance(element, ElementTree.ElementTree): element = element.getroot() if element.tag == "": if element.get("publicId") or element.get("systemId"): publicId = element.get("publicId") or "" systemId = element.get("systemId") or "" rv.append("""""" % (element.text, publicId, systemId)) else: rv.append("" % (element.text,)) elif element.tag == "DOCUMENT_ROOT": if element.text is not None: rv.append(element.text) if element.tail is not None: raise TypeError("Document node cannot have tail") if hasattr(element, "attrib") and len(element.attrib): raise TypeError("Document node cannot have attributes") for child in element: serializeElement(child) elif element.tag == ElementTreeCommentType: rv.append("" % (element.text,)) else: # This is assumed to be an ordinary element if not element.attrib: rv.append("<%s>" % (filter.fromXmlName(element.tag),)) else: attr = " ".join(["%s=\"%s\"" % ( filter.fromXmlName(name), value) for name, value in element.attrib.items()]) rv.append("<%s %s>" % (element.tag, attr)) if element.text: rv.append(element.text) for child in element: serializeElement(child) rv.append("" % (element.tag,)) if element.tail: rv.append(element.tail) serializeElement(element) return "".join(rv) class TreeBuilder(base.TreeBuilder): # pylint:disable=unused-variable documentClass = Document doctypeClass = DocumentType elementClass = Element commentClass = Comment fragmentClass = DocumentFragment implementation = ElementTreeImplementation def testSerializer(self, element): return testSerializer(element) def getDocument(self): if fullTree: return self.document._element else: if self.defaultNamespace is not None: return self.document._element.find( "{%s}html" % self.defaultNamespace) else: return self.document._element.find("html") def getFragment(self): return base.TreeBuilder.getFragment(self)._element return locals() getETreeModule = moduleFactoryFactory(getETreeBuilder) PKÒ¶N]ÄÕ¢¬ó8ó87site-packages/pip/_vendor/html5lib/treebuilders/base.pynu„[µü¤from __future__ import absolute_import, division, unicode_literals from pip._vendor.six import text_type from ..constants import scopingElements, tableInsertModeElements, namespaces # The scope markers are inserted when entering object elements, # marquees, table cells, and table captions, and are used to prevent formatting # from "leaking" into tables, object elements, and marquees. Marker = None listElementsMap = { None: (frozenset(scopingElements), False), "button": (frozenset(scopingElements | set([(namespaces["html"], "button")])), False), "list": (frozenset(scopingElements | set([(namespaces["html"], "ol"), (namespaces["html"], "ul")])), False), "table": (frozenset([(namespaces["html"], "html"), (namespaces["html"], "table")]), False), "select": (frozenset([(namespaces["html"], "optgroup"), (namespaces["html"], "option")]), True) } class Node(object): """Represents an item in the tree""" def __init__(self, name): """Creates a Node :arg name: The tag name associated with the node """ # The tag name assocaited with the node self.name = name # The parent of the current node (or None for the document node) self.parent = None # The value of the current node (applies to text nodes and comments) self.value = None # A dict holding name -> value pairs for attributes of the node self.attributes = {} # A list of child nodes of the current node. This must include all # elements but not necessarily other node types. self.childNodes = [] # A list of miscellaneous flags that can be set on the node. self._flags = [] def __str__(self): attributesStr = " ".join(["%s=\"%s\"" % (name, value) for name, value in self.attributes.items()]) if attributesStr: return "<%s %s>" % (self.name, attributesStr) else: return "<%s>" % (self.name) def __repr__(self): return "<%s>" % (self.name) def appendChild(self, node): """Insert node as a child of the current node :arg node: the node to insert """ raise NotImplementedError def insertText(self, data, insertBefore=None): """Insert data as text in the current node, positioned before the start of node insertBefore or to the end of the node's text. :arg data: the data to insert :arg insertBefore: True if you want to insert the text before the node and False if you want to insert it after the node """ raise NotImplementedError def insertBefore(self, node, refNode): """Insert node as a child of the current node, before refNode in the list of child nodes. Raises ValueError if refNode is not a child of the current node :arg node: the node to insert :arg refNode: the child node to insert the node before """ raise NotImplementedError def removeChild(self, node): """Remove node from the children of the current node :arg node: the child node to remove """ raise NotImplementedError def reparentChildren(self, newParent): """Move all the children of the current node to newParent. This is needed so that trees that don't store text as nodes move the text in the correct way :arg newParent: the node to move all this node's children to """ # XXX - should this method be made more general? for child in self.childNodes: newParent.appendChild(child) self.childNodes = [] def cloneNode(self): """Return a shallow copy of the current node i.e. a node with the same name and attributes but with no parent or child nodes """ raise NotImplementedError def hasContent(self): """Return true if the node has children or text, false otherwise """ raise NotImplementedError class ActiveFormattingElements(list): def append(self, node): equalCount = 0 if node != Marker: for element in self[::-1]: if element == Marker: break if self.nodesEqual(element, node): equalCount += 1 if equalCount == 3: self.remove(element) break list.append(self, node) def nodesEqual(self, node1, node2): if not node1.nameTuple == node2.nameTuple: return False if not node1.attributes == node2.attributes: return False return True class TreeBuilder(object): """Base treebuilder implementation * documentClass - the class to use for the bottommost node of a document * elementClass - the class to use for HTML Elements * commentClass - the class to use for comments * doctypeClass - the class to use for doctypes """ # pylint:disable=not-callable # Document class documentClass = None # The class to use for creating a node elementClass = None # The class to use for creating comments commentClass = None # The class to use for creating doctypes doctypeClass = None # Fragment class fragmentClass = None def __init__(self, namespaceHTMLElements): """Create a TreeBuilder :arg namespaceHTMLElements: whether or not to namespace HTML elements """ if namespaceHTMLElements: self.defaultNamespace = "http://www.w3.org/1999/xhtml" else: self.defaultNamespace = None self.reset() def reset(self): self.openElements = [] self.activeFormattingElements = ActiveFormattingElements() # XXX - rename these to headElement, formElement self.headPointer = None self.formPointer = None self.insertFromTable = False self.document = self.documentClass() def elementInScope(self, target, variant=None): # If we pass a node in we match that. if we pass a string # match any node with that name exactNode = hasattr(target, "nameTuple") if not exactNode: if isinstance(target, text_type): target = (namespaces["html"], target) assert isinstance(target, tuple) listElements, invert = listElementsMap[variant] for node in reversed(self.openElements): if exactNode and node == target: return True elif not exactNode and node.nameTuple == target: return True elif (invert ^ (node.nameTuple in listElements)): return False assert False # We should never reach this point def reconstructActiveFormattingElements(self): # Within this algorithm the order of steps described in the # specification is not quite the same as the order of steps in the # code. It should still do the same though. # Step 1: stop the algorithm when there's nothing to do. if not self.activeFormattingElements: return # Step 2 and step 3: we start with the last element. So i is -1. i = len(self.activeFormattingElements) - 1 entry = self.activeFormattingElements[i] if entry == Marker or entry in self.openElements: return # Step 6 while entry != Marker and entry not in self.openElements: if i == 0: # This will be reset to 0 below i = -1 break i -= 1 # Step 5: let entry be one earlier in the list. entry = self.activeFormattingElements[i] while True: # Step 7 i += 1 # Step 8 entry = self.activeFormattingElements[i] clone = entry.cloneNode() # Mainly to get a new copy of the attributes # Step 9 element = self.insertElement({"type": "StartTag", "name": clone.name, "namespace": clone.namespace, "data": clone.attributes}) # Step 10 self.activeFormattingElements[i] = element # Step 11 if element == self.activeFormattingElements[-1]: break def clearActiveFormattingElements(self): entry = self.activeFormattingElements.pop() while self.activeFormattingElements and entry != Marker: entry = self.activeFormattingElements.pop() def elementInActiveFormattingElements(self, name): """Check if an element exists between the end of the active formatting elements and the last marker. If it does, return it, else return false""" for item in self.activeFormattingElements[::-1]: # Check for Marker first because if it's a Marker it doesn't have a # name attribute. if item == Marker: break elif item.name == name: return item return False def insertRoot(self, token): element = self.createElement(token) self.openElements.append(element) self.document.appendChild(element) def insertDoctype(self, token): name = token["name"] publicId = token["publicId"] systemId = token["systemId"] doctype = self.doctypeClass(name, publicId, systemId) self.document.appendChild(doctype) def insertComment(self, token, parent=None): if parent is None: parent = self.openElements[-1] parent.appendChild(self.commentClass(token["data"])) def createElement(self, token): """Create an element but don't insert it anywhere""" name = token["name"] namespace = token.get("namespace", self.defaultNamespace) element = self.elementClass(name, namespace) element.attributes = token["data"] return element def _getInsertFromTable(self): return self._insertFromTable def _setInsertFromTable(self, value): """Switch the function used to insert an element from the normal one to the misnested table one and back again""" self._insertFromTable = value if value: self.insertElement = self.insertElementTable else: self.insertElement = self.insertElementNormal insertFromTable = property(_getInsertFromTable, _setInsertFromTable) def insertElementNormal(self, token): name = token["name"] assert isinstance(name, text_type), "Element %s not unicode" % name namespace = token.get("namespace", self.defaultNamespace) element = self.elementClass(name, namespace) element.attributes = token["data"] self.openElements[-1].appendChild(element) self.openElements.append(element) return element def insertElementTable(self, token): """Create an element and insert it into the tree""" element = self.createElement(token) if self.openElements[-1].name not in tableInsertModeElements: return self.insertElementNormal(token) else: # We should be in the InTable mode. This means we want to do # special magic element rearranging parent, insertBefore = self.getTableMisnestedNodePosition() if insertBefore is None: parent.appendChild(element) else: parent.insertBefore(element, insertBefore) self.openElements.append(element) return element def insertText(self, data, parent=None): """Insert text data.""" if parent is None: parent = self.openElements[-1] if (not self.insertFromTable or (self.insertFromTable and self.openElements[-1].name not in tableInsertModeElements)): parent.insertText(data) else: # We should be in the InTable mode. This means we want to do # special magic element rearranging parent, insertBefore = self.getTableMisnestedNodePosition() parent.insertText(data, insertBefore) def getTableMisnestedNodePosition(self): """Get the foster parent element, and sibling to insert before (or None) when inserting a misnested table node""" # The foster parent element is the one which comes before the most # recently opened table element # XXX - this is really inelegant lastTable = None fosterParent = None insertBefore = None for elm in self.openElements[::-1]: if elm.name == "table": lastTable = elm break if lastTable: # XXX - we should really check that this parent is actually a # node here if lastTable.parent: fosterParent = lastTable.parent insertBefore = lastTable else: fosterParent = self.openElements[ self.openElements.index(lastTable) - 1] else: fosterParent = self.openElements[0] return fosterParent, insertBefore def generateImpliedEndTags(self, exclude=None): name = self.openElements[-1].name # XXX td, th and tr are not actually needed if (name in frozenset(("dd", "dt", "li", "option", "optgroup", "p", "rp", "rt")) and name != exclude): self.openElements.pop() # XXX This is not entirely what the specification says. We should # investigate it more closely. self.generateImpliedEndTags(exclude) def getDocument(self): """Return the final tree""" return self.document def getFragment(self): """Return the final fragment""" # assert self.innerHTML fragment = self.fragmentClass() self.openElements[0].reparentChildren(fragment) return fragment def testSerializer(self, node): """Serialize the subtree of node in the format required by unit tests :arg node: the node from which to start serializing """ raise NotImplementedError PKÒ¶N]Oê·*7*7=site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.pynu„[µü¤"""Module for supporting the lxml.etree library. The idea here is to use as much of the native library as possible, without using fragile hacks like custom element names that break between releases. The downside of this is that we cannot represent all possible trees; specifically the following are known to cause problems: Text or comments as siblings of the root element Docypes with no name When any of these things occur, we emit a DataLossWarning """ from __future__ import absolute_import, division, unicode_literals # pylint:disable=protected-access import warnings import re import sys from . import base from ..constants import DataLossWarning from .. import constants from . import etree as etree_builders from .. import _ihatexml import lxml.etree as etree fullTree = True tag_regexp = re.compile("{([^}]*)}(.*)") comment_type = etree.Comment("asd").tag class DocumentType(object): def __init__(self, name, publicId, systemId): self.name = name self.publicId = publicId self.systemId = systemId class Document(object): def __init__(self): self._elementTree = None self._childNodes = [] def appendChild(self, element): self._elementTree.getroot().addnext(element._element) def _getChildNodes(self): return self._childNodes childNodes = property(_getChildNodes) def testSerializer(element): rv = [] infosetFilter = _ihatexml.InfosetFilter(preventDoubleDashComments=True) def serializeElement(element, indent=0): if not hasattr(element, "tag"): if hasattr(element, "getroot"): # Full tree case rv.append("#document") if element.docinfo.internalDTD: if not (element.docinfo.public_id or element.docinfo.system_url): dtd_str = "" % element.docinfo.root_name else: dtd_str = """""" % ( element.docinfo.root_name, element.docinfo.public_id, element.docinfo.system_url) rv.append("|%s%s" % (' ' * (indent + 2), dtd_str)) next_element = element.getroot() while next_element.getprevious() is not None: next_element = next_element.getprevious() while next_element is not None: serializeElement(next_element, indent + 2) next_element = next_element.getnext() elif isinstance(element, str) or isinstance(element, bytes): # Text in a fragment assert isinstance(element, str) or sys.version_info[0] == 2 rv.append("|%s\"%s\"" % (' ' * indent, element)) else: # Fragment case rv.append("#document-fragment") for next_element in element: serializeElement(next_element, indent + 2) elif element.tag == comment_type: rv.append("|%s" % (' ' * indent, element.text)) if hasattr(element, "tail") and element.tail: rv.append("|%s\"%s\"" % (' ' * indent, element.tail)) else: assert isinstance(element, etree._Element) nsmatch = etree_builders.tag_regexp.match(element.tag) if nsmatch is not None: ns = nsmatch.group(1) tag = nsmatch.group(2) prefix = constants.prefixes[ns] rv.append("|%s<%s %s>" % (' ' * indent, prefix, infosetFilter.fromXmlName(tag))) else: rv.append("|%s<%s>" % (' ' * indent, infosetFilter.fromXmlName(element.tag))) if hasattr(element, "attrib"): attributes = [] for name, value in element.attrib.items(): nsmatch = tag_regexp.match(name) if nsmatch is not None: ns, name = nsmatch.groups() name = infosetFilter.fromXmlName(name) prefix = constants.prefixes[ns] attr_string = "%s %s" % (prefix, name) else: attr_string = infosetFilter.fromXmlName(name) attributes.append((attr_string, value)) for name, value in sorted(attributes): rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value)) if element.text: rv.append("|%s\"%s\"" % (' ' * (indent + 2), element.text)) indent += 2 for child in element: serializeElement(child, indent) if hasattr(element, "tail") and element.tail: rv.append("|%s\"%s\"" % (' ' * (indent - 2), element.tail)) serializeElement(element, 0) return "\n".join(rv) def tostring(element): """Serialize an element and its child nodes to a string""" rv = [] def serializeElement(element): if not hasattr(element, "tag"): if element.docinfo.internalDTD: if element.docinfo.doctype: dtd_str = element.docinfo.doctype else: dtd_str = "" % element.docinfo.root_name rv.append(dtd_str) serializeElement(element.getroot()) elif element.tag == comment_type: rv.append("" % (element.text,)) else: # This is assumed to be an ordinary element if not element.attrib: rv.append("<%s>" % (element.tag,)) else: attr = " ".join(["%s=\"%s\"" % (name, value) for name, value in element.attrib.items()]) rv.append("<%s %s>" % (element.tag, attr)) if element.text: rv.append(element.text) for child in element: serializeElement(child) rv.append("" % (element.tag,)) if hasattr(element, "tail") and element.tail: rv.append(element.tail) serializeElement(element) return "".join(rv) class TreeBuilder(base.TreeBuilder): documentClass = Document doctypeClass = DocumentType elementClass = None commentClass = None fragmentClass = Document implementation = etree def __init__(self, namespaceHTMLElements, fullTree=False): builder = etree_builders.getETreeModule(etree, fullTree=fullTree) infosetFilter = self.infosetFilter = _ihatexml.InfosetFilter(preventDoubleDashComments=True) self.namespaceHTMLElements = namespaceHTMLElements class Attributes(dict): def __init__(self, element, value=None): if value is None: value = {} self._element = element dict.__init__(self, value) # pylint:disable=non-parent-init-called for key, value in self.items(): if isinstance(key, tuple): name = "{%s}%s" % (key[2], infosetFilter.coerceAttribute(key[1])) else: name = infosetFilter.coerceAttribute(key) self._element._element.attrib[name] = value def __setitem__(self, key, value): dict.__setitem__(self, key, value) if isinstance(key, tuple): name = "{%s}%s" % (key[2], infosetFilter.coerceAttribute(key[1])) else: name = infosetFilter.coerceAttribute(key) self._element._element.attrib[name] = value class Element(builder.Element): def __init__(self, name, namespace): name = infosetFilter.coerceElement(name) builder.Element.__init__(self, name, namespace=namespace) self._attributes = Attributes(self) def _setName(self, name): self._name = infosetFilter.coerceElement(name) self._element.tag = self._getETreeTag( self._name, self._namespace) def _getName(self): return infosetFilter.fromXmlName(self._name) name = property(_getName, _setName) def _getAttributes(self): return self._attributes def _setAttributes(self, attributes): self._attributes = Attributes(self, attributes) attributes = property(_getAttributes, _setAttributes) def insertText(self, data, insertBefore=None): data = infosetFilter.coerceCharacters(data) builder.Element.insertText(self, data, insertBefore) def appendChild(self, child): builder.Element.appendChild(self, child) class Comment(builder.Comment): def __init__(self, data): data = infosetFilter.coerceComment(data) builder.Comment.__init__(self, data) def _setData(self, data): data = infosetFilter.coerceComment(data) self._element.text = data def _getData(self): return self._element.text data = property(_getData, _setData) self.elementClass = Element self.commentClass = Comment # self.fragmentClass = builder.DocumentFragment base.TreeBuilder.__init__(self, namespaceHTMLElements) def reset(self): base.TreeBuilder.reset(self) self.insertComment = self.insertCommentInitial self.initial_comments = [] self.doctype = None def testSerializer(self, element): return testSerializer(element) def getDocument(self): if fullTree: return self.document._elementTree else: return self.document._elementTree.getroot() def getFragment(self): fragment = [] element = self.openElements[0]._element if element.text: fragment.append(element.text) fragment.extend(list(element)) if element.tail: fragment.append(element.tail) return fragment def insertDoctype(self, token): name = token["name"] publicId = token["publicId"] systemId = token["systemId"] if not name: warnings.warn("lxml cannot represent empty doctype", DataLossWarning) self.doctype = None else: coercedName = self.infosetFilter.coerceElement(name) if coercedName != name: warnings.warn("lxml cannot represent non-xml doctype", DataLossWarning) doctype = self.doctypeClass(coercedName, publicId, systemId) self.doctype = doctype def insertCommentInitial(self, data, parent=None): assert parent is None or parent is self.document assert self.document._elementTree is None self.initial_comments.append(data) def insertCommentMain(self, data, parent=None): if (parent == self.document and self.document._elementTree.getroot()[-1].tag == comment_type): warnings.warn("lxml cannot represent adjacent comments beyond the root elements", DataLossWarning) super(TreeBuilder, self).insertComment(data, parent) def insertRoot(self, token): # Because of the way libxml2 works, it doesn't seem to be possible to # alter information like the doctype after the tree has been parsed. # Therefore we need to use the built-in parser to create our initial # tree, after which we can add elements like normal docStr = "" if self.doctype: assert self.doctype.name docStr += "= 0 and sysid.find('"') >= 0: warnings.warn("DOCTYPE system cannot contain single and double quotes", DataLossWarning) sysid = sysid.replace("'", 'U00027') if sysid.find("'") >= 0: docStr += '"%s"' % sysid else: docStr += "'%s'" % sysid else: docStr += "''" docStr += ">" if self.doctype.name != token["name"]: warnings.warn("lxml cannot represent doctype with a different name to the root element", DataLossWarning) docStr += "" root = etree.fromstring(docStr) # Append the initial comments: for comment_token in self.initial_comments: comment = self.commentClass(comment_token["data"]) root.addprevious(comment._element) # Create the root document and add the ElementTree to it self.document = self.documentClass() self.document._elementTree = root.getroottree() # Give the root element the right name name = token["name"] namespace = token.get("namespace", self.defaultNamespace) if namespace is None: etree_tag = name else: etree_tag = "{%s}%s" % (namespace, name) root.tag = etree_tag # Add the root element to the internal child/open data structures root_element = self.elementClass(name, namespace) root_element._element = root self.document._childNodes.append(root_element) self.openElements.append(root_element) # Reset to the default insert comment function self.insertComment = self.insertCommentMain PKÒ¶N]unAAAA/site-packages/pip/_vendor/html5lib/_ihatexml.pynu„[µü¤from __future__ import absolute_import, division, unicode_literals import re import warnings from .constants import DataLossWarning baseChar = """ [#x0041-#x005A] | [#x0061-#x007A] | [#x00C0-#x00D6] | [#x00D8-#x00F6] | [#x00F8-#x00FF] | [#x0100-#x0131] | [#x0134-#x013E] | [#x0141-#x0148] | [#x014A-#x017E] | [#x0180-#x01C3] | [#x01CD-#x01F0] | [#x01F4-#x01F5] | [#x01FA-#x0217] | [#x0250-#x02A8] | [#x02BB-#x02C1] | #x0386 | [#x0388-#x038A] | #x038C | [#x038E-#x03A1] | [#x03A3-#x03CE] | [#x03D0-#x03D6] | #x03DA | #x03DC | #x03DE | #x03E0 | [#x03E2-#x03F3] | [#x0401-#x040C] | [#x040E-#x044F] | [#x0451-#x045C] | [#x045E-#x0481] | [#x0490-#x04C4] | [#x04C7-#x04C8] | [#x04CB-#x04CC] | [#x04D0-#x04EB] | [#x04EE-#x04F5] | [#x04F8-#x04F9] | [#x0531-#x0556] | #x0559 | [#x0561-#x0586] | [#x05D0-#x05EA] | [#x05F0-#x05F2] | [#x0621-#x063A] | [#x0641-#x064A] | [#x0671-#x06B7] | [#x06BA-#x06BE] | [#x06C0-#x06CE] | [#x06D0-#x06D3] | #x06D5 | [#x06E5-#x06E6] | [#x0905-#x0939] | #x093D | [#x0958-#x0961] | [#x0985-#x098C] | [#x098F-#x0990] | [#x0993-#x09A8] | [#x09AA-#x09B0] | #x09B2 | [#x09B6-#x09B9] | [#x09DC-#x09DD] | [#x09DF-#x09E1] | [#x09F0-#x09F1] | [#x0A05-#x0A0A] | [#x0A0F-#x0A10] | [#x0A13-#x0A28] | [#x0A2A-#x0A30] | [#x0A32-#x0A33] | [#x0A35-#x0A36] | [#x0A38-#x0A39] | [#x0A59-#x0A5C] | #x0A5E | [#x0A72-#x0A74] | [#x0A85-#x0A8B] | #x0A8D | [#x0A8F-#x0A91] | [#x0A93-#x0AA8] | [#x0AAA-#x0AB0] | [#x0AB2-#x0AB3] | [#x0AB5-#x0AB9] | #x0ABD | #x0AE0 | [#x0B05-#x0B0C] | [#x0B0F-#x0B10] | [#x0B13-#x0B28] | [#x0B2A-#x0B30] | [#x0B32-#x0B33] | [#x0B36-#x0B39] | #x0B3D | [#x0B5C-#x0B5D] | [#x0B5F-#x0B61] | [#x0B85-#x0B8A] | [#x0B8E-#x0B90] | [#x0B92-#x0B95] | [#x0B99-#x0B9A] | #x0B9C | [#x0B9E-#x0B9F] | [#x0BA3-#x0BA4] | [#x0BA8-#x0BAA] | [#x0BAE-#x0BB5] | [#x0BB7-#x0BB9] | [#x0C05-#x0C0C] | [#x0C0E-#x0C10] | [#x0C12-#x0C28] | [#x0C2A-#x0C33] | [#x0C35-#x0C39] | [#x0C60-#x0C61] | [#x0C85-#x0C8C] | [#x0C8E-#x0C90] | [#x0C92-#x0CA8] | [#x0CAA-#x0CB3] | [#x0CB5-#x0CB9] | #x0CDE | [#x0CE0-#x0CE1] | [#x0D05-#x0D0C] | [#x0D0E-#x0D10] | [#x0D12-#x0D28] | [#x0D2A-#x0D39] | [#x0D60-#x0D61] | [#x0E01-#x0E2E] | #x0E30 | [#x0E32-#x0E33] | [#x0E40-#x0E45] | [#x0E81-#x0E82] | #x0E84 | [#x0E87-#x0E88] | #x0E8A | #x0E8D | [#x0E94-#x0E97] | [#x0E99-#x0E9F] | [#x0EA1-#x0EA3] | #x0EA5 | #x0EA7 | [#x0EAA-#x0EAB] | [#x0EAD-#x0EAE] | #x0EB0 | [#x0EB2-#x0EB3] | #x0EBD | [#x0EC0-#x0EC4] | [#x0F40-#x0F47] | [#x0F49-#x0F69] | [#x10A0-#x10C5] | [#x10D0-#x10F6] | #x1100 | [#x1102-#x1103] | [#x1105-#x1107] | #x1109 | [#x110B-#x110C] | [#x110E-#x1112] | #x113C | #x113E | #x1140 | #x114C | #x114E | #x1150 | [#x1154-#x1155] | #x1159 | [#x115F-#x1161] | #x1163 | #x1165 | #x1167 | #x1169 | [#x116D-#x116E] | [#x1172-#x1173] | #x1175 | #x119E | #x11A8 | #x11AB | [#x11AE-#x11AF] | [#x11B7-#x11B8] | #x11BA | [#x11BC-#x11C2] | #x11EB | #x11F0 | #x11F9 | [#x1E00-#x1E9B] | [#x1EA0-#x1EF9] | [#x1F00-#x1F15] | [#x1F18-#x1F1D] | [#x1F20-#x1F45] | [#x1F48-#x1F4D] | [#x1F50-#x1F57] | #x1F59 | #x1F5B | #x1F5D | [#x1F5F-#x1F7D] | [#x1F80-#x1FB4] | [#x1FB6-#x1FBC] | #x1FBE | [#x1FC2-#x1FC4] | [#x1FC6-#x1FCC] | [#x1FD0-#x1FD3] | [#x1FD6-#x1FDB] | [#x1FE0-#x1FEC] | [#x1FF2-#x1FF4] | [#x1FF6-#x1FFC] | #x2126 | [#x212A-#x212B] | #x212E | [#x2180-#x2182] | [#x3041-#x3094] | [#x30A1-#x30FA] | [#x3105-#x312C] | [#xAC00-#xD7A3]""" ideographic = """[#x4E00-#x9FA5] | #x3007 | [#x3021-#x3029]""" combiningCharacter = """ [#x0300-#x0345] | [#x0360-#x0361] | [#x0483-#x0486] | [#x0591-#x05A1] | [#x05A3-#x05B9] | [#x05BB-#x05BD] | #x05BF | [#x05C1-#x05C2] | #x05C4 | [#x064B-#x0652] | #x0670 | [#x06D6-#x06DC] | [#x06DD-#x06DF] | [#x06E0-#x06E4] | [#x06E7-#x06E8] | [#x06EA-#x06ED] | [#x0901-#x0903] | #x093C | [#x093E-#x094C] | #x094D | [#x0951-#x0954] | [#x0962-#x0963] | [#x0981-#x0983] | #x09BC | #x09BE | #x09BF | [#x09C0-#x09C4] | [#x09C7-#x09C8] | [#x09CB-#x09CD] | #x09D7 | [#x09E2-#x09E3] | #x0A02 | #x0A3C | #x0A3E | #x0A3F | [#x0A40-#x0A42] | [#x0A47-#x0A48] | [#x0A4B-#x0A4D] | [#x0A70-#x0A71] | [#x0A81-#x0A83] | #x0ABC | [#x0ABE-#x0AC5] | [#x0AC7-#x0AC9] | [#x0ACB-#x0ACD] | [#x0B01-#x0B03] | #x0B3C | [#x0B3E-#x0B43] | [#x0B47-#x0B48] | [#x0B4B-#x0B4D] | [#x0B56-#x0B57] | [#x0B82-#x0B83] | [#x0BBE-#x0BC2] | [#x0BC6-#x0BC8] | [#x0BCA-#x0BCD] | #x0BD7 | [#x0C01-#x0C03] | [#x0C3E-#x0C44] | [#x0C46-#x0C48] | [#x0C4A-#x0C4D] | [#x0C55-#x0C56] | [#x0C82-#x0C83] | [#x0CBE-#x0CC4] | [#x0CC6-#x0CC8] | [#x0CCA-#x0CCD] | [#x0CD5-#x0CD6] | [#x0D02-#x0D03] | [#x0D3E-#x0D43] | [#x0D46-#x0D48] | [#x0D4A-#x0D4D] | #x0D57 | #x0E31 | [#x0E34-#x0E3A] | [#x0E47-#x0E4E] | #x0EB1 | [#x0EB4-#x0EB9] | [#x0EBB-#x0EBC] | [#x0EC8-#x0ECD] | [#x0F18-#x0F19] | #x0F35 | #x0F37 | #x0F39 | #x0F3E | #x0F3F | [#x0F71-#x0F84] | [#x0F86-#x0F8B] | [#x0F90-#x0F95] | #x0F97 | [#x0F99-#x0FAD] | [#x0FB1-#x0FB7] | #x0FB9 | [#x20D0-#x20DC] | #x20E1 | [#x302A-#x302F] | #x3099 | #x309A""" digit = """ [#x0030-#x0039] | [#x0660-#x0669] | [#x06F0-#x06F9] | [#x0966-#x096F] | [#x09E6-#x09EF] | [#x0A66-#x0A6F] | [#x0AE6-#x0AEF] | [#x0B66-#x0B6F] | [#x0BE7-#x0BEF] | [#x0C66-#x0C6F] | [#x0CE6-#x0CEF] | [#x0D66-#x0D6F] | [#x0E50-#x0E59] | [#x0ED0-#x0ED9] | [#x0F20-#x0F29]""" extender = """ #x00B7 | #x02D0 | #x02D1 | #x0387 | #x0640 | #x0E46 | #x0EC6 | #x3005 | #[#x3031-#x3035] | [#x309D-#x309E] | [#x30FC-#x30FE]""" letter = " | ".join([baseChar, ideographic]) # Without the name = " | ".join([letter, digit, ".", "-", "_", combiningCharacter, extender]) nameFirst = " | ".join([letter, "_"]) reChar = re.compile(r"#x([\d|A-F]{4,4})") reCharRange = re.compile(r"\[#x([\d|A-F]{4,4})-#x([\d|A-F]{4,4})\]") def charStringToList(chars): charRanges = [item.strip() for item in chars.split(" | ")] rv = [] for item in charRanges: foundMatch = False for regexp in (reChar, reCharRange): match = regexp.match(item) if match is not None: rv.append([hexToInt(item) for item in match.groups()]) if len(rv[-1]) == 1: rv[-1] = rv[-1] * 2 foundMatch = True break if not foundMatch: assert len(item) == 1 rv.append([ord(item)] * 2) rv = normaliseCharList(rv) return rv def normaliseCharList(charList): charList = sorted(charList) for item in charList: assert item[1] >= item[0] rv = [] i = 0 while i < len(charList): j = 1 rv.append(charList[i]) while i + j < len(charList) and charList[i + j][0] <= rv[-1][1] + 1: rv[-1][1] = charList[i + j][1] j += 1 i += j return rv # We don't really support characters above the BMP :( max_unicode = int("FFFF", 16) def missingRanges(charList): rv = [] if charList[0] != 0: rv.append([0, charList[0][0] - 1]) for i, item in enumerate(charList[:-1]): rv.append([item[1] + 1, charList[i + 1][0] - 1]) if charList[-1][1] != max_unicode: rv.append([charList[-1][1] + 1, max_unicode]) return rv def listToRegexpStr(charList): rv = [] for item in charList: if item[0] == item[1]: rv.append(escapeRegexp(chr(item[0]))) else: rv.append(escapeRegexp(chr(item[0])) + "-" + escapeRegexp(chr(item[1]))) return "[%s]" % "".join(rv) def hexToInt(hex_str): return int(hex_str, 16) def escapeRegexp(string): specialCharacters = (".", "^", "$", "*", "+", "?", "{", "}", "[", "]", "|", "(", ")", "-") for char in specialCharacters: string = string.replace(char, "\\" + char) return string # output from the above nonXmlNameBMPRegexp = re.compile('[\x00-,/:-@\\[-\\^`\\{-\xb6\xb8-\xbf\xd7\xf7\u0132-\u0133\u013f-\u0140\u0149\u017f\u01c4-\u01cc\u01f1-\u01f3\u01f6-\u01f9\u0218-\u024f\u02a9-\u02ba\u02c2-\u02cf\u02d2-\u02ff\u0346-\u035f\u0362-\u0385\u038b\u038d\u03a2\u03cf\u03d7-\u03d9\u03db\u03dd\u03df\u03e1\u03f4-\u0400\u040d\u0450\u045d\u0482\u0487-\u048f\u04c5-\u04c6\u04c9-\u04ca\u04cd-\u04cf\u04ec-\u04ed\u04f6-\u04f7\u04fa-\u0530\u0557-\u0558\u055a-\u0560\u0587-\u0590\u05a2\u05ba\u05be\u05c0\u05c3\u05c5-\u05cf\u05eb-\u05ef\u05f3-\u0620\u063b-\u063f\u0653-\u065f\u066a-\u066f\u06b8-\u06b9\u06bf\u06cf\u06d4\u06e9\u06ee-\u06ef\u06fa-\u0900\u0904\u093a-\u093b\u094e-\u0950\u0955-\u0957\u0964-\u0965\u0970-\u0980\u0984\u098d-\u098e\u0991-\u0992\u09a9\u09b1\u09b3-\u09b5\u09ba-\u09bb\u09bd\u09c5-\u09c6\u09c9-\u09ca\u09ce-\u09d6\u09d8-\u09db\u09de\u09e4-\u09e5\u09f2-\u0a01\u0a03-\u0a04\u0a0b-\u0a0e\u0a11-\u0a12\u0a29\u0a31\u0a34\u0a37\u0a3a-\u0a3b\u0a3d\u0a43-\u0a46\u0a49-\u0a4a\u0a4e-\u0a58\u0a5d\u0a5f-\u0a65\u0a75-\u0a80\u0a84\u0a8c\u0a8e\u0a92\u0aa9\u0ab1\u0ab4\u0aba-\u0abb\u0ac6\u0aca\u0ace-\u0adf\u0ae1-\u0ae5\u0af0-\u0b00\u0b04\u0b0d-\u0b0e\u0b11-\u0b12\u0b29\u0b31\u0b34-\u0b35\u0b3a-\u0b3b\u0b44-\u0b46\u0b49-\u0b4a\u0b4e-\u0b55\u0b58-\u0b5b\u0b5e\u0b62-\u0b65\u0b70-\u0b81\u0b84\u0b8b-\u0b8d\u0b91\u0b96-\u0b98\u0b9b\u0b9d\u0ba0-\u0ba2\u0ba5-\u0ba7\u0bab-\u0bad\u0bb6\u0bba-\u0bbd\u0bc3-\u0bc5\u0bc9\u0bce-\u0bd6\u0bd8-\u0be6\u0bf0-\u0c00\u0c04\u0c0d\u0c11\u0c29\u0c34\u0c3a-\u0c3d\u0c45\u0c49\u0c4e-\u0c54\u0c57-\u0c5f\u0c62-\u0c65\u0c70-\u0c81\u0c84\u0c8d\u0c91\u0ca9\u0cb4\u0cba-\u0cbd\u0cc5\u0cc9\u0cce-\u0cd4\u0cd7-\u0cdd\u0cdf\u0ce2-\u0ce5\u0cf0-\u0d01\u0d04\u0d0d\u0d11\u0d29\u0d3a-\u0d3d\u0d44-\u0d45\u0d49\u0d4e-\u0d56\u0d58-\u0d5f\u0d62-\u0d65\u0d70-\u0e00\u0e2f\u0e3b-\u0e3f\u0e4f\u0e5a-\u0e80\u0e83\u0e85-\u0e86\u0e89\u0e8b-\u0e8c\u0e8e-\u0e93\u0e98\u0ea0\u0ea4\u0ea6\u0ea8-\u0ea9\u0eac\u0eaf\u0eba\u0ebe-\u0ebf\u0ec5\u0ec7\u0ece-\u0ecf\u0eda-\u0f17\u0f1a-\u0f1f\u0f2a-\u0f34\u0f36\u0f38\u0f3a-\u0f3d\u0f48\u0f6a-\u0f70\u0f85\u0f8c-\u0f8f\u0f96\u0f98\u0fae-\u0fb0\u0fb8\u0fba-\u109f\u10c6-\u10cf\u10f7-\u10ff\u1101\u1104\u1108\u110a\u110d\u1113-\u113b\u113d\u113f\u1141-\u114b\u114d\u114f\u1151-\u1153\u1156-\u1158\u115a-\u115e\u1162\u1164\u1166\u1168\u116a-\u116c\u116f-\u1171\u1174\u1176-\u119d\u119f-\u11a7\u11a9-\u11aa\u11ac-\u11ad\u11b0-\u11b6\u11b9\u11bb\u11c3-\u11ea\u11ec-\u11ef\u11f1-\u11f8\u11fa-\u1dff\u1e9c-\u1e9f\u1efa-\u1eff\u1f16-\u1f17\u1f1e-\u1f1f\u1f46-\u1f47\u1f4e-\u1f4f\u1f58\u1f5a\u1f5c\u1f5e\u1f7e-\u1f7f\u1fb5\u1fbd\u1fbf-\u1fc1\u1fc5\u1fcd-\u1fcf\u1fd4-\u1fd5\u1fdc-\u1fdf\u1fed-\u1ff1\u1ff5\u1ffd-\u20cf\u20dd-\u20e0\u20e2-\u2125\u2127-\u2129\u212c-\u212d\u212f-\u217f\u2183-\u3004\u3006\u3008-\u3020\u3030\u3036-\u3040\u3095-\u3098\u309b-\u309c\u309f-\u30a0\u30fb\u30ff-\u3104\u312d-\u4dff\u9fa6-\uabff\ud7a4-\uffff]') # noqa nonXmlNameFirstBMPRegexp = re.compile('[\x00-@\\[-\\^`\\{-\xbf\xd7\xf7\u0132-\u0133\u013f-\u0140\u0149\u017f\u01c4-\u01cc\u01f1-\u01f3\u01f6-\u01f9\u0218-\u024f\u02a9-\u02ba\u02c2-\u0385\u0387\u038b\u038d\u03a2\u03cf\u03d7-\u03d9\u03db\u03dd\u03df\u03e1\u03f4-\u0400\u040d\u0450\u045d\u0482-\u048f\u04c5-\u04c6\u04c9-\u04ca\u04cd-\u04cf\u04ec-\u04ed\u04f6-\u04f7\u04fa-\u0530\u0557-\u0558\u055a-\u0560\u0587-\u05cf\u05eb-\u05ef\u05f3-\u0620\u063b-\u0640\u064b-\u0670\u06b8-\u06b9\u06bf\u06cf\u06d4\u06d6-\u06e4\u06e7-\u0904\u093a-\u093c\u093e-\u0957\u0962-\u0984\u098d-\u098e\u0991-\u0992\u09a9\u09b1\u09b3-\u09b5\u09ba-\u09db\u09de\u09e2-\u09ef\u09f2-\u0a04\u0a0b-\u0a0e\u0a11-\u0a12\u0a29\u0a31\u0a34\u0a37\u0a3a-\u0a58\u0a5d\u0a5f-\u0a71\u0a75-\u0a84\u0a8c\u0a8e\u0a92\u0aa9\u0ab1\u0ab4\u0aba-\u0abc\u0abe-\u0adf\u0ae1-\u0b04\u0b0d-\u0b0e\u0b11-\u0b12\u0b29\u0b31\u0b34-\u0b35\u0b3a-\u0b3c\u0b3e-\u0b5b\u0b5e\u0b62-\u0b84\u0b8b-\u0b8d\u0b91\u0b96-\u0b98\u0b9b\u0b9d\u0ba0-\u0ba2\u0ba5-\u0ba7\u0bab-\u0bad\u0bb6\u0bba-\u0c04\u0c0d\u0c11\u0c29\u0c34\u0c3a-\u0c5f\u0c62-\u0c84\u0c8d\u0c91\u0ca9\u0cb4\u0cba-\u0cdd\u0cdf\u0ce2-\u0d04\u0d0d\u0d11\u0d29\u0d3a-\u0d5f\u0d62-\u0e00\u0e2f\u0e31\u0e34-\u0e3f\u0e46-\u0e80\u0e83\u0e85-\u0e86\u0e89\u0e8b-\u0e8c\u0e8e-\u0e93\u0e98\u0ea0\u0ea4\u0ea6\u0ea8-\u0ea9\u0eac\u0eaf\u0eb1\u0eb4-\u0ebc\u0ebe-\u0ebf\u0ec5-\u0f3f\u0f48\u0f6a-\u109f\u10c6-\u10cf\u10f7-\u10ff\u1101\u1104\u1108\u110a\u110d\u1113-\u113b\u113d\u113f\u1141-\u114b\u114d\u114f\u1151-\u1153\u1156-\u1158\u115a-\u115e\u1162\u1164\u1166\u1168\u116a-\u116c\u116f-\u1171\u1174\u1176-\u119d\u119f-\u11a7\u11a9-\u11aa\u11ac-\u11ad\u11b0-\u11b6\u11b9\u11bb\u11c3-\u11ea\u11ec-\u11ef\u11f1-\u11f8\u11fa-\u1dff\u1e9c-\u1e9f\u1efa-\u1eff\u1f16-\u1f17\u1f1e-\u1f1f\u1f46-\u1f47\u1f4e-\u1f4f\u1f58\u1f5a\u1f5c\u1f5e\u1f7e-\u1f7f\u1fb5\u1fbd\u1fbf-\u1fc1\u1fc5\u1fcd-\u1fcf\u1fd4-\u1fd5\u1fdc-\u1fdf\u1fed-\u1ff1\u1ff5\u1ffd-\u2125\u2127-\u2129\u212c-\u212d\u212f-\u217f\u2183-\u3006\u3008-\u3020\u302a-\u3040\u3095-\u30a0\u30fb-\u3104\u312d-\u4dff\u9fa6-\uabff\ud7a4-\uffff]') # noqa # Simpler things nonPubidCharRegexp = re.compile("[^\x20\x0D\x0Aa-zA-Z0-9\\-'()+,./:=?;!*#@$_%]") class InfosetFilter(object): replacementRegexp = re.compile(r"U[\dA-F]{5,5}") def __init__(self, dropXmlnsLocalName=False, dropXmlnsAttrNs=False, preventDoubleDashComments=False, preventDashAtCommentEnd=False, replaceFormFeedCharacters=True, preventSingleQuotePubid=False): self.dropXmlnsLocalName = dropXmlnsLocalName self.dropXmlnsAttrNs = dropXmlnsAttrNs self.preventDoubleDashComments = preventDoubleDashComments self.preventDashAtCommentEnd = preventDashAtCommentEnd self.replaceFormFeedCharacters = replaceFormFeedCharacters self.preventSingleQuotePubid = preventSingleQuotePubid self.replaceCache = {} def coerceAttribute(self, name, namespace=None): if self.dropXmlnsLocalName and name.startswith("xmlns:"): warnings.warn("Attributes cannot begin with xmlns", DataLossWarning) return None elif (self.dropXmlnsAttrNs and namespace == "http://www.w3.org/2000/xmlns/"): warnings.warn("Attributes cannot be in the xml namespace", DataLossWarning) return None else: return self.toXmlName(name) def coerceElement(self, name): return self.toXmlName(name) def coerceComment(self, data): if self.preventDoubleDashComments: while "--" in data: warnings.warn("Comments cannot contain adjacent dashes", DataLossWarning) data = data.replace("--", "- -") if data.endswith("-"): warnings.warn("Comments cannot end in a dash", DataLossWarning) data += " " return data def coerceCharacters(self, data): if self.replaceFormFeedCharacters: for _ in range(data.count("\x0C")): warnings.warn("Text cannot contain U+000C", DataLossWarning) data = data.replace("\x0C", " ") # Other non-xml characters return data def coercePubid(self, data): dataOutput = data for char in nonPubidCharRegexp.findall(data): warnings.warn("Coercing non-XML pubid", DataLossWarning) replacement = self.getReplacementCharacter(char) dataOutput = dataOutput.replace(char, replacement) if self.preventSingleQuotePubid and dataOutput.find("'") >= 0: warnings.warn("Pubid cannot contain single quote", DataLossWarning) dataOutput = dataOutput.replace("'", self.getReplacementCharacter("'")) return dataOutput def toXmlName(self, name): nameFirst = name[0] nameRest = name[1:] m = nonXmlNameFirstBMPRegexp.match(nameFirst) if m: warnings.warn("Coercing non-XML name", DataLossWarning) nameFirstOutput = self.getReplacementCharacter(nameFirst) else: nameFirstOutput = nameFirst nameRestOutput = nameRest replaceChars = set(nonXmlNameBMPRegexp.findall(nameRest)) for char in replaceChars: warnings.warn("Coercing non-XML name", DataLossWarning) replacement = self.getReplacementCharacter(char) nameRestOutput = nameRestOutput.replace(char, replacement) return nameFirstOutput + nameRestOutput def getReplacementCharacter(self, char): if char in self.replaceCache: replacement = self.replaceCache[char] else: replacement = self.escapeChar(char) return replacement def fromXmlName(self, name): for item in set(self.replacementRegexp.findall(name)): name = name.replace(item, self.unescapeChar(item)) return name def escapeChar(self, char): replacement = "U%05X" % ord(char) self.replaceCache[char] = replacement return replacement def unescapeChar(self, charcode): return chr(int(charcode[1:], 16)) PKÒ¶N]Ö †ï>F>F/site-packages/pip/_vendor/html5lib/constants.pynu„[µü¤from __future__ import absolute_import, division, unicode_literals import string EOF = None E = { "null-character": "Null character in input stream, replaced with U+FFFD.", "invalid-codepoint": "Invalid codepoint in stream.", "incorrectly-placed-solidus": "Solidus (/) incorrectly placed in tag.", "incorrect-cr-newline-entity": "Incorrect CR newline entity, replaced with LF.", "illegal-windows-1252-entity": "Entity used with illegal number (windows-1252 reference).", "cant-convert-numeric-entity": "Numeric entity couldn't be converted to character " "(codepoint U+%(charAsInt)08x).", "illegal-codepoint-for-numeric-entity": "Numeric entity represents an illegal codepoint: " "U+%(charAsInt)08x.", "numeric-entity-without-semicolon": "Numeric entity didn't end with ';'.", "expected-numeric-entity-but-got-eof": "Numeric entity expected. Got end of file instead.", "expected-numeric-entity": "Numeric entity expected but none found.", "named-entity-without-semicolon": "Named entity didn't end with ';'.", "expected-named-entity": "Named entity expected. Got none.", "attributes-in-end-tag": "End tag contains unexpected attributes.", 'self-closing-flag-on-end-tag': "End tag contains unexpected self-closing flag.", "expected-tag-name-but-got-right-bracket": "Expected tag name. Got '>' instead.", "expected-tag-name-but-got-question-mark": "Expected tag name. Got '?' instead. (HTML doesn't " "support processing instructions.)", "expected-tag-name": "Expected tag name. Got something else instead", "expected-closing-tag-but-got-right-bracket": "Expected closing tag. Got '>' instead. Ignoring ''.", "expected-closing-tag-but-got-eof": "Expected closing tag. Unexpected end of file.", "expected-closing-tag-but-got-char": "Expected closing tag. Unexpected character '%(data)s' found.", "eof-in-tag-name": "Unexpected end of file in the tag name.", "expected-attribute-name-but-got-eof": "Unexpected end of file. Expected attribute name instead.", "eof-in-attribute-name": "Unexpected end of file in attribute name.", "invalid-character-in-attribute-name": "Invalid character in attribute name", "duplicate-attribute": "Dropped duplicate attribute on tag.", "expected-end-of-tag-name-but-got-eof": "Unexpected end of file. Expected = or end of tag.", "expected-attribute-value-but-got-eof": "Unexpected end of file. Expected attribute value.", "expected-attribute-value-but-got-right-bracket": "Expected attribute value. Got '>' instead.", 'equals-in-unquoted-attribute-value': "Unexpected = in unquoted attribute", 'unexpected-character-in-unquoted-attribute-value': "Unexpected character in unquoted attribute", "invalid-character-after-attribute-name": "Unexpected character after attribute name.", "unexpected-character-after-attribute-value": "Unexpected character after attribute value.", "eof-in-attribute-value-double-quote": "Unexpected end of file in attribute value (\").", "eof-in-attribute-value-single-quote": "Unexpected end of file in attribute value (').", "eof-in-attribute-value-no-quotes": "Unexpected end of file in attribute value.", "unexpected-EOF-after-solidus-in-tag": "Unexpected end of file in tag. Expected >", "unexpected-character-after-solidus-in-tag": "Unexpected character after / in tag. Expected >", "expected-dashes-or-doctype": "Expected '--' or 'DOCTYPE'. Not found.", "unexpected-bang-after-double-dash-in-comment": "Unexpected ! after -- in comment", "unexpected-space-after-double-dash-in-comment": "Unexpected space after -- in comment", "incorrect-comment": "Incorrect comment.", "eof-in-comment": "Unexpected end of file in comment.", "eof-in-comment-end-dash": "Unexpected end of file in comment (-)", "unexpected-dash-after-double-dash-in-comment": "Unexpected '-' after '--' found in comment.", "eof-in-comment-double-dash": "Unexpected end of file in comment (--).", "eof-in-comment-end-space-state": "Unexpected end of file in comment.", "eof-in-comment-end-bang-state": "Unexpected end of file in comment.", "unexpected-char-in-comment": "Unexpected character in comment found.", "need-space-after-doctype": "No space after literal string 'DOCTYPE'.", "expected-doctype-name-but-got-right-bracket": "Unexpected > character. Expected DOCTYPE name.", "expected-doctype-name-but-got-eof": "Unexpected end of file. Expected DOCTYPE name.", "eof-in-doctype-name": "Unexpected end of file in DOCTYPE name.", "eof-in-doctype": "Unexpected end of file in DOCTYPE.", "expected-space-or-right-bracket-in-doctype": "Expected space or '>'. Got '%(data)s'", "unexpected-end-of-doctype": "Unexpected end of DOCTYPE.", "unexpected-char-in-doctype": "Unexpected character in DOCTYPE.", "eof-in-innerhtml": "XXX innerHTML EOF", "unexpected-doctype": "Unexpected DOCTYPE. Ignored.", "non-html-root": "html needs to be the first start tag.", "expected-doctype-but-got-eof": "Unexpected End of file. Expected DOCTYPE.", "unknown-doctype": "Erroneous DOCTYPE.", "expected-doctype-but-got-chars": "Unexpected non-space characters. Expected DOCTYPE.", "expected-doctype-but-got-start-tag": "Unexpected start tag (%(name)s). Expected DOCTYPE.", "expected-doctype-but-got-end-tag": "Unexpected end tag (%(name)s). Expected DOCTYPE.", "end-tag-after-implied-root": "Unexpected end tag (%(name)s) after the (implied) root element.", "expected-named-closing-tag-but-got-eof": "Unexpected end of file. Expected end tag (%(name)s).", "two-heads-are-not-better-than-one": "Unexpected start tag head in existing head. Ignored.", "unexpected-end-tag": "Unexpected end tag (%(name)s). Ignored.", "unexpected-start-tag-out-of-my-head": "Unexpected start tag (%(name)s) that can be in head. Moved.", "unexpected-start-tag": "Unexpected start tag (%(name)s).", "missing-end-tag": "Missing end tag (%(name)s).", "missing-end-tags": "Missing end tags (%(name)s).", "unexpected-start-tag-implies-end-tag": "Unexpected start tag (%(startName)s) " "implies end tag (%(endName)s).", "unexpected-start-tag-treated-as": "Unexpected start tag (%(originalName)s). Treated as %(newName)s.", "deprecated-tag": "Unexpected start tag %(name)s. Don't use it!", "unexpected-start-tag-ignored": "Unexpected start tag %(name)s. Ignored.", "expected-one-end-tag-but-got-another": "Unexpected end tag (%(gotName)s). " "Missing end tag (%(expectedName)s).", "end-tag-too-early": "End tag (%(name)s) seen too early. Expected other end tag.", "end-tag-too-early-named": "Unexpected end tag (%(gotName)s). Expected end tag (%(expectedName)s).", "end-tag-too-early-ignored": "End tag (%(name)s) seen too early. Ignored.", "adoption-agency-1.1": "End tag (%(name)s) violates step 1, " "paragraph 1 of the adoption agency algorithm.", "adoption-agency-1.2": "End tag (%(name)s) violates step 1, " "paragraph 2 of the adoption agency algorithm.", "adoption-agency-1.3": "End tag (%(name)s) violates step 1, " "paragraph 3 of the adoption agency algorithm.", "adoption-agency-4.4": "End tag (%(name)s) violates step 4, " "paragraph 4 of the adoption agency algorithm.", "unexpected-end-tag-treated-as": "Unexpected end tag (%(originalName)s). Treated as %(newName)s.", "no-end-tag": "This element (%(name)s) has no end tag.", "unexpected-implied-end-tag-in-table": "Unexpected implied end tag (%(name)s) in the table phase.", "unexpected-implied-end-tag-in-table-body": "Unexpected implied end tag (%(name)s) in the table body phase.", "unexpected-char-implies-table-voodoo": "Unexpected non-space characters in " "table context caused voodoo mode.", "unexpected-hidden-input-in-table": "Unexpected input with type hidden in table context.", "unexpected-form-in-table": "Unexpected form in table context.", "unexpected-start-tag-implies-table-voodoo": "Unexpected start tag (%(name)s) in " "table context caused voodoo mode.", "unexpected-end-tag-implies-table-voodoo": "Unexpected end tag (%(name)s) in " "table context caused voodoo mode.", "unexpected-cell-in-table-body": "Unexpected table cell start tag (%(name)s) " "in the table body phase.", "unexpected-cell-end-tag": "Got table cell end tag (%(name)s) " "while required end tags are missing.", "unexpected-end-tag-in-table-body": "Unexpected end tag (%(name)s) in the table body phase. Ignored.", "unexpected-implied-end-tag-in-table-row": "Unexpected implied end tag (%(name)s) in the table row phase.", "unexpected-end-tag-in-table-row": "Unexpected end tag (%(name)s) in the table row phase. Ignored.", "unexpected-select-in-select": "Unexpected select start tag in the select phase " "treated as select end tag.", "unexpected-input-in-select": "Unexpected input start tag in the select phase.", "unexpected-start-tag-in-select": "Unexpected start tag token (%(name)s in the select phase. " "Ignored.", "unexpected-end-tag-in-select": "Unexpected end tag (%(name)s) in the select phase. Ignored.", "unexpected-table-element-start-tag-in-select-in-table": "Unexpected table element start tag (%(name)s) in the select in table phase.", "unexpected-table-element-end-tag-in-select-in-table": "Unexpected table element end tag (%(name)s) in the select in table phase.", "unexpected-char-after-body": "Unexpected non-space characters in the after body phase.", "unexpected-start-tag-after-body": "Unexpected start tag token (%(name)s)" " in the after body phase.", "unexpected-end-tag-after-body": "Unexpected end tag token (%(name)s)" " in the after body phase.", "unexpected-char-in-frameset": "Unexpected characters in the frameset phase. Characters ignored.", "unexpected-start-tag-in-frameset": "Unexpected start tag token (%(name)s)" " in the frameset phase. Ignored.", "unexpected-frameset-in-frameset-innerhtml": "Unexpected end tag token (frameset) " "in the frameset phase (innerHTML).", "unexpected-end-tag-in-frameset": "Unexpected end tag token (%(name)s)" " in the frameset phase. Ignored.", "unexpected-char-after-frameset": "Unexpected non-space characters in the " "after frameset phase. Ignored.", "unexpected-start-tag-after-frameset": "Unexpected start tag (%(name)s)" " in the after frameset phase. Ignored.", "unexpected-end-tag-after-frameset": "Unexpected end tag (%(name)s)" " in the after frameset phase. Ignored.", "unexpected-end-tag-after-body-innerhtml": "Unexpected end tag after body(innerHtml)", "expected-eof-but-got-char": "Unexpected non-space characters. Expected end of file.", "expected-eof-but-got-start-tag": "Unexpected start tag (%(name)s)" ". Expected end of file.", "expected-eof-but-got-end-tag": "Unexpected end tag (%(name)s)" ". Expected end of file.", "eof-in-table": "Unexpected end of file. Expected table content.", "eof-in-select": "Unexpected end of file. Expected select content.", "eof-in-frameset": "Unexpected end of file. Expected frameset content.", "eof-in-script-in-script": "Unexpected end of file. Expected script content.", "eof-in-foreign-lands": "Unexpected end of file. Expected foreign content", "non-void-element-with-trailing-solidus": "Trailing solidus not allowed on element %(name)s", "unexpected-html-element-in-foreign-content": "Element %(name)s not allowed in a non-html context", "unexpected-end-tag-before-html": "Unexpected end tag (%(name)s) before html.", "unexpected-inhead-noscript-tag": "Element %(name)s not allowed in a inhead-noscript context", "eof-in-head-noscript": "Unexpected end of file. Expected inhead-noscript content", "char-in-head-noscript": "Unexpected non-space character. Expected inhead-noscript content", "XXX-undefined-error": "Undefined error (this sucks and should be fixed)", } namespaces = { "html": "http://www.w3.org/1999/xhtml", "mathml": "http://www.w3.org/1998/Math/MathML", "svg": "http://www.w3.org/2000/svg", "xlink": "http://www.w3.org/1999/xlink", "xml": "http://www.w3.org/XML/1998/namespace", "xmlns": "http://www.w3.org/2000/xmlns/" } scopingElements = frozenset([ (namespaces["html"], "applet"), (namespaces["html"], "caption"), (namespaces["html"], "html"), (namespaces["html"], "marquee"), (namespaces["html"], "object"), (namespaces["html"], "table"), (namespaces["html"], "td"), (namespaces["html"], "th"), (namespaces["mathml"], "mi"), (namespaces["mathml"], "mo"), (namespaces["mathml"], "mn"), (namespaces["mathml"], "ms"), (namespaces["mathml"], "mtext"), (namespaces["mathml"], "annotation-xml"), (namespaces["svg"], "foreignObject"), (namespaces["svg"], "desc"), (namespaces["svg"], "title"), ]) formattingElements = frozenset([ (namespaces["html"], "a"), (namespaces["html"], "b"), (namespaces["html"], "big"), (namespaces["html"], "code"), (namespaces["html"], "em"), (namespaces["html"], "font"), (namespaces["html"], "i"), (namespaces["html"], "nobr"), (namespaces["html"], "s"), (namespaces["html"], "small"), (namespaces["html"], "strike"), (namespaces["html"], "strong"), (namespaces["html"], "tt"), (namespaces["html"], "u") ]) specialElements = frozenset([ (namespaces["html"], "address"), (namespaces["html"], "applet"), (namespaces["html"], "area"), (namespaces["html"], "article"), (namespaces["html"], "aside"), (namespaces["html"], "base"), (namespaces["html"], "basefont"), (namespaces["html"], "bgsound"), (namespaces["html"], "blockquote"), (namespaces["html"], "body"), (namespaces["html"], "br"), (namespaces["html"], "button"), (namespaces["html"], "caption"), (namespaces["html"], "center"), (namespaces["html"], "col"), (namespaces["html"], "colgroup"), (namespaces["html"], "command"), (namespaces["html"], "dd"), (namespaces["html"], "details"), (namespaces["html"], "dir"), (namespaces["html"], "div"), (namespaces["html"], "dl"), (namespaces["html"], "dt"), (namespaces["html"], "embed"), (namespaces["html"], "fieldset"), (namespaces["html"], "figure"), (namespaces["html"], "footer"), (namespaces["html"], "form"), (namespaces["html"], "frame"), (namespaces["html"], "frameset"), (namespaces["html"], "h1"), (namespaces["html"], "h2"), (namespaces["html"], "h3"), (namespaces["html"], "h4"), (namespaces["html"], "h5"), (namespaces["html"], "h6"), (namespaces["html"], "head"), (namespaces["html"], "header"), (namespaces["html"], "hr"), (namespaces["html"], "html"), (namespaces["html"], "iframe"), # Note that image is commented out in the spec as "this isn't an # element that can end up on the stack, so it doesn't matter," (namespaces["html"], "image"), (namespaces["html"], "img"), (namespaces["html"], "input"), (namespaces["html"], "isindex"), (namespaces["html"], "li"), (namespaces["html"], "link"), (namespaces["html"], "listing"), (namespaces["html"], "marquee"), (namespaces["html"], "menu"), (namespaces["html"], "meta"), (namespaces["html"], "nav"), (namespaces["html"], "noembed"), (namespaces["html"], "noframes"), (namespaces["html"], "noscript"), (namespaces["html"], "object"), (namespaces["html"], "ol"), (namespaces["html"], "p"), (namespaces["html"], "param"), (namespaces["html"], "plaintext"), (namespaces["html"], "pre"), (namespaces["html"], "script"), (namespaces["html"], "section"), (namespaces["html"], "select"), (namespaces["html"], "style"), (namespaces["html"], "table"), (namespaces["html"], "tbody"), (namespaces["html"], "td"), (namespaces["html"], "textarea"), (namespaces["html"], "tfoot"), (namespaces["html"], "th"), (namespaces["html"], "thead"), (namespaces["html"], "title"), (namespaces["html"], "tr"), (namespaces["html"], "ul"), (namespaces["html"], "wbr"), (namespaces["html"], "xmp"), (namespaces["svg"], "foreignObject") ]) htmlIntegrationPointElements = frozenset([ (namespaces["mathml"], "annotation-xml"), (namespaces["svg"], "foreignObject"), (namespaces["svg"], "desc"), (namespaces["svg"], "title") ]) mathmlTextIntegrationPointElements = frozenset([ (namespaces["mathml"], "mi"), (namespaces["mathml"], "mo"), (namespaces["mathml"], "mn"), (namespaces["mathml"], "ms"), (namespaces["mathml"], "mtext") ]) adjustSVGAttributes = { "attributename": "attributeName", "attributetype": "attributeType", "basefrequency": "baseFrequency", "baseprofile": "baseProfile", "calcmode": "calcMode", "clippathunits": "clipPathUnits", "contentscripttype": "contentScriptType", "contentstyletype": "contentStyleType", "diffuseconstant": "diffuseConstant", "edgemode": "edgeMode", "externalresourcesrequired": "externalResourcesRequired", "filterres": "filterRes", "filterunits": "filterUnits", "glyphref": "glyphRef", "gradienttransform": "gradientTransform", "gradientunits": "gradientUnits", "kernelmatrix": "kernelMatrix", "kernelunitlength": "kernelUnitLength", "keypoints": "keyPoints", "keysplines": "keySplines", "keytimes": "keyTimes", "lengthadjust": "lengthAdjust", "limitingconeangle": "limitingConeAngle", "markerheight": "markerHeight", "markerunits": "markerUnits", "markerwidth": "markerWidth", "maskcontentunits": "maskContentUnits", "maskunits": "maskUnits", "numoctaves": "numOctaves", "pathlength": "pathLength", "patterncontentunits": "patternContentUnits", "patterntransform": "patternTransform", "patternunits": "patternUnits", "pointsatx": "pointsAtX", "pointsaty": "pointsAtY", "pointsatz": "pointsAtZ", "preservealpha": "preserveAlpha", "preserveaspectratio": "preserveAspectRatio", "primitiveunits": "primitiveUnits", "refx": "refX", "refy": "refY", "repeatcount": "repeatCount", "repeatdur": "repeatDur", "requiredextensions": "requiredExtensions", "requiredfeatures": "requiredFeatures", "specularconstant": "specularConstant", "specularexponent": "specularExponent", "spreadmethod": "spreadMethod", "startoffset": "startOffset", "stddeviation": "stdDeviation", "stitchtiles": "stitchTiles", "surfacescale": "surfaceScale", "systemlanguage": "systemLanguage", "tablevalues": "tableValues", "targetx": "targetX", "targety": "targetY", "textlength": "textLength", "viewbox": "viewBox", "viewtarget": "viewTarget", "xchannelselector": "xChannelSelector", "ychannelselector": "yChannelSelector", "zoomandpan": "zoomAndPan" } adjustMathMLAttributes = {"definitionurl": "definitionURL"} adjustForeignAttributes = { "xlink:actuate": ("xlink", "actuate", namespaces["xlink"]), "xlink:arcrole": ("xlink", "arcrole", namespaces["xlink"]), "xlink:href": ("xlink", "href", namespaces["xlink"]), "xlink:role": ("xlink", "role", namespaces["xlink"]), "xlink:show": ("xlink", "show", namespaces["xlink"]), "xlink:title": ("xlink", "title", namespaces["xlink"]), "xlink:type": ("xlink", "type", namespaces["xlink"]), "xml:base": ("xml", "base", namespaces["xml"]), "xml:lang": ("xml", "lang", namespaces["xml"]), "xml:space": ("xml", "space", namespaces["xml"]), "xmlns": (None, "xmlns", namespaces["xmlns"]), "xmlns:xlink": ("xmlns", "xlink", namespaces["xmlns"]) } unadjustForeignAttributes = dict([((ns, local), qname) for qname, (prefix, local, ns) in adjustForeignAttributes.items()]) spaceCharacters = frozenset([ "\t", "\n", "\u000C", " ", "\r" ]) tableInsertModeElements = frozenset([ "table", "tbody", "tfoot", "thead", "tr" ]) asciiLowercase = frozenset(string.ascii_lowercase) asciiUppercase = frozenset(string.ascii_uppercase) asciiLetters = frozenset(string.ascii_letters) digits = frozenset(string.digits) hexDigits = frozenset(string.hexdigits) asciiUpper2Lower = dict([(ord(c), ord(c.lower())) for c in string.ascii_uppercase]) # Heading elements need to be ordered headingElements = ( "h1", "h2", "h3", "h4", "h5", "h6" ) voidElements = frozenset([ "base", "command", "event-source", "link", "meta", "hr", "br", "img", "embed", "param", "area", "col", "input", "source", "track" ]) cdataElements = frozenset(['title', 'textarea']) rcdataElements = frozenset([ 'style', 'script', 'xmp', 'iframe', 'noembed', 'noframes', 'noscript' ]) booleanAttributes = { "": frozenset(["irrelevant", "itemscope"]), "style": frozenset(["scoped"]), "img": frozenset(["ismap"]), "audio": frozenset(["autoplay", "controls"]), "video": frozenset(["autoplay", "controls"]), "script": frozenset(["defer", "async"]), "details": frozenset(["open"]), "datagrid": frozenset(["multiple", "disabled"]), "command": frozenset(["hidden", "disabled", "checked", "default"]), "hr": frozenset(["noshade"]), "menu": frozenset(["autosubmit"]), "fieldset": frozenset(["disabled", "readonly"]), "option": frozenset(["disabled", "readonly", "selected"]), "optgroup": frozenset(["disabled", "readonly"]), "button": frozenset(["disabled", "autofocus"]), "input": frozenset(["disabled", "readonly", "required", "autofocus", "checked", "ismap"]), "select": frozenset(["disabled", "readonly", "autofocus", "multiple"]), "output": frozenset(["disabled", "readonly"]), "iframe": frozenset(["seamless"]), } # entitiesWindows1252 has to be _ordered_ and needs to have an index. It # therefore can't be a frozenset. entitiesWindows1252 = ( 8364, # 0x80 0x20AC EURO SIGN 65533, # 0x81 UNDEFINED 8218, # 0x82 0x201A SINGLE LOW-9 QUOTATION MARK 402, # 0x83 0x0192 LATIN SMALL LETTER F WITH HOOK 8222, # 0x84 0x201E DOUBLE LOW-9 QUOTATION MARK 8230, # 0x85 0x2026 HORIZONTAL ELLIPSIS 8224, # 0x86 0x2020 DAGGER 8225, # 0x87 0x2021 DOUBLE DAGGER 710, # 0x88 0x02C6 MODIFIER LETTER CIRCUMFLEX ACCENT 8240, # 0x89 0x2030 PER MILLE SIGN 352, # 0x8A 0x0160 LATIN CAPITAL LETTER S WITH CARON 8249, # 0x8B 0x2039 SINGLE LEFT-POINTING ANGLE QUOTATION MARK 338, # 0x8C 0x0152 LATIN CAPITAL LIGATURE OE 65533, # 0x8D UNDEFINED 381, # 0x8E 0x017D LATIN CAPITAL LETTER Z WITH CARON 65533, # 0x8F UNDEFINED 65533, # 0x90 UNDEFINED 8216, # 0x91 0x2018 LEFT SINGLE QUOTATION MARK 8217, # 0x92 0x2019 RIGHT SINGLE QUOTATION MARK 8220, # 0x93 0x201C LEFT DOUBLE QUOTATION MARK 8221, # 0x94 0x201D RIGHT DOUBLE QUOTATION MARK 8226, # 0x95 0x2022 BULLET 8211, # 0x96 0x2013 EN DASH 8212, # 0x97 0x2014 EM DASH 732, # 0x98 0x02DC SMALL TILDE 8482, # 0x99 0x2122 TRADE MARK SIGN 353, # 0x9A 0x0161 LATIN SMALL LETTER S WITH CARON 8250, # 0x9B 0x203A SINGLE RIGHT-POINTING ANGLE QUOTATION MARK 339, # 0x9C 0x0153 LATIN SMALL LIGATURE OE 65533, # 0x9D UNDEFINED 382, # 0x9E 0x017E LATIN SMALL LETTER Z WITH CARON 376 # 0x9F 0x0178 LATIN CAPITAL LETTER Y WITH DIAERESIS ) xmlEntities = frozenset(['lt;', 'gt;', 'amp;', 'apos;', 'quot;']) entities = { "AElig": "\xc6", "AElig;": "\xc6", "AMP": "&", "AMP;": "&", "Aacute": "\xc1", "Aacute;": "\xc1", "Abreve;": "\u0102", "Acirc": "\xc2", "Acirc;": "\xc2", "Acy;": "\u0410", "Afr;": "\U0001d504", "Agrave": "\xc0", "Agrave;": "\xc0", "Alpha;": "\u0391", "Amacr;": "\u0100", "And;": "\u2a53", "Aogon;": "\u0104", "Aopf;": "\U0001d538", "ApplyFunction;": "\u2061", "Aring": "\xc5", "Aring;": "\xc5", "Ascr;": "\U0001d49c", "Assign;": "\u2254", "Atilde": "\xc3", "Atilde;": "\xc3", "Auml": "\xc4", "Auml;": "\xc4", "Backslash;": "\u2216", "Barv;": "\u2ae7", "Barwed;": "\u2306", "Bcy;": "\u0411", "Because;": "\u2235", "Bernoullis;": "\u212c", "Beta;": "\u0392", "Bfr;": "\U0001d505", "Bopf;": "\U0001d539", "Breve;": "\u02d8", "Bscr;": "\u212c", "Bumpeq;": "\u224e", "CHcy;": "\u0427", "COPY": "\xa9", "COPY;": "\xa9", "Cacute;": "\u0106", "Cap;": "\u22d2", "CapitalDifferentialD;": "\u2145", "Cayleys;": "\u212d", "Ccaron;": "\u010c", "Ccedil": "\xc7", "Ccedil;": "\xc7", "Ccirc;": "\u0108", "Cconint;": "\u2230", "Cdot;": "\u010a", "Cedilla;": "\xb8", "CenterDot;": "\xb7", "Cfr;": "\u212d", "Chi;": "\u03a7", "CircleDot;": "\u2299", "CircleMinus;": "\u2296", "CirclePlus;": "\u2295", "CircleTimes;": "\u2297", "ClockwiseContourIntegral;": "\u2232", "CloseCurlyDoubleQuote;": "\u201d", "CloseCurlyQuote;": "\u2019", "Colon;": "\u2237", "Colone;": "\u2a74", "Congruent;": "\u2261", "Conint;": "\u222f", "ContourIntegral;": "\u222e", "Copf;": "\u2102", "Coproduct;": "\u2210", "CounterClockwiseContourIntegral;": "\u2233", "Cross;": "\u2a2f", "Cscr;": "\U0001d49e", "Cup;": "\u22d3", "CupCap;": "\u224d", "DD;": "\u2145", "DDotrahd;": "\u2911", "DJcy;": "\u0402", "DScy;": "\u0405", "DZcy;": "\u040f", "Dagger;": "\u2021", "Darr;": "\u21a1", "Dashv;": "\u2ae4", "Dcaron;": "\u010e", "Dcy;": "\u0414", "Del;": "\u2207", "Delta;": "\u0394", "Dfr;": "\U0001d507", "DiacriticalAcute;": "\xb4", "DiacriticalDot;": "\u02d9", "DiacriticalDoubleAcute;": "\u02dd", "DiacriticalGrave;": "`", "DiacriticalTilde;": "\u02dc", "Diamond;": "\u22c4", "DifferentialD;": "\u2146", "Dopf;": "\U0001d53b", "Dot;": "\xa8", "DotDot;": "\u20dc", "DotEqual;": "\u2250", "DoubleContourIntegral;": "\u222f", "DoubleDot;": "\xa8", "DoubleDownArrow;": "\u21d3", "DoubleLeftArrow;": "\u21d0", "DoubleLeftRightArrow;": "\u21d4", "DoubleLeftTee;": "\u2ae4", "DoubleLongLeftArrow;": "\u27f8", "DoubleLongLeftRightArrow;": "\u27fa", "DoubleLongRightArrow;": "\u27f9", "DoubleRightArrow;": "\u21d2", "DoubleRightTee;": "\u22a8", "DoubleUpArrow;": "\u21d1", "DoubleUpDownArrow;": "\u21d5", "DoubleVerticalBar;": "\u2225", "DownArrow;": "\u2193", "DownArrowBar;": "\u2913", "DownArrowUpArrow;": "\u21f5", "DownBreve;": "\u0311", "DownLeftRightVector;": "\u2950", "DownLeftTeeVector;": "\u295e", "DownLeftVector;": "\u21bd", "DownLeftVectorBar;": "\u2956", "DownRightTeeVector;": "\u295f", "DownRightVector;": "\u21c1", "DownRightVectorBar;": "\u2957", "DownTee;": "\u22a4", "DownTeeArrow;": "\u21a7", "Downarrow;": "\u21d3", "Dscr;": "\U0001d49f", "Dstrok;": "\u0110", "ENG;": "\u014a", "ETH": "\xd0", "ETH;": "\xd0", "Eacute": "\xc9", "Eacute;": "\xc9", "Ecaron;": "\u011a", "Ecirc": "\xca", "Ecirc;": "\xca", "Ecy;": "\u042d", "Edot;": "\u0116", "Efr;": "\U0001d508", "Egrave": "\xc8", "Egrave;": "\xc8", "Element;": "\u2208", "Emacr;": "\u0112", "EmptySmallSquare;": "\u25fb", "EmptyVerySmallSquare;": "\u25ab", "Eogon;": "\u0118", "Eopf;": "\U0001d53c", "Epsilon;": "\u0395", "Equal;": "\u2a75", "EqualTilde;": "\u2242", "Equilibrium;": "\u21cc", "Escr;": "\u2130", "Esim;": "\u2a73", "Eta;": "\u0397", "Euml": "\xcb", "Euml;": "\xcb", "Exists;": "\u2203", "ExponentialE;": "\u2147", "Fcy;": "\u0424", "Ffr;": "\U0001d509", "FilledSmallSquare;": "\u25fc", "FilledVerySmallSquare;": "\u25aa", "Fopf;": "\U0001d53d", "ForAll;": "\u2200", "Fouriertrf;": "\u2131", "Fscr;": "\u2131", "GJcy;": "\u0403", "GT": ">", "GT;": ">", "Gamma;": "\u0393", "Gammad;": "\u03dc", "Gbreve;": "\u011e", "Gcedil;": "\u0122", "Gcirc;": "\u011c", "Gcy;": "\u0413", "Gdot;": "\u0120", "Gfr;": "\U0001d50a", "Gg;": "\u22d9", "Gopf;": "\U0001d53e", "GreaterEqual;": "\u2265", "GreaterEqualLess;": "\u22db", "GreaterFullEqual;": "\u2267", "GreaterGreater;": "\u2aa2", "GreaterLess;": "\u2277", "GreaterSlantEqual;": "\u2a7e", "GreaterTilde;": "\u2273", "Gscr;": "\U0001d4a2", "Gt;": "\u226b", "HARDcy;": "\u042a", "Hacek;": "\u02c7", "Hat;": "^", "Hcirc;": "\u0124", "Hfr;": "\u210c", "HilbertSpace;": "\u210b", "Hopf;": "\u210d", "HorizontalLine;": "\u2500", "Hscr;": "\u210b", "Hstrok;": "\u0126", "HumpDownHump;": "\u224e", "HumpEqual;": "\u224f", "IEcy;": "\u0415", "IJlig;": "\u0132", "IOcy;": "\u0401", "Iacute": "\xcd", "Iacute;": "\xcd", "Icirc": "\xce", "Icirc;": "\xce", "Icy;": "\u0418", "Idot;": "\u0130", "Ifr;": "\u2111", "Igrave": "\xcc", "Igrave;": "\xcc", "Im;": "\u2111", "Imacr;": "\u012a", "ImaginaryI;": "\u2148", "Implies;": "\u21d2", "Int;": "\u222c", "Integral;": "\u222b", "Intersection;": "\u22c2", "InvisibleComma;": "\u2063", "InvisibleTimes;": "\u2062", "Iogon;": "\u012e", "Iopf;": "\U0001d540", "Iota;": "\u0399", "Iscr;": "\u2110", "Itilde;": "\u0128", "Iukcy;": "\u0406", "Iuml": "\xcf", "Iuml;": "\xcf", "Jcirc;": "\u0134", "Jcy;": "\u0419", "Jfr;": "\U0001d50d", "Jopf;": "\U0001d541", "Jscr;": "\U0001d4a5", "Jsercy;": "\u0408", "Jukcy;": "\u0404", "KHcy;": "\u0425", "KJcy;": "\u040c", "Kappa;": "\u039a", "Kcedil;": "\u0136", "Kcy;": "\u041a", "Kfr;": "\U0001d50e", "Kopf;": "\U0001d542", "Kscr;": "\U0001d4a6", "LJcy;": "\u0409", "LT": "<", "LT;": "<", "Lacute;": "\u0139", "Lambda;": "\u039b", "Lang;": "\u27ea", "Laplacetrf;": "\u2112", "Larr;": "\u219e", "Lcaron;": "\u013d", "Lcedil;": "\u013b", "Lcy;": "\u041b", "LeftAngleBracket;": "\u27e8", "LeftArrow;": "\u2190", "LeftArrowBar;": "\u21e4", "LeftArrowRightArrow;": "\u21c6", "LeftCeiling;": "\u2308", "LeftDoubleBracket;": "\u27e6", "LeftDownTeeVector;": "\u2961", "LeftDownVector;": "\u21c3", "LeftDownVectorBar;": "\u2959", "LeftFloor;": "\u230a", "LeftRightArrow;": "\u2194", "LeftRightVector;": "\u294e", "LeftTee;": "\u22a3", "LeftTeeArrow;": "\u21a4", "LeftTeeVector;": "\u295a", "LeftTriangle;": "\u22b2", "LeftTriangleBar;": "\u29cf", "LeftTriangleEqual;": "\u22b4", "LeftUpDownVector;": "\u2951", "LeftUpTeeVector;": "\u2960", "LeftUpVector;": "\u21bf", "LeftUpVectorBar;": "\u2958", "LeftVector;": "\u21bc", "LeftVectorBar;": "\u2952", "Leftarrow;": "\u21d0", "Leftrightarrow;": "\u21d4", "LessEqualGreater;": "\u22da", "LessFullEqual;": "\u2266", "LessGreater;": "\u2276", "LessLess;": "\u2aa1", "LessSlantEqual;": "\u2a7d", "LessTilde;": "\u2272", "Lfr;": "\U0001d50f", "Ll;": "\u22d8", "Lleftarrow;": "\u21da", "Lmidot;": "\u013f", "LongLeftArrow;": "\u27f5", "LongLeftRightArrow;": "\u27f7", "LongRightArrow;": "\u27f6", "Longleftarrow;": "\u27f8", "Longleftrightarrow;": "\u27fa", "Longrightarrow;": "\u27f9", "Lopf;": "\U0001d543", "LowerLeftArrow;": "\u2199", "LowerRightArrow;": "\u2198", "Lscr;": "\u2112", "Lsh;": "\u21b0", "Lstrok;": "\u0141", "Lt;": "\u226a", "Map;": "\u2905", "Mcy;": "\u041c", "MediumSpace;": "\u205f", "Mellintrf;": "\u2133", "Mfr;": "\U0001d510", "MinusPlus;": "\u2213", "Mopf;": "\U0001d544", "Mscr;": "\u2133", "Mu;": "\u039c", "NJcy;": "\u040a", "Nacute;": "\u0143", "Ncaron;": "\u0147", "Ncedil;": "\u0145", "Ncy;": "\u041d", "NegativeMediumSpace;": "\u200b", "NegativeThickSpace;": "\u200b", "NegativeThinSpace;": "\u200b", "NegativeVeryThinSpace;": "\u200b", "NestedGreaterGreater;": "\u226b", "NestedLessLess;": "\u226a", "NewLine;": "\n", "Nfr;": "\U0001d511", "NoBreak;": "\u2060", "NonBreakingSpace;": "\xa0", "Nopf;": "\u2115", "Not;": "\u2aec", "NotCongruent;": "\u2262", "NotCupCap;": "\u226d", "NotDoubleVerticalBar;": "\u2226", "NotElement;": "\u2209", "NotEqual;": "\u2260", "NotEqualTilde;": "\u2242\u0338", "NotExists;": "\u2204", "NotGreater;": "\u226f", "NotGreaterEqual;": "\u2271", "NotGreaterFullEqual;": "\u2267\u0338", "NotGreaterGreater;": "\u226b\u0338", "NotGreaterLess;": "\u2279", "NotGreaterSlantEqual;": "\u2a7e\u0338", "NotGreaterTilde;": "\u2275", "NotHumpDownHump;": "\u224e\u0338", "NotHumpEqual;": "\u224f\u0338", "NotLeftTriangle;": "\u22ea", "NotLeftTriangleBar;": "\u29cf\u0338", "NotLeftTriangleEqual;": "\u22ec", "NotLess;": "\u226e", "NotLessEqual;": "\u2270", "NotLessGreater;": "\u2278", "NotLessLess;": "\u226a\u0338", "NotLessSlantEqual;": "\u2a7d\u0338", "NotLessTilde;": "\u2274", "NotNestedGreaterGreater;": "\u2aa2\u0338", "NotNestedLessLess;": "\u2aa1\u0338", "NotPrecedes;": "\u2280", "NotPrecedesEqual;": "\u2aaf\u0338", "NotPrecedesSlantEqual;": "\u22e0", "NotReverseElement;": "\u220c", "NotRightTriangle;": "\u22eb", "NotRightTriangleBar;": "\u29d0\u0338", "NotRightTriangleEqual;": "\u22ed", "NotSquareSubset;": "\u228f\u0338", "NotSquareSubsetEqual;": "\u22e2", "NotSquareSuperset;": "\u2290\u0338", "NotSquareSupersetEqual;": "\u22e3", "NotSubset;": "\u2282\u20d2", "NotSubsetEqual;": "\u2288", "NotSucceeds;": "\u2281", "NotSucceedsEqual;": "\u2ab0\u0338", "NotSucceedsSlantEqual;": "\u22e1", "NotSucceedsTilde;": "\u227f\u0338", "NotSuperset;": "\u2283\u20d2", "NotSupersetEqual;": "\u2289", "NotTilde;": "\u2241", "NotTildeEqual;": "\u2244", "NotTildeFullEqual;": "\u2247", "NotTildeTilde;": "\u2249", "NotVerticalBar;": "\u2224", "Nscr;": "\U0001d4a9", "Ntilde": "\xd1", "Ntilde;": "\xd1", "Nu;": "\u039d", "OElig;": "\u0152", "Oacute": "\xd3", "Oacute;": "\xd3", "Ocirc": "\xd4", "Ocirc;": "\xd4", "Ocy;": "\u041e", "Odblac;": "\u0150", "Ofr;": "\U0001d512", "Ograve": "\xd2", "Ograve;": "\xd2", "Omacr;": "\u014c", "Omega;": "\u03a9", "Omicron;": "\u039f", "Oopf;": "\U0001d546", "OpenCurlyDoubleQuote;": "\u201c", "OpenCurlyQuote;": "\u2018", "Or;": "\u2a54", "Oscr;": "\U0001d4aa", "Oslash": "\xd8", "Oslash;": "\xd8", "Otilde": "\xd5", "Otilde;": "\xd5", "Otimes;": "\u2a37", "Ouml": "\xd6", "Ouml;": "\xd6", "OverBar;": "\u203e", "OverBrace;": "\u23de", "OverBracket;": "\u23b4", "OverParenthesis;": "\u23dc", "PartialD;": "\u2202", "Pcy;": "\u041f", "Pfr;": "\U0001d513", "Phi;": "\u03a6", "Pi;": "\u03a0", "PlusMinus;": "\xb1", "Poincareplane;": "\u210c", "Popf;": "\u2119", "Pr;": "\u2abb", "Precedes;": "\u227a", "PrecedesEqual;": "\u2aaf", "PrecedesSlantEqual;": "\u227c", "PrecedesTilde;": "\u227e", "Prime;": "\u2033", "Product;": "\u220f", "Proportion;": "\u2237", "Proportional;": "\u221d", "Pscr;": "\U0001d4ab", "Psi;": "\u03a8", "QUOT": "\"", "QUOT;": "\"", "Qfr;": "\U0001d514", "Qopf;": "\u211a", "Qscr;": "\U0001d4ac", "RBarr;": "\u2910", "REG": "\xae", "REG;": "\xae", "Racute;": "\u0154", "Rang;": "\u27eb", "Rarr;": "\u21a0", "Rarrtl;": "\u2916", "Rcaron;": "\u0158", "Rcedil;": "\u0156", "Rcy;": "\u0420", "Re;": "\u211c", "ReverseElement;": "\u220b", "ReverseEquilibrium;": "\u21cb", "ReverseUpEquilibrium;": "\u296f", "Rfr;": "\u211c", "Rho;": "\u03a1", "RightAngleBracket;": "\u27e9", "RightArrow;": "\u2192", "RightArrowBar;": "\u21e5", "RightArrowLeftArrow;": "\u21c4", "RightCeiling;": "\u2309", "RightDoubleBracket;": "\u27e7", "RightDownTeeVector;": "\u295d", "RightDownVector;": "\u21c2", "RightDownVectorBar;": "\u2955", "RightFloor;": "\u230b", "RightTee;": "\u22a2", "RightTeeArrow;": "\u21a6", "RightTeeVector;": "\u295b", "RightTriangle;": "\u22b3", "RightTriangleBar;": "\u29d0", "RightTriangleEqual;": "\u22b5", "RightUpDownVector;": "\u294f", "RightUpTeeVector;": "\u295c", "RightUpVector;": "\u21be", "RightUpVectorBar;": "\u2954", "RightVector;": "\u21c0", "RightVectorBar;": "\u2953", "Rightarrow;": "\u21d2", "Ropf;": "\u211d", "RoundImplies;": "\u2970", "Rrightarrow;": "\u21db", "Rscr;": "\u211b", "Rsh;": "\u21b1", "RuleDelayed;": "\u29f4", "SHCHcy;": "\u0429", "SHcy;": "\u0428", "SOFTcy;": "\u042c", "Sacute;": "\u015a", "Sc;": "\u2abc", "Scaron;": "\u0160", "Scedil;": "\u015e", "Scirc;": "\u015c", "Scy;": "\u0421", "Sfr;": "\U0001d516", "ShortDownArrow;": "\u2193", "ShortLeftArrow;": "\u2190", "ShortRightArrow;": "\u2192", "ShortUpArrow;": "\u2191", "Sigma;": "\u03a3", "SmallCircle;": "\u2218", "Sopf;": "\U0001d54a", "Sqrt;": "\u221a", "Square;": "\u25a1", "SquareIntersection;": "\u2293", "SquareSubset;": "\u228f", "SquareSubsetEqual;": "\u2291", "SquareSuperset;": "\u2290", "SquareSupersetEqual;": "\u2292", "SquareUnion;": "\u2294", "Sscr;": "\U0001d4ae", "Star;": "\u22c6", "Sub;": "\u22d0", "Subset;": "\u22d0", "SubsetEqual;": "\u2286", "Succeeds;": "\u227b", "SucceedsEqual;": "\u2ab0", "SucceedsSlantEqual;": "\u227d", "SucceedsTilde;": "\u227f", "SuchThat;": "\u220b", "Sum;": "\u2211", "Sup;": "\u22d1", "Superset;": "\u2283", "SupersetEqual;": "\u2287", "Supset;": "\u22d1", "THORN": "\xde", "THORN;": "\xde", "TRADE;": "\u2122", "TSHcy;": "\u040b", "TScy;": "\u0426", "Tab;": "\t", "Tau;": "\u03a4", "Tcaron;": "\u0164", "Tcedil;": "\u0162", "Tcy;": "\u0422", "Tfr;": "\U0001d517", "Therefore;": "\u2234", "Theta;": "\u0398", "ThickSpace;": "\u205f\u200a", "ThinSpace;": "\u2009", "Tilde;": "\u223c", "TildeEqual;": "\u2243", "TildeFullEqual;": "\u2245", "TildeTilde;": "\u2248", "Topf;": "\U0001d54b", "TripleDot;": "\u20db", "Tscr;": "\U0001d4af", "Tstrok;": "\u0166", "Uacute": "\xda", "Uacute;": "\xda", "Uarr;": "\u219f", "Uarrocir;": "\u2949", "Ubrcy;": "\u040e", "Ubreve;": "\u016c", "Ucirc": "\xdb", "Ucirc;": "\xdb", "Ucy;": "\u0423", "Udblac;": "\u0170", "Ufr;": "\U0001d518", "Ugrave": "\xd9", "Ugrave;": "\xd9", "Umacr;": "\u016a", "UnderBar;": "_", "UnderBrace;": "\u23df", "UnderBracket;": "\u23b5", "UnderParenthesis;": "\u23dd", "Union;": "\u22c3", "UnionPlus;": "\u228e", "Uogon;": "\u0172", "Uopf;": "\U0001d54c", "UpArrow;": "\u2191", "UpArrowBar;": "\u2912", "UpArrowDownArrow;": "\u21c5", "UpDownArrow;": "\u2195", "UpEquilibrium;": "\u296e", "UpTee;": "\u22a5", "UpTeeArrow;": "\u21a5", "Uparrow;": "\u21d1", "Updownarrow;": "\u21d5", "UpperLeftArrow;": "\u2196", "UpperRightArrow;": "\u2197", "Upsi;": "\u03d2", "Upsilon;": "\u03a5", "Uring;": "\u016e", "Uscr;": "\U0001d4b0", "Utilde;": "\u0168", "Uuml": "\xdc", "Uuml;": "\xdc", "VDash;": "\u22ab", "Vbar;": "\u2aeb", "Vcy;": "\u0412", "Vdash;": "\u22a9", "Vdashl;": "\u2ae6", "Vee;": "\u22c1", "Verbar;": "\u2016", "Vert;": "\u2016", "VerticalBar;": "\u2223", "VerticalLine;": "|", "VerticalSeparator;": "\u2758", "VerticalTilde;": "\u2240", "VeryThinSpace;": "\u200a", "Vfr;": "\U0001d519", "Vopf;": "\U0001d54d", "Vscr;": "\U0001d4b1", "Vvdash;": "\u22aa", "Wcirc;": "\u0174", "Wedge;": "\u22c0", "Wfr;": "\U0001d51a", "Wopf;": "\U0001d54e", "Wscr;": "\U0001d4b2", "Xfr;": "\U0001d51b", "Xi;": "\u039e", "Xopf;": "\U0001d54f", "Xscr;": "\U0001d4b3", "YAcy;": "\u042f", "YIcy;": "\u0407", "YUcy;": "\u042e", "Yacute": "\xdd", "Yacute;": "\xdd", "Ycirc;": "\u0176", "Ycy;": "\u042b", "Yfr;": "\U0001d51c", "Yopf;": "\U0001d550", "Yscr;": "\U0001d4b4", "Yuml;": "\u0178", "ZHcy;": "\u0416", "Zacute;": "\u0179", "Zcaron;": "\u017d", "Zcy;": "\u0417", "Zdot;": "\u017b", "ZeroWidthSpace;": "\u200b", "Zeta;": "\u0396", "Zfr;": "\u2128", "Zopf;": "\u2124", "Zscr;": "\U0001d4b5", "aacute": "\xe1", "aacute;": "\xe1", "abreve;": "\u0103", "ac;": "\u223e", "acE;": "\u223e\u0333", "acd;": "\u223f", "acirc": "\xe2", "acirc;": "\xe2", "acute": "\xb4", "acute;": "\xb4", "acy;": "\u0430", "aelig": "\xe6", "aelig;": "\xe6", "af;": "\u2061", "afr;": "\U0001d51e", "agrave": "\xe0", "agrave;": "\xe0", "alefsym;": "\u2135", "aleph;": "\u2135", "alpha;": "\u03b1", "amacr;": "\u0101", "amalg;": "\u2a3f", "amp": "&", "amp;": "&", "and;": "\u2227", "andand;": "\u2a55", "andd;": "\u2a5c", "andslope;": "\u2a58", "andv;": "\u2a5a", "ang;": "\u2220", "ange;": "\u29a4", "angle;": "\u2220", "angmsd;": "\u2221", "angmsdaa;": "\u29a8", "angmsdab;": "\u29a9", "angmsdac;": "\u29aa", "angmsdad;": "\u29ab", "angmsdae;": "\u29ac", "angmsdaf;": "\u29ad", "angmsdag;": "\u29ae", "angmsdah;": "\u29af", "angrt;": "\u221f", "angrtvb;": "\u22be", "angrtvbd;": "\u299d", "angsph;": "\u2222", "angst;": "\xc5", "angzarr;": "\u237c", "aogon;": "\u0105", "aopf;": "\U0001d552", "ap;": "\u2248", "apE;": "\u2a70", "apacir;": "\u2a6f", "ape;": "\u224a", "apid;": "\u224b", "apos;": "'", "approx;": "\u2248", "approxeq;": "\u224a", "aring": "\xe5", "aring;": "\xe5", "ascr;": "\U0001d4b6", "ast;": "*", "asymp;": "\u2248", "asympeq;": "\u224d", "atilde": "\xe3", "atilde;": "\xe3", "auml": "\xe4", "auml;": "\xe4", "awconint;": "\u2233", "awint;": "\u2a11", "bNot;": "\u2aed", "backcong;": "\u224c", "backepsilon;": "\u03f6", "backprime;": "\u2035", "backsim;": "\u223d", "backsimeq;": "\u22cd", "barvee;": "\u22bd", "barwed;": "\u2305", "barwedge;": "\u2305", "bbrk;": "\u23b5", "bbrktbrk;": "\u23b6", "bcong;": "\u224c", "bcy;": "\u0431", "bdquo;": "\u201e", "becaus;": "\u2235", "because;": "\u2235", "bemptyv;": "\u29b0", "bepsi;": "\u03f6", "bernou;": "\u212c", "beta;": "\u03b2", "beth;": "\u2136", "between;": "\u226c", "bfr;": "\U0001d51f", "bigcap;": "\u22c2", "bigcirc;": "\u25ef", "bigcup;": "\u22c3", "bigodot;": "\u2a00", "bigoplus;": "\u2a01", "bigotimes;": "\u2a02", "bigsqcup;": "\u2a06", "bigstar;": "\u2605", "bigtriangledown;": "\u25bd", "bigtriangleup;": "\u25b3", "biguplus;": "\u2a04", "bigvee;": "\u22c1", "bigwedge;": "\u22c0", "bkarow;": "\u290d", "blacklozenge;": "\u29eb", "blacksquare;": "\u25aa", "blacktriangle;": "\u25b4", "blacktriangledown;": "\u25be", "blacktriangleleft;": "\u25c2", "blacktriangleright;": "\u25b8", "blank;": "\u2423", "blk12;": "\u2592", "blk14;": "\u2591", "blk34;": "\u2593", "block;": "\u2588", "bne;": "=\u20e5", "bnequiv;": "\u2261\u20e5", "bnot;": "\u2310", "bopf;": "\U0001d553", "bot;": "\u22a5", "bottom;": "\u22a5", "bowtie;": "\u22c8", "boxDL;": "\u2557", "boxDR;": "\u2554", "boxDl;": "\u2556", "boxDr;": "\u2553", "boxH;": "\u2550", "boxHD;": "\u2566", "boxHU;": "\u2569", "boxHd;": "\u2564", "boxHu;": "\u2567", "boxUL;": "\u255d", "boxUR;": "\u255a", "boxUl;": "\u255c", "boxUr;": "\u2559", "boxV;": "\u2551", "boxVH;": "\u256c", "boxVL;": "\u2563", "boxVR;": "\u2560", "boxVh;": "\u256b", "boxVl;": "\u2562", "boxVr;": "\u255f", "boxbox;": "\u29c9", "boxdL;": "\u2555", "boxdR;": "\u2552", "boxdl;": "\u2510", "boxdr;": "\u250c", "boxh;": "\u2500", "boxhD;": "\u2565", "boxhU;": "\u2568", "boxhd;": "\u252c", "boxhu;": "\u2534", "boxminus;": "\u229f", "boxplus;": "\u229e", "boxtimes;": "\u22a0", "boxuL;": "\u255b", "boxuR;": "\u2558", "boxul;": "\u2518", "boxur;": "\u2514", "boxv;": "\u2502", "boxvH;": "\u256a", "boxvL;": "\u2561", "boxvR;": "\u255e", "boxvh;": "\u253c", "boxvl;": "\u2524", "boxvr;": "\u251c", "bprime;": "\u2035", "breve;": "\u02d8", "brvbar": "\xa6", "brvbar;": "\xa6", "bscr;": "\U0001d4b7", "bsemi;": "\u204f", "bsim;": "\u223d", "bsime;": "\u22cd", "bsol;": "\\", "bsolb;": "\u29c5", "bsolhsub;": "\u27c8", "bull;": "\u2022", "bullet;": "\u2022", "bump;": "\u224e", "bumpE;": "\u2aae", "bumpe;": "\u224f", "bumpeq;": "\u224f", "cacute;": "\u0107", "cap;": "\u2229", "capand;": "\u2a44", "capbrcup;": "\u2a49", "capcap;": "\u2a4b", "capcup;": "\u2a47", "capdot;": "\u2a40", "caps;": "\u2229\ufe00", "caret;": "\u2041", "caron;": "\u02c7", "ccaps;": "\u2a4d", "ccaron;": "\u010d", "ccedil": "\xe7", "ccedil;": "\xe7", "ccirc;": "\u0109", "ccups;": "\u2a4c", "ccupssm;": "\u2a50", "cdot;": "\u010b", "cedil": "\xb8", "cedil;": "\xb8", "cemptyv;": "\u29b2", "cent": "\xa2", "cent;": "\xa2", "centerdot;": "\xb7", "cfr;": "\U0001d520", "chcy;": "\u0447", "check;": "\u2713", "checkmark;": "\u2713", "chi;": "\u03c7", "cir;": "\u25cb", "cirE;": "\u29c3", "circ;": "\u02c6", "circeq;": "\u2257", "circlearrowleft;": "\u21ba", "circlearrowright;": "\u21bb", "circledR;": "\xae", "circledS;": "\u24c8", "circledast;": "\u229b", "circledcirc;": "\u229a", "circleddash;": "\u229d", "cire;": "\u2257", "cirfnint;": "\u2a10", "cirmid;": "\u2aef", "cirscir;": "\u29c2", "clubs;": "\u2663", "clubsuit;": "\u2663", "colon;": ":", "colone;": "\u2254", "coloneq;": "\u2254", "comma;": ",", "commat;": "@", "comp;": "\u2201", "compfn;": "\u2218", "complement;": "\u2201", "complexes;": "\u2102", "cong;": "\u2245", "congdot;": "\u2a6d", "conint;": "\u222e", "copf;": "\U0001d554", "coprod;": "\u2210", "copy": "\xa9", "copy;": "\xa9", "copysr;": "\u2117", "crarr;": "\u21b5", "cross;": "\u2717", "cscr;": "\U0001d4b8", "csub;": "\u2acf", "csube;": "\u2ad1", "csup;": "\u2ad0", "csupe;": "\u2ad2", "ctdot;": "\u22ef", "cudarrl;": "\u2938", "cudarrr;": "\u2935", "cuepr;": "\u22de", "cuesc;": "\u22df", "cularr;": "\u21b6", "cularrp;": "\u293d", "cup;": "\u222a", "cupbrcap;": "\u2a48", "cupcap;": "\u2a46", "cupcup;": "\u2a4a", "cupdot;": "\u228d", "cupor;": "\u2a45", "cups;": "\u222a\ufe00", "curarr;": "\u21b7", "curarrm;": "\u293c", "curlyeqprec;": "\u22de", "curlyeqsucc;": "\u22df", "curlyvee;": "\u22ce", "curlywedge;": "\u22cf", "curren": "\xa4", "curren;": "\xa4", "curvearrowleft;": "\u21b6", "curvearrowright;": "\u21b7", "cuvee;": "\u22ce", "cuwed;": "\u22cf", "cwconint;": "\u2232", "cwint;": "\u2231", "cylcty;": "\u232d", "dArr;": "\u21d3", "dHar;": "\u2965", "dagger;": "\u2020", "daleth;": "\u2138", "darr;": "\u2193", "dash;": "\u2010", "dashv;": "\u22a3", "dbkarow;": "\u290f", "dblac;": "\u02dd", "dcaron;": "\u010f", "dcy;": "\u0434", "dd;": "\u2146", "ddagger;": "\u2021", "ddarr;": "\u21ca", "ddotseq;": "\u2a77", "deg": "\xb0", "deg;": "\xb0", "delta;": "\u03b4", "demptyv;": "\u29b1", "dfisht;": "\u297f", "dfr;": "\U0001d521", "dharl;": "\u21c3", "dharr;": "\u21c2", "diam;": "\u22c4", "diamond;": "\u22c4", "diamondsuit;": "\u2666", "diams;": "\u2666", "die;": "\xa8", "digamma;": "\u03dd", "disin;": "\u22f2", "div;": "\xf7", "divide": "\xf7", "divide;": "\xf7", "divideontimes;": "\u22c7", "divonx;": "\u22c7", "djcy;": "\u0452", "dlcorn;": "\u231e", "dlcrop;": "\u230d", "dollar;": "$", "dopf;": "\U0001d555", "dot;": "\u02d9", "doteq;": "\u2250", "doteqdot;": "\u2251", "dotminus;": "\u2238", "dotplus;": "\u2214", "dotsquare;": "\u22a1", "doublebarwedge;": "\u2306", "downarrow;": "\u2193", "downdownarrows;": "\u21ca", "downharpoonleft;": "\u21c3", "downharpoonright;": "\u21c2", "drbkarow;": "\u2910", "drcorn;": "\u231f", "drcrop;": "\u230c", "dscr;": "\U0001d4b9", "dscy;": "\u0455", "dsol;": "\u29f6", "dstrok;": "\u0111", "dtdot;": "\u22f1", "dtri;": "\u25bf", "dtrif;": "\u25be", "duarr;": "\u21f5", "duhar;": "\u296f", "dwangle;": "\u29a6", "dzcy;": "\u045f", "dzigrarr;": "\u27ff", "eDDot;": "\u2a77", "eDot;": "\u2251", "eacute": "\xe9", "eacute;": "\xe9", "easter;": "\u2a6e", "ecaron;": "\u011b", "ecir;": "\u2256", "ecirc": "\xea", "ecirc;": "\xea", "ecolon;": "\u2255", "ecy;": "\u044d", "edot;": "\u0117", "ee;": "\u2147", "efDot;": "\u2252", "efr;": "\U0001d522", "eg;": "\u2a9a", "egrave": "\xe8", "egrave;": "\xe8", "egs;": "\u2a96", "egsdot;": "\u2a98", "el;": "\u2a99", "elinters;": "\u23e7", "ell;": "\u2113", "els;": "\u2a95", "elsdot;": "\u2a97", "emacr;": "\u0113", "empty;": "\u2205", "emptyset;": "\u2205", "emptyv;": "\u2205", "emsp13;": "\u2004", "emsp14;": "\u2005", "emsp;": "\u2003", "eng;": "\u014b", "ensp;": "\u2002", "eogon;": "\u0119", "eopf;": "\U0001d556", "epar;": "\u22d5", "eparsl;": "\u29e3", "eplus;": "\u2a71", "epsi;": "\u03b5", "epsilon;": "\u03b5", "epsiv;": "\u03f5", "eqcirc;": "\u2256", "eqcolon;": "\u2255", "eqsim;": "\u2242", "eqslantgtr;": "\u2a96", "eqslantless;": "\u2a95", "equals;": "=", "equest;": "\u225f", "equiv;": "\u2261", "equivDD;": "\u2a78", "eqvparsl;": "\u29e5", "erDot;": "\u2253", "erarr;": "\u2971", "escr;": "\u212f", "esdot;": "\u2250", "esim;": "\u2242", "eta;": "\u03b7", "eth": "\xf0", "eth;": "\xf0", "euml": "\xeb", "euml;": "\xeb", "euro;": "\u20ac", "excl;": "!", "exist;": "\u2203", "expectation;": "\u2130", "exponentiale;": "\u2147", "fallingdotseq;": "\u2252", "fcy;": "\u0444", "female;": "\u2640", "ffilig;": "\ufb03", "fflig;": "\ufb00", "ffllig;": "\ufb04", "ffr;": "\U0001d523", "filig;": "\ufb01", "fjlig;": "fj", "flat;": "\u266d", "fllig;": "\ufb02", "fltns;": "\u25b1", "fnof;": "\u0192", "fopf;": "\U0001d557", "forall;": "\u2200", "fork;": "\u22d4", "forkv;": "\u2ad9", "fpartint;": "\u2a0d", "frac12": "\xbd", "frac12;": "\xbd", "frac13;": "\u2153", "frac14": "\xbc", "frac14;": "\xbc", "frac15;": "\u2155", "frac16;": "\u2159", "frac18;": "\u215b", "frac23;": "\u2154", "frac25;": "\u2156", "frac34": "\xbe", "frac34;": "\xbe", "frac35;": "\u2157", "frac38;": "\u215c", "frac45;": "\u2158", "frac56;": "\u215a", "frac58;": "\u215d", "frac78;": "\u215e", "frasl;": "\u2044", "frown;": "\u2322", "fscr;": "\U0001d4bb", "gE;": "\u2267", "gEl;": "\u2a8c", "gacute;": "\u01f5", "gamma;": "\u03b3", "gammad;": "\u03dd", "gap;": "\u2a86", "gbreve;": "\u011f", "gcirc;": "\u011d", "gcy;": "\u0433", "gdot;": "\u0121", "ge;": "\u2265", "gel;": "\u22db", "geq;": "\u2265", "geqq;": "\u2267", "geqslant;": "\u2a7e", "ges;": "\u2a7e", "gescc;": "\u2aa9", "gesdot;": "\u2a80", "gesdoto;": "\u2a82", "gesdotol;": "\u2a84", "gesl;": "\u22db\ufe00", "gesles;": "\u2a94", "gfr;": "\U0001d524", "gg;": "\u226b", "ggg;": "\u22d9", "gimel;": "\u2137", "gjcy;": "\u0453", "gl;": "\u2277", "glE;": "\u2a92", "gla;": "\u2aa5", "glj;": "\u2aa4", "gnE;": "\u2269", "gnap;": "\u2a8a", "gnapprox;": "\u2a8a", "gne;": "\u2a88", "gneq;": "\u2a88", "gneqq;": "\u2269", "gnsim;": "\u22e7", "gopf;": "\U0001d558", "grave;": "`", "gscr;": "\u210a", "gsim;": "\u2273", "gsime;": "\u2a8e", "gsiml;": "\u2a90", "gt": ">", "gt;": ">", "gtcc;": "\u2aa7", "gtcir;": "\u2a7a", "gtdot;": "\u22d7", "gtlPar;": "\u2995", "gtquest;": "\u2a7c", "gtrapprox;": "\u2a86", "gtrarr;": "\u2978", "gtrdot;": "\u22d7", "gtreqless;": "\u22db", "gtreqqless;": "\u2a8c", "gtrless;": "\u2277", "gtrsim;": "\u2273", "gvertneqq;": "\u2269\ufe00", "gvnE;": "\u2269\ufe00", "hArr;": "\u21d4", "hairsp;": "\u200a", "half;": "\xbd", "hamilt;": "\u210b", "hardcy;": "\u044a", "harr;": "\u2194", "harrcir;": "\u2948", "harrw;": "\u21ad", "hbar;": "\u210f", "hcirc;": "\u0125", "hearts;": "\u2665", "heartsuit;": "\u2665", "hellip;": "\u2026", "hercon;": "\u22b9", "hfr;": "\U0001d525", "hksearow;": "\u2925", "hkswarow;": "\u2926", "hoarr;": "\u21ff", "homtht;": "\u223b", "hookleftarrow;": "\u21a9", "hookrightarrow;": "\u21aa", "hopf;": "\U0001d559", "horbar;": "\u2015", "hscr;": "\U0001d4bd", "hslash;": "\u210f", "hstrok;": "\u0127", "hybull;": "\u2043", "hyphen;": "\u2010", "iacute": "\xed", "iacute;": "\xed", "ic;": "\u2063", "icirc": "\xee", "icirc;": "\xee", "icy;": "\u0438", "iecy;": "\u0435", "iexcl": "\xa1", "iexcl;": "\xa1", "iff;": "\u21d4", "ifr;": "\U0001d526", "igrave": "\xec", "igrave;": "\xec", "ii;": "\u2148", "iiiint;": "\u2a0c", "iiint;": "\u222d", "iinfin;": "\u29dc", "iiota;": "\u2129", "ijlig;": "\u0133", "imacr;": "\u012b", "image;": "\u2111", "imagline;": "\u2110", "imagpart;": "\u2111", "imath;": "\u0131", "imof;": "\u22b7", "imped;": "\u01b5", "in;": "\u2208", "incare;": "\u2105", "infin;": "\u221e", "infintie;": "\u29dd", "inodot;": "\u0131", "int;": "\u222b", "intcal;": "\u22ba", "integers;": "\u2124", "intercal;": "\u22ba", "intlarhk;": "\u2a17", "intprod;": "\u2a3c", "iocy;": "\u0451", "iogon;": "\u012f", "iopf;": "\U0001d55a", "iota;": "\u03b9", "iprod;": "\u2a3c", "iquest": "\xbf", "iquest;": "\xbf", "iscr;": "\U0001d4be", "isin;": "\u2208", "isinE;": "\u22f9", "isindot;": "\u22f5", "isins;": "\u22f4", "isinsv;": "\u22f3", "isinv;": "\u2208", "it;": "\u2062", "itilde;": "\u0129", "iukcy;": "\u0456", "iuml": "\xef", "iuml;": "\xef", "jcirc;": "\u0135", "jcy;": "\u0439", "jfr;": "\U0001d527", "jmath;": "\u0237", "jopf;": "\U0001d55b", "jscr;": "\U0001d4bf", "jsercy;": "\u0458", "jukcy;": "\u0454", "kappa;": "\u03ba", "kappav;": "\u03f0", "kcedil;": "\u0137", "kcy;": "\u043a", "kfr;": "\U0001d528", "kgreen;": "\u0138", "khcy;": "\u0445", "kjcy;": "\u045c", "kopf;": "\U0001d55c", "kscr;": "\U0001d4c0", "lAarr;": "\u21da", "lArr;": "\u21d0", "lAtail;": "\u291b", "lBarr;": "\u290e", "lE;": "\u2266", "lEg;": "\u2a8b", "lHar;": "\u2962", "lacute;": "\u013a", "laemptyv;": "\u29b4", "lagran;": "\u2112", "lambda;": "\u03bb", "lang;": "\u27e8", "langd;": "\u2991", "langle;": "\u27e8", "lap;": "\u2a85", "laquo": "\xab", "laquo;": "\xab", "larr;": "\u2190", "larrb;": "\u21e4", "larrbfs;": "\u291f", "larrfs;": "\u291d", "larrhk;": "\u21a9", "larrlp;": "\u21ab", "larrpl;": "\u2939", "larrsim;": "\u2973", "larrtl;": "\u21a2", "lat;": "\u2aab", "latail;": "\u2919", "late;": "\u2aad", "lates;": "\u2aad\ufe00", "lbarr;": "\u290c", "lbbrk;": "\u2772", "lbrace;": "{", "lbrack;": "[", "lbrke;": "\u298b", "lbrksld;": "\u298f", "lbrkslu;": "\u298d", "lcaron;": "\u013e", "lcedil;": "\u013c", "lceil;": "\u2308", "lcub;": "{", "lcy;": "\u043b", "ldca;": "\u2936", "ldquo;": "\u201c", "ldquor;": "\u201e", "ldrdhar;": "\u2967", "ldrushar;": "\u294b", "ldsh;": "\u21b2", "le;": "\u2264", "leftarrow;": "\u2190", "leftarrowtail;": "\u21a2", "leftharpoondown;": "\u21bd", "leftharpoonup;": "\u21bc", "leftleftarrows;": "\u21c7", "leftrightarrow;": "\u2194", "leftrightarrows;": "\u21c6", "leftrightharpoons;": "\u21cb", "leftrightsquigarrow;": "\u21ad", "leftthreetimes;": "\u22cb", "leg;": "\u22da", "leq;": "\u2264", "leqq;": "\u2266", "leqslant;": "\u2a7d", "les;": "\u2a7d", "lescc;": "\u2aa8", "lesdot;": "\u2a7f", "lesdoto;": "\u2a81", "lesdotor;": "\u2a83", "lesg;": "\u22da\ufe00", "lesges;": "\u2a93", "lessapprox;": "\u2a85", "lessdot;": "\u22d6", "lesseqgtr;": "\u22da", "lesseqqgtr;": "\u2a8b", "lessgtr;": "\u2276", "lesssim;": "\u2272", "lfisht;": "\u297c", "lfloor;": "\u230a", "lfr;": "\U0001d529", "lg;": "\u2276", "lgE;": "\u2a91", "lhard;": "\u21bd", "lharu;": "\u21bc", "lharul;": "\u296a", "lhblk;": "\u2584", "ljcy;": "\u0459", "ll;": "\u226a", "llarr;": "\u21c7", "llcorner;": "\u231e", "llhard;": "\u296b", "lltri;": "\u25fa", "lmidot;": "\u0140", "lmoust;": "\u23b0", "lmoustache;": "\u23b0", "lnE;": "\u2268", "lnap;": "\u2a89", "lnapprox;": "\u2a89", "lne;": "\u2a87", "lneq;": "\u2a87", "lneqq;": "\u2268", "lnsim;": "\u22e6", "loang;": "\u27ec", "loarr;": "\u21fd", "lobrk;": "\u27e6", "longleftarrow;": "\u27f5", "longleftrightarrow;": "\u27f7", "longmapsto;": "\u27fc", "longrightarrow;": "\u27f6", "looparrowleft;": "\u21ab", "looparrowright;": "\u21ac", "lopar;": "\u2985", "lopf;": "\U0001d55d", "loplus;": "\u2a2d", "lotimes;": "\u2a34", "lowast;": "\u2217", "lowbar;": "_", "loz;": "\u25ca", "lozenge;": "\u25ca", "lozf;": "\u29eb", "lpar;": "(", "lparlt;": "\u2993", "lrarr;": "\u21c6", "lrcorner;": "\u231f", "lrhar;": "\u21cb", "lrhard;": "\u296d", "lrm;": "\u200e", "lrtri;": "\u22bf", "lsaquo;": "\u2039", "lscr;": "\U0001d4c1", "lsh;": "\u21b0", "lsim;": "\u2272", "lsime;": "\u2a8d", "lsimg;": "\u2a8f", "lsqb;": "[", "lsquo;": "\u2018", "lsquor;": "\u201a", "lstrok;": "\u0142", "lt": "<", "lt;": "<", "ltcc;": "\u2aa6", "ltcir;": "\u2a79", "ltdot;": "\u22d6", "lthree;": "\u22cb", "ltimes;": "\u22c9", "ltlarr;": "\u2976", "ltquest;": "\u2a7b", "ltrPar;": "\u2996", "ltri;": "\u25c3", "ltrie;": "\u22b4", "ltrif;": "\u25c2", "lurdshar;": "\u294a", "luruhar;": "\u2966", "lvertneqq;": "\u2268\ufe00", "lvnE;": "\u2268\ufe00", "mDDot;": "\u223a", "macr": "\xaf", "macr;": "\xaf", "male;": "\u2642", "malt;": "\u2720", "maltese;": "\u2720", "map;": "\u21a6", "mapsto;": "\u21a6", "mapstodown;": "\u21a7", "mapstoleft;": "\u21a4", "mapstoup;": "\u21a5", "marker;": "\u25ae", "mcomma;": "\u2a29", "mcy;": "\u043c", "mdash;": "\u2014", "measuredangle;": "\u2221", "mfr;": "\U0001d52a", "mho;": "\u2127", "micro": "\xb5", "micro;": "\xb5", "mid;": "\u2223", "midast;": "*", "midcir;": "\u2af0", "middot": "\xb7", "middot;": "\xb7", "minus;": "\u2212", "minusb;": "\u229f", "minusd;": "\u2238", "minusdu;": "\u2a2a", "mlcp;": "\u2adb", "mldr;": "\u2026", "mnplus;": "\u2213", "models;": "\u22a7", "mopf;": "\U0001d55e", "mp;": "\u2213", "mscr;": "\U0001d4c2", "mstpos;": "\u223e", "mu;": "\u03bc", "multimap;": "\u22b8", "mumap;": "\u22b8", "nGg;": "\u22d9\u0338", "nGt;": "\u226b\u20d2", "nGtv;": "\u226b\u0338", "nLeftarrow;": "\u21cd", "nLeftrightarrow;": "\u21ce", "nLl;": "\u22d8\u0338", "nLt;": "\u226a\u20d2", "nLtv;": "\u226a\u0338", "nRightarrow;": "\u21cf", "nVDash;": "\u22af", "nVdash;": "\u22ae", "nabla;": "\u2207", "nacute;": "\u0144", "nang;": "\u2220\u20d2", "nap;": "\u2249", "napE;": "\u2a70\u0338", "napid;": "\u224b\u0338", "napos;": "\u0149", "napprox;": "\u2249", "natur;": "\u266e", "natural;": "\u266e", "naturals;": "\u2115", "nbsp": "\xa0", "nbsp;": "\xa0", "nbump;": "\u224e\u0338", "nbumpe;": "\u224f\u0338", "ncap;": "\u2a43", "ncaron;": "\u0148", "ncedil;": "\u0146", "ncong;": "\u2247", "ncongdot;": "\u2a6d\u0338", "ncup;": "\u2a42", "ncy;": "\u043d", "ndash;": "\u2013", "ne;": "\u2260", "neArr;": "\u21d7", "nearhk;": "\u2924", "nearr;": "\u2197", "nearrow;": "\u2197", "nedot;": "\u2250\u0338", "nequiv;": "\u2262", "nesear;": "\u2928", "nesim;": "\u2242\u0338", "nexist;": "\u2204", "nexists;": "\u2204", "nfr;": "\U0001d52b", "ngE;": "\u2267\u0338", "nge;": "\u2271", "ngeq;": "\u2271", "ngeqq;": "\u2267\u0338", "ngeqslant;": "\u2a7e\u0338", "nges;": "\u2a7e\u0338", "ngsim;": "\u2275", "ngt;": "\u226f", "ngtr;": "\u226f", "nhArr;": "\u21ce", "nharr;": "\u21ae", "nhpar;": "\u2af2", "ni;": "\u220b", "nis;": "\u22fc", "nisd;": "\u22fa", "niv;": "\u220b", "njcy;": "\u045a", "nlArr;": "\u21cd", "nlE;": "\u2266\u0338", "nlarr;": "\u219a", "nldr;": "\u2025", "nle;": "\u2270", "nleftarrow;": "\u219a", "nleftrightarrow;": "\u21ae", "nleq;": "\u2270", "nleqq;": "\u2266\u0338", "nleqslant;": "\u2a7d\u0338", "nles;": "\u2a7d\u0338", "nless;": "\u226e", "nlsim;": "\u2274", "nlt;": "\u226e", "nltri;": "\u22ea", "nltrie;": "\u22ec", "nmid;": "\u2224", "nopf;": "\U0001d55f", "not": "\xac", "not;": "\xac", "notin;": "\u2209", "notinE;": "\u22f9\u0338", "notindot;": "\u22f5\u0338", "notinva;": "\u2209", "notinvb;": "\u22f7", "notinvc;": "\u22f6", "notni;": "\u220c", "notniva;": "\u220c", "notnivb;": "\u22fe", "notnivc;": "\u22fd", "npar;": "\u2226", "nparallel;": "\u2226", "nparsl;": "\u2afd\u20e5", "npart;": "\u2202\u0338", "npolint;": "\u2a14", "npr;": "\u2280", "nprcue;": "\u22e0", "npre;": "\u2aaf\u0338", "nprec;": "\u2280", "npreceq;": "\u2aaf\u0338", "nrArr;": "\u21cf", "nrarr;": "\u219b", "nrarrc;": "\u2933\u0338", "nrarrw;": "\u219d\u0338", "nrightarrow;": "\u219b", "nrtri;": "\u22eb", "nrtrie;": "\u22ed", "nsc;": "\u2281", "nsccue;": "\u22e1", "nsce;": "\u2ab0\u0338", "nscr;": "\U0001d4c3", "nshortmid;": "\u2224", "nshortparallel;": "\u2226", "nsim;": "\u2241", "nsime;": "\u2244", "nsimeq;": "\u2244", "nsmid;": "\u2224", "nspar;": "\u2226", "nsqsube;": "\u22e2", "nsqsupe;": "\u22e3", "nsub;": "\u2284", "nsubE;": "\u2ac5\u0338", "nsube;": "\u2288", "nsubset;": "\u2282\u20d2", "nsubseteq;": "\u2288", "nsubseteqq;": "\u2ac5\u0338", "nsucc;": "\u2281", "nsucceq;": "\u2ab0\u0338", "nsup;": "\u2285", "nsupE;": "\u2ac6\u0338", "nsupe;": "\u2289", "nsupset;": "\u2283\u20d2", "nsupseteq;": "\u2289", "nsupseteqq;": "\u2ac6\u0338", "ntgl;": "\u2279", "ntilde": "\xf1", "ntilde;": "\xf1", "ntlg;": "\u2278", "ntriangleleft;": "\u22ea", "ntrianglelefteq;": "\u22ec", "ntriangleright;": "\u22eb", "ntrianglerighteq;": "\u22ed", "nu;": "\u03bd", "num;": "#", "numero;": "\u2116", "numsp;": "\u2007", "nvDash;": "\u22ad", "nvHarr;": "\u2904", "nvap;": "\u224d\u20d2", "nvdash;": "\u22ac", "nvge;": "\u2265\u20d2", "nvgt;": ">\u20d2", "nvinfin;": "\u29de", "nvlArr;": "\u2902", "nvle;": "\u2264\u20d2", "nvlt;": "<\u20d2", "nvltrie;": "\u22b4\u20d2", "nvrArr;": "\u2903", "nvrtrie;": "\u22b5\u20d2", "nvsim;": "\u223c\u20d2", "nwArr;": "\u21d6", "nwarhk;": "\u2923", "nwarr;": "\u2196", "nwarrow;": "\u2196", "nwnear;": "\u2927", "oS;": "\u24c8", "oacute": "\xf3", "oacute;": "\xf3", "oast;": "\u229b", "ocir;": "\u229a", "ocirc": "\xf4", "ocirc;": "\xf4", "ocy;": "\u043e", "odash;": "\u229d", "odblac;": "\u0151", "odiv;": "\u2a38", "odot;": "\u2299", "odsold;": "\u29bc", "oelig;": "\u0153", "ofcir;": "\u29bf", "ofr;": "\U0001d52c", "ogon;": "\u02db", "ograve": "\xf2", "ograve;": "\xf2", "ogt;": "\u29c1", "ohbar;": "\u29b5", "ohm;": "\u03a9", "oint;": "\u222e", "olarr;": "\u21ba", "olcir;": "\u29be", "olcross;": "\u29bb", "oline;": "\u203e", "olt;": "\u29c0", "omacr;": "\u014d", "omega;": "\u03c9", "omicron;": "\u03bf", "omid;": "\u29b6", "ominus;": "\u2296", "oopf;": "\U0001d560", "opar;": "\u29b7", "operp;": "\u29b9", "oplus;": "\u2295", "or;": "\u2228", "orarr;": "\u21bb", "ord;": "\u2a5d", "order;": "\u2134", "orderof;": "\u2134", "ordf": "\xaa", "ordf;": "\xaa", "ordm": "\xba", "ordm;": "\xba", "origof;": "\u22b6", "oror;": "\u2a56", "orslope;": "\u2a57", "orv;": "\u2a5b", "oscr;": "\u2134", "oslash": "\xf8", "oslash;": "\xf8", "osol;": "\u2298", "otilde": "\xf5", "otilde;": "\xf5", "otimes;": "\u2297", "otimesas;": "\u2a36", "ouml": "\xf6", "ouml;": "\xf6", "ovbar;": "\u233d", "par;": "\u2225", "para": "\xb6", "para;": "\xb6", "parallel;": "\u2225", "parsim;": "\u2af3", "parsl;": "\u2afd", "part;": "\u2202", "pcy;": "\u043f", "percnt;": "%", "period;": ".", "permil;": "\u2030", "perp;": "\u22a5", "pertenk;": "\u2031", "pfr;": "\U0001d52d", "phi;": "\u03c6", "phiv;": "\u03d5", "phmmat;": "\u2133", "phone;": "\u260e", "pi;": "\u03c0", "pitchfork;": "\u22d4", "piv;": "\u03d6", "planck;": "\u210f", "planckh;": "\u210e", "plankv;": "\u210f", "plus;": "+", "plusacir;": "\u2a23", "plusb;": "\u229e", "pluscir;": "\u2a22", "plusdo;": "\u2214", "plusdu;": "\u2a25", "pluse;": "\u2a72", "plusmn": "\xb1", "plusmn;": "\xb1", "plussim;": "\u2a26", "plustwo;": "\u2a27", "pm;": "\xb1", "pointint;": "\u2a15", "popf;": "\U0001d561", "pound": "\xa3", "pound;": "\xa3", "pr;": "\u227a", "prE;": "\u2ab3", "prap;": "\u2ab7", "prcue;": "\u227c", "pre;": "\u2aaf", "prec;": "\u227a", "precapprox;": "\u2ab7", "preccurlyeq;": "\u227c", "preceq;": "\u2aaf", "precnapprox;": "\u2ab9", "precneqq;": "\u2ab5", "precnsim;": "\u22e8", "precsim;": "\u227e", "prime;": "\u2032", "primes;": "\u2119", "prnE;": "\u2ab5", "prnap;": "\u2ab9", "prnsim;": "\u22e8", "prod;": "\u220f", "profalar;": "\u232e", "profline;": "\u2312", "profsurf;": "\u2313", "prop;": "\u221d", "propto;": "\u221d", "prsim;": "\u227e", "prurel;": "\u22b0", "pscr;": "\U0001d4c5", "psi;": "\u03c8", "puncsp;": "\u2008", "qfr;": "\U0001d52e", "qint;": "\u2a0c", "qopf;": "\U0001d562", "qprime;": "\u2057", "qscr;": "\U0001d4c6", "quaternions;": "\u210d", "quatint;": "\u2a16", "quest;": "?", "questeq;": "\u225f", "quot": "\"", "quot;": "\"", "rAarr;": "\u21db", "rArr;": "\u21d2", "rAtail;": "\u291c", "rBarr;": "\u290f", "rHar;": "\u2964", "race;": "\u223d\u0331", "racute;": "\u0155", "radic;": "\u221a", "raemptyv;": "\u29b3", "rang;": "\u27e9", "rangd;": "\u2992", "range;": "\u29a5", "rangle;": "\u27e9", "raquo": "\xbb", "raquo;": "\xbb", "rarr;": "\u2192", "rarrap;": "\u2975", "rarrb;": "\u21e5", "rarrbfs;": "\u2920", "rarrc;": "\u2933", "rarrfs;": "\u291e", "rarrhk;": "\u21aa", "rarrlp;": "\u21ac", "rarrpl;": "\u2945", "rarrsim;": "\u2974", "rarrtl;": "\u21a3", "rarrw;": "\u219d", "ratail;": "\u291a", "ratio;": "\u2236", "rationals;": "\u211a", "rbarr;": "\u290d", "rbbrk;": "\u2773", "rbrace;": "}", "rbrack;": "]", "rbrke;": "\u298c", "rbrksld;": "\u298e", "rbrkslu;": "\u2990", "rcaron;": "\u0159", "rcedil;": "\u0157", "rceil;": "\u2309", "rcub;": "}", "rcy;": "\u0440", "rdca;": "\u2937", "rdldhar;": "\u2969", "rdquo;": "\u201d", "rdquor;": "\u201d", "rdsh;": "\u21b3", "real;": "\u211c", "realine;": "\u211b", "realpart;": "\u211c", "reals;": "\u211d", "rect;": "\u25ad", "reg": "\xae", "reg;": "\xae", "rfisht;": "\u297d", "rfloor;": "\u230b", "rfr;": "\U0001d52f", "rhard;": "\u21c1", "rharu;": "\u21c0", "rharul;": "\u296c", "rho;": "\u03c1", "rhov;": "\u03f1", "rightarrow;": "\u2192", "rightarrowtail;": "\u21a3", "rightharpoondown;": "\u21c1", "rightharpoonup;": "\u21c0", "rightleftarrows;": "\u21c4", "rightleftharpoons;": "\u21cc", "rightrightarrows;": "\u21c9", "rightsquigarrow;": "\u219d", "rightthreetimes;": "\u22cc", "ring;": "\u02da", "risingdotseq;": "\u2253", "rlarr;": "\u21c4", "rlhar;": "\u21cc", "rlm;": "\u200f", "rmoust;": "\u23b1", "rmoustache;": "\u23b1", "rnmid;": "\u2aee", "roang;": "\u27ed", "roarr;": "\u21fe", "robrk;": "\u27e7", "ropar;": "\u2986", "ropf;": "\U0001d563", "roplus;": "\u2a2e", "rotimes;": "\u2a35", "rpar;": ")", "rpargt;": "\u2994", "rppolint;": "\u2a12", "rrarr;": "\u21c9", "rsaquo;": "\u203a", "rscr;": "\U0001d4c7", "rsh;": "\u21b1", "rsqb;": "]", "rsquo;": "\u2019", "rsquor;": "\u2019", "rthree;": "\u22cc", "rtimes;": "\u22ca", "rtri;": "\u25b9", "rtrie;": "\u22b5", "rtrif;": "\u25b8", "rtriltri;": "\u29ce", "ruluhar;": "\u2968", "rx;": "\u211e", "sacute;": "\u015b", "sbquo;": "\u201a", "sc;": "\u227b", "scE;": "\u2ab4", "scap;": "\u2ab8", "scaron;": "\u0161", "sccue;": "\u227d", "sce;": "\u2ab0", "scedil;": "\u015f", "scirc;": "\u015d", "scnE;": "\u2ab6", "scnap;": "\u2aba", "scnsim;": "\u22e9", "scpolint;": "\u2a13", "scsim;": "\u227f", "scy;": "\u0441", "sdot;": "\u22c5", "sdotb;": "\u22a1", "sdote;": "\u2a66", "seArr;": "\u21d8", "searhk;": "\u2925", "searr;": "\u2198", "searrow;": "\u2198", "sect": "\xa7", "sect;": "\xa7", "semi;": ";", "seswar;": "\u2929", "setminus;": "\u2216", "setmn;": "\u2216", "sext;": "\u2736", "sfr;": "\U0001d530", "sfrown;": "\u2322", "sharp;": "\u266f", "shchcy;": "\u0449", "shcy;": "\u0448", "shortmid;": "\u2223", "shortparallel;": "\u2225", "shy": "\xad", "shy;": "\xad", "sigma;": "\u03c3", "sigmaf;": "\u03c2", "sigmav;": "\u03c2", "sim;": "\u223c", "simdot;": "\u2a6a", "sime;": "\u2243", "simeq;": "\u2243", "simg;": "\u2a9e", "simgE;": "\u2aa0", "siml;": "\u2a9d", "simlE;": "\u2a9f", "simne;": "\u2246", "simplus;": "\u2a24", "simrarr;": "\u2972", "slarr;": "\u2190", "smallsetminus;": "\u2216", "smashp;": "\u2a33", "smeparsl;": "\u29e4", "smid;": "\u2223", "smile;": "\u2323", "smt;": "\u2aaa", "smte;": "\u2aac", "smtes;": "\u2aac\ufe00", "softcy;": "\u044c", "sol;": "/", "solb;": "\u29c4", "solbar;": "\u233f", "sopf;": "\U0001d564", "spades;": "\u2660", "spadesuit;": "\u2660", "spar;": "\u2225", "sqcap;": "\u2293", "sqcaps;": "\u2293\ufe00", "sqcup;": "\u2294", "sqcups;": "\u2294\ufe00", "sqsub;": "\u228f", "sqsube;": "\u2291", "sqsubset;": "\u228f", "sqsubseteq;": "\u2291", "sqsup;": "\u2290", "sqsupe;": "\u2292", "sqsupset;": "\u2290", "sqsupseteq;": "\u2292", "squ;": "\u25a1", "square;": "\u25a1", "squarf;": "\u25aa", "squf;": "\u25aa", "srarr;": "\u2192", "sscr;": "\U0001d4c8", "ssetmn;": "\u2216", "ssmile;": "\u2323", "sstarf;": "\u22c6", "star;": "\u2606", "starf;": "\u2605", "straightepsilon;": "\u03f5", "straightphi;": "\u03d5", "strns;": "\xaf", "sub;": "\u2282", "subE;": "\u2ac5", "subdot;": "\u2abd", "sube;": "\u2286", "subedot;": "\u2ac3", "submult;": "\u2ac1", "subnE;": "\u2acb", "subne;": "\u228a", "subplus;": "\u2abf", "subrarr;": "\u2979", "subset;": "\u2282", "subseteq;": "\u2286", "subseteqq;": "\u2ac5", "subsetneq;": "\u228a", "subsetneqq;": "\u2acb", "subsim;": "\u2ac7", "subsub;": "\u2ad5", "subsup;": "\u2ad3", "succ;": "\u227b", "succapprox;": "\u2ab8", "succcurlyeq;": "\u227d", "succeq;": "\u2ab0", "succnapprox;": "\u2aba", "succneqq;": "\u2ab6", "succnsim;": "\u22e9", "succsim;": "\u227f", "sum;": "\u2211", "sung;": "\u266a", "sup1": "\xb9", "sup1;": "\xb9", "sup2": "\xb2", "sup2;": "\xb2", "sup3": "\xb3", "sup3;": "\xb3", "sup;": "\u2283", "supE;": "\u2ac6", "supdot;": "\u2abe", "supdsub;": "\u2ad8", "supe;": "\u2287", "supedot;": "\u2ac4", "suphsol;": "\u27c9", "suphsub;": "\u2ad7", "suplarr;": "\u297b", "supmult;": "\u2ac2", "supnE;": "\u2acc", "supne;": "\u228b", "supplus;": "\u2ac0", "supset;": "\u2283", "supseteq;": "\u2287", "supseteqq;": "\u2ac6", "supsetneq;": "\u228b", "supsetneqq;": "\u2acc", "supsim;": "\u2ac8", "supsub;": "\u2ad4", "supsup;": "\u2ad6", "swArr;": "\u21d9", "swarhk;": "\u2926", "swarr;": "\u2199", "swarrow;": "\u2199", "swnwar;": "\u292a", "szlig": "\xdf", "szlig;": "\xdf", "target;": "\u2316", "tau;": "\u03c4", "tbrk;": "\u23b4", "tcaron;": "\u0165", "tcedil;": "\u0163", "tcy;": "\u0442", "tdot;": "\u20db", "telrec;": "\u2315", "tfr;": "\U0001d531", "there4;": "\u2234", "therefore;": "\u2234", "theta;": "\u03b8", "thetasym;": "\u03d1", "thetav;": "\u03d1", "thickapprox;": "\u2248", "thicksim;": "\u223c", "thinsp;": "\u2009", "thkap;": "\u2248", "thksim;": "\u223c", "thorn": "\xfe", "thorn;": "\xfe", "tilde;": "\u02dc", "times": "\xd7", "times;": "\xd7", "timesb;": "\u22a0", "timesbar;": "\u2a31", "timesd;": "\u2a30", "tint;": "\u222d", "toea;": "\u2928", "top;": "\u22a4", "topbot;": "\u2336", "topcir;": "\u2af1", "topf;": "\U0001d565", "topfork;": "\u2ada", "tosa;": "\u2929", "tprime;": "\u2034", "trade;": "\u2122", "triangle;": "\u25b5", "triangledown;": "\u25bf", "triangleleft;": "\u25c3", "trianglelefteq;": "\u22b4", "triangleq;": "\u225c", "triangleright;": "\u25b9", "trianglerighteq;": "\u22b5", "tridot;": "\u25ec", "trie;": "\u225c", "triminus;": "\u2a3a", "triplus;": "\u2a39", "trisb;": "\u29cd", "tritime;": "\u2a3b", "trpezium;": "\u23e2", "tscr;": "\U0001d4c9", "tscy;": "\u0446", "tshcy;": "\u045b", "tstrok;": "\u0167", "twixt;": "\u226c", "twoheadleftarrow;": "\u219e", "twoheadrightarrow;": "\u21a0", "uArr;": "\u21d1", "uHar;": "\u2963", "uacute": "\xfa", "uacute;": "\xfa", "uarr;": "\u2191", "ubrcy;": "\u045e", "ubreve;": "\u016d", "ucirc": "\xfb", "ucirc;": "\xfb", "ucy;": "\u0443", "udarr;": "\u21c5", "udblac;": "\u0171", "udhar;": "\u296e", "ufisht;": "\u297e", "ufr;": "\U0001d532", "ugrave": "\xf9", "ugrave;": "\xf9", "uharl;": "\u21bf", "uharr;": "\u21be", "uhblk;": "\u2580", "ulcorn;": "\u231c", "ulcorner;": "\u231c", "ulcrop;": "\u230f", "ultri;": "\u25f8", "umacr;": "\u016b", "uml": "\xa8", "uml;": "\xa8", "uogon;": "\u0173", "uopf;": "\U0001d566", "uparrow;": "\u2191", "updownarrow;": "\u2195", "upharpoonleft;": "\u21bf", "upharpoonright;": "\u21be", "uplus;": "\u228e", "upsi;": "\u03c5", "upsih;": "\u03d2", "upsilon;": "\u03c5", "upuparrows;": "\u21c8", "urcorn;": "\u231d", "urcorner;": "\u231d", "urcrop;": "\u230e", "uring;": "\u016f", "urtri;": "\u25f9", "uscr;": "\U0001d4ca", "utdot;": "\u22f0", "utilde;": "\u0169", "utri;": "\u25b5", "utrif;": "\u25b4", "uuarr;": "\u21c8", "uuml": "\xfc", "uuml;": "\xfc", "uwangle;": "\u29a7", "vArr;": "\u21d5", "vBar;": "\u2ae8", "vBarv;": "\u2ae9", "vDash;": "\u22a8", "vangrt;": "\u299c", "varepsilon;": "\u03f5", "varkappa;": "\u03f0", "varnothing;": "\u2205", "varphi;": "\u03d5", "varpi;": "\u03d6", "varpropto;": "\u221d", "varr;": "\u2195", "varrho;": "\u03f1", "varsigma;": "\u03c2", "varsubsetneq;": "\u228a\ufe00", "varsubsetneqq;": "\u2acb\ufe00", "varsupsetneq;": "\u228b\ufe00", "varsupsetneqq;": "\u2acc\ufe00", "vartheta;": "\u03d1", "vartriangleleft;": "\u22b2", "vartriangleright;": "\u22b3", "vcy;": "\u0432", "vdash;": "\u22a2", "vee;": "\u2228", "veebar;": "\u22bb", "veeeq;": "\u225a", "vellip;": "\u22ee", "verbar;": "|", "vert;": "|", "vfr;": "\U0001d533", "vltri;": "\u22b2", "vnsub;": "\u2282\u20d2", "vnsup;": "\u2283\u20d2", "vopf;": "\U0001d567", "vprop;": "\u221d", "vrtri;": "\u22b3", "vscr;": "\U0001d4cb", "vsubnE;": "\u2acb\ufe00", "vsubne;": "\u228a\ufe00", "vsupnE;": "\u2acc\ufe00", "vsupne;": "\u228b\ufe00", "vzigzag;": "\u299a", "wcirc;": "\u0175", "wedbar;": "\u2a5f", "wedge;": "\u2227", "wedgeq;": "\u2259", "weierp;": "\u2118", "wfr;": "\U0001d534", "wopf;": "\U0001d568", "wp;": "\u2118", "wr;": "\u2240", "wreath;": "\u2240", "wscr;": "\U0001d4cc", "xcap;": "\u22c2", "xcirc;": "\u25ef", "xcup;": "\u22c3", "xdtri;": "\u25bd", "xfr;": "\U0001d535", "xhArr;": "\u27fa", "xharr;": "\u27f7", "xi;": "\u03be", "xlArr;": "\u27f8", "xlarr;": "\u27f5", "xmap;": "\u27fc", "xnis;": "\u22fb", "xodot;": "\u2a00", "xopf;": "\U0001d569", "xoplus;": "\u2a01", "xotime;": "\u2a02", "xrArr;": "\u27f9", "xrarr;": "\u27f6", "xscr;": "\U0001d4cd", "xsqcup;": "\u2a06", "xuplus;": "\u2a04", "xutri;": "\u25b3", "xvee;": "\u22c1", "xwedge;": "\u22c0", "yacute": "\xfd", "yacute;": "\xfd", "yacy;": "\u044f", "ycirc;": "\u0177", "ycy;": "\u044b", "yen": "\xa5", "yen;": "\xa5", "yfr;": "\U0001d536", "yicy;": "\u0457", "yopf;": "\U0001d56a", "yscr;": "\U0001d4ce", "yucy;": "\u044e", "yuml": "\xff", "yuml;": "\xff", "zacute;": "\u017a", "zcaron;": "\u017e", "zcy;": "\u0437", "zdot;": "\u017c", "zeetrf;": "\u2128", "zeta;": "\u03b6", "zfr;": "\U0001d537", "zhcy;": "\u0436", "zigrarr;": "\u21dd", "zopf;": "\U0001d56b", "zscr;": "\U0001d4cf", "zwj;": "\u200d", "zwnj;": "\u200c", } replacementCharacters = { 0x0: "\uFFFD", 0x0d: "\u000D", 0x80: "\u20AC", 0x81: "\u0081", 0x82: "\u201A", 0x83: "\u0192", 0x84: "\u201E", 0x85: "\u2026", 0x86: "\u2020", 0x87: "\u2021", 0x88: "\u02C6", 0x89: "\u2030", 0x8A: "\u0160", 0x8B: "\u2039", 0x8C: "\u0152", 0x8D: "\u008D", 0x8E: "\u017D", 0x8F: "\u008F", 0x90: "\u0090", 0x91: "\u2018", 0x92: "\u2019", 0x93: "\u201C", 0x94: "\u201D", 0x95: "\u2022", 0x96: "\u2013", 0x97: "\u2014", 0x98: "\u02DC", 0x99: "\u2122", 0x9A: "\u0161", 0x9B: "\u203A", 0x9C: "\u0153", 0x9D: "\u009D", 0x9E: "\u017E", 0x9F: "\u0178", } tokenTypes = { "Doctype": 0, "Characters": 1, "SpaceCharacters": 2, "StartTag": 3, "EndTag": 4, "EmptyTag": 5, "Comment": 6, "ParseError": 7 } tagTokenTypes = frozenset([tokenTypes["StartTag"], tokenTypes["EndTag"], tokenTypes["EmptyTag"]]) prefixes = dict([(v, k) for k, v in namespaces.items()]) prefixes["http://www.w3.org/1998/Math/MathML"] = "math" class DataLossWarning(UserWarning): """Raised when the current tree is unable to represent the input data""" pass class _ReparseException(Exception): pass PKÒ¶N]eŠo©……5site-packages/pip/_vendor/html5lib/treewalkers/dom.pynu„[µü¤from __future__ import absolute_import, division, unicode_literals from xml.dom import Node from . import base class TreeWalker(base.NonRecursiveTreeWalker): def getNodeDetails(self, node): if node.nodeType == Node.DOCUMENT_TYPE_NODE: return base.DOCTYPE, node.name, node.publicId, node.systemId elif node.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE): return base.TEXT, node.nodeValue elif node.nodeType == Node.ELEMENT_NODE: attrs = {} for attr in list(node.attributes.keys()): attr = node.getAttributeNode(attr) if attr.namespaceURI: attrs[(attr.namespaceURI, attr.localName)] = attr.value else: attrs[(None, attr.name)] = attr.value return (base.ELEMENT, node.namespaceURI, node.nodeName, attrs, node.hasChildNodes()) elif node.nodeType == Node.COMMENT_NODE: return base.COMMENT, node.nodeValue elif node.nodeType in (Node.DOCUMENT_NODE, Node.DOCUMENT_FRAGMENT_NODE): return (base.DOCUMENT,) else: return base.UNKNOWN, node.nodeType def getFirstChild(self, node): return node.firstChild def getNextSibling(self, node): return node.nextSibling def getParentNode(self, node): return node.parentNode PKÓ¶N]­fÜRR:site-packages/pip/_vendor/html5lib/treewalkers/__init__.pynu„[µü¤"""A collection of modules for iterating through different kinds of tree, generating tokens identical to those produced by the tokenizer module. To create a tree walker for a new type of tree, you need to do implement a tree walker object (called TreeWalker by convention) that implements a 'serialize' method taking a tree as sole argument and returning an iterator generating tokens. """ from __future__ import absolute_import, division, unicode_literals from .. import constants from .._utils import default_etree __all__ = ["getTreeWalker", "pprint"] treeWalkerCache = {} def getTreeWalker(treeType, implementation=None, **kwargs): """Get a TreeWalker class for various types of tree with built-in support :arg str treeType: the name of the tree type required (case-insensitive). Supported values are: * "dom": The xml.dom.minidom DOM implementation * "etree": A generic walker for tree implementations exposing an elementtree-like interface (known to work with ElementTree, cElementTree and lxml.etree). * "lxml": Optimized walker for lxml.etree * "genshi": a Genshi stream :arg implementation: A module implementing the tree type e.g. xml.etree.ElementTree or cElementTree (Currently applies to the "etree" tree type only). :arg kwargs: keyword arguments passed to the etree walker--for other walkers, this has no effect :returns: a TreeWalker class """ treeType = treeType.lower() if treeType not in treeWalkerCache: if treeType == "dom": from . import dom treeWalkerCache[treeType] = dom.TreeWalker elif treeType == "genshi": from . import genshi treeWalkerCache[treeType] = genshi.TreeWalker elif treeType == "lxml": from . import etree_lxml treeWalkerCache[treeType] = etree_lxml.TreeWalker elif treeType == "etree": from . import etree if implementation is None: implementation = default_etree # XXX: NEVER cache here, caching is done in the etree submodule return etree.getETreeModule(implementation, **kwargs).TreeWalker return treeWalkerCache.get(treeType) def concatenateCharacterTokens(tokens): pendingCharacters = [] for token in tokens: type = token["type"] if type in ("Characters", "SpaceCharacters"): pendingCharacters.append(token["data"]) else: if pendingCharacters: yield {"type": "Characters", "data": "".join(pendingCharacters)} pendingCharacters = [] yield token if pendingCharacters: yield {"type": "Characters", "data": "".join(pendingCharacters)} def pprint(walker): """Pretty printer for tree walkers Takes a TreeWalker instance and pretty prints the output of walking the tree. :arg walker: a TreeWalker instance """ output = [] indent = 0 for token in concatenateCharacterTokens(walker): type = token["type"] if type in ("StartTag", "EmptyTag"): # tag name if token["namespace"] and token["namespace"] != constants.namespaces["html"]: if token["namespace"] in constants.prefixes: ns = constants.prefixes[token["namespace"]] else: ns = token["namespace"] name = "%s %s" % (ns, token["name"]) else: name = token["name"] output.append("%s<%s>" % (" " * indent, name)) indent += 2 # attributes (sorted for consistent ordering) attrs = token["data"] for (namespace, localname), value in sorted(attrs.items()): if namespace: if namespace in constants.prefixes: ns = constants.prefixes[namespace] else: ns = namespace name = "%s %s" % (ns, localname) else: name = localname output.append("%s%s=\"%s\"" % (" " * indent, name, value)) # self-closing if type == "EmptyTag": indent -= 2 elif type == "EndTag": indent -= 2 elif type == "Comment": output.append("%s" % (" " * indent, token["data"])) elif type == "Doctype": if token["name"]: if token["publicId"]: output.append("""%s""" % (" " * indent, token["name"], token["publicId"], token["systemId"] if token["systemId"] else "")) elif token["systemId"]: output.append("""%s""" % (" " * indent, token["name"], token["systemId"])) else: output.append("%s" % (" " * indent, token["name"])) else: output.append("%s" % (" " * indent,)) elif type == "Characters": output.append("%s\"%s\"" % (" " * indent, token["data"])) elif type == "SpaceCharacters": assert False, "concatenateCharacterTokens should have got rid of all Space tokens" else: raise ValueError("Unknown token type, %s" % type) return "\n".join(output) PKÓ¶N]Á´¾¶¶Tsite-packages/pip/_vendor/html5lib/treewalkers/__pycache__/etree_lxml.cpython-38.pycnu„[µü¤U ÀÒ.e¥ã@s®ddlmZmZmZddlmZddlmZddlm Z ddl m Z ddl m Z d d „Z Gd d „d eƒZGd d„deƒZGdd„deƒZGdd„deƒZGdd„de jƒZdS)é)Úabsolute_importÚdivisionÚunicode_literals)Ú text_type)Úetreeé)Ú tag_regexpé)Úbase)Ú _ihatexmlcCs*|dkr dSt|tƒr|S| dd¡SdS)NÚasciiÚstrict)Ú isinstancerÚdecode)Ús©rúO/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.pyÚ ensure_str s  rc@s,eZdZdd„Zdd„Zdd„Zdd„Zd S) ÚRootcCsÆ||_g|_z:|jjrD|j t|t|jjƒt|jjƒt|jj ƒƒ¡Wnt k rZYnXz |  ¡}Wnt k r€|}YnX|  ¡dk r˜|  ¡}q‚|dk r¶|j |¡|  ¡}q˜d|_d|_dS©N)Z elementtreeÚchildrenZdocinfoZ internalDTDÚappendÚDoctyperZ root_nameÚ public_idZ system_urlÚAttributeErrorZgetrootZ getpreviousÚgetnextÚtextÚtail)ÚselfZetÚnoderrrÚ__init__s,    ý       z Root.__init__cCs |j|Sr)r©rÚkeyrrrÚ __getitem__1szRoot.__getitem__cCsdSrr©rrrrr4sz Root.getnextcCsdS©Nr rr$rrrÚ__len__7sz Root.__len__N)Ú__name__Ú __module__Ú __qualname__r r#rr&rrrrrsrc@seZdZdd„Zdd„ZdS)rcCs(||_||_||_||_d|_d|_dSr)Ú root_nodeÚnamerÚ system_idrr)rr*r+rr,rrrr <s zDoctype.__init__cCs |jjdSr%)r*rr$rrrrEszDoctype.getnextN©r'r(r)r rrrrrr;s rc@seZdZdd„Zdd„ZdS)Ú FragmentRootcs$‡fdd„|Dƒˆ_dˆ_ˆ_dS)Ncsg|]}tˆ|ƒ‘qSr)ÚFragmentWrapper)Ú.0Zchildr$rrÚ Ksz)FragmentRoot.__init__..)rrr)rrrr$rr JszFragmentRoot.__init__cCsdSrrr$rrrrNszFragmentRoot.getnextNr-rrrrr.Isr.c@sTeZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dd„Z dS)r/cCsT||_||_t|jdƒr(t|jjƒ|_nd|_t|jdƒrJt|jjƒ|_nd|_dS)Nrr)r*ÚobjÚhasattrrrr)rZ fragment_rootr2rrrr Ss  zFragmentWrapper.__init__cCs t|j|ƒSr)Úgetattrr2)rr+rrrÚ __getattr___szFragmentWrapper.__getattr__cCs6|jj}| |¡}|t|ƒdkr.||dSdSdSr%)r*rÚindexÚlen)rZsiblingsÚidxrrrrbs   zFragmentWrapper.getnextcCs |j|Sr)r2r!rrrr#jszFragmentWrapper.__getitem__cCs t|jƒSr)Úboolr2r$rrrÚ__bool__mszFragmentWrapper.__bool__cCsdSrrr$rrrÚ getparentpszFragmentWrapper.getparentcCs t|jƒSr©Ústrr2r$rrrÚ__str__sszFragmentWrapper.__str__cCs t|jƒSrr<r$rrrÚ __unicode__vszFragmentWrapper.__unicode__cCs t|jƒSr)r7r2r$rrrr&yszFragmentWrapper.__len__N) r'r(r)r r5rr#r:r;r>r?r&rrrrr/Rs r/c@s4eZdZdd„Zdd„Zdd„Zdd„Zd d „Zd S) Ú TreeWalkercCsJt|tƒrt|ƒ|_t|ƒ}ntƒ|_t|ƒ}tj ||¡t   ¡|_ dSr) rÚlistÚsetÚfragmentChildrenr.rr ÚNonRecursiveTreeWalkerr r Z InfosetFilterÚfilter)rZtreerrrr ~s   zTreeWalker.__init__c Cs�t|tƒr:|\}}|dks&td|ƒ‚tjtt||ƒƒfSt|tƒrLtjfSt|t ƒrjtj |j |j |j fSt|tƒrŽt|dƒsŽtjt|jƒfS|jtjkrªtjt|jƒfS|jtjkrÎtjt|jƒdd…fSt t|jƒ¡}|�rò| ¡\}}nd}t|jƒ}i}t|j ¡ƒD]P\}}t|ƒ}t|ƒ}t |¡}|�rT||| d¡| d¡f<n ||d|f<�qtj||j  !|¡|t"|ƒdk�pˆ|jfSdS)N©rrú%Text nodes are text or tail, found %sÚtagr éÿÿÿÿrr)#rÚtupleÚAssertionErrorr ZTEXTrr4rZDOCUMENTrZDOCTYPEr+rr,r/r3r2rHrÚCommentÚCOMMENTrZEntityZENTITYrÚmatchÚgroupsrAZattribÚitemsÚgroupZELEMENTrEZ fromXmlNamer7) rrr"rNÚ namespacerHZattrsr+ÚvaluerrrÚgetNodeDetails‰s>       ÿzTreeWalker.getNodeDetailscCsBt|tƒrtdƒ‚t|ƒs(|js(tdƒ‚|jr6|dfS|dSdS)NzText nodes have no childrenzNode has no childrenrr)rrJrKr7r)rrrrrÚ getFirstChild²s zTreeWalker.getFirstChildcCsbt|tƒrL|\}}|dks&td|ƒ‚|dkrDt|ƒr>|dSdSn| ¡S|jrZ|dfS| ¡S)NrFrGrrr)rrJrKr7rr©rrr"rrrÚgetNextSibling»s zTreeWalker.getNextSiblingcCsJt|tƒr4|\}}|dks&td|ƒ‚|dkrB|Sn||jkrBdS| ¡S)NrFrGr)rrJrKrCr;rVrrrÚ getParentNodeËs  zTreeWalker.getParentNodeN)r'r(r)r rTrUrWrXrrrrr@}s  ) r@N)Z __future__rrrZpip._vendor.sixrZlxmlrZtreebuilders.etreerÚr r rÚobjectrrr.r/rDr@rrrrÚs      & +PKÓ¶N]—-—†žžZsite-packages/pip/_vendor/html5lib/treewalkers/__pycache__/etree_lxml.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.e¥ã@s®ddlmZmZmZddlmZddlmZddlm Z ddl m Z ddl m Z d d „Z Gd d „d eƒZGd d„deƒZGdd„deƒZGdd„deƒZGdd„de jƒZdS)é)Úabsolute_importÚdivisionÚunicode_literals)Ú text_type)Úetreeé)Ú tag_regexpé)Úbase)Ú _ihatexmlcCs*|dkr dSt|tƒr|S| dd¡SdS)NÚasciiÚstrict)Ú isinstancerÚdecode)Ús©rúO/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.pyÚ ensure_str s  rc@s,eZdZdd„Zdd„Zdd„Zdd„Zd S) ÚRootcCsÆ||_g|_z:|jjrD|j t|t|jjƒt|jjƒt|jj ƒƒ¡Wnt k rZYnXz |  ¡}Wnt k r€|}YnX|  ¡dk r˜|  ¡}q‚|dk r¶|j |¡|  ¡}q˜d|_d|_dS©N)Z elementtreeÚchildrenZdocinfoZ internalDTDÚappendÚDoctyperZ root_nameÚ public_idZ system_urlÚAttributeErrorZgetrootZ getpreviousÚgetnextÚtextÚtail)ÚselfZetÚnoderrrÚ__init__s,    ý       z Root.__init__cCs |j|Sr)r©rÚkeyrrrÚ __getitem__1szRoot.__getitem__cCsdSrr©rrrrr4sz Root.getnextcCsdS©Nr rr$rrrÚ__len__7sz Root.__len__N)Ú__name__Ú __module__Ú __qualname__r r#rr&rrrrrsrc@seZdZdd„Zdd„ZdS)rcCs(||_||_||_||_d|_d|_dSr)Ú root_nodeÚnamerÚ system_idrr)rr*r+rr,rrrr <s zDoctype.__init__cCs |jjdSr%)r*rr$rrrrEszDoctype.getnextN©r'r(r)r rrrrrr;s rc@seZdZdd„Zdd„ZdS)Ú FragmentRootcs$‡fdd„|Dƒˆ_dˆ_ˆ_dS)Ncsg|]}tˆ|ƒ‘qSr)ÚFragmentWrapper)Ú.0Zchildr$rrÚ Ksz)FragmentRoot.__init__..)rrr)rrrr$rr JszFragmentRoot.__init__cCsdSrrr$rrrrNszFragmentRoot.getnextNr-rrrrr.Isr.c@sTeZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dd„Z dS)r/cCsT||_||_t|jdƒr(t|jjƒ|_nd|_t|jdƒrJt|jjƒ|_nd|_dS)Nrr)r*ÚobjÚhasattrrrr)rZ fragment_rootr2rrrr Ss  zFragmentWrapper.__init__cCs t|j|ƒSr)Úgetattrr2)rr+rrrÚ __getattr___szFragmentWrapper.__getattr__cCs6|jj}| |¡}|t|ƒdkr.||dSdSdSr%)r*rÚindexÚlen)rZsiblingsÚidxrrrrbs   zFragmentWrapper.getnextcCs |j|Sr)r2r!rrrr#jszFragmentWrapper.__getitem__cCs t|jƒSr)Úboolr2r$rrrÚ__bool__mszFragmentWrapper.__bool__cCsdSrrr$rrrÚ getparentpszFragmentWrapper.getparentcCs t|jƒSr©Ústrr2r$rrrÚ__str__sszFragmentWrapper.__str__cCs t|jƒSrr<r$rrrÚ __unicode__vszFragmentWrapper.__unicode__cCs t|jƒSr)r7r2r$rrrr&yszFragmentWrapper.__len__N) r'r(r)r r5rr#r:r;r>r?r&rrrrr/Rs r/c@s4eZdZdd„Zdd„Zdd„Zdd„Zd d „Zd S) Ú TreeWalkercCsJt|tƒrt|ƒ|_t|ƒ}ntƒ|_t|ƒ}tj ||¡t   ¡|_ dSr) rÚlistÚsetÚfragmentChildrenr.rr ÚNonRecursiveTreeWalkerr r Z InfosetFilterÚfilter)rZtreerrrr ~s   zTreeWalker.__init__c Cszt|tƒr&|\}}tjtt||ƒƒfSt|tƒr8tjfSt|tƒrVtj |j |j |j fSt|t ƒrzt|dƒsztjt|jƒfS|jtjkr–tjt|jƒfS|jtjkrºtjt|jƒdd…fSt t|jƒ¡}|rÜ| ¡\}}nd}t|jƒ}i}t|j ¡ƒD]P\}}t|ƒ}t|ƒ}t |¡}|�r>||| d¡| d¡f<n ||d|f<�qütj||j  |¡|t!|ƒdk�pr|jfSdS)NÚtagr éÿÿÿÿrr)"rÚtupler ZTEXTrr4rZDOCUMENTrZDOCTYPEr+rr,r/r3r2rFrÚCommentÚCOMMENTrZEntityZENTITYrÚmatchÚgroupsrAZattribÚitemsÚgroupZELEMENTrEZ fromXmlNamer7) rrr"rKÚ namespacerFZattrsr+ÚvaluerrrÚgetNodeDetails‰s<       ÿzTreeWalker.getNodeDetailscCs|jr|dfS|dSdS)Nrr)r)rrrrrÚ getFirstChild²szTreeWalker.getFirstChildcCsNt|tƒr8|\}}|dkr0t|ƒr*|dSdSn| ¡S|jrF|dfS| ¡S)Nrrr)rrHr7rr©rrr"rrrÚgetNextSibling»s zTreeWalker.getNextSiblingcCs6t|tƒr |\}}|dkr.|Sn||jkr.dS| ¡S)Nr)rrHrCr;rSrrrÚ getParentNodeËs  zTreeWalker.getParentNodeN)r'r(r)r rQrRrTrUrrrrr@}s  ) r@N)Z __future__rrrZpip._vendor.sixrZlxmlrZtreebuilders.etreerÚr r rÚobjectrrr.r/rDr@rrrrÚs      & +PKÓ¶N]Ù_)¢¢Msite-packages/pip/_vendor/html5lib/treewalkers/__pycache__/dom.cpython-38.pycnu„[µü¤U ÀÒ.e…ã@sBddlmZmZmZddlmZddlmZGdd„dejƒZ dS)é)Úabsolute_importÚdivisionÚunicode_literals)ÚNodeé)Úbasec@s,eZdZdd„Zdd„Zdd„Zdd„Zd S) Ú TreeWalkercCsð|jtjkr tj|j|j|jfS|jtjtj fkr>tj |j fS|jtj kr®i}t |j ¡ƒD]8}| |¡}|jr„|j||j|jf<q\|j|d|jf<q\tj|j|j|| ¡fS|jtjkrÆtj|j fS|jtjtjfkràtjfStj|jfSdS©N)ZnodeTyperZDOCUMENT_TYPE_NODErZDOCTYPEÚnameZpublicIdZsystemIdZ TEXT_NODEZCDATA_SECTION_NODEZTEXTZ nodeValueZ ELEMENT_NODEÚlistZ attributesÚkeysZgetAttributeNodeZ namespaceURIÚvalueZ localNameZELEMENTZnodeNameZ hasChildNodesZ COMMENT_NODEÚCOMMENTZ DOCUMENT_NODEZDOCUMENT_FRAGMENT_NODEZDOCUMENTZUNKNOWN)ÚselfÚnodeZattrsÚattr©rúH/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treewalkers/dom.pyÚgetNodeDetails s(     ÿ  zTreeWalker.getNodeDetailscCs|jSr )Z firstChild©rrrrrÚ getFirstChild$szTreeWalker.getFirstChildcCs|jSr )Z nextSiblingrrrrÚgetNextSibling'szTreeWalker.getNextSiblingcCs|jSr )Z parentNoderrrrÚ getParentNode*szTreeWalker.getParentNodeN)Ú__name__Ú __module__Ú __qualname__rrrrrrrrrsrN) Z __future__rrrZxml.domrÚrZNonRecursiveTreeWalkerrrrrrÚs  PKÓ¶N]Ù_)¢¢Ssite-packages/pip/_vendor/html5lib/treewalkers/__pycache__/dom.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.e…ã@sBddlmZmZmZddlmZddlmZGdd„dejƒZ dS)é)Úabsolute_importÚdivisionÚunicode_literals)ÚNodeé)Úbasec@s,eZdZdd„Zdd„Zdd„Zdd„Zd S) Ú TreeWalkercCsð|jtjkr tj|j|j|jfS|jtjtj fkr>tj |j fS|jtj kr®i}t |j ¡ƒD]8}| |¡}|jr„|j||j|jf<q\|j|d|jf<q\tj|j|j|| ¡fS|jtjkrÆtj|j fS|jtjtjfkràtjfStj|jfSdS©N)ZnodeTyperZDOCUMENT_TYPE_NODErZDOCTYPEÚnameZpublicIdZsystemIdZ TEXT_NODEZCDATA_SECTION_NODEZTEXTZ nodeValueZ ELEMENT_NODEÚlistZ attributesÚkeysZgetAttributeNodeZ namespaceURIÚvalueZ localNameZELEMENTZnodeNameZ hasChildNodesZ COMMENT_NODEÚCOMMENTZ DOCUMENT_NODEZDOCUMENT_FRAGMENT_NODEZDOCUMENTZUNKNOWN)ÚselfÚnodeZattrsÚattr©rúH/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treewalkers/dom.pyÚgetNodeDetails s(     ÿ  zTreeWalker.getNodeDetailscCs|jSr )Z firstChild©rrrrrÚ getFirstChild$szTreeWalker.getFirstChildcCs|jSr )Z nextSiblingrrrrÚgetNextSibling'szTreeWalker.getNextSiblingcCs|jSr )Z parentNoderrrrÚ getParentNode*szTreeWalker.getParentNodeN)Ú__name__Ú __module__Ú __qualname__rrrrrrrrrsrN) Z __future__rrrZxml.domrÚrZNonRecursiveTreeWalkerrrrrrÚs  PKÓ¶N]AÂ99Tsite-packages/pip/_vendor/html5lib/treewalkers/__pycache__/base.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.e4ã @s ddlmZmZmZddlmZddlmZmZm Z ddddd d d d d g Z ej Z ej ZejZejZejZejZdZd e ¡Z Gdd „d eƒZGdd „d eƒZdS)é)Úabsolute_importÚdivisionÚunicode_literals)ÚNodeé)Ú namespacesÚ voidElementsÚspaceCharactersÚDOCUMENTÚDOCTYPEÚTEXTÚELEMENTÚCOMMENTÚENTITYÚUNKNOWNÚ TreeWalkerÚNonRecursiveTreeWalkerz <#UNKNOWN#>Úc@sleZdZdZdd„Zdd„Zdd„Zdd d „Zd d „Zd d„Z dd„Z dd„Z ddd„Z dd„Z dd„ZdS)rz}Walks a tree yielding tokens Tokens are dicts that all have a ``type`` field specifying the type of the token. cCs ||_dS)zCCreates a TreeWalker :arg tree: the tree to walk N)Útree)Úselfr©rúI/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treewalkers/base.pyÚ__init__szTreeWalker.__init__cCst‚dS©N©ÚNotImplementedError)rrrrÚ__iter__#szTreeWalker.__iter__cCs d|dœS)z†Generates an error token with the given message :arg msg: the error message :returns: SerializeError token ZSerializeError©ÚtypeÚdatar)rÚmsgrrrÚerror&szTreeWalker.errorFccs$d|||dœV|r | d¡VdS)arGenerates an EmptyTag token :arg namespace: the namespace of the token--can be ``None`` :arg name: the name of the element :arg attrs: the attributes of the element as a dict :arg hasChildren: whether or not to yield a SerializationError because this tag shouldn't have children :returns: EmptyTag token ZEmptyTag©rÚnameÚ namespacerzVoid element has childrenN©r!)rr$r#ÚattrsÚ hasChildrenrrrÚemptyTag0s þzTreeWalker.emptyTagcCsd|||dœS)zôGenerates a StartTag token :arg namespace: the namespace of the token--can be ``None`` :arg name: the name of the element :arg attrs: the attributes of the element as a dict :returns: StartTag token ZStartTagr"r)rr$r#r&rrrÚstartTagEs ýzTreeWalker.startTagcCs d||dœS)z´Generates an EndTag token :arg namespace: the namespace of the token--can be ``None`` :arg name: the name of the element :returns: EndTag token ZEndTag)rr#r$r)rr$r#rrrÚendTagVs þzTreeWalker.endTagccsx|}| t¡}|dt|ƒt|ƒ…}|r6d|dœV|}| t¡}|t|ƒd…}|rdd|dœV|rtd|dœVdS)atGenerates SpaceCharacters and Characters tokens Depending on what's in the data, this generates one or more ``SpaceCharacters`` and ``Characters`` tokens. For example: >>> from html5lib.treewalkers.base import TreeWalker >>> # Give it an empty tree just so it instantiates >>> walker = TreeWalker([]) >>> list(walker.text('')) [] >>> list(walker.text(' ')) [{u'data': ' ', u'type': u'SpaceCharacters'}] >>> list(walker.text(' abc ')) # doctest: +NORMALIZE_WHITESPACE [{u'data': ' ', u'type': u'SpaceCharacters'}, {u'data': u'abc', u'type': u'Characters'}, {u'data': u' ', u'type': u'SpaceCharacters'}] :arg data: the text data :returns: one or more ``SpaceCharacters`` and ``Characters`` tokens NZSpaceCharactersrZ Characters)Úlstripr ÚlenÚrstrip)rrZmiddleÚleftÚrightrrrÚtextds    zTreeWalker.textcCs d|dœS)zdGenerates a Comment token :arg data: the comment :returns: Comment token ÚCommentrr)rrrrrÚcommentŠszTreeWalker.commentNcCsd|||dœS)zŒGenerates a Doctype token :arg name: :arg publicId: :arg systemId: :returns: the Doctype token ZDoctype)rr#ÚpublicIdÚsystemIdr)rr#r3r4rrrÚdoctype”s ýzTreeWalker.doctypecCs d|dœS)zjGenerates an Entity token :arg name: the entity name :returns: an Entity token ZEntity)rr#r)rr#rrrÚentity¥szTreeWalker.entitycCs| d|¡S)zHandles unknown node typeszUnknown node type: r%)rZnodeTyperrrÚunknown¯szTreeWalker.unknown)F)NN)Ú__name__Ú __module__Ú __qualname__Ú__doc__rrr!r(r)r*r0r2r5r6r7rrrrrs &  c@s4eZdZdd„Zdd„Zdd„Zdd„Zd d „Zd S) rcCst‚dSrr©rZnoderrrÚgetNodeDetailsµsz%NonRecursiveTreeWalker.getNodeDetailscCst‚dSrrr<rrrÚ getFirstChild¸sz$NonRecursiveTreeWalker.getFirstChildcCst‚dSrrr<rrrÚgetNextSibling»sz%NonRecursiveTreeWalker.getNextSiblingcCst‚dSrrr<rrrÚ getParentNode¾sz$NonRecursiveTreeWalker.getParentNodec csò|j}|dk �rî| |¡}|d|dd…}}d}|tkrJ|j|ŽVnÖ|tkrj|j|ŽD] }|Vq\n¶|tkrÊ|\}}}}|rŽ|tdkr¸|tkr¸|  ||||¡D] }|Vq¦d}n|  |||¡VnV|t krä|  |d¡Vn<|t k�r| |d¡Vn |tk�rd}n| |d¡V|�r2| |¡} nd} | dk �rF| }q|dk r| |¡}|d|dd…}}|tk�r°|\}}}}|�r˜|tdk�s¢|tk�r°| ||¡V|j|k�rÂd}q| |¡} | dk �rÞ| }qn | |¡}�qFqdS)NréFZhtmlT)rr=r r5r r0r rrr(r)rr2rr6r r7r>r*r?r@) rZ currentNodeZdetailsrr'Útokenr$r#Z attributesZ firstChildZ nextSiblingrrrrÁs\     ÿ          zNonRecursiveTreeWalker.__iter__N)r8r9r:r=r>r?r@rrrrrr´s N)Z __future__rrrZxml.domrZ constantsrrr Ú__all__Z DOCUMENT_NODEr ZDOCUMENT_TYPE_NODEr Z TEXT_NODEr Z ELEMENT_NODEr Z COMMENT_NODErZ ENTITY_NODErrÚjoinÚobjectrrrrrrÚs" ÿ !PKÓ¶N]¼Xg1Xsite-packages/pip/_vendor/html5lib/treewalkers/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.eRã@sZdZddlmZmZmZddlmZddlmZddgZ iZ d d d„Z d d „Z d d„Z dS)a€A collection of modules for iterating through different kinds of tree, generating tokens identical to those produced by the tokenizer module. To create a tree walker for a new type of tree, you need to do implement a tree walker object (called TreeWalker by convention) that implements a 'serialize' method taking a tree as sole argument and returning an iterator generating tokens. é)Úabsolute_importÚdivisionÚunicode_literalsé)Ú constants)Ú default_etreeÚ getTreeWalkerÚpprintNcKsª| ¡}|tkr |dkr0ddlm}|jt|<np|dkrPddlm}|jt|<nP|dkrpddlm}|jt|<n0|dkr dd lm}|d kr�t}|j |f|ŽjSt  |¡S) a;Get a TreeWalker class for various types of tree with built-in support :arg str treeType: the name of the tree type required (case-insensitive). Supported values are: * "dom": The xml.dom.minidom DOM implementation * "etree": A generic walker for tree implementations exposing an elementtree-like interface (known to work with ElementTree, cElementTree and lxml.etree). * "lxml": Optimized walker for lxml.etree * "genshi": a Genshi stream :arg implementation: A module implementing the tree type e.g. xml.etree.ElementTree or cElementTree (Currently applies to the "etree" tree type only). :arg kwargs: keyword arguments passed to the etree walker--for other walkers, this has no effect :returns: a TreeWalker class Údomé)r Úgenshi)r Zlxml)Ú etree_lxmlÚetree)rN) ÚlowerÚtreeWalkerCacheÚr Z TreeWalkerr r rrZgetETreeModuleÚget)ZtreeTypeÚimplementationÚkwargsr r r r©rúM/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treewalkers/__init__.pyrs"       ccshg}|D]D}|d}|dkr,| |d¡q|rFdd |¡dœVg}|Vq|rddd |¡dœVdS)NÚtype)Ú CharactersÚSpaceCharactersÚdatarr)rr)ÚappendÚjoin)ÚtokensZpendingCharactersÚtokenrrrrÚconcatenateCharacterTokensAsrc CsTg}d}t|ƒD�]6}|d}|dk�r|drz|dtjdkrz|dtjkr`tj|d}n|d}d||df}n|d}| dd ||f¡|d 7}|d }t| ¡ƒD]T\\}} } |rì|tjkrÚtj|}n|}d|| f}n| }| d d ||| f¡q´|d k�rH|d 8}q|dk�r2|d 8}q|dk�rX| dd ||d f¡q|dk�r |d�rô|d�r¬| dd ||d|d|d�r |dndf¡nF|d�rØ| dd ||d|df¡n| dd ||df¡n| dd |f¡q|dk�r0| dd ||d f¡q|dk�rú rrz %s%s="%s"r ZEndTagÚCommentz %sZDoctypeZpublicIdz%sZsystemIdrz%sz%sz %srz%s"%s"rzUnknown token type, %sÚ ) rrZ namespacesÚprefixesrÚsortedÚitemsÚ ValueErrorr) ZwalkerÚoutputÚindentrrÚnsr"Zattrsr!Z localnameÚvaluerrrr Psn           ýÿ þÿ ÿ   )N)Ú__doc__Z __future__rrrrrZ_utilsrÚ__all__rrrr rrrrÚs    ,PKÓ¶N]AÂ99Nsite-packages/pip/_vendor/html5lib/treewalkers/__pycache__/base.cpython-38.pycnu„[µü¤U ÀÒ.e4ã @s ddlmZmZmZddlmZddlmZmZm Z ddddd d d d d g Z ej Z ej ZejZejZejZejZdZd e ¡Z Gdd „d eƒZGdd „d eƒZdS)é)Úabsolute_importÚdivisionÚunicode_literals)ÚNodeé)Ú namespacesÚ voidElementsÚspaceCharactersÚDOCUMENTÚDOCTYPEÚTEXTÚELEMENTÚCOMMENTÚENTITYÚUNKNOWNÚ TreeWalkerÚNonRecursiveTreeWalkerz <#UNKNOWN#>Úc@sleZdZdZdd„Zdd„Zdd„Zdd d „Zd d „Zd d„Z dd„Z dd„Z ddd„Z dd„Z dd„ZdS)rz}Walks a tree yielding tokens Tokens are dicts that all have a ``type`` field specifying the type of the token. cCs ||_dS)zCCreates a TreeWalker :arg tree: the tree to walk N)Útree)Úselfr©rúI/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treewalkers/base.pyÚ__init__szTreeWalker.__init__cCst‚dS©N©ÚNotImplementedError)rrrrÚ__iter__#szTreeWalker.__iter__cCs d|dœS)z†Generates an error token with the given message :arg msg: the error message :returns: SerializeError token ZSerializeError©ÚtypeÚdatar)rÚmsgrrrÚerror&szTreeWalker.errorFccs$d|||dœV|r | d¡VdS)arGenerates an EmptyTag token :arg namespace: the namespace of the token--can be ``None`` :arg name: the name of the element :arg attrs: the attributes of the element as a dict :arg hasChildren: whether or not to yield a SerializationError because this tag shouldn't have children :returns: EmptyTag token ZEmptyTag©rÚnameÚ namespacerzVoid element has childrenN©r!)rr$r#ÚattrsÚ hasChildrenrrrÚemptyTag0s þzTreeWalker.emptyTagcCsd|||dœS)zôGenerates a StartTag token :arg namespace: the namespace of the token--can be ``None`` :arg name: the name of the element :arg attrs: the attributes of the element as a dict :returns: StartTag token ZStartTagr"r)rr$r#r&rrrÚstartTagEs ýzTreeWalker.startTagcCs d||dœS)z´Generates an EndTag token :arg namespace: the namespace of the token--can be ``None`` :arg name: the name of the element :returns: EndTag token ZEndTag)rr#r$r)rr$r#rrrÚendTagVs þzTreeWalker.endTagccsx|}| t¡}|dt|ƒt|ƒ…}|r6d|dœV|}| t¡}|t|ƒd…}|rdd|dœV|rtd|dœVdS)atGenerates SpaceCharacters and Characters tokens Depending on what's in the data, this generates one or more ``SpaceCharacters`` and ``Characters`` tokens. For example: >>> from html5lib.treewalkers.base import TreeWalker >>> # Give it an empty tree just so it instantiates >>> walker = TreeWalker([]) >>> list(walker.text('')) [] >>> list(walker.text(' ')) [{u'data': ' ', u'type': u'SpaceCharacters'}] >>> list(walker.text(' abc ')) # doctest: +NORMALIZE_WHITESPACE [{u'data': ' ', u'type': u'SpaceCharacters'}, {u'data': u'abc', u'type': u'Characters'}, {u'data': u' ', u'type': u'SpaceCharacters'}] :arg data: the text data :returns: one or more ``SpaceCharacters`` and ``Characters`` tokens NZSpaceCharactersrZ Characters)Úlstripr ÚlenÚrstrip)rrZmiddleÚleftÚrightrrrÚtextds    zTreeWalker.textcCs d|dœS)zdGenerates a Comment token :arg data: the comment :returns: Comment token ÚCommentrr)rrrrrÚcommentŠszTreeWalker.commentNcCsd|||dœS)zŒGenerates a Doctype token :arg name: :arg publicId: :arg systemId: :returns: the Doctype token ZDoctype)rr#ÚpublicIdÚsystemIdr)rr#r3r4rrrÚdoctype”s ýzTreeWalker.doctypecCs d|dœS)zjGenerates an Entity token :arg name: the entity name :returns: an Entity token ZEntity)rr#r)rr#rrrÚentity¥szTreeWalker.entitycCs| d|¡S)zHandles unknown node typeszUnknown node type: r%)rZnodeTyperrrÚunknown¯szTreeWalker.unknown)F)NN)Ú__name__Ú __module__Ú __qualname__Ú__doc__rrr!r(r)r*r0r2r5r6r7rrrrrs &  c@s4eZdZdd„Zdd„Zdd„Zdd„Zd d „Zd S) rcCst‚dSrr©rZnoderrrÚgetNodeDetailsµsz%NonRecursiveTreeWalker.getNodeDetailscCst‚dSrrr<rrrÚ getFirstChild¸sz$NonRecursiveTreeWalker.getFirstChildcCst‚dSrrr<rrrÚgetNextSibling»sz%NonRecursiveTreeWalker.getNextSiblingcCst‚dSrrr<rrrÚ getParentNode¾sz$NonRecursiveTreeWalker.getParentNodec csò|j}|dk �rî| |¡}|d|dd…}}d}|tkrJ|j|ŽVnÖ|tkrj|j|ŽD] }|Vq\n¶|tkrÊ|\}}}}|rŽ|tdkr¸|tkr¸|  ||||¡D] }|Vq¦d}n|  |||¡VnV|t krä|  |d¡Vn<|t k�r| |d¡Vn |tk�rd}n| |d¡V|�r2| |¡} nd} | dk �rF| }q|dk r| |¡}|d|dd…}}|tk�r°|\}}}}|�r˜|tdk�s¢|tk�r°| ||¡V|j|k�rÂd}q| |¡} | dk �rÞ| }qn | |¡}�qFqdS)NréFZhtmlT)rr=r r5r r0r rrr(r)rr2rr6r r7r>r*r?r@) rZ currentNodeZdetailsrr'Útokenr$r#Z attributesZ firstChildZ nextSiblingrrrrÁs\     ÿ          zNonRecursiveTreeWalker.__iter__N)r8r9r:r=r>r?r@rrrrrr´s N)Z __future__rrrZxml.domrZ constantsrrr Ú__all__Z DOCUMENT_NODEr ZDOCUMENT_TYPE_NODEr Z TEXT_NODEr Z ELEMENT_NODEr Z COMMENT_NODErZ ENTITY_NODErrÚjoinÚobjectrrrrrrÚs" ÿ !PKÓ¶N]-Û@��Rsite-packages/pip/_vendor/html5lib/treewalkers/__pycache__/__init__.cpython-38.pycnu„[µü¤U ÀÒ.eRã@sZdZddlmZmZmZddlmZddlmZddgZ iZ d d d„Z d d „Z d d„Z dS)a€A collection of modules for iterating through different kinds of tree, generating tokens identical to those produced by the tokenizer module. To create a tree walker for a new type of tree, you need to do implement a tree walker object (called TreeWalker by convention) that implements a 'serialize' method taking a tree as sole argument and returning an iterator generating tokens. é)Úabsolute_importÚdivisionÚunicode_literalsé)Ú constants)Ú default_etreeÚ getTreeWalkerÚpprintNcKsª| ¡}|tkr |dkr0ddlm}|jt|<np|dkrPddlm}|jt|<nP|dkrpddlm}|jt|<n0|dkr dd lm}|d kr�t}|j |f|ŽjSt  |¡S) a;Get a TreeWalker class for various types of tree with built-in support :arg str treeType: the name of the tree type required (case-insensitive). Supported values are: * "dom": The xml.dom.minidom DOM implementation * "etree": A generic walker for tree implementations exposing an elementtree-like interface (known to work with ElementTree, cElementTree and lxml.etree). * "lxml": Optimized walker for lxml.etree * "genshi": a Genshi stream :arg implementation: A module implementing the tree type e.g. xml.etree.ElementTree or cElementTree (Currently applies to the "etree" tree type only). :arg kwargs: keyword arguments passed to the etree walker--for other walkers, this has no effect :returns: a TreeWalker class Údomé)r Úgenshi)r Zlxml)Ú etree_lxmlÚetree)rN) ÚlowerÚtreeWalkerCacheÚr Z TreeWalkerr r rrZgetETreeModuleÚget)ZtreeTypeÚimplementationÚkwargsr r r r©rúM/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treewalkers/__init__.pyrs"       ccshg}|D]D}|d}|dkr,| |d¡q|rFdd |¡dœVg}|Vq|rddd |¡dœVdS)NÚtype)Ú CharactersÚSpaceCharactersÚdatarr)rr)ÚappendÚjoin)ÚtokensZpendingCharactersÚtokenrrrrÚconcatenateCharacterTokensAsrc Csbg}d}t|ƒD�]D}|d}|dk�r|drz|dtjdkrz|dtjkr`tj|d}n|d}d||df}n|d}| dd ||f¡|d 7}|d }t| ¡ƒD]T\\}} } |rì|tjkrÚtj|}n|}d|| f}n| }| d d ||| f¡q´|d k�rV|d 8}q|dk�r2|d 8}q|dk�rX| dd ||d f¡q|dk�r |d�rô|d�r¬| dd ||d|d|d�r |dndf¡nF|d�rØ| dd ||d|df¡n| dd ||df¡n| dd |f¡q|dk�r0| dd ||d f¡q|dk�rJd�sVtdƒ‚qtd|ƒ‚qd  |¡S) z Pretty printer for tree walkers Takes a TreeWalker instance and pretty prints the output of walking the tree. :arg walker: a TreeWalker instance rr)ZStartTagÚEmptyTagÚ namespaceZhtmlz%s %sÚnamez%s<%s>ú rrz %s%s="%s"r ZEndTagÚCommentz %sZDoctypeZpublicIdz%sZsystemIdrz%sz%sz %srz%s"%s"rFzBconcatenateCharacterTokens should have got rid of all Space tokenszUnknown token type, %sÚ ) rrZ namespacesÚprefixesrÚsortedÚitemsÚAssertionErrorÚ ValueErrorr) ZwalkerÚoutputÚindentrrÚnsr"Zattrsr!Z localnameÚvaluerrrr Psn           ýÿ þÿ ÿ   )N)Ú__doc__Z __future__rrrrrZ_utilsrÚ__all__rrrr rrrrÚs    ,PKÓ¶N]“¼ @@Vsite-packages/pip/_vendor/html5lib/treewalkers/__pycache__/genshi.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.e ã@sŽddlmZmZmZddlmZddlmZmZmZm Z m Z ddlm Z m Z m Z mZmZmZddlmZddlmZmZGd d „d ejƒZd S) é)Úabsolute_importÚdivisionÚunicode_literals)ÚQName)ÚSTARTÚENDÚ XML_NAMESPACEÚDOCTYPEÚTEXT)ÚSTART_NSÚEND_NSÚ START_CDATAÚ END_CDATAÚPIÚCOMMENTé)Úbaseé)Ú voidElementsÚ namespacesc@seZdZdd„Zdd„ZdS)Ú TreeWalkerccsXd}|jD](}|dk r.| ||¡D] }|Vq"|}q |dk rT| |d¡D] }|VqHdS)N)ZtreeÚtokens)ÚselfZpreviousÚeventÚtoken©rúK/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treewalkers/genshi.pyÚ__iter__ s zTreeWalker.__iter__ccst|\}}}|tkr¾|\}}|j}|j} i} |D]0\} } t| tƒrR| | | j| jf<q.| | d| f<q.| tdkr¬|tkr¬| | || | pš|dtkpš|d|k¡D] } | Vqžn|  | || ¡Vn²|tkrö|j}|j} | tdksæ|tkrô|  | |¡Vnz|t k�r|  |¡Vnb|t k�r2| |¡D] } | V�q"n>|tk�rJ|j|ŽVn&|tttttttfk�rdn | |¡VdS)NZhtmlrr)rZ localnameÚ namespaceÚ isinstancerrrZemptyTagrZstartTagZendTagrZcommentr Útextr Zdoctyperr r r rrÚunknown)rrÚnextZkindÚdataÚ_ÚtagZattribsÚnamerZconverted_attribsÚkÚvrrrrrsH     þ      ÿzTreeWalker.tokensN)Ú__name__Ú __module__Ú __qualname__rrrrrrr srN)Z __future__rrrZ genshi.corerrrrr r r r r rrrÚrZ constantsrrrrrrrÚs    PKÓ¶N]8YÂx7 7 Usite-packages/pip/_vendor/html5lib/treewalkers/__pycache__/etree.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.eÆã@sjddlmZmZmZddlmZddlZddlmZddl m Z ddl m Z e  d ¡Zd d „Ze eƒZdS) é)Úabsolute_importÚdivisionÚunicode_literals)Ú OrderedDictN)Ú string_typesé)Úbaseé)ÚmoduleFactoryFactoryz {([^}]*)}(.*)cs,|}| d¡j‰G‡fdd„dtjƒ}tƒS)NZasdcs4eZdZdZ‡fdd„Zdd„Zdd„Zdd „Zd S) z#getETreeBuilder..TreeWalkeraËGiven the particular ElementTree representation, this implementation, to avoid using recursion, returns "nodes" as tuples with the following content: 1. The current element 2. The index of the element relative to its parent 3. A stack of ancestor elements 4. A flag "text", "tail" or None to indicate if the current node is a text node; either the text or tail of the current element (1) c s.t|tƒr2|\}}}}|dkr.tjt||ƒfS|}t|dƒsD| ¡}|jdkrVtjfS|jdkr|tj |j |  d¡|  d¡fS|jˆkr’tj |j fSt  |j¡}|r°| ¡\}}n d}|j}tƒ}t|j ¡ƒD]>\} } t  | ¡}|�r| || d¡| d¡f<qÎ| |d| f<qÎtj|||t|ƒ�p&|j fSdS) N©ÚtextÚtailÚtag)Z DOCUMENT_ROOTZDOCUMENT_FRAGMENTz ZpublicIdZsystemIdrr )Ú isinstanceÚtuplerZTEXTÚgetattrÚhasattrZgetrootrZDOCUMENTZDOCTYPEr ÚgetÚCOMMENTÚ tag_regexpÚmatchÚgroupsrÚlistZattribÚitemsÚgroupZELEMENTÚlen) ÚselfÚnodeZeltÚ_ÚflagrÚ namespacerZattrsÚnameÚvalue©ZElementTreeCommentType©úJ/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treewalkers/etree.pyÚgetNodeDetails s>     ÿ    ÿz2getETreeBuilder..TreeWalker.getNodeDetailscSstt|tƒr|\}}}}n|dgdf\}}}}|dkr8dS|jrJ|||dfSt|ƒrl| |¡|dd|dfSdSdS)Nr r r)rrr rÚappend©rrÚelementÚkeyÚparentsrr$r$r%Ú getFirstChildHs   z1getETreeBuilder..TreeWalker.getFirstChildcSsžt|tƒr|\}}}}ndS|dkrLt|ƒrF| |¡|dd|dfSdSnN|jrf|dkrf|||dfS|t|dƒdkr–|d|d|d|dfSdSdS)Nr rr éÿÿÿÿr)rrrr'r r(r$r$r%ÚgetNextSiblingYs   z2getETreeBuilder..TreeWalker.getNextSiblingcSsht|tƒr|\}}}}ndS|dkr:|s,|S|||dfSn*| ¡}|sJ|S|t|dƒ |¡|dfSdS)Nr r-)rrÚpoprÚindex)rrr)r*r+rÚparentr$r$r%Ú getParentNodems z1getETreeBuilder..TreeWalker.getParentNodeN)Ú__name__Ú __module__Ú __qualname__Ú__doc__r&r,r.r2r$r#r$r%Ú TreeWalkers  (r7)ÚCommentrrZNonRecursiveTreeWalkerÚlocals)ZElementTreeImplementationZ ElementTreer7r$r#r%ÚgetETreeBuilders nr:)Z __future__rrrÚ collectionsrÚreZpip._vendor.sixrÚrZ_utilsr Úcompilerr:ZgetETreeModuler$r$r$r%Ús     tPKÓ¶N]TÖ o› › Osite-packages/pip/_vendor/html5lib/treewalkers/__pycache__/etree.cpython-38.pycnu„[µü¤U ÀÒ.eÆã@sjddlmZmZmZddlmZddlZddlmZddl m Z ddl m Z e  d ¡Zd d „Ze eƒZdS) é)Úabsolute_importÚdivisionÚunicode_literals)Ú OrderedDictN)Ú string_typesé)Úbaseé)ÚmoduleFactoryFactoryz {([^}]*)}(.*)cs,|}| d¡j‰G‡fdd„dtjƒ}tƒS)NZasdcs4eZdZdZ‡fdd„Zdd„Zdd„Zdd „Zd S) z#getETreeBuilder..TreeWalkeraËGiven the particular ElementTree representation, this implementation, to avoid using recursion, returns "nodes" as tuples with the following content: 1. The current element 2. The index of the element relative to its parent 3. A stack of ancestor elements 4. A flag "text", "tail" or None to indicate if the current node is a text node; either the text or tail of the current element (1) c sHt|tƒr2|\}}}}|dkr.tjt||ƒfS|}t|dƒsD| ¡}|jdkrVtjfS|jdkr|tj |j |  d¡|  d¡fS|jˆkr’tj |j fSt|jt ƒs¬tt|jƒƒ‚t |j¡}|rÊ| ¡\}}n d}|j}tƒ}t|j ¡ƒD]>\} } t | ¡}|�r| || d¡| d¡f<qè| |d| f<qètj|||t|ƒ�p@|j fSdS) N©ÚtextÚtailÚtag)Z DOCUMENT_ROOTZDOCUMENT_FRAGMENTz ZpublicIdZsystemIdrr )Ú isinstanceÚtuplerZTEXTÚgetattrÚhasattrZgetrootrZDOCUMENTZDOCTYPEr ÚgetÚCOMMENTrÚAssertionErrorÚtypeÚ tag_regexpÚmatchÚgroupsrÚlistZattribÚitemsÚgroupZELEMENTÚlen) ÚselfÚnodeZeltÚ_ÚflagrÚ namespacerZattrsÚnameÚvalue©ZElementTreeCommentType©úJ/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treewalkers/etree.pyÚgetNodeDetails s@     ÿ    ÿz2getETreeBuilder..TreeWalker.getNodeDetailscSstt|tƒr|\}}}}n|dgdf\}}}}|dkr8dS|jrJ|||dfSt|ƒrl| |¡|dd|dfSdSdS)Nr r r)rrr rÚappend©rrÚelementÚkeyÚparentsr!r&r&r'Ú getFirstChildHs   z1getETreeBuilder..TreeWalker.getFirstChildcSsžt|tƒr|\}}}}ndS|dkrLt|ƒrF| |¡|dd|dfSdSnN|jrf|dkrf|||dfS|t|dƒdkr–|d|d|d|dfSdSdS)Nr rr éÿÿÿÿr)rrrr)r r*r&r&r'ÚgetNextSiblingYs   z2getETreeBuilder..TreeWalker.getNextSiblingcSs‚t|tƒr|\}}}}ndS|dkr:|s,|S|||dfSnD| ¡}|sJ|St|dƒ |¡dksdt‚|t|dƒ |¡|dfSdS)Nr r/r)rrÚpoprÚcountrÚindex)rrr+r,r-r!Úparentr&r&r'Ú getParentNodems z1getETreeBuilder..TreeWalker.getParentNodeN)Ú__name__Ú __module__Ú __qualname__Ú__doc__r(r.r0r5r&r%r&r'Ú TreeWalkers  (r:)ÚCommentrrZNonRecursiveTreeWalkerÚlocals)ZElementTreeImplementationZ ElementTreer:r&r%r'ÚgetETreeBuilders nr=)Z __future__rrrÚ collectionsrÚreZpip._vendor.sixrÚrZ_utilsr Úcompilerr=ZgetETreeModuler&r&r&r'Ús     tPKÓ¶N]“¼ @@Psite-packages/pip/_vendor/html5lib/treewalkers/__pycache__/genshi.cpython-38.pycnu„[µü¤U ÀÒ.e ã@sŽddlmZmZmZddlmZddlmZmZmZm Z m Z ddlm Z m Z m Z mZmZmZddlmZddlmZmZGd d „d ejƒZd S) é)Úabsolute_importÚdivisionÚunicode_literals)ÚQName)ÚSTARTÚENDÚ XML_NAMESPACEÚDOCTYPEÚTEXT)ÚSTART_NSÚEND_NSÚ START_CDATAÚ END_CDATAÚPIÚCOMMENTé)Úbaseé)Ú voidElementsÚ namespacesc@seZdZdd„Zdd„ZdS)Ú TreeWalkerccsXd}|jD](}|dk r.| ||¡D] }|Vq"|}q |dk rT| |d¡D] }|VqHdS)N)ZtreeÚtokens)ÚselfZpreviousÚeventÚtoken©rúK/usr/lib/python3.8/site-packages/pip/_vendor/html5lib/treewalkers/genshi.pyÚ__iter__ s zTreeWalker.__iter__ccst|\}}}|tkr¾|\}}|j}|j} i} |D]0\} } t| tƒrR| | | j| jf<q.| | d| f<q.| tdkr¬|tkr¬| | || | pš|dtkpš|d|k¡D] } | Vqžn|  | || ¡Vn²|tkrö|j}|j} | tdksæ|tkrô|  | |¡Vnz|t k�r|  |¡Vnb|t k�r2| |¡D] } | V�q"n>|tk�rJ|j|ŽVn&|tttttttfk�rdn | |¡VdS)NZhtmlrr)rZ localnameÚ namespaceÚ isinstancerrrZemptyTagrZstartTagZendTagrZcommentr Útextr Zdoctyperr r r rrÚunknown)rrÚnextZkindÚdataÚ_ÚtagZattribsÚnamerZconverted_attribsÚkÚvrrrrrsH     þ      ÿzTreeWalker.tokensN)Ú__name__Ú __module__Ú __qualname__rrrrrrr srN)Z __future__rrrZ genshi.corerrrrr r r r r rrrÚrZ constantsrrrrrrrÚs    PKÓ¶N]¾Åò-ÆÆ7site-packages/pip/_vendor/html5lib/treewalkers/etree.pynu„[µü¤from __future__ import absolute_import, division, unicode_literals from collections import OrderedDict import re from pip._vendor.six import string_types from . import base from .._utils import moduleFactoryFactory tag_regexp = re.compile("{([^}]*)}(.*)") def getETreeBuilder(ElementTreeImplementation): ElementTree = ElementTreeImplementation ElementTreeCommentType = ElementTree.Comment("asd").tag class TreeWalker(base.NonRecursiveTreeWalker): # pylint:disable=unused-variable """Given the particular ElementTree representation, this implementation, to avoid using recursion, returns "nodes" as tuples with the following content: 1. The current element 2. The index of the element relative to its parent 3. A stack of ancestor elements 4. A flag "text", "tail" or None to indicate if the current node is a text node; either the text or tail of the current element (1) """ def getNodeDetails(self, node): if isinstance(node, tuple): # It might be the root Element elt, _, _, flag = node if flag in ("text", "tail"): return base.TEXT, getattr(elt, flag) else: node = elt if not(hasattr(node, "tag")): node = node.getroot() if node.tag in ("DOCUMENT_ROOT", "DOCUMENT_FRAGMENT"): return (base.DOCUMENT,) elif node.tag == "": return (base.DOCTYPE, node.text, node.get("publicId"), node.get("systemId")) elif node.tag == ElementTreeCommentType: return base.COMMENT, node.text else: assert isinstance(node.tag, string_types), type(node.tag) # This is assumed to be an ordinary element match = tag_regexp.match(node.tag) if match: namespace, tag = match.groups() else: namespace = None tag = node.tag attrs = OrderedDict() for name, value in list(node.attrib.items()): match = tag_regexp.match(name) if match: attrs[(match.group(1), match.group(2))] = value else: attrs[(None, name)] = value return (base.ELEMENT, namespace, tag, attrs, len(node) or node.text) def getFirstChild(self, node): if isinstance(node, tuple): element, key, parents, flag = node else: element, key, parents, flag = node, None, [], None if flag in ("text", "tail"): return None else: if element.text: return element, key, parents, "text" elif len(element): parents.append(element) return element[0], 0, parents, None else: return None def getNextSibling(self, node): if isinstance(node, tuple): element, key, parents, flag = node else: return None if flag == "text": if len(element): parents.append(element) return element[0], 0, parents, None else: return None else: if element.tail and flag != "tail": return element, key, parents, "tail" elif key < len(parents[-1]) - 1: return parents[-1][key + 1], key + 1, parents, None else: return None def getParentNode(self, node): if isinstance(node, tuple): element, key, parents, flag = node else: return None if flag == "text": if not parents: return element else: return element, key, parents, None else: parent = parents.pop() if not parents: return parent else: assert list(parents[-1]).count(parent) == 1 return parent, list(parents[-1]).index(parent), parents, None return locals() getETreeModule = moduleFactoryFactory(getETreeBuilder) PKÓ¶N]_m  8site-packages/pip/_vendor/html5lib/treewalkers/genshi.pynu„[µü¤from __future__ import absolute_import, division, unicode_literals from genshi.core import QName from genshi.core import START, END, XML_NAMESPACE, DOCTYPE, TEXT from genshi.core import START_NS, END_NS, START_CDATA, END_CDATA, PI, COMMENT from . import base from ..constants import voidElements, namespaces class TreeWalker(base.TreeWalker): def __iter__(self): # Buffer the events so we can pass in the following one previous = None for event in self.tree: if previous is not None: for token in self.tokens(previous, event): yield token previous = event # Don't forget the final event! if previous is not None: for token in self.tokens(previous, None): yield token def tokens(self, event, next): kind, data, _ = event if kind == START: tag, attribs = data name = tag.localname namespace = tag.namespace converted_attribs = {} for k, v in attribs: if isinstance(k, QName): converted_attribs[(k.namespace, k.localname)] = v else: converted_attribs[(None, k)] = v if namespace == namespaces["html"] and name in voidElements: for token in self.emptyTag(namespace, name, converted_attribs, not next or next[0] != END or next[1] != tag): yield token else: yield self.startTag(namespace, name, converted_attribs) elif kind == END: name = data.localname namespace = data.namespace if namespace != namespaces["html"] or name not in voidElements: yield self.endTag(namespace, name) elif kind == COMMENT: yield self.comment(data) elif kind == TEXT: for token in self.text(data): yield token elif kind == DOCTYPE: yield self.doctype(*data) elif kind in (XML_NAMESPACE, DOCTYPE, START_NS, END_NS, START_CDATA, END_CDATA, PI): pass else: yield self.unknown(kind) PKÓ¶N]!-ÚB446site-packages/pip/_vendor/html5lib/treewalkers/base.pynu„[µü¤from __future__ import absolute_import, division, unicode_literals from xml.dom import Node from ..constants import namespaces, voidElements, spaceCharacters __all__ = ["DOCUMENT", "DOCTYPE", "TEXT", "ELEMENT", "COMMENT", "ENTITY", "UNKNOWN", "TreeWalker", "NonRecursiveTreeWalker"] DOCUMENT = Node.DOCUMENT_NODE DOCTYPE = Node.DOCUMENT_TYPE_NODE TEXT = Node.TEXT_NODE ELEMENT = Node.ELEMENT_NODE COMMENT = Node.COMMENT_NODE ENTITY = Node.ENTITY_NODE UNKNOWN = "<#UNKNOWN#>" spaceCharacters = "".join(spaceCharacters) class TreeWalker(object): """Walks a tree yielding tokens Tokens are dicts that all have a ``type`` field specifying the type of the token. """ def __init__(self, tree): """Creates a TreeWalker :arg tree: the tree to walk """ self.tree = tree def __iter__(self): raise NotImplementedError def error(self, msg): """Generates an error token with the given message :arg msg: the error message :returns: SerializeError token """ return {"type": "SerializeError", "data": msg} def emptyTag(self, namespace, name, attrs, hasChildren=False): """Generates an EmptyTag token :arg namespace: the namespace of the token--can be ``None`` :arg name: the name of the element :arg attrs: the attributes of the element as a dict :arg hasChildren: whether or not to yield a SerializationError because this tag shouldn't have children :returns: EmptyTag token """ yield {"type": "EmptyTag", "name": name, "namespace": namespace, "data": attrs} if hasChildren: yield self.error("Void element has children") def startTag(self, namespace, name, attrs): """Generates a StartTag token :arg namespace: the namespace of the token--can be ``None`` :arg name: the name of the element :arg attrs: the attributes of the element as a dict :returns: StartTag token """ return {"type": "StartTag", "name": name, "namespace": namespace, "data": attrs} def endTag(self, namespace, name): """Generates an EndTag token :arg namespace: the namespace of the token--can be ``None`` :arg name: the name of the element :returns: EndTag token """ return {"type": "EndTag", "name": name, "namespace": namespace} def text(self, data): """Generates SpaceCharacters and Characters tokens Depending on what's in the data, this generates one or more ``SpaceCharacters`` and ``Characters`` tokens. For example: >>> from html5lib.treewalkers.base import TreeWalker >>> # Give it an empty tree just so it instantiates >>> walker = TreeWalker([]) >>> list(walker.text('')) [] >>> list(walker.text(' ')) [{u'data': ' ', u'type': u'SpaceCharacters'}] >>> list(walker.text(' abc ')) # doctest: +NORMALIZE_WHITESPACE [{u'data': ' ', u'type': u'SpaceCharacters'}, {u'data': u'abc', u'type': u'Characters'}, {u'data': u' ', u'type': u'SpaceCharacters'}] :arg data: the text data :returns: one or more ``SpaceCharacters`` and ``Characters`` tokens """ data = data middle = data.lstrip(spaceCharacters) left = data[:len(data) - len(middle)] if left: yield {"type": "SpaceCharacters", "data": left} data = middle middle = data.rstrip(spaceCharacters) right = data[len(middle):] if middle: yield {"type": "Characters", "data": middle} if right: yield {"type": "SpaceCharacters", "data": right} def comment(self, data): """Generates a Comment token :arg data: the comment :returns: Comment token """ return {"type": "Comment", "data": data} def doctype(self, name, publicId=None, systemId=None): """Generates a Doctype token :arg name: :arg publicId: :arg systemId: :returns: the Doctype token """ return {"type": "Doctype", "name": name, "publicId": publicId, "systemId": systemId} def entity(self, name): """Generates an Entity token :arg name: the entity name :returns: an Entity token """ return {"type": "Entity", "name": name} def unknown(self, nodeType): """Handles unknown node types""" return self.error("Unknown node type: " + nodeType) class NonRecursiveTreeWalker(TreeWalker): def getNodeDetails(self, node): raise NotImplementedError def getFirstChild(self, node): raise NotImplementedError def getNextSibling(self, node): raise NotImplementedError def getParentNode(self, node): raise NotImplementedError def __iter__(self): currentNode = self.tree while currentNode is not None: details = self.getNodeDetails(currentNode) type, details = details[0], details[1:] hasChildren = False if type == DOCTYPE: yield self.doctype(*details) elif type == TEXT: for token in self.text(*details): yield token elif type == ELEMENT: namespace, name, attributes, hasChildren = details if (not namespace or namespace == namespaces["html"]) and name in voidElements: for token in self.emptyTag(namespace, name, attributes, hasChildren): yield token hasChildren = False else: yield self.startTag(namespace, name, attributes) elif type == COMMENT: yield self.comment(details[0]) elif type == ENTITY: yield self.entity(details[0]) elif type == DOCUMENT: hasChildren = True else: yield self.unknown(details[0]) if hasChildren: firstChild = self.getFirstChild(currentNode) else: firstChild = None if firstChild is not None: currentNode = firstChild else: while currentNode is not None: details = self.getNodeDetails(currentNode) type, details = details[0], details[1:] if type == ELEMENT: namespace, name, attributes, hasChildren = details if (namespace and namespace != namespaces["html"]) or name not in voidElements: yield self.endTag(namespace, name) if self.tree is currentNode: currentNode = None break nextSibling = self.getNextSibling(currentNode) if nextSibling is not None: currentNode = nextSibling break else: currentNode = self.getParentNode(currentNode) PKÓ¶N]– œG¥¥<site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.pynu„[µü¤from __future__ import absolute_import, division, unicode_literals from pip._vendor.six import text_type from lxml import etree from ..treebuilders.etree import tag_regexp from . import base from .. import _ihatexml def ensure_str(s): if s is None: return None elif isinstance(s, text_type): return s else: return s.decode("ascii", "strict") class Root(object): def __init__(self, et): self.elementtree = et self.children = [] try: if et.docinfo.internalDTD: self.children.append(Doctype(self, ensure_str(et.docinfo.root_name), ensure_str(et.docinfo.public_id), ensure_str(et.docinfo.system_url))) except AttributeError: pass try: node = et.getroot() except AttributeError: node = et while node.getprevious() is not None: node = node.getprevious() while node is not None: self.children.append(node) node = node.getnext() self.text = None self.tail = None def __getitem__(self, key): return self.children[key] def getnext(self): return None def __len__(self): return 1 class Doctype(object): def __init__(self, root_node, name, public_id, system_id): self.root_node = root_node self.name = name self.public_id = public_id self.system_id = system_id self.text = None self.tail = None def getnext(self): return self.root_node.children[1] class FragmentRoot(Root): def __init__(self, children): self.children = [FragmentWrapper(self, child) for child in children] self.text = self.tail = None def getnext(self): return None class FragmentWrapper(object): def __init__(self, fragment_root, obj): self.root_node = fragment_root self.obj = obj if hasattr(self.obj, 'text'): self.text = ensure_str(self.obj.text) else: self.text = None if hasattr(self.obj, 'tail'): self.tail = ensure_str(self.obj.tail) else: self.tail = None def __getattr__(self, name): return getattr(self.obj, name) def getnext(self): siblings = self.root_node.children idx = siblings.index(self) if idx < len(siblings) - 1: return siblings[idx + 1] else: return None def __getitem__(self, key): return self.obj[key] def __bool__(self): return bool(self.obj) def getparent(self): return None def __str__(self): return str(self.obj) def __unicode__(self): return str(self.obj) def __len__(self): return len(self.obj) class TreeWalker(base.NonRecursiveTreeWalker): def __init__(self, tree): # pylint:disable=redefined-variable-type if isinstance(tree, list): self.fragmentChildren = set(tree) tree = FragmentRoot(tree) else: self.fragmentChildren = set() tree = Root(tree) base.NonRecursiveTreeWalker.__init__(self, tree) self.filter = _ihatexml.InfosetFilter() def getNodeDetails(self, node): if isinstance(node, tuple): # Text node node, key = node assert key in ("text", "tail"), "Text nodes are text or tail, found %s" % key return base.TEXT, ensure_str(getattr(node, key)) elif isinstance(node, Root): return (base.DOCUMENT,) elif isinstance(node, Doctype): return base.DOCTYPE, node.name, node.public_id, node.system_id elif isinstance(node, FragmentWrapper) and not hasattr(node, "tag"): return base.TEXT, ensure_str(node.obj) elif node.tag == etree.Comment: return base.COMMENT, ensure_str(node.text) elif node.tag == etree.Entity: return base.ENTITY, ensure_str(node.text)[1:-1] # strip &; else: # This is assumed to be an ordinary element match = tag_regexp.match(ensure_str(node.tag)) if match: namespace, tag = match.groups() else: namespace = None tag = ensure_str(node.tag) attrs = {} for name, value in list(node.attrib.items()): name = ensure_str(name) value = ensure_str(value) match = tag_regexp.match(name) if match: attrs[(match.group(1), match.group(2))] = value else: attrs[(None, name)] = value return (base.ELEMENT, namespace, self.filter.fromXmlName(tag), attrs, len(node) > 0 or node.text) def getFirstChild(self, node): assert not isinstance(node, tuple), "Text nodes have no children" assert len(node) or node.text, "Node has no children" if node.text: return (node, "text") else: return node[0] def getNextSibling(self, node): if isinstance(node, tuple): # Text node node, key = node assert key in ("text", "tail"), "Text nodes are text or tail, found %s" % key if key == "text": # XXX: we cannot use a "bool(node) and node[0] or None" construct here # because node[0] might evaluate to False if it has no child element if len(node): return node[0] else: return None else: # tail return node.getnext() return (node, "tail") if node.tail else node.getnext() def getParentNode(self, node): if isinstance(node, tuple): # Text node node, key = node assert key in ("text", "tail"), "Text nodes are text or tail, found %s" % key if key == "text": return node # else: fallback to "normal" processing elif node in self.fragmentChildren: return None return node.getparent() PKÓ¶N]eD22/site-packages/pip/_vendor/packaging/__init__.pynu„[µü¤# This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from .__about__ import ( __author__, __copyright__, __email__, __license__, __summary__, __title__, __uri__, __version__, ) __all__ = [ "__title__", "__summary__", "__uri__", "__version__", "__author__", "__email__", "__license__", "__copyright__", ] PKÓ¶N]øGW^4*4*Isite-packages/pip/_vendor/packaging/__pycache__/tags.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.e…2ã@snddlmZddlZzddlmZWn0ek rTddlZdd„e ¡DƒZ[YnXddl Z ddl Z ddl Z ddl Z ddl Z dddd d d œZe jd kZGd d„deƒZdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd „Zd!d"„Zd#d$„Zefd%d&„Zd'd(„Zd=d)d*„Z d+d,„Z!d-d.„Z"d/d0„Z#d1d2„Z$efd3d4„Z%d5d6„Z&d7d8„Z'd9d:„Z(d;d<„Z)dS)>é)Úabsolute_importN)ÚEXTENSION_SUFFIXEScCsg|] }|d‘qS)r©)Ú.0Úxrrú>/usr/lib/python3.8/site-packages/pip/_vendor/packaging/tags.pyÚ srÚpyÚcpÚppZipZjy)ÚpythonZcpythonZpypyZ ironpythonZjythonlc@sbeZdZdddgZdd„Zedd„ƒZedd „ƒZed d „ƒZd d „Z dd„Z dd„Z dd„Z dS)ÚTagÚ _interpreterÚ_abiÚ _platformcCs"| ¡|_| ¡|_| ¡|_dS©N)Úlowerrrr)ÚselfÚ interpreterÚabiÚplatformrrrÚ__init__'s  z Tag.__init__cCs|jSr)r©rrrrr,szTag.interpretercCs|jSr)rrrrrr0szTag.abicCs|jSr)rrrrrr4sz Tag.platformcCs$|j|jko"|j|jko"|j|jkSr)rrr)rÚotherrrrÚ__eq__8s   ÿ ýz Tag.__eq__cCst|j|j|jfƒSr)ÚhashrrrrrrrÚ__hash__?sz Tag.__hash__cCsd |j|j|j¡S)Nz{}-{}-{})ÚformatrrrrrrrÚ__str__Bsz Tag.__str__cCsdj|t|ƒd�S)Nz<{self} @ {self_id}>)rZself_id)rÚidrrrrÚ__repr__Esz Tag.__repr__N) Ú__name__Ú __module__Ú __qualname__Ú __slots__rÚpropertyrrrrrrr rrrrr #s    r c Cs`tƒ}| d¡\}}}| d¡D]6}| d¡D]&}| d¡D]}| t|||ƒ¡qƒsz _cpython_tags..c3s|]}tˆd|ƒVqdS©ÚnoneNrSrTrUrrrV…sr8éÿÿÿÿr7rr9rR)r Úranger)r<rr.r/rr0r,Ú minor_versionrrUrÚ _cpython_tagssÿr\cCsdjtjdtjjtjjd�S)Nz$pp{py_major}{pypy_major}{pypy_minor}r)Zpy_majorZ pypy_majorZ pypy_minor)rrMÚ version_infoZpypy_version_infor:r;rrrrÚ_pypy_interpreter�s ýr^cCst d¡}|rt|ƒSdSdS)NZSOABIrX)rJrKr6)rrrrÚ _generic_abi˜s r_c#sB‡‡fdd„|DƒD] }|Vq‡fdd„|DƒD] }|Vq2dS)Nc3s|]}tˆˆ|ƒVqdSrrS©rr©rrrrrV¡sz_pypy_tags..c3s|]}tˆd|ƒVqdSrWrSr`rUrrrV£sr)r<rrr/r,rrarÚ _pypy_tags srbc#sN‡‡fdd„|DƒD] }|VqˆdkrJ‡fdd„|Dƒ}|D] }|Vq>dS)Nc3s|]}tˆˆ|ƒVqdSrrSr`rarrrV¨sz _generic_tags..rXc3s|]}tˆd|ƒVqdSrWrSrTrUrrrV«sr)rr<rr/r,r-rrarÚ _generic_tags§s rcccs\dj|d|dd�Vdj|dd�Vt|ddddƒD]}dj|d|d�Vq>dS) z¬ Yield Python versions in descending order. After the latest version, the major-only version will be yielded, and then all following versions up to 'end'. zpy{major}{minor}rr8r9z py{major})r:rYN)rrZ)r<r;rrrÚ_py_interpreter_range°srdccsTt|ƒD]}|D]}t|d|ƒVqqt|ddƒVt|ƒD]}t|ddƒVq - -none-any - py*-none-any rXÚanyN)rdr )rr<r/rFr0rrrÚ_independent_tags½s  rfcCs|s|S| d¡rdSdS)NÚppcÚi386)Ú startswith)ÚarchÚis_32bitrrrÚ _mac_archÎs  rlcCsª|g}|dkr,|dkrgS| dddg¡np|dkrR|dkr@gS| dddg¡nJ|dkrz|d ksj|dkrngS| d¡n"|d krœ|d krŽgS| ddg¡| d ¡|S) NZx86_64)é rDZintelZfat64Zfat32rhZfatZppc64)rmérg)rméZ universal)ÚextendrO)rFÚcpu_archZformatsrrrÚ_mac_binary_formatsØs&  rrc Csžt ¡\}}}|dkr2ttt| d¡dd…ƒƒ}|dkrBt|ƒ}g}t|dddƒD]B}|d|f}t||ƒ}|D]"} |  dj |d|d| d�¡qtqV|S)Nr'r>r8rYrz&macosx_{major}_{minor}_{binary_format})r:r;Ú binary_format) rZmac_verÚtupleÚmapÚintr)rlrZrrrOr) rFrjÚ version_strr2rqr/r[Zcompat_versionZbinary_formatsrsrrrÚ_mac_platformsós$  ýÿrxc Cs>zddl}tt||dƒƒWSttfk r4YnXt|ŽS)NrZ _compatible)Ú _manylinuxÚboolÚgetattrÚ ImportErrorÚAttributeErrorÚ_have_compatible_glibc)ÚnameÚ glibc_versionryrrrÚ_is_manylinux_compatible s r�cCsZddl}| d¡}z |j}Wntk r2YdSX|j|_|ƒ}t|tƒsV| d¡}|S)NrÚascii) ÚctypesZCDLLÚgnu_get_libc_versionr}Zc_char_pZrestypeÚ isinstanceÚstrÚdecode)rƒZprocess_namespacer„rwrrrÚ_glibc_version_strings    rˆcCsHt d|¡}|s$t d|t¡dSt| d¡ƒ|koFt| d¡ƒ|kS)Nz$(?P[0-9]+)\.(?P[0-9]+)z=Expected glibc version with 2 components major.minor, got: %sFr:r;)ÚreÚmatchÚwarningsÚwarnÚRuntimeWarningrvÚgroup)rwÚrequired_majorÚ minimum_minorrCrrrÚ_check_glibc_version1s ÿýþr‘cCstƒ}|dkrdSt|||ƒS)NF)rˆr‘)r�r�rwrrrr~Fsr~cs|ttj ¡ƒ‰ˆdkr|rd‰d}t|ƒ}|D]$\}}t||ƒr.ˆ d|¡g}qXq.g}|‡fdd„|Dƒ7}| ˆ¡|S)NZ linux_x86_64Z linux_i686))Z manylinux2014)r>é)Z manylinux2010)r>é )Z manylinux1)r>rnÚlinuxcsg|]\}}ˆ d|¡‘qS©r”r3)rrr2r•rrr^sz$_linux_platforms..)r6Ú distutilsÚutilÚ get_platformÚiterr�r4rO)rkZmanylinux_supportZmanylinux_support_iterrr€r/rr•rÚ_linux_platformsMs    ršcCsttj ¡ƒ}|gSr)r6r–r—r˜)rrrrÚ_generic_platformscsr›cCst ¡ ¡}t |¡p|Sr)rZpython_implementationrÚINTERPRETER_SHORT_NAMESÚget)rrrrÚ_interpreter_namehs ržcCs4t d¡}|s&d tt|dd…ƒ¡}dj||d�S)NZpy_version_nodotr?r>z{name}{version})rrF)rJrKÚjoinrur†r)rr<rFrrrÚ_generic_interpreterms r ccsìtjdd…}tƒ}t ¡dkr(tƒ}nt ¡dkrZDarwinZLinuxr r )rMr]ržrÚsystemrxršr›r=rQr\r^r_rbr rcrf)r<Zinterpreter_namer/rr.r,rrrrÚsys_tagsts.     r¢)NN)*Z __future__rZdistutils.utilr–Zimportlib.machineryrr|ZimpZ get_suffixesrr‰rMrJr‹rœÚmaxsizeZ_32_BIT_INTERPRETERÚobjectr r1r6r=rQr\r^r_rbrcrdrfrlrrrxr�rˆr‘r~ršr›ržr r¢rrrrÚsV û & #      PKÓ¶N]Uù˜Msite-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.e2ã@sTddlmZmZmZddlmZmZmZmZm Z m Z m Z m Z dddddd d d gZ d S) é)Úabsolute_importÚdivisionÚprint_functioné)Ú __author__Ú __copyright__Ú __email__Ú __license__Ú __summary__Ú __title__Ú__uri__Ú __version__r r r r rrr rN)Z __future__rrrÚ __about__rrrr r r r r Ú__all__©rrúB/usr/lib/python3.8/site-packages/pip/_vendor/packaging/__init__.pyÚs( øPKÓ¶N]î9ìóMMIsite-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-38.pycnu„[µü¤U ÀÒ.e‚lã@sæddlmZmZmZddlZddlZddlZddlZddlm Z m Z ddl m Z m Z mZGdd„deƒZGdd „d e ejeƒƒZGd d „d eƒZGd d „d eƒZdd„ZGdd„deƒZe d¡Zdd„Zdd„ZGdd„deƒZdS)é)Úabsolute_importÚdivisionÚprint_functionNé)Ú string_typesÚwith_metaclass)ÚVersionÚ LegacyVersionÚparsec@seZdZdZdS)ÚInvalidSpecifierzH An invalid specifier was found, users should refer to PEP 440. N)Ú__name__Ú __module__Ú __qualname__Ú__doc__©rrúD/usr/lib/python3.8/site-packages/pip/_vendor/packaging/specifiers.pyr sr c@s€eZdZejdd„ƒZejdd„ƒZejdd„ƒZejdd„ƒZej d d „ƒZ e j d d „ƒZ ejdd d„ƒZ ejddd„ƒZ d S)Ú BaseSpecifiercCsdS)zŽ Returns the str representation of this Specifier like object. This should be representative of the Specifier itself. Nr©ÚselfrrrÚ__str__szBaseSpecifier.__str__cCsdS)zF Returns a hash value for this Specifier like object. NrrrrrÚ__hash__szBaseSpecifier.__hash__cCsdS)zq Returns a boolean representing whether or not the two Specifier like objects are equal. Nr©rÚotherrrrÚ__eq__#szBaseSpecifier.__eq__cCsdS)zu Returns a boolean representing whether or not the two Specifier like objects are not equal. NrrrrrÚ__ne__*szBaseSpecifier.__ne__cCsdS)zg Returns whether or not pre-releases as a whole are allowed by this specifier. NrrrrrÚ prereleases1szBaseSpecifier.prereleasescCsdS)zd Sets whether or not pre-releases as a whole are allowed by this specifier. Nr©rÚvaluerrrr8sNcCsdS)zR Determines if the given item is contained within this specifier. Nr©rÚitemrrrrÚcontains?szBaseSpecifier.containscCsdS)z• Takes an iterable of items and filters them so that only items which are contained within this specifier are allowed in it. Nr)rÚiterablerrrrÚfilterEszBaseSpecifier.filter)N)N)r r rÚabcÚabstractmethodrrrrÚabstractpropertyrÚsetterr r"rrrrrs        rc@s eZdZiZd dd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dd„Z e dd„ƒZ e dd„ƒZe dd„ƒZejdd„ƒZdd„Zd!dd„Zd"dd„ZdS)#Ú_IndividualSpecifierÚNcCsF|j |¡}|std |¡ƒ‚| d¡ ¡| d¡ ¡f|_||_dS)NzInvalid specifier: '{0}'ÚoperatorÚversion)Ú_regexÚsearchr ÚformatÚgroupÚstripÚ_specÚ _prereleases)rÚspecrÚmatchrrrÚ__init__Qs  z_IndividualSpecifier.__init__cCs0|jdk rd |j¡nd}d |jjt|ƒ|¡S)Nú, prereleases={0!r}r(z<{0}({1!r}{2})>)r1r-rÚ __class__r Ústr©rZprerrrÚ__repr__[s ÿýz_IndividualSpecifier.__repr__cCs dj|jŽS)Nz{0}{1})r-r0rrrrrdsz_IndividualSpecifier.__str__cCs t|jƒS©N)Úhashr0rrrrrgsz_IndividualSpecifier.__hash__cCsPt|tƒr4z| |¡}WqDtk r0tYSXnt||jƒsDtS|j|jkSr:©Ú isinstancerr6r ÚNotImplementedr0rrrrrjs   z_IndividualSpecifier.__eq__cCsPt|tƒr4z| |¡}WqDtk r0tYSXnt||jƒsDtS|j|jkSr:r<rrrrrus   z_IndividualSpecifier.__ne__cCst|d |j|¡ƒS)Nz _compare_{0})Úgetattrr-Ú _operators)rÚoprrrÚ _get_operator€sz"_IndividualSpecifier._get_operatorcCst|ttfƒst|ƒ}|Sr:)r=r rr ©rr*rrrÚ_coerce_versionƒsz$_IndividualSpecifier._coerce_versioncCs |jdS)Nr©r0rrrrr)ˆsz_IndividualSpecifier.operatorcCs |jdS)NrrErrrrr*Œsz_IndividualSpecifier.versioncCs|jSr:©r1rrrrr�sz _IndividualSpecifier.prereleasescCs ||_dSr:rFrrrrr”scCs | |¡Sr:©r ©rrrrrÚ __contains__˜sz!_IndividualSpecifier.__contains__cCs:|dkr|j}| |¡}|jr&|s&dS| |j¡||jƒS©NF)rrDÚ is_prereleaserBr)r*rrrrr ›s   z_IndividualSpecifier.containsccs€d}g}d|dk r|ndi}|D]B}| |¡}|j|f|Žr |jrX|sX|jsX| |¡q d}|Vq |s||r||D] }|VqpdS)NFrT)rDr rKrÚappend)rr!rZyieldedÚfound_prereleasesÚkwr*Úparsed_versionrrrr"®s" ÿÿ z_IndividualSpecifier.filter)r(N)N)N)r r rr@r4r9rrrrrBrDÚpropertyr)r*rr&rIr r"rrrrr'Ms(         r'c@sveZdZdZe dedejejB¡Zdddddd d œZ d d „Z d d„Z dd„Z dd„Z dd„Zdd„Zdd„ZdS)ÚLegacySpecifieraÛ (?P(==|!=|<=|>=|<|>)) \s* (?P [^,;\s)]* # Since this is a "legacy" specifier, and the version # string can be just about anything, we match everything # except for whitespace, a semi-colon for marker support, # a closing paren since versions can be enclosed in # them, and a comma since it's a version separator. ) ú^\s*ú\s*$ÚequalÚ not_equalÚless_than_equalÚgreater_than_equalÚ less_thanÚ greater_than)ú==ú!=ú<=ú>=ú<ú>cCst|tƒstt|ƒƒ}|Sr:)r=r r7rCrrrrDès  zLegacySpecifier._coerce_versioncCs|| |¡kSr:©rD©rÚ prospectiver2rrrÚ_compare_equalíszLegacySpecifier._compare_equalcCs|| |¡kSr:r`rarrrÚ_compare_not_equalðsz"LegacySpecifier._compare_not_equalcCs|| |¡kSr:r`rarrrÚ_compare_less_than_equalósz(LegacySpecifier._compare_less_than_equalcCs|| |¡kSr:r`rarrrÚ_compare_greater_than_equalösz+LegacySpecifier._compare_greater_than_equalcCs|| |¡kSr:r`rarrrÚ_compare_less_thanùsz"LegacySpecifier._compare_less_thancCs|| |¡kSr:r`rarrrÚ_compare_greater_thanüsz%LegacySpecifier._compare_greater_thanN)r r rÚ _regex_strÚreÚcompileÚVERBOSEÚ IGNORECASEr+r@rDrcrdrerfrgrhrrrrrQÏs  ú rQcst ˆ¡‡fdd„ƒ}|S)Ncst|tƒsdSˆ|||ƒSrJ)r=rra©ÚfnrrÚwrappeds z)_require_version_compare..wrapped)Ú functoolsÚwraps)rorprrnrÚ_require_version_comparesrsc @s¸eZdZdZe dedejejB¡Zdddddd d d d œZ e d d„ƒZ e dd„ƒZ e dd„ƒZ e dd„ƒZe dd„ƒZe dd„ƒZe dd„ƒZdd„Zedd„ƒZejdd„ƒZd S)!Ú Specifiera (?P(~=|==|!=|<=|>=|<|>|===)) (?P (?: # The identity operators allow for an escape hatch that will # do an exact string match of the version you wish to install. # This will not be parsed by PEP 440 and we cannot determine # any semantic meaning from it. This operator is discouraged # but included entirely as an escape hatch. (?<====) # Only match for the identity operator \s* [^\s]* # We just match everything, except for whitespace # since we are only testing for strict identity. ) | (?: # The (non)equality operators allow for wild card and local # versions to be specified so we have to define these two # operators separately to enable that. (?<===|!=) # Only match for equals and not equals \s* v? (?:[0-9]+!)? # epoch [0-9]+(?:\.[0-9]+)* # release (?: # pre release [-_\.]? (a|b|c|rc|alpha|beta|pre|preview) [-_\.]? [0-9]* )? (?: # post release (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) )? # You cannot use a wild card and a dev or local version # together so group them with a | and make them optional. (?: (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local | \.\* # Wild card syntax of .* )? ) | (?: # The compatible operator requires at least two digits in the # release segment. (?<=~=) # Only match for the compatible operator \s* v? (?:[0-9]+!)? # epoch [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) (?: # pre release [-_\.]? (a|b|c|rc|alpha|beta|pre|preview) [-_\.]? [0-9]* )? (?: # post release (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) )? (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release ) | (?: # All other operators only allow a sub set of what the # (non)equality operators do. Specifically they do not allow # local versions to be specified nor do they allow the prefix # matching wild cards. (?„óz/Specifier._compare_compatible..éÿÿÿÿú.*r]rZ)ÚjoinÚlistÚ itertoolsÚ takewhileÚ_version_splitrB)rrbr2ÚprefixrrrÚ_compare_compatiblevs þÿûÿ ÿzSpecifier._compare_compatiblecCsp| d¡rPt|jƒ}t|dd…ƒ}tt|ƒƒ}|dt|ƒ…}t||ƒ\}}nt|ƒ}|jsht|jƒ}||kS)Nr~éþÿÿÿ)ÚendswithrZpublicrƒr7ÚlenÚ _pad_versionÚlocalrarrrrc‘s    zSpecifier._compare_equalcCs| ||¡ Sr:)rcrarrrrd´szSpecifier._compare_not_equalcCs |t|ƒkSr:©rrarrrre¸sz"Specifier._compare_less_than_equalcCs |t|ƒkSr:r‹rarrrrf¼sz%Specifier._compare_greater_than_equalcCs<t|ƒ}||ksdS|js8|jr8t|jƒt|jƒkr8dSdS©NFT)rrKÚ base_versionrarrrrgÀs zSpecifier._compare_less_thancCs^t|ƒ}||ksdS|js8|jr8t|jƒt|jƒkr8dS|jdk rZt|jƒt|jƒkrZdSdSrŒ)rZis_postreleaser�rŠrarrrrhÙs  zSpecifier._compare_greater_thancCst|ƒ ¡t|ƒ ¡kSr:)r7ÚlowerrarrrÚ_compare_arbitraryøszSpecifier._compare_arbitrarycCsR|jdk r|jS|j\}}|dkrN|dkr@| d¡r@|dd…}t|ƒjrNdSdS)N)rZr]r\rurvrZr~r†TF)r1r0r‡r rK)rr)r*rrrrûs    zSpecifier.prereleasescCs ||_dSr:rFrrrrrsN)r r rrirjrkrlrmr+r@rsr…rcrdrerfrgrhr�rPrr&rrrrrt s<]ø   "      rtz^([0-9]+)((?:a|b|c|rc)[0-9]+)$cCs@g}| d¡D],}t |¡}|r0| | ¡¡q| |¡q|S)Nrw)ÚsplitÚ _prefix_regexr,ÚextendÚgroupsrL)r*Úresultrr3rrrrƒs  rƒc Csægg}}| tt dd„|¡ƒ¡| tt dd„|¡ƒ¡| |t|dƒd…¡| |t|dƒd…¡| ddgtdt|dƒt|dƒƒ¡| ddgtdt|dƒt|dƒƒ¡ttj|Žƒttj|ŽƒfS)NcSs| ¡Sr:©Úisdigitryrrrr{*r|z_pad_version..cSs| ¡Sr:r•ryrrrr{+r|rrÚ0)rLr€r�r‚rˆÚinsertÚmaxÚchain)ÚleftÚrightZ left_splitZ right_splitrrrr‰&s ,,r‰c@sŒeZdZddd„Zdd„Zdd„Zd d „Zd d „Zd d„Zdd„Z dd„Z dd„Z e dd„ƒZ e jdd„ƒZ dd„Zddd„Zd dd„ZdS)!Ú SpecifierSetr(Nc Csndd„| d¡Dƒ}tƒ}|D]:}z| t|ƒ¡Wqtk rV| t|ƒ¡YqXqt|ƒ|_||_dS)NcSsg|]}| ¡r| ¡‘qSr)r/©Ú.0ÚsrrrÚ <sz)SpecifierSet.__init__..ú,) r�ÚsetÚaddrtr rQÚ frozensetÚ_specsr1)rZ specifiersrZparsedÚ specifierrrrr49s zSpecifierSet.__init__cCs*|jdk rd |j¡nd}d t|ƒ|¡S)Nr5r(z)r1r-rr7r8rrrr9Ns ÿýzSpecifierSet.__repr__cCsd tdd„|jDƒƒ¡S)Nr¢css|]}t|ƒVqdSr:)r7ržrrrÚ Xsz'SpecifierSet.__str__..)rÚsortedr¦rrrrrWszSpecifierSet.__str__cCs t|jƒSr:)r;r¦rrrrrZszSpecifierSet.__hash__cCs˜t|tƒrt|ƒ}nt|tƒs"tStƒ}t|j|jBƒ|_|jdkrX|jdk rX|j|_n<|jdk rv|jdkrv|j|_n|j|jkrŒ|j|_ntdƒ‚|S)NzFCannot combine SpecifierSets with True and False prerelease overrides.)r=rr�r>r¥r¦r1Ú ValueError)rrr§rrrÚ__and__]s        ÿzSpecifierSet.__and__cCsFt|tƒrt|ƒ}n&t|tƒr,tt|ƒƒ}nt|tƒs:tS|j|jkSr:©r=rr�r'r7r>r¦rrrrrts    zSpecifierSet.__eq__cCsFt|tƒrt|ƒ}n&t|tƒr,tt|ƒƒ}nt|tƒs:tS|j|jkSr:r¬rrrrr~s    zSpecifierSet.__ne__cCs t|jƒSr:)rˆr¦rrrrÚ__len__ˆszSpecifierSet.__len__cCs t|jƒSr:)Úiterr¦rrrrÚ__iter__‹szSpecifierSet.__iter__cCs.|jdk r|jS|jsdStdd„|jDƒƒS)Ncss|] }|jVqdSr:©rržrrrr¨�sz+SpecifierSet.prereleases..)r1r¦ÚanyrrrrrŽs  zSpecifierSet.prereleasescCs ||_dSr:rFrrrrrŸscCs | |¡Sr:rGrHrrrrI£szSpecifierSet.__contains__csLtˆttfƒstˆƒ‰ˆdkr$|j‰ˆs2ˆjr2dSt‡‡fdd„|jDƒƒS)NFc3s|]}|jˆˆd�VqdS)r°NrGrž©rrrrr¨¾sz(SpecifierSet.contains..)r=r rr rrKÚallr¦rrr²rr ¦s zSpecifierSet.containscCs°|dkr|j}|jr6|jD]}|j|t|ƒd�}q|Sg}g}|D]P}t|ttfƒs^t|ƒ}n|}t|tƒrnqB|jrˆ|sˆ|s’|  |¡qB|  |¡qB|s¨|r¨|dkr¨|S|SdS)Nr°) rr¦r"Úboolr=r rr rKrL)rr!rr2ZfilteredrMrrOrrrr"Às*      zSpecifierSet.filter)r(N)N)N)r r rr4r9rrr«rrr­r¯rPrr&rIr r"rrrrr�8s        r�)Z __future__rrrr#rqr�rjZ_compatrrr*rr r rªr ÚABCMetaÚobjectrr'rQrsrtrkr‘rƒr‰r�rrrrÚs&81   PKÓ¶N]»µmã¹¹Nsite-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.eèã@sPddlmZmZmZdddddddd gZd Zd Zd Zd ZdZ dZ dZ de Z dS)é)Úabsolute_importÚdivisionÚprint_functionÚ __title__Ú __summary__Ú__uri__Ú __version__Ú __author__Ú __email__Ú __license__Ú __copyright__Z packagingz"Core utilities for Python packagesz!https://github.com/pypa/packagingz19.2z)Donald Stufft and individual contributorszdonald@stufft.ioz"BSD or Apache License, Version 2.0zCopyright 2014-2019 %sN) Z __future__rrrÚ__all__rrrrr r r r ©rrúC/usr/lib/python3.8/site-packages/pip/_vendor/packaging/__about__.pyÚs"ø PKÓ¶N]S‚ÜÒ"Ò"Fsite-packages/pip/_vendor/packaging/__pycache__/markers.cpython-38.pycnu„[µü¤U ÀÒ.e: ã @s@ddlmZmZmZddlZddlZddlZddlZddlm Z m Z m Z m Z ddlm Z mZmZmZddlmZddlmZddlmZmZd d d d d gZGdd „d eƒZGdd „d eƒZGdd „d eƒZGdd„deƒZGdd„deƒZGdd„deƒZ Gdd„deƒZ!edƒedƒBedƒBedƒBedƒBedƒBedƒBed ƒBed!ƒBed"ƒBed#ƒBed$ƒBed%ƒBed&ƒBed'ƒBed(ƒBed)ƒBed*ƒBZ"d#d"ddddd+œZ#e" $d,d-„¡ed.ƒed/ƒBed0ƒBed1ƒBed2ƒBed3ƒBed4ƒBed5ƒBZ%e%ed6ƒBed7ƒBZ&e& $d8d-„¡ed9ƒed:ƒBZ'e' $d;d-„¡ed<ƒed=ƒBZ(e"e'BZ)ee)e&e)ƒZ*e* $d>d-„¡ed?ƒ +¡Z,ed@ƒ +¡Z-eƒZ.e*ee,e.e-ƒBZ/e.e/e e(e.ƒ>e e.e Z0dAdB„Z1dSdDdE„Z2dFd-„dGd-„ej3ej4ej5ej6ej7ej8dHœZ9dIdJ„Z:eƒZ;dKdL„ZdQd „Z?GdRd „d eƒZ@dS)Té)Úabsolute_importÚdivisionÚprint_functionN)ÚParseExceptionÚ ParseResultsÚ stringStartÚ stringEnd)Ú ZeroOrMoreÚGroupÚForwardÚ QuotedString)ÚLiteralé)Ú string_types)Ú SpecifierÚInvalidSpecifierÚ InvalidMarkerÚUndefinedComparisonÚUndefinedEnvironmentNameÚMarkerÚdefault_environmentc@seZdZdZdS)rzE An invalid marker was found, users should refer to PEP 508. N©Ú__name__Ú __module__Ú __qualname__Ú__doc__©rrúA/usr/lib/python3.8/site-packages/pip/_vendor/packaging/markers.pyrsc@seZdZdZdS)rzP An invalid operation was attempted on a value that doesn't support it. Nrrrrrr"sc@seZdZdZdS)rz\ A name was attempted to be used that does not exist inside of the environment. Nrrrrrr(sc@s,eZdZdd„Zdd„Zdd„Zdd„Zd S) ÚNodecCs ||_dS©N)Úvalue)Úselfr rrrÚ__init__0sz Node.__init__cCs t|jƒSr)Ústrr ©r!rrrÚ__str__3sz Node.__str__cCsd |jjt|ƒ¡S)Nz <{0}({1!r})>)ÚformatÚ __class__rr#r$rrrÚ__repr__6sz Node.__repr__cCst‚dSr)ÚNotImplementedErrorr$rrrÚ serialize9szNode.serializeN)rrrr"r%r(r*rrrrr/src@seZdZdd„ZdS)ÚVariablecCst|ƒSr©r#r$rrrr*>szVariable.serializeN©rrrr*rrrrr+=sr+c@seZdZdd„ZdS)ÚValuecCs d |¡S)Nz"{0}")r&r$rrrr*CszValue.serializeNr-rrrrr.Bsr.c@seZdZdd„ZdS)ÚOpcCst|ƒSrr,r$rrrr*Hsz Op.serializeNr-rrrrr/Gsr/Úimplementation_versionÚplatform_python_implementationÚimplementation_nameÚpython_full_versionÚplatform_releaseÚplatform_versionÚplatform_machineÚplatform_systemÚpython_versionÚ sys_platformÚos_nameúos.nameú sys.platformúplatform.versionúplatform.machineúplatform.python_implementationÚpython_implementationZextra)r;r<r=r>r?r@cCstt |d|d¡ƒS©Nr)r+ÚALIASESÚget©ÚsÚlÚtrrrÚhórHz===ú==ú>=ú<=ú!=z~=ú>ú<únot inÚincCs t|dƒSrA)r/rDrrrrHorIú'ú"cCs t|dƒSrA)r.rDrrrrHrrIÚandÚorcCs t|dƒSrA)ÚtuplerDrrrrHyrIú(ú)cCs t|tƒrdd„|DƒS|SdS)NcSsg|] }t|ƒ‘qSr)Ú_coerce_parse_result)Ú.0ÚirrrÚ ‡sz(_coerce_parse_result..)Ú isinstancer)ÚresultsrrrrY…s rYTcCs¨t|tttfƒst‚t|tƒrHt|ƒdkrHt|dttfƒrHt|dƒSt|tƒr‚dd„|Dƒ}|rnd |¡Sdd |¡dSn"t|tƒr d dd „|Dƒ¡S|SdS) Nrrcss|]}t|dd�VqdS)F)ÚfirstN)Ú_format_marker©rZÚmrrrÚ ›sz!_format_marker..ú rWrXcSsg|] }| ¡‘qSr)r*rarrrr\¡sz"_format_marker..)r]ÚlistrVrÚAssertionErrorÚlenr`Újoin)Úmarkerr_Úinnerrrrr`Œs ÿ þý    r`cCs||kSrr©ÚlhsÚrhsrrrrH§rIcCs||kSrrrkrrrrH¨rI)rQrPrOrLrJrMrKrNcCslztd | ¡|g¡ƒ}Wntk r.Yn X| |¡St | ¡¡}|dkrbtd |||¡ƒ‚|||ƒS)NÚz#Undefined {0!r} on {1!r} and {2!r}.) rrhr*rÚcontainsÚ _operatorsrCrr&)rlÚoprmÚspecZoperrrrÚ_eval_op²s  ÿrscCs&| |t¡}|tkr"td |¡ƒ‚|S)Nz/{0!r} does not exist in evaluation environment.)rCÚ _undefinedrr&)Ú environmentÚnamer rrrÚ_get_envÆs  ÿrwc CsÐgg}|D]²}t|tttfƒs"t‚t|tƒrB|d t||ƒ¡q t|tƒrž|\}}}t|tƒrtt||j ƒ}|j }n|j }t||j ƒ}|d t |||ƒ¡q |dksªt‚|dkr | g¡q t dd„|DƒƒS)Néÿÿÿÿ)rTrUrUcss|]}t|ƒVqdSr)Úall)rZÚitemrrrrcész$_evaluate_markers..) r]rerVrrfÚappendÚ_evaluate_markersr+rwr rsÚany) ZmarkersruÚgroupsrirlrqrmZ lhs_valueZ rhs_valuerrrr|Ñs"        r|cCs2d |¡}|j}|dkr.||dt|jƒ7}|S)Nz{0.major}.{0.minor}.{0.micro}Úfinalr)r&Ú releaselevelr#Úserial)ÚinfoÚversionZkindrrrÚformat_full_versionìs  r„cCsrttdƒr ttjjƒ}tjj}nd}d}||tjt ¡t  ¡t  ¡t ¡t  ¡t  ¡d  t ¡dd…¡tjdœ S)NÚimplementationÚ0rnÚ.é) r2r0r:r6r4r7r5r3r1r8r9)ÚhasattrÚsysr„r…rƒrvÚosÚplatformÚmachineÚreleaseÚsystemr8r@rhZpython_version_tuple)Ziverr2rrrrôs"   õc@s.eZdZdd„Zdd„Zdd„Zd dd „ZdS) rc Cs`ztt |¡ƒ|_WnFtk rZ}z(d |||j|jd…¡}t|ƒ‚W5d}~XYnXdS)Nz+Invalid marker: {0!r}, parse error at {1!r}é)rYÚMARKERZ parseStringÚ_markersrr&Zlocr)r!riÚeZerr_strrrrr" sÿzMarker.__init__cCs t|jƒSr)r`r’r$rrrr%szMarker.__str__cCsd t|ƒ¡S)Nz)r&r#r$rrrr(szMarker.__repr__NcCs$tƒ}|dk r| |¡t|j|ƒS)a$Evaluate a marker. Return the boolean from evaluating the given marker against the environment. environment is an optional argument to override all or part of the determined environment. The environment is determined from the current Python process. N)rÚupdater|r’)r!ruZcurrent_environmentrrrÚevaluates  zMarker.evaluate)N)rrrr"r%r(r•rrrrr s )T)AZ __future__rrrÚoperatorr‹rŒrŠZpip._vendor.pyparsingrrrrr r r r r ÚLZ_compatrZ specifiersrrÚ__all__Ú ValueErrorrrrÚobjectrr+r.r/ZVARIABLErBZsetParseActionZ VERSION_CMPZ MARKER_OPZ MARKER_VALUEZBOOLOPZ MARKER_VARZ MARKER_ITEMÚsuppressZLPARENZRPARENZ MARKER_EXPRZ MARKER_ATOMr‘rYr`ÚltÚleÚeqÚneÚgeÚgtrprsrtrwr|r„rrrrrrÚsÈ  û ÿþýüûúùø ÷ ö õ ô óòñðïÿú>ÿ    ø  PKÓ¶N]7[½Á Á Psite-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.eˆã@sDddlmZmZmZGdd„deƒZeƒZGdd„deƒZeƒZdS)é)Úabsolute_importÚdivisionÚprint_functionc@sTeZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dd„Z dS)ÚInfinitycCsdS)Nr©©ÚselfrrúE/usr/lib/python3.8/site-packages/pip/_vendor/packaging/_structures.pyÚ__repr__szInfinity.__repr__cCs tt|ƒƒS©N©ÚhashÚreprrrrr Ú__hash__ szInfinity.__hash__cCsdS©NFr©rÚotherrrr Ú__lt__szInfinity.__lt__cCsdSrrrrrr Ú__le__szInfinity.__le__cCs t||jƒSr ©Ú isinstanceÚ __class__rrrr Ú__eq__szInfinity.__eq__cCst||jƒ Sr rrrrr Ú__ne__szInfinity.__ne__cCsdS©NTrrrrr Ú__gt__szInfinity.__gt__cCsdSrrrrrr Ú__ge__szInfinity.__ge__cCstSr )ÚNegativeInfinityrrrr Ú__neg__ szInfinity.__neg__N© Ú__name__Ú __module__Ú __qualname__r rrrrrrrrrrrr rsrc@sTeZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dd„Z dS)rcCsdS)Nz -Infinityrrrrr r (szNegativeInfinity.__repr__cCs tt|ƒƒSr r rrrr r+szNegativeInfinity.__hash__cCsdSrrrrrr r.szNegativeInfinity.__lt__cCsdSrrrrrr r1szNegativeInfinity.__le__cCs t||jƒSr rrrrr r4szNegativeInfinity.__eq__cCst||jƒ Sr rrrrr r7szNegativeInfinity.__ne__cCsdSrrrrrr r:szNegativeInfinity.__gt__cCsdSrrrrrr r=szNegativeInfinity.__ge__cCstSr )rrrrr r@szNegativeInfinity.__neg__Nrrrrr r'srN)Z __future__rrrÚobjectrrrrrr ÚsPKÓ¶N]7[½Á Á Jsite-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-38.pycnu„[µü¤U ÀÒ.eˆã@sDddlmZmZmZGdd„deƒZeƒZGdd„deƒZeƒZdS)é)Úabsolute_importÚdivisionÚprint_functionc@sTeZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dd„Z dS)ÚInfinitycCsdS)Nr©©ÚselfrrúE/usr/lib/python3.8/site-packages/pip/_vendor/packaging/_structures.pyÚ__repr__szInfinity.__repr__cCs tt|ƒƒS©N©ÚhashÚreprrrrr Ú__hash__ szInfinity.__hash__cCsdS©NFr©rÚotherrrr Ú__lt__szInfinity.__lt__cCsdSrrrrrr Ú__le__szInfinity.__le__cCs t||jƒSr ©Ú isinstanceÚ __class__rrrr Ú__eq__szInfinity.__eq__cCst||jƒ Sr rrrrr Ú__ne__szInfinity.__ne__cCsdS©NTrrrrr Ú__gt__szInfinity.__gt__cCsdSrrrrrr Ú__ge__szInfinity.__ge__cCstSr )ÚNegativeInfinityrrrr Ú__neg__ szInfinity.__neg__N© Ú__name__Ú __module__Ú __qualname__r rrrrrrrrrrrr rsrc@sTeZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dd„Z dS)rcCsdS)Nz -Infinityrrrrr r (szNegativeInfinity.__repr__cCs tt|ƒƒSr r rrrr r+szNegativeInfinity.__hash__cCsdSrrrrrr r.szNegativeInfinity.__lt__cCsdSrrrrrr r1szNegativeInfinity.__le__cCs t||jƒSr rrrrr r4szNegativeInfinity.__eq__cCst||jƒ Sr rrrrr r7szNegativeInfinity.__ne__cCsdSrrrrrr r:szNegativeInfinity.__gt__cCsdSrrrrrr r=szNegativeInfinity.__ge__cCstSr )rrrrr r@szNegativeInfinity.__neg__Nrrrrr r'srN)Z __future__rrrÚobjectrrrrrr ÚsPKÓ¶N]³±�„ËËFsite-packages/pip/_vendor/packaging/__pycache__/_compat.cpython-38.pycnu„[µü¤U ÀÒ.eaã@sVddlmZmZmZddlZejddkZejddkZerDefZ ne fZ dd„Z dS)é)Úabsolute_importÚdivisionÚprint_functionNéécs&G‡‡fdd„dˆƒ}t |ddi¡S)z/ Create a base class with a metaclass. cseZdZ‡‡fdd„ZdS)z!with_metaclass..metaclasscs ˆ|ˆ|ƒS)N©)ÚclsÚnameZ this_basesÚd©ÚbasesÚmetarúA/usr/lib/python3.8/site-packages/pip/_vendor/packaging/_compat.pyÚ__new__sz)with_metaclass..metaclass.__new__N)Ú__name__Ú __module__Ú __qualname__rrr rrÚ metaclasssrZtemporary_classr)Útyper)r r rrr rÚwith_metaclasssr) Z __future__rrrÚsysÚ version_infoZPY2ZPY3ÚstrZ string_typesZ basestringrrrrrÚsPKÓ¶N]³±�„ËËLsite-packages/pip/_vendor/packaging/__pycache__/_compat.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.eaã@sVddlmZmZmZddlZejddkZejddkZerDefZ ne fZ dd„Z dS)é)Úabsolute_importÚdivisionÚprint_functionNéécs&G‡‡fdd„dˆƒ}t |ddi¡S)z/ Create a base class with a metaclass. cseZdZ‡‡fdd„ZdS)z!with_metaclass..metaclasscs ˆ|ˆ|ƒS)N©)ÚclsÚnameZ this_basesÚd©ÚbasesÚmetarúA/usr/lib/python3.8/site-packages/pip/_vendor/packaging/_compat.pyÚ__new__sz)with_metaclass..metaclass.__new__N)Ú__name__Ú __module__Ú __qualname__rrr rrÚ metaclasssrZtemporary_classr)Útyper)r r rrr rÚwith_metaclasssr) Z __future__rrrÚsysÚ version_infoZPY2ZPY3ÚstrZ string_typesZ basestringrrrrrÚsPKÓ¶N]Uù˜Gsite-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-38.pycnu„[µü¤U ÀÒ.e2ã@sTddlmZmZmZddlmZmZmZmZm Z m Z m Z m Z dddddd d d gZ d S) é)Úabsolute_importÚdivisionÚprint_functioné)Ú __author__Ú __copyright__Ú __email__Ú __license__Ú __summary__Ú __title__Ú__uri__Ú __version__r r r r rrr rN)Z __future__rrrÚ __about__rrrr r r r r Ú__all__©rrúB/usr/lib/python3.8/site-packages/pip/_vendor/packaging/__init__.pyÚs( øPKÓ¶N]|´vÚ//Lsite-packages/pip/_vendor/packaging/__pycache__/version.cpython-38.opt-1.pycnu„[µü¤U ÀÒ.eÊ.ã @sþddlmZmZmZddlZddlZddlZddlmZddddd gZ e  d d d d dddg¡Z dd„Z Gdd„de ƒZGdd„deƒZGdd„deƒZe dej¡ZddddddœZdd„Zdd„ZdZGd d„deƒZd!d"„Ze d#¡Zd$d%„Zd&d'„ZdS)(é)Úabsolute_importÚdivisionÚprint_functionNé)ÚInfinityÚparseÚVersionÚ LegacyVersionÚInvalidVersionÚVERSION_PATTERNÚ_VersionÚepochÚreleaseÚdevÚpreÚpostÚlocalcCs,z t|ƒWStk r&t|ƒYSXdS)zÑ Parse the given version string and return either a :class:`Version` object or a :class:`LegacyVersion` object depending on if the given version is a valid PEP 440 version or a legacy version. N)rr r )Úversion©rúA/usr/lib/python3.8/site-packages/pip/_vendor/packaging/version.pyrs c@seZdZdZdS)r zF An invalid version was found, users should refer to PEP 440. N)Ú__name__Ú __module__Ú __qualname__Ú__doc__rrrrr !sc@sLeZdZdd„Zdd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dS)Ú _BaseVersioncCs t|jƒS©N)ÚhashÚ_key©ÚselfrrrÚ__hash__(sz_BaseVersion.__hash__cCs| |dd„¡S)NcSs||kSrr©ÚsÚorrrÚ,óz%_BaseVersion.__lt__..©Ú_compare©rÚotherrrrÚ__lt__+sz_BaseVersion.__lt__cCs| |dd„¡S)NcSs||kSrrr!rrrr$/r%z%_BaseVersion.__le__..r&r(rrrÚ__le__.sz_BaseVersion.__le__cCs| |dd„¡S)NcSs||kSrrr!rrrr$2r%z%_BaseVersion.__eq__..r&r(rrrÚ__eq__1sz_BaseVersion.__eq__cCs| |dd„¡S)NcSs||kSrrr!rrrr$5r%z%_BaseVersion.__ge__..r&r(rrrÚ__ge__4sz_BaseVersion.__ge__cCs| |dd„¡S)NcSs||kSrrr!rrrr$8r%z%_BaseVersion.__gt__..r&r(rrrÚ__gt__7sz_BaseVersion.__gt__cCs| |dd„¡S)NcSs||kSrrr!rrrr$;r%z%_BaseVersion.__ne__..r&r(rrrÚ__ne__:sz_BaseVersion.__ne__cCst|tƒstS||j|jƒSr)Ú isinstancerÚNotImplementedr)rr)Úmethodrrrr'=s z_BaseVersion._compareN) rrrr r*r+r,r-r.r/r'rrrrr'src@s¨eZdZdd„Zdd„Zdd„Zedd„ƒZed d „ƒZed d „ƒZ ed d„ƒZ edd„ƒZ edd„ƒZ edd„ƒZ edd„ƒZedd„ƒZedd„ƒZedd„ƒZdS)r cCst|ƒ|_t|jƒ|_dSr)ÚstrÚ_versionÚ_legacy_cmpkeyr)rrrrrÚ__init__Es zLegacyVersion.__init__cCs|jSr©r4rrrrÚ__str__IszLegacyVersion.__str__cCsd tt|ƒƒ¡S)Nz©ÚformatÚreprr3rrrrÚ__repr__LszLegacyVersion.__repr__cCs|jSrr7rrrrÚpublicOszLegacyVersion.publiccCs|jSrr7rrrrÚ base_versionSszLegacyVersion.base_versioncCsdS)Néÿÿÿÿrrrrrr WszLegacyVersion.epochcCsdSrrrrrrr[szLegacyVersion.releasecCsdSrrrrrrr_szLegacyVersion.precCsdSrrrrrrrcszLegacyVersion.postcCsdSrrrrrrrgszLegacyVersion.devcCsdSrrrrrrrkszLegacyVersion.localcCsdS©NFrrrrrÚ is_prereleaseoszLegacyVersion.is_prereleasecCsdSr@rrrrrÚis_postreleasesszLegacyVersion.is_postreleasecCsdSr@rrrrrÚ is_devreleasewszLegacyVersion.is_devreleaseN)rrrr6r8r<Úpropertyr=r>r rrrrrrArBrCrrrrr Ds2          z(\d+ | [a-z]+ | \.| -)Úczfinal-ú@)rÚpreviewú-Úrcrccs\t |¡D]F}t ||¡}|r |dkr(q |dd…dkrF| d¡Vq d|Vq dVdS)NÚ.rÚ 0123456789éÚ*ú*final)Ú_legacy_version_component_reÚsplitÚ_legacy_version_replacement_mapÚgetÚzfill)r"ÚpartrrrÚ_parse_version_parts‡s   rUcCszd}g}t| ¡ƒD]T}| d¡r^|dkrD|rD|ddkrD| ¡q*|r^|ddkr^| ¡qD| |¡qt|ƒ}||fS)Nr?rMrNz*final-Z00000000)rUÚlowerÚ startswithÚpopÚappendÚtuple)rr ÚpartsrTrrrr5˜s    r5a— v? (?: (?:(?P[0-9]+)!)? # epoch (?P[0-9]+(?:\.[0-9]+)*) # release segment (?P
                                          # pre-release
            [-_\.]?
            (?P(a|b|c|rc|alpha|beta|pre|preview))
            [-_\.]?
            (?P[0-9]+)?
        )?
        (?P                                         # post release
            (?:-(?P[0-9]+))
            |
            (?:
                [-_\.]?
                (?Ppost|rev|r)
                [-_\.]?
                (?P[0-9]+)?
            )
        )?
        (?P                                          # dev release
            [-_\.]?
            (?Pdev)
            [-_\.]?
            (?P[0-9]+)?
        )?
    )
    (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
c@sÄeZdZe dedejejB¡Zdd„Z	dd„Z
dd„Zed	d
„ƒZ
edd„ƒZed
d„ƒZedd„ƒZedd„ƒZedd„ƒZedd„ƒZedd„ƒZedd„ƒZedd„ƒZedd„ƒZdS) rz^\s*z\s*$c
Csà|j |¡}|std |¡ƒ‚t| d¡r8t| d¡ƒndtdd„| d¡ d¡Dƒƒt	| d¡| d	¡ƒt	| d
¡| d¡p†| d¡ƒt	| d
¡| d¡ƒt
| d¡ƒd�|_t|jj
|jj|jj|jj|jj|jjƒ|_dS)NzInvalid version: '{0}'r
rcss|]}t|ƒVqdSr)Úint©Ú.0ÚirrrÚ	âsz#Version.__init__..rrJZpre_lZpre_nZpost_lZpost_n1Zpost_n2Zdev_lZdev_nr©r
rrrrr)Ú_regexÚsearchr
r:rÚgroupr\rZrPÚ_parse_letter_versionÚ_parse_local_versionr4Ú_cmpkeyr
rrrrrr)rrÚmatchrrrr6Ùs,ÿøúzVersion.__init__cCsd tt|ƒƒ¡S)Nzr9rrrrr<õszVersion.__repr__cCsÀg}|jdkr | d |j¡¡| d dd„|jDƒ¡¡|jdk	rb| d dd„|jDƒ¡¡|jdk	r~| d |j¡¡|jdk	rš| d	 |j¡¡|jdk	r¶| d
 |j¡¡d |¡S)Nrú{0}!rJcss|]}t|ƒVqdSr©r3©r^Úxrrrr`sz"Version.__str__..Úcss|]}t|ƒVqdSrrjrkrrrr`sz.post{0}z.dev{0}z+{0})	r
rYr:Újoinrrrrr©rr[rrrr8øs




zVersion.__str__cCs|jjSr)r4r
rrrrr
sz
Version.epochcCs|jjSr)r4rrrrrrszVersion.releasecCs|jjSr)r4rrrrrrszVersion.precCs|jjr|jjdSdS©Nr)r4rrrrrr szVersion.postcCs|jjr|jjdSdSrp)r4rrrrrr$szVersion.devcCs(|jjr d dd„|jjDƒ¡SdSdS)NrJcss|]}t|ƒVqdSrrjrkrrrr`+sz Version.local..)r4rrnrrrrr(sz
Version.localcCst|ƒ dd¡dS)Nú+rr)r3rPrrrrr=/szVersion.publiccCsFg}|jdkr | d |j¡¡| d dd„|jDƒ¡¡d |¡S)NrrirJcss|]}t|ƒVqdSrrjrkrrrr`<sz'Version.base_version..rm)r
rYr:rnrrorrrr>3s

zVersion.base_versioncCs|jdk	p|jdk	Sr)rrrrrrrA@szVersion.is_prereleasecCs
|jdk	Sr)rrrrrrBDszVersion.is_postreleasecCs
|jdk	Sr)rrrrrrCHszVersion.is_devreleaseN)rrrÚreÚcompilerÚVERBOSEÚ
IGNORECASErbr6r<r8rDr
rrrrrr=r>rArBrCrrrrrÕs4









cCsv|rZ|dkrd}| ¡}|dkr&d}n(|dkr4d}n|dkrBd}n|dkrNd	}|t|ƒfS|sr|rrd	}|t|ƒfSdS)
NrZalphaÚaZbetaÚb)rErrGrI)ZrevÚrr)rVr\)ZletterZnumberrrrreMs rez[\._-]cCs$|dk	r tdd„t |¡DƒƒSdS)zR
    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
    Ncss&|]}| ¡s| ¡nt|ƒVqdSr)ÚisdigitrVr\)r^rTrrrr`tsÿz'_parse_local_version..)rZÚ_local_version_separatorsrP)rrrrrfosþrfcCs˜tttt dd„t|ƒ¡ƒƒƒ}|dkr@|dkr@|dk	r@t}n|dkrLt}|dkrZt}|dkrft}|dkrvt}ntdd„|Dƒƒ}||||||fS)NcSs|dkS)Nrr)rlrrrr$�r%z_cmpkey..css*|]"}t|tƒr|dfnt|fVqdS)rmN)r0r\rr]rrrr`¢sz_cmpkey..)rZÚreversedÚlistÚ	itertoolsÚ	dropwhilerrarrrrgzsÿ	rg)Z
__future__rrrÚcollectionsr}rrZ_structuresrÚ__all__Ú
namedtuplerrÚ
ValueErrorr
Úobjectrr	rsrtrOrQrUr5rrrerzrfrgrrrrÚs8ÿ8û	 x
PKÓ¶N]¦»Ö†ˆˆQsite-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.e\ã@s|ddlmZmZmZddlZddlZddlmZmZm	Z	m
Z
ddlmZmZm
Z
mZmZddlmZddlmZddlmZmZdd	lmZmZmZGd
d„deƒZeejejƒZ edƒ !¡Z"ed
ƒ !¡Z#edƒ !¡Z$edƒ !¡Z%edƒ !¡Z&edƒ !¡Z'edƒ !¡Z(edƒZ)e ee)ƒe BZ*ee ee*ƒƒZ+e+dƒZ,e+Z-edƒdƒZ.e(e.Z/e-ee&e-ƒZ0e"e
e0ƒe#dƒZ1eej2ej3ej4BƒZ5eej2ej3ej4BƒZ6e5e6AZ7ee7ee&e7ƒddd�dƒZ8e
e$e8e%e8BƒZ9e9 :dd„¡e	e9ƒdƒZ;e; :dd„¡e	eƒƒdƒZe :d d„¡e'Ze/e
e=ƒZ?e,e
e1ƒe?e>BZ@ee@eZAeA Bd!¡Gd"d#„d#eCƒZDdS)$é)Úabsolute_importÚdivisionÚprint_functionN)ÚstringStartÚ	stringEndÚoriginalTextForÚParseException)Ú
ZeroOrMoreÚWordÚOptionalÚRegexÚCombine)ÚLiteral)Úparseé)ÚMARKER_EXPRÚMarker)ÚLegacySpecifierÚ	SpecifierÚSpecifierSetc@seZdZdZdS)ÚInvalidRequirementzJ
    An invalid requirement was found, users should refer to PEP 508.
    N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__©rrúF/usr/lib/python3.8/site-packages/pip/_vendor/packaging/requirements.pyrsrú[ú]ú(ú)ú,ú;ú@z-_.Únamez[^ ]+ÚurlÚextrasF)Z
joinStringZadjacentÚ	_raw_speccCs
|jpdS)NÚ)r'©ÚsÚlÚtrrrÚ7ór-Ú	specifiercCs|dS)Nrrr)rrrr-:r.ÚmarkercCst||j|j…ƒS)N)rZ_original_startZ
_original_endr)rrrr->r.zx[]c@s(eZdZdZdd„Zdd„Zdd„ZdS)	ÚRequirementzÁParse a requirement.

    Parse a given requirement string into its parts, such as name, specifier,
    URL, and extras. Raises InvalidRequirement on a badly-formed requirement
    string.
    c
Cszt |¡}WnDtk
rR}z&td ||j|jd…|j¡ƒ‚W5d}~XYnX|j|_|jrÄt	 	|j¡}|j
dkr’t	 |¡|jkrºtdƒ‚n(|j
rª|jrª|j
sº|jsºtd |j¡ƒ‚|j|_nd|_t
|jrÜ|j ¡ngƒ|_t|jƒ|_|jrü|jnd|_dS)NzParse error at "{0!r}": {1}éÚfilezInvalid URL givenzInvalid URL: {0})ÚREQUIREMENTÚparseStringrrÚformatZlocÚmsgr$r%ÚurlparseZschemeZ
urlunparseZnetlocÚsetr&ZasListrr/r0)ÚselfZrequirement_stringZreqÚeZ
parsed_urlrrrÚ__init__[s4ÿÿ

ÿÿ
zRequirement.__init__cCsŠ|jg}|jr*| d d t|jƒ¡¡¡|jr@| t|jƒ¡|jrh| d |j¡¡|j	rh| d¡|j	r€| d |j	¡¡d |¡S)Nz[{0}]r!z@ {0}ú z; {0}r()
r$r&Úappendr6ÚjoinÚsortedr/Ústrr%r0)r:ÚpartsrrrÚ__str__vs
zRequirement.__str__cCsd t|ƒ¡S)Nz)r6rA)r:rrrÚ__repr__‰szRequirement.__repr__N)rrrrr<rCrDrrrrr1Nsr1)EZ
__future__rrrÚstringÚreZpip._vendor.pyparsingrrrrr	r
rrr
rÚLZpip._vendor.six.moves.urllibrr8ZmarkersrrZ
specifiersrrrÚ
ValueErrorrZ
ascii_lettersZdigitsZALPHANUMÚsuppressZLBRACKETZRBRACKETZLPARENZRPARENÚCOMMAZ	SEMICOLONÚATZPUNCTUATIONZIDENTIFIER_ENDZ
IDENTIFIERÚNAMEZEXTRAZURIZURLZEXTRAS_LISTZEXTRASZ
_regex_strÚVERBOSEÚ
IGNORECASEZVERSION_PEP440ZVERSION_LEGACYZVERSION_ONEZVERSION_MANYZ
_VERSION_SPECZsetParseActionZVERSION_SPECZMARKER_SEPARATORZMARKERZVERSION_AND_MARKERZURL_AND_MARKERZNAMED_REQUIREMENTr4r5Úobjectr1rrrrÚshÿþÿ
PKÓ¶N]ÓôuÖ””Jsite-packages/pip/_vendor/packaging/__pycache__/utils.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eðã@sJddlmZmZmZddlZddlmZmZe d¡Z	dd„Z
dd	„ZdS)
é)Úabsolute_importÚdivisionÚprint_functionNé)ÚInvalidVersionÚVersionz[-_.]+cCst d|¡ ¡S)Nú-)Ú_canonicalize_regexÚsubÚlower)Úname©r
ú?/usr/lib/python3.8/site-packages/pip/_vendor/packaging/utils.pyÚcanonicalize_namesrc
Csðzt|ƒ}Wntk
r$|YSXg}|jdkrF| d |j¡¡| t ddd dd„|jDƒ¡¡¡|j	dk	r’| d d	d„|j	Dƒ¡¡|j
dk	r®| d
 |j
¡¡|jdk	rÊ| d |j¡¡|jdk	ræ| d |j¡¡d |¡S)
z‚
    This is very similar to Version.__str__, but has one subtle differences
    with the way it handles the release segment.
    rz{0}!z(\.0)+$ÚÚ.css|]}t|ƒVqdS©N©Ústr©Ú.0Úxr
r
rÚ	'sz'canonicalize_version..Ncss|]}t|ƒVqdSrrrr
r
rr+sz.post{0}z.dev{0}z+{0})
rrZepochÚappendÚformatÚrer
ÚjoinÚreleaseZpreZpostZdevZlocal)ÚversionÚpartsr
r
rÚcanonicalize_versions"

&



r )Z
__future__rrrrrrrÚcompiler	rr r
r
r
rÚs

PKÓ¶N]¦»Ö†ˆˆKsite-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-38.pycnu„[µü¤U

ÀÒ.e\ã@s|ddlmZmZmZddlZddlZddlmZmZm	Z	m
Z
ddlmZmZm
Z
mZmZddlmZddlmZddlmZmZdd	lmZmZmZGd
d„deƒZeejejƒZ edƒ !¡Z"ed
ƒ !¡Z#edƒ !¡Z$edƒ !¡Z%edƒ !¡Z&edƒ !¡Z'edƒ !¡Z(edƒZ)e ee)ƒe BZ*ee ee*ƒƒZ+e+dƒZ,e+Z-edƒdƒZ.e(e.Z/e-ee&e-ƒZ0e"e
e0ƒe#dƒZ1eej2ej3ej4BƒZ5eej2ej3ej4BƒZ6e5e6AZ7ee7ee&e7ƒddd�dƒZ8e
e$e8e%e8BƒZ9e9 :dd„¡e	e9ƒdƒZ;e; :dd„¡e	eƒƒdƒZe :d d„¡e'Ze/e
e=ƒZ?e,e
e1ƒe?e>BZ@ee@eZAeA Bd!¡Gd"d#„d#eCƒZDdS)$é)Úabsolute_importÚdivisionÚprint_functionN)ÚstringStartÚ	stringEndÚoriginalTextForÚParseException)Ú
ZeroOrMoreÚWordÚOptionalÚRegexÚCombine)ÚLiteral)Úparseé)ÚMARKER_EXPRÚMarker)ÚLegacySpecifierÚ	SpecifierÚSpecifierSetc@seZdZdZdS)ÚInvalidRequirementzJ
    An invalid requirement was found, users should refer to PEP 508.
    N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__©rrúF/usr/lib/python3.8/site-packages/pip/_vendor/packaging/requirements.pyrsrú[ú]ú(ú)ú,ú;ú@z-_.Únamez[^ ]+ÚurlÚextrasF)Z
joinStringZadjacentÚ	_raw_speccCs
|jpdS)NÚ)r'©ÚsÚlÚtrrrÚ7ór-Ú	specifiercCs|dS)Nrrr)rrrr-:r.ÚmarkercCst||j|j…ƒS)N)rZ_original_startZ
_original_endr)rrrr->r.zx[]c@s(eZdZdZdd„Zdd„Zdd„ZdS)	ÚRequirementzÁParse a requirement.

    Parse a given requirement string into its parts, such as name, specifier,
    URL, and extras. Raises InvalidRequirement on a badly-formed requirement
    string.
    c
Cszt |¡}WnDtk
rR}z&td ||j|jd…|j¡ƒ‚W5d}~XYnX|j|_|jrÄt	 	|j¡}|j
dkr’t	 |¡|jkrºtdƒ‚n(|j
rª|jrª|j
sº|jsºtd |j¡ƒ‚|j|_nd|_t
|jrÜ|j ¡ngƒ|_t|jƒ|_|jrü|jnd|_dS)NzParse error at "{0!r}": {1}éÚfilezInvalid URL givenzInvalid URL: {0})ÚREQUIREMENTÚparseStringrrÚformatZlocÚmsgr$r%ÚurlparseZschemeZ
urlunparseZnetlocÚsetr&ZasListrr/r0)ÚselfZrequirement_stringZreqÚeZ
parsed_urlrrrÚ__init__[s4ÿÿ

ÿÿ
zRequirement.__init__cCsŠ|jg}|jr*| d d t|jƒ¡¡¡|jr@| t|jƒ¡|jrh| d |j¡¡|j	rh| d¡|j	r€| d |j	¡¡d |¡S)Nz[{0}]r!z@ {0}ú z; {0}r()
r$r&Úappendr6ÚjoinÚsortedr/Ústrr%r0)r:ÚpartsrrrÚ__str__vs
zRequirement.__str__cCsd t|ƒ¡S)Nz)r6rA)r:rrrÚ__repr__‰szRequirement.__repr__N)rrrrr<rCrDrrrrr1Nsr1)EZ
__future__rrrÚstringÚreZpip._vendor.pyparsingrrrrr	r
rrr
rÚLZpip._vendor.six.moves.urllibrr8ZmarkersrrZ
specifiersrrrÚ
ValueErrorrZ
ascii_lettersZdigitsZALPHANUMÚsuppressZLBRACKETZRBRACKETZLPARENZRPARENÚCOMMAZ	SEMICOLONÚATZPUNCTUATIONZIDENTIFIER_ENDZ
IDENTIFIERÚNAMEZEXTRAZURIZURLZEXTRAS_LISTZEXTRASZ
_regex_strÚVERBOSEÚ
IGNORECASEZVERSION_PEP440ZVERSION_LEGACYZVERSION_ONEZVERSION_MANYZ
_VERSION_SPECZsetParseActionZVERSION_SPECZMARKER_SEPARATORZMARKERZVERSION_AND_MARKERZURL_AND_MARKERZNAMED_REQUIREMENTr4r5Úobjectr1rrrrÚshÿþÿ
PKÓ¶N]øGW^4*4*Csite-packages/pip/_vendor/packaging/__pycache__/tags.cpython-38.pycnu„[µü¤U

ÀÒ.e…2ã@snddlmZddlZzddlmZWn0ek
rTddlZdd„e ¡DƒZ[YnXddl	Z	ddl
Z
ddlZddlZddl
Z
dddd	d
dœZejdkZGd
d„deƒZdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd „Zd!d"„Zd#d$„Zefd%d&„Zd'd(„Zd=d)d*„Z d+d,„Z!d-d.„Z"d/d0„Z#d1d2„Z$efd3d4„Z%d5d6„Z&d7d8„Z'd9d:„Z(d;d<„Z)dS)>é)Úabsolute_importN)ÚEXTENSION_SUFFIXEScCsg|]}|d‘qS)r©)Ú.0Úxrrú>/usr/lib/python3.8/site-packages/pip/_vendor/packaging/tags.pyÚ
srÚpyÚcpÚppZipZjy)ÚpythonZcpythonZpypyZ
ironpythonZjythonlc@sbeZdZdddgZdd„Zedd„ƒZedd	„ƒZed
d„ƒZdd
„Z	dd„Z
dd„Zdd„ZdS)ÚTagÚ_interpreterÚ_abiÚ	_platformcCs"| ¡|_| ¡|_| ¡|_dS©N)Úlowerrrr)ÚselfÚinterpreterÚabiÚplatformrrrÚ__init__'s

zTag.__init__cCs|jSr)r©rrrrr,szTag.interpretercCs|jSr)rrrrrr0szTag.abicCs|jSr)rrrrrr4szTag.platformcCs$|j|jko"|j|jko"|j|jkSr)rrr)rÚotherrrrÚ__eq__8s

ÿ
ýz
Tag.__eq__cCst|j|j|jfƒSr)ÚhashrrrrrrrÚ__hash__?szTag.__hash__cCsd |j|j|j¡S)Nz{}-{}-{})ÚformatrrrrrrrÚ__str__BszTag.__str__cCsdj|t|ƒd�S)Nz<{self} @ {self_id}>)rZself_id)rÚidrrrrÚ__repr__EszTag.__repr__N)
Ú__name__Ú
__module__Ú__qualname__Ú	__slots__rÚpropertyrrrrrrr rrrrr
#s



r
c	Cs`tƒ}| d¡\}}}| d¡D]6}| d¡D]&}| d¡D]}| t|||ƒ¡qƒsz _cpython_tags..c3s|]}tˆd|ƒVqdS©ÚnoneNrSrTrUrrrV…sr8éÿÿÿÿr7rr9rR)r
Úranger)r<rr.r/rr0r,Ú
minor_versionrrUrÚ
_cpython_tagssÿr\cCsdjtjdtjjtjjd�S)Nz$pp{py_major}{pypy_major}{pypy_minor}r)Zpy_majorZ
pypy_majorZ
pypy_minor)rrMÚversion_infoZpypy_version_infor:r;rrrrÚ_pypy_interpreter�s
ýr^cCst d¡}|rt|ƒSdSdS)NZSOABIrX)rJrKr6)rrrrÚ_generic_abi˜s
r_c#sB‡‡fdd„|DƒD]
}|Vq‡fdd„|DƒD]
}|Vq2dS)Nc3s|]}tˆˆ|ƒVqdSrrS©rr©rrrrrV¡sz_pypy_tags..c3s|]}tˆd|ƒVqdSrWrSr`rUrrrV£sr)r<rrr/r,rrarÚ
_pypy_tags srbc#sN‡‡fdd„|DƒD]
}|VqˆdkrJ‡fdd„|Dƒ}|D]
}|Vq>dS)Nc3s|]}tˆˆ|ƒVqdSrrSr`rarrrV¨sz _generic_tags..rXc3s|]}tˆd|ƒVqdSrWrSrTrUrrrV«sr)rr<rr/r,r-rrarÚ
_generic_tags§srcccs\dj|d|dd�Vdj|dd�Vt|ddddƒD]}dj|d|d�Vq>dS)	z¬
    Yield Python versions in descending order.

    After the latest version, the major-only version will be yielded, and then
    all following versions up to 'end'.
    zpy{major}{minor}rr8r9z	py{major})r:rYN)rrZ)r<r;rrrÚ_py_interpreter_range°srdccsTt|ƒD]}|D]}t|d|ƒVqqt|ddƒVt|ƒD]}t|ddƒVq
    - -none-any
    - py*-none-any
    rXÚanyN)rdr
)rr<r/rFr0rrrÚ_independent_tags½s	rfcCs|s|S| d¡rdSdS)NÚppcÚi386)Ú
startswith)ÚarchÚis_32bitrrrÚ	_mac_archÎs

rlcCsª|g}|dkr,|dkrgS| dddg¡np|dkrR|dkr@gS| dddg¡nJ|dkrz|d	ksj|dkrngS| d¡n"|d
krœ|dkrŽgS| ddg¡| d¡|S)
NZx86_64)é
rDZintelZfat64Zfat32rhZfatZppc64)rmérg)rméZ	universal)ÚextendrO)rFÚcpu_archZformatsrrrÚ_mac_binary_formatsØs&
rrc
	Csžt ¡\}}}|dkr2ttt| d¡dd…ƒƒ}|dkrBt|ƒ}g}t|dddƒD]B}|d|f}t||ƒ}|D]"}	| 	dj
|d|d|	d�¡qtqV|S)Nr'r>r8rYrz&macosx_{major}_{minor}_{binary_format})r:r;Ú
binary_format)rZmac_verÚtupleÚmapÚintr)rlrZrrrOr)
rFrjÚversion_strr2rqr/r[Zcompat_versionZbinary_formatsrsrrrÚ_mac_platformsós$
ýÿrxc	Cs>zddl}tt||dƒƒWSttfk
r4YnXt|ŽS)NrZ_compatible)Ú
_manylinuxÚboolÚgetattrÚImportErrorÚAttributeErrorÚ_have_compatible_glibc)ÚnameÚ
glibc_versionryrrrÚ_is_manylinux_compatible	sr�cCsZddl}| d¡}z
|j}Wntk
r2YdSX|j|_|ƒ}t|tƒsV| d¡}|S)NrÚascii)	ÚctypesZCDLLÚgnu_get_libc_versionr}Zc_char_pZrestypeÚ
isinstanceÚstrÚdecode)rƒZprocess_namespacer„rwrrrÚ_glibc_version_strings



rˆcCsHt d|¡}|s$t d|t¡dSt| d¡ƒ|koFt| d¡ƒ|kS)Nz$(?P[0-9]+)\.(?P[0-9]+)z=Expected glibc version with 2 components major.minor, got: %sFr:r;)ÚreÚmatchÚwarningsÚwarnÚRuntimeWarningrvÚgroup)rwÚrequired_majorÚ
minimum_minorrCrrrÚ_check_glibc_version1sÿýþr‘cCstƒ}|dkrdSt|||ƒS)NF)rˆr‘)r�r�rwrrrr~Fsr~cs|ttj ¡ƒ‰ˆdkr|rd‰d}t|ƒ}|D]$\}}t||ƒr.ˆ d|¡g}qXq.g}|‡fdd„|Dƒ7}| ˆ¡|S)NZlinux_x86_64Z
linux_i686))Z
manylinux2014)r>é)Z
manylinux2010)r>é)Z
manylinux1)r>rnÚlinuxcsg|]\}}ˆ d|¡‘qS©r”r3)rrr2r•rrr^sz$_linux_platforms..)r6Ú	distutilsÚutilÚget_platformÚiterr�r4rO)rkZmanylinux_supportZmanylinux_support_iterrr€r/rr•rÚ_linux_platformsMs

ršcCsttj ¡ƒ}|gSr)r6r–r—r˜)rrrrÚ_generic_platformscsr›cCst ¡ ¡}t |¡p|Sr)rZpython_implementationrÚINTERPRETER_SHORT_NAMESÚget)rrrrÚ_interpreter_namehsržcCs4t d¡}|s&d tt|dd…ƒ¡}dj||d�S)NZpy_version_nodotr?r>z{name}{version})rrF)rJrKÚjoinrur†r)rr<rFrrrÚ_generic_interpreterms
r ccsìtjdd…}tƒ}t ¡dkr(tƒ}nt ¡dkrZDarwinZLinuxr
r)rMr]ržrÚsystemrxršr›r=rQr\r^r_rbr rcrf)r<Zinterpreter_namer/rr.r,rrrrÚsys_tagsts.


r¢)NN)*Z
__future__rZdistutils.utilr–Zimportlib.machineryrr|ZimpZget_suffixesrr‰rMrJr‹rœÚmaxsizeZ_32_BIT_INTERPRETERÚobjectr
r1r6r=rQr\r^r_rbrcrdrfrlrrrxr�rˆr‘r~ršr›ržr r¢rrrrÚsVû	
&
#	



PKÓ¶N]<2m"m"Lsite-packages/pip/_vendor/packaging/__pycache__/markers.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.e: ã	@s@ddlmZmZmZddlZddlZddlZddlZddlm	Z	m
Z
mZmZddlm
Z
mZmZmZddlmZddlmZddlmZmZd	d
ddd
gZGdd	„d	eƒZGdd
„d
eƒZGdd„deƒZGdd„deƒZGdd„deƒZGdd„deƒZ Gdd„deƒZ!edƒedƒBedƒBedƒBedƒBedƒBedƒBed ƒBed!ƒBed"ƒBed#ƒBed$ƒBed%ƒBed&ƒBed'ƒBed(ƒBed)ƒBed*ƒBZ"d#d"ddddd+œZ#e" $d,d-„¡ed.ƒed/ƒBed0ƒBed1ƒBed2ƒBed3ƒBed4ƒBed5ƒBZ%e%ed6ƒBed7ƒBZ&e& $d8d-„¡ed9ƒed:ƒBZ'e' $d;d-„¡ed<ƒed=ƒBZ(e"e'BZ)ee)e&e)ƒZ*e* $d>d-„¡ed?ƒ +¡Z,ed@ƒ +¡Z-eƒZ.e*ee,e.e-ƒBZ/e.e/e
e(e.ƒ>ee.eZ0dAdB„Z1dSdDdE„Z2dFd-„dGd-„ej3ej4ej5ej6ej7ej8dHœZ9dIdJ„Z:eƒZ;dKdL„ZdQd
„Z?GdRd„deƒZ@dS)Té)Úabsolute_importÚdivisionÚprint_functionN)ÚParseExceptionÚParseResultsÚstringStartÚ	stringEnd)Ú
ZeroOrMoreÚGroupÚForwardÚQuotedString)ÚLiteralé)Ústring_types)Ú	SpecifierÚInvalidSpecifierÚ
InvalidMarkerÚUndefinedComparisonÚUndefinedEnvironmentNameÚMarkerÚdefault_environmentc@seZdZdZdS)rzE
    An invalid marker was found, users should refer to PEP 508.
    N©Ú__name__Ú
__module__Ú__qualname__Ú__doc__©rrúA/usr/lib/python3.8/site-packages/pip/_vendor/packaging/markers.pyrsc@seZdZdZdS)rzP
    An invalid operation was attempted on a value that doesn't support it.
    Nrrrrrr"sc@seZdZdZdS)rz\
    A name was attempted to be used that does not exist inside of the
    environment.
    Nrrrrrr(sc@s,eZdZdd„Zdd„Zdd„Zdd„Zd	S)
ÚNodecCs
||_dS©N)Úvalue)Úselfr rrrÚ__init__0sz
Node.__init__cCs
t|jƒSr)Ústrr ©r!rrrÚ__str__3szNode.__str__cCsd |jjt|ƒ¡S)Nz<{0}({1!r})>)ÚformatÚ	__class__rr#r$rrrÚ__repr__6sz
Node.__repr__cCst‚dSr)ÚNotImplementedErrorr$rrrÚ	serialize9szNode.serializeN)rrrr"r%r(r*rrrrr/src@seZdZdd„ZdS)ÚVariablecCst|ƒSr©r#r$rrrr*>szVariable.serializeN©rrrr*rrrrr+=sr+c@seZdZdd„ZdS)ÚValuecCs
d |¡S)Nz"{0}")r&r$rrrr*CszValue.serializeNr-rrrrr.Bsr.c@seZdZdd„ZdS)ÚOpcCst|ƒSrr,r$rrrr*HszOp.serializeNr-rrrrr/Gsr/Úimplementation_versionÚplatform_python_implementationÚimplementation_nameÚpython_full_versionÚplatform_releaseÚplatform_versionÚplatform_machineÚplatform_systemÚpython_versionÚsys_platformÚos_nameúos.nameúsys.platformúplatform.versionúplatform.machineúplatform.python_implementationÚpython_implementationZextra)r;r<r=r>r?r@cCstt |d|d¡ƒS©Nr)r+ÚALIASESÚget©ÚsÚlÚtrrrÚhórHz===ú==ú>=ú<=ú!=z~=ú>ú<únot inÚincCst|dƒSrA)r/rDrrrrHorIú'ú"cCst|dƒSrA)r.rDrrrrHrrIÚandÚorcCst|dƒSrA)ÚtuplerDrrrrHyrIú(ú)cCs t|tƒrdd„|DƒS|SdS)NcSsg|]}t|ƒ‘qSr)Ú_coerce_parse_result)Ú.0ÚirrrÚ
‡sz(_coerce_parse_result..)Ú
isinstancer)ÚresultsrrrrY…s
rYTcCs”t|tƒr4t|ƒdkr4t|dttfƒr4t|dƒSt|tƒrndd„|Dƒ}|rZd |¡Sdd |¡dSn"t|tƒrŒd dd	„|Dƒ¡S|SdS)
Nrrcss|]}t|dd�VqdS)F)ÚfirstN)Ú_format_marker©rZÚmrrrÚ	›sz!_format_marker..ú rWrXcSsg|]}| ¡‘qSr)r*rarrrr\¡sz"_format_marker..)r]ÚlistÚlenrVr`Újoin)Úmarkerr_Úinnerrrrr`Œsÿ
þý


r`cCs||kSrr©ÚlhsÚrhsrrrrH§rIcCs||kSrrrjrrrrH¨rI)rQrPrOrLrJrMrKrNcCslztd | ¡|g¡ƒ}Wntk
r.YnX| |¡St | ¡¡}|dkrbtd |||¡ƒ‚|||ƒS)NÚz#Undefined {0!r} on {1!r} and {2!r}.)	rrgr*rÚcontainsÚ
_operatorsrCrr&)rkÚoprlÚspecZoperrrrÚ_eval_op²s
ÿrrcCs&| |t¡}|tkr"td |¡ƒ‚|S)Nz/{0!r} does not exist in evaluation environment.)rCÚ
_undefinedrr&)ÚenvironmentÚnamer rrrÚ_get_envÆsÿrvc	Cs°gg}|D]’}t|tƒr.|d t||ƒ¡q
t|tƒrŠ|\}}}t|tƒr`t||jƒ}|j}n|j}t||jƒ}|d t|||ƒ¡q
|dkr
| g¡q
t	dd„|DƒƒS)NéÿÿÿÿrUcss|]}t|ƒVqdSr)Úall)rZÚitemrrrrcész$_evaluate_markers..)
r]reÚappendÚ_evaluate_markersrVr+rvr rrÚany)	ZmarkersrtÚgroupsrhrkrprlZ	lhs_valueZ	rhs_valuerrrr{Ñs



r{cCs2d |¡}|j}|dkr.||dt|jƒ7}|S)Nz{0.major}.{0.minor}.{0.micro}Úfinalr)r&Úreleaselevelr#Úserial)ÚinfoÚversionZkindrrrÚformat_full_versionìs

rƒcCsrttdƒr ttjjƒ}tjj}nd}d}||tjt ¡t 	¡t 
¡t ¡t ¡t ¡d 
t ¡dd…¡tjdœS)NÚimplementationÚ0rmÚ.é)r2r0r:r6r4r7r5r3r1r8r9)ÚhasattrÚsysrƒr„r‚ruÚosÚplatformÚmachineÚreleaseÚsystemr8r@rgZpython_version_tuple)Ziverr2rrrrôs"

õc@s.eZdZdd„Zdd„Zdd„Zd
dd	„ZdS)rc
Cs`ztt |¡ƒ|_WnFtk
rZ}z(d |||j|jd…¡}t|ƒ‚W5d}~XYnXdS)Nz+Invalid marker: {0!r}, parse error at {1!r}é)rYÚMARKERZparseStringÚ_markersrr&Zlocr)r!rhÚeZerr_strrrrr"sÿzMarker.__init__cCs
t|jƒSr)r`r‘r$rrrr%szMarker.__str__cCsd t|ƒ¡S)Nz)r&r#r$rrrr(szMarker.__repr__NcCs$tƒ}|dk	r| |¡t|j|ƒS)a$Evaluate a marker.

        Return the boolean from evaluating the given marker against the
        environment. environment is an optional argument to override all or
        part of the determined environment.

        The environment is determined from the current Python process.
        N)rÚupdater{r‘)r!rtZcurrent_environmentrrrÚevaluates	
zMarker.evaluate)N)rrrr"r%r(r”rrrrrs	)T)AZ
__future__rrrÚoperatorrŠr‹r‰Zpip._vendor.pyparsingrrrrr	r
rrr
ÚLZ_compatrZ
specifiersrrÚ__all__Ú
ValueErrorrrrÚobjectrr+r.r/ZVARIABLErBZsetParseActionZVERSION_CMPZ	MARKER_OPZMARKER_VALUEZBOOLOPZ
MARKER_VARZMARKER_ITEMÚsuppressZLPARENZRPARENZMARKER_EXPRZMARKER_ATOMr�rYr`ÚltÚleÚeqÚneÚgeÚgtrorrrsrvr{rƒrrrrrrÚsÈû	ÿþýüûúùø	÷
öõô
óòñðïÿú>ÿ
øPKÓ¶N]»µmã¹¹Hsite-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-38.pycnu„[µü¤U

ÀÒ.eèã@sPddlmZmZmZdddddddd	gZd
ZdZdZd
ZdZ	dZ
dZde	ZdS)é)Úabsolute_importÚdivisionÚprint_functionÚ	__title__Ú__summary__Ú__uri__Ú__version__Ú
__author__Ú	__email__Ú__license__Ú
__copyright__Z	packagingz"Core utilities for Python packagesz!https://github.com/pypa/packagingz19.2z)Donald Stufft and individual contributorszdonald@stufft.ioz"BSD or Apache License, Version 2.0zCopyright 2014-2019 %sN)
Z
__future__rrrÚ__all__rrrrr	r
rr©rrúC/usr/lib/python3.8/site-packages/pip/_vendor/packaging/__about__.pyÚs"øPKÓ¶N]|´vÚ//Fsite-packages/pip/_vendor/packaging/__pycache__/version.cpython-38.pycnu„[µü¤U

ÀÒ.eÊ.ã	@sþddlmZmZmZddlZddlZddlZddlmZddddd	gZ	e 
d
ddd
dddg¡Zdd„ZGdd„de
ƒZGdd„deƒZGdd„deƒZe dej¡ZddddddœZdd„Zdd„ZdZGd d„deƒZd!d"„Ze d#¡Zd$d%„Zd&d'„ZdS)(é)Úabsolute_importÚdivisionÚprint_functionNé)ÚInfinityÚparseÚVersionÚ
LegacyVersionÚInvalidVersionÚVERSION_PATTERNÚ_VersionÚepochÚreleaseÚdevÚpreÚpostÚlocalcCs,z
t|ƒWStk
r&t|ƒYSXdS)zÑ
    Parse the given version string and return either a :class:`Version` object
    or a :class:`LegacyVersion` object depending on if the given version is
    a valid PEP 440 version or a legacy version.
    N)rr
r	)Úversion©rúA/usr/lib/python3.8/site-packages/pip/_vendor/packaging/version.pyrs
c@seZdZdZdS)r
zF
    An invalid version was found, users should refer to PEP 440.
    N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rrrrr
!sc@sLeZdZdd„Zdd„Zdd„Zdd„Zd	d
„Zdd„Zd
d„Z	dd„Z
dS)Ú_BaseVersioncCs
t|jƒS©N)ÚhashÚ_key©ÚselfrrrÚ__hash__(sz_BaseVersion.__hash__cCs| |dd„¡S)NcSs||kSrr©ÚsÚorrrÚ,óz%_BaseVersion.__lt__..©Ú_compare©rÚotherrrrÚ__lt__+sz_BaseVersion.__lt__cCs| |dd„¡S)NcSs||kSrrr!rrrr$/r%z%_BaseVersion.__le__..r&r(rrrÚ__le__.sz_BaseVersion.__le__cCs| |dd„¡S)NcSs||kSrrr!rrrr$2r%z%_BaseVersion.__eq__..r&r(rrrÚ__eq__1sz_BaseVersion.__eq__cCs| |dd„¡S)NcSs||kSrrr!rrrr$5r%z%_BaseVersion.__ge__..r&r(rrrÚ__ge__4sz_BaseVersion.__ge__cCs| |dd„¡S)NcSs||kSrrr!rrrr$8r%z%_BaseVersion.__gt__..r&r(rrrÚ__gt__7sz_BaseVersion.__gt__cCs| |dd„¡S)NcSs||kSrrr!rrrr$;r%z%_BaseVersion.__ne__..r&r(rrrÚ__ne__:sz_BaseVersion.__ne__cCst|tƒstS||j|jƒSr)Ú
isinstancerÚNotImplementedr)rr)Úmethodrrrr'=s
z_BaseVersion._compareN)rrrr r*r+r,r-r.r/r'rrrrr'src@s¨eZdZdd„Zdd„Zdd„Zedd„ƒZed	d
„ƒZedd„ƒZ	ed
d„ƒZ
edd„ƒZedd„ƒZedd„ƒZ
edd„ƒZedd„ƒZedd„ƒZedd„ƒZdS)r	cCst|ƒ|_t|jƒ|_dSr)ÚstrÚ_versionÚ_legacy_cmpkeyr)rrrrrÚ__init__Es
zLegacyVersion.__init__cCs|jSr©r4rrrrÚ__str__IszLegacyVersion.__str__cCsd tt|ƒƒ¡S)Nz©ÚformatÚreprr3rrrrÚ__repr__LszLegacyVersion.__repr__cCs|jSrr7rrrrÚpublicOszLegacyVersion.publiccCs|jSrr7rrrrÚbase_versionSszLegacyVersion.base_versioncCsdS)Néÿÿÿÿrrrrrr
WszLegacyVersion.epochcCsdSrrrrrrr[szLegacyVersion.releasecCsdSrrrrrrr_szLegacyVersion.precCsdSrrrrrrrcszLegacyVersion.postcCsdSrrrrrrrgszLegacyVersion.devcCsdSrrrrrrrkszLegacyVersion.localcCsdS©NFrrrrrÚ
is_prereleaseoszLegacyVersion.is_prereleasecCsdSr@rrrrrÚis_postreleasesszLegacyVersion.is_postreleasecCsdSr@rrrrrÚ
is_devreleasewszLegacyVersion.is_devreleaseN)rrrr6r8r<Úpropertyr=r>r
rrrrrrArBrCrrrrr	Ds2









z(\d+ | [a-z]+ | \.| -)Úczfinal-ú@)rÚpreviewú-Úrcrccs\t |¡D]F}t ||¡}|r
|dkr(q
|dd…dkrF| d¡Vq
d|Vq
dVdS)NÚ.rÚ
0123456789éÚ*ú*final)Ú_legacy_version_component_reÚsplitÚ_legacy_version_replacement_mapÚgetÚzfill)r"ÚpartrrrÚ_parse_version_parts‡srUcCszd}g}t| ¡ƒD]T}| d¡r^|dkrD|rD|ddkrD| ¡q*|r^|ddkr^| ¡qD| |¡qt|ƒ}||fS)Nr?rMrNz*final-Z00000000)rUÚlowerÚ
startswithÚpopÚappendÚtuple)rr
ÚpartsrTrrrr5˜s


r5a—
    v?
    (?:
        (?:(?P[0-9]+)!)?                           # epoch
        (?P[0-9]+(?:\.[0-9]+)*)                  # release segment
        (?P
                                          # pre-release
            [-_\.]?
            (?P(a|b|c|rc|alpha|beta|pre|preview))
            [-_\.]?
            (?P[0-9]+)?
        )?
        (?P                                         # post release
            (?:-(?P[0-9]+))
            |
            (?:
                [-_\.]?
                (?Ppost|rev|r)
                [-_\.]?
                (?P[0-9]+)?
            )
        )?
        (?P                                          # dev release
            [-_\.]?
            (?Pdev)
            [-_\.]?
            (?P[0-9]+)?
        )?
    )
    (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
c@sÄeZdZe dedejejB¡Zdd„Z	dd„Z
dd„Zed	d
„ƒZ
edd„ƒZed
d„ƒZedd„ƒZedd„ƒZedd„ƒZedd„ƒZedd„ƒZedd„ƒZedd„ƒZedd„ƒZdS) rz^\s*z\s*$c
Csà|j |¡}|std |¡ƒ‚t| d¡r8t| d¡ƒndtdd„| d¡ d¡Dƒƒt	| d¡| d	¡ƒt	| d
¡| d¡p†| d¡ƒt	| d
¡| d¡ƒt
| d¡ƒd�|_t|jj
|jj|jj|jj|jj|jjƒ|_dS)NzInvalid version: '{0}'r
rcss|]}t|ƒVqdSr)Úint©Ú.0ÚirrrÚ	âsz#Version.__init__..rrJZpre_lZpre_nZpost_lZpost_n1Zpost_n2Zdev_lZdev_nr©r
rrrrr)Ú_regexÚsearchr
r:rÚgroupr\rZrPÚ_parse_letter_versionÚ_parse_local_versionr4Ú_cmpkeyr
rrrrrr)rrÚmatchrrrr6Ùs,ÿøúzVersion.__init__cCsd tt|ƒƒ¡S)Nzr9rrrrr<õszVersion.__repr__cCsÀg}|jdkr | d |j¡¡| d dd„|jDƒ¡¡|jdk	rb| d dd„|jDƒ¡¡|jdk	r~| d |j¡¡|jdk	rš| d	 |j¡¡|jdk	r¶| d
 |j¡¡d |¡S)Nrú{0}!rJcss|]}t|ƒVqdSr©r3©r^Úxrrrr`sz"Version.__str__..Úcss|]}t|ƒVqdSrrjrkrrrr`sz.post{0}z.dev{0}z+{0})	r
rYr:Újoinrrrrr©rr[rrrr8øs




zVersion.__str__cCs|jjSr)r4r
rrrrr
sz
Version.epochcCs|jjSr)r4rrrrrrszVersion.releasecCs|jjSr)r4rrrrrrszVersion.precCs|jjr|jjdSdS©Nr)r4rrrrrr szVersion.postcCs|jjr|jjdSdSrp)r4rrrrrr$szVersion.devcCs(|jjr d dd„|jjDƒ¡SdSdS)NrJcss|]}t|ƒVqdSrrjrkrrrr`+sz Version.local..)r4rrnrrrrr(sz
Version.localcCst|ƒ dd¡dS)Nú+rr)r3rPrrrrr=/szVersion.publiccCsFg}|jdkr | d |j¡¡| d dd„|jDƒ¡¡d |¡S)NrrirJcss|]}t|ƒVqdSrrjrkrrrr`<sz'Version.base_version..rm)r
rYr:rnrrorrrr>3s

zVersion.base_versioncCs|jdk	p|jdk	Sr)rrrrrrrA@szVersion.is_prereleasecCs
|jdk	Sr)rrrrrrBDszVersion.is_postreleasecCs
|jdk	Sr)rrrrrrCHszVersion.is_devreleaseN)rrrÚreÚcompilerÚVERBOSEÚ
IGNORECASErbr6r<r8rDr
rrrrrr=r>rArBrCrrrrrÕs4









cCsv|rZ|dkrd}| ¡}|dkr&d}n(|dkr4d}n|dkrBd}n|dkrNd	}|t|ƒfS|sr|rrd	}|t|ƒfSdS)
NrZalphaÚaZbetaÚb)rErrGrI)ZrevÚrr)rVr\)ZletterZnumberrrrreMs rez[\._-]cCs$|dk	r tdd„t |¡DƒƒSdS)zR
    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
    Ncss&|]}| ¡s| ¡nt|ƒVqdSr)ÚisdigitrVr\)r^rTrrrr`tsÿz'_parse_local_version..)rZÚ_local_version_separatorsrP)rrrrrfosþrfcCs˜tttt dd„t|ƒ¡ƒƒƒ}|dkr@|dkr@|dk	r@t}n|dkrLt}|dkrZt}|dkrft}|dkrvt}ntdd„|Dƒƒ}||||||fS)NcSs|dkS)Nrr)rlrrrr$�r%z_cmpkey..css*|]"}t|tƒr|dfnt|fVqdS)rmN)r0r\rr]rrrr`¢sz_cmpkey..)rZÚreversedÚlistÚ	itertoolsÚ	dropwhilerrarrrrgzsÿ	rg)Z
__future__rrrÚcollectionsr}rrZ_structuresrÚ__all__Ú
namedtuplerrÚ
ValueErrorr
Úobjectrr	rsrtrOrQrUr5rrrerzrfrgrrrrÚs8ÿ8û	 x
PKÓ¶N]ÓôuÖ””Dsite-packages/pip/_vendor/packaging/__pycache__/utils.cpython-38.pycnu„[µü¤U

ÀÒ.eðã@sJddlmZmZmZddlZddlmZmZe d¡Z	dd„Z
dd	„ZdS)
é)Úabsolute_importÚdivisionÚprint_functionNé)ÚInvalidVersionÚVersionz[-_.]+cCst d|¡ ¡S)Nú-)Ú_canonicalize_regexÚsubÚlower)Úname©r
ú?/usr/lib/python3.8/site-packages/pip/_vendor/packaging/utils.pyÚcanonicalize_namesrc
Csðzt|ƒ}Wntk
r$|YSXg}|jdkrF| d |j¡¡| t ddd dd„|jDƒ¡¡¡|j	dk	r’| d d	d„|j	Dƒ¡¡|j
dk	r®| d
 |j
¡¡|jdk	rÊ| d |j¡¡|jdk	ræ| d |j¡¡d |¡S)
z‚
    This is very similar to Version.__str__, but has one subtle differences
    with the way it handles the release segment.
    rz{0}!z(\.0)+$ÚÚ.css|]}t|ƒVqdS©N©Ústr©Ú.0Úxr
r
rÚ	'sz'canonicalize_version..Ncss|]}t|ƒVqdSrrrr
r
rr+sz.post{0}z.dev{0}z+{0})
rrZepochÚappendÚformatÚrer
ÚjoinÚreleaseZpreZpostZdevZlocal)ÚversionÚpartsr
r
rÚcanonicalize_versions"

&



r )Z
__future__rrrrrrrÚcompiler	rr r
r
r
rÚs

PKÓ¶N]î9ìóMMOsite-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.e‚lã@sæddlmZmZmZddlZddlZddlZddlZddlm	Z	m
Z
ddlmZm
Z
mZGdd„deƒZGdd	„d	e
ejeƒƒZGd
d„deƒZGdd
„d
eƒZdd„ZGdd„deƒZe d¡Zdd„Zdd„ZGdd„deƒZdS)é)Úabsolute_importÚdivisionÚprint_functionNé)Ústring_typesÚwith_metaclass)ÚVersionÚ
LegacyVersionÚparsec@seZdZdZdS)ÚInvalidSpecifierzH
    An invalid specifier was found, users should refer to PEP 440.
    N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__©rrúD/usr/lib/python3.8/site-packages/pip/_vendor/packaging/specifiers.pyrsrc@s€eZdZejdd„ƒZejdd„ƒZejdd„ƒZejdd„ƒZej	d	d
„ƒZ
e
jdd
„ƒZ
ejdd
d„ƒZejddd„ƒZ
dS)Ú
BaseSpecifiercCsdS)zŽ
        Returns the str representation of this Specifier like object. This
        should be representative of the Specifier itself.
        Nr©ÚselfrrrÚ__str__szBaseSpecifier.__str__cCsdS)zF
        Returns a hash value for this Specifier like object.
        NrrrrrÚ__hash__szBaseSpecifier.__hash__cCsdS)zq
        Returns a boolean representing whether or not the two Specifier like
        objects are equal.
        Nr©rÚotherrrrÚ__eq__#szBaseSpecifier.__eq__cCsdS)zu
        Returns a boolean representing whether or not the two Specifier like
        objects are not equal.
        NrrrrrÚ__ne__*szBaseSpecifier.__ne__cCsdS)zg
        Returns whether or not pre-releases as a whole are allowed by this
        specifier.
        NrrrrrÚprereleases1szBaseSpecifier.prereleasescCsdS)zd
        Sets whether or not pre-releases as a whole are allowed by this
        specifier.
        Nr©rÚvaluerrrr8sNcCsdS)zR
        Determines if the given item is contained within this specifier.
        Nr©rÚitemrrrrÚcontains?szBaseSpecifier.containscCsdS)z•
        Takes an iterable of items and filters them so that only items which
        are contained within this specifier are allowed in it.
        Nr)rÚiterablerrrrÚfilterEszBaseSpecifier.filter)N)N)rr
rÚabcÚabstractmethodrrrrÚabstractpropertyrÚsetterr r"rrrrrs 





rc@s eZdZiZd dd„Zdd„Zdd„Zd	d
„Zdd„Zd
d„Z	dd„Z
dd„Zedd„ƒZ
edd„ƒZedd„ƒZejdd„ƒZdd„Zd!dd„Zd"dd„ZdS)#Ú_IndividualSpecifierÚNcCsF|j |¡}|std |¡ƒ‚| d¡ ¡| d¡ ¡f|_||_dS)NzInvalid specifier: '{0}'ÚoperatorÚversion)Ú_regexÚsearchrÚformatÚgroupÚstripÚ_specÚ_prereleases)rÚspecrÚmatchrrrÚ__init__Qs
z_IndividualSpecifier.__init__cCs0|jdk	rd |j¡nd}d |jjt|ƒ|¡S)Nú, prereleases={0!r}r(z<{0}({1!r}{2})>)r1r-rÚ	__class__rÚstr©rZprerrrÚ__repr__[s
ÿýz_IndividualSpecifier.__repr__cCsdj|jŽS)Nz{0}{1})r-r0rrrrrdsz_IndividualSpecifier.__str__cCs
t|jƒS©N)Úhashr0rrrrrgsz_IndividualSpecifier.__hash__cCsPt|tƒr4z| |¡}WqDtk
r0tYSXnt||jƒsDtS|j|jkSr:©Ú
isinstancerr6rÚNotImplementedr0rrrrrjs
z_IndividualSpecifier.__eq__cCsPt|tƒr4z| |¡}WqDtk
r0tYSXnt||jƒsDtS|j|jkSr:r<rrrrrus
z_IndividualSpecifier.__ne__cCst|d |j|¡ƒS)Nz_compare_{0})Úgetattrr-Ú
_operators)rÚoprrrÚ
_get_operator€sz"_IndividualSpecifier._get_operatorcCst|ttfƒst|ƒ}|Sr:)r=r	rr
©rr*rrrÚ_coerce_versionƒsz$_IndividualSpecifier._coerce_versioncCs
|jdS)Nr©r0rrrrr)ˆsz_IndividualSpecifier.operatorcCs
|jdS)NrrErrrrr*Œsz_IndividualSpecifier.versioncCs|jSr:©r1rrrrr�sz _IndividualSpecifier.prereleasescCs
||_dSr:rFrrrrr”scCs
| |¡Sr:©r ©rrrrrÚ__contains__˜sz!_IndividualSpecifier.__contains__cCs:|dkr|j}| |¡}|jr&|s&dS| |j¡||jƒS©NF)rrDÚ
is_prereleaserBr)r*rrrrr ›s

z_IndividualSpecifier.containsccs€d}g}d|dk	r|ndi}|D]B}| |¡}|j|f|Žr |jrX|sX|jsX| |¡q d}|Vq |s||r||D]
}|VqpdS)NFrT)rDr rKrÚappend)rr!rZyieldedÚfound_prereleasesÚkwr*Úparsed_versionrrrr"®s"
ÿÿz_IndividualSpecifier.filter)r(N)N)N)rr
rr@r4r9rrrrrBrDÚpropertyr)r*rr&rIr r"rrrrr'Ms(

	




r'c@sveZdZdZe dedejejB¡Zdddddd	d
œZ	dd„Z
d
d„Zdd„Zdd„Z
dd„Zdd„Zdd„ZdS)ÚLegacySpecifieraÛ
        (?P(==|!=|<=|>=|<|>))
        \s*
        (?P
            [^,;\s)]* # Since this is a "legacy" specifier, and the version
                      # string can be just about anything, we match everything
                      # except for whitespace, a semi-colon for marker support,
                      # a closing paren since versions can be enclosed in
                      # them, and a comma since it's a version separator.
        )
        ú^\s*ú\s*$ÚequalÚ	not_equalÚless_than_equalÚgreater_than_equalÚ	less_thanÚgreater_than)ú==ú!=ú<=ú>=ú<ú>cCst|tƒstt|ƒƒ}|Sr:)r=r	r7rCrrrrDès
zLegacySpecifier._coerce_versioncCs|| |¡kSr:©rD©rÚprospectiver2rrrÚ_compare_equalíszLegacySpecifier._compare_equalcCs|| |¡kSr:r`rarrrÚ_compare_not_equalðsz"LegacySpecifier._compare_not_equalcCs|| |¡kSr:r`rarrrÚ_compare_less_than_equalósz(LegacySpecifier._compare_less_than_equalcCs|| |¡kSr:r`rarrrÚ_compare_greater_than_equalösz+LegacySpecifier._compare_greater_than_equalcCs|| |¡kSr:r`rarrrÚ_compare_less_thanùsz"LegacySpecifier._compare_less_thancCs|| |¡kSr:r`rarrrÚ_compare_greater_thanüsz%LegacySpecifier._compare_greater_thanN)rr
rÚ
_regex_strÚreÚcompileÚVERBOSEÚ
IGNORECASEr+r@rDrcrdrerfrgrhrrrrrQÏs ú	rQcst ˆ¡‡fdd„ƒ}|S)Ncst|tƒsdSˆ|||ƒSrJ)r=rra©ÚfnrrÚwrappeds
z)_require_version_compare..wrapped)Ú	functoolsÚwraps)rorprrnrÚ_require_version_comparesrsc	@s¸eZdZdZe dedejejB¡Zdddddd	d
ddœZ	e
d
d„ƒZe
dd„ƒZe
dd„ƒZ
e
dd„ƒZe
dd„ƒZe
dd„ƒZe
dd„ƒZdd„Zedd„ƒZejdd„ƒZd S)!Ú	Specifiera
        (?P(~=|==|!=|<=|>=|<|>|===))
        (?P
            (?:
                # The identity operators allow for an escape hatch that will
                # do an exact string match of the version you wish to install.
                # This will not be parsed by PEP 440 and we cannot determine
                # any semantic meaning from it. This operator is discouraged
                # but included entirely as an escape hatch.
                (?<====)  # Only match for the identity operator
                \s*
                [^\s]*    # We just match everything, except for whitespace
                          # since we are only testing for strict identity.
            )
            |
            (?:
                # The (non)equality operators allow for wild card and local
                # versions to be specified so we have to define these two
                # operators separately to enable that.
                (?<===|!=)            # Only match for equals and not equals

                \s*
                v?
                (?:[0-9]+!)?          # epoch
                [0-9]+(?:\.[0-9]+)*   # release
                (?:                   # pre release
                    [-_\.]?
                    (a|b|c|rc|alpha|beta|pre|preview)
                    [-_\.]?
                    [0-9]*
                )?
                (?:                   # post release
                    (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
                )?

                # You cannot use a wild card and a dev or local version
                # together so group them with a | and make them optional.
                (?:
                    (?:[-_\.]?dev[-_\.]?[0-9]*)?         # dev release
                    (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local
                    |
                    \.\*  # Wild card syntax of .*
                )?
            )
            |
            (?:
                # The compatible operator requires at least two digits in the
                # release segment.
                (?<=~=)               # Only match for the compatible operator

                \s*
                v?
                (?:[0-9]+!)?          # epoch
                [0-9]+(?:\.[0-9]+)+   # release  (We have a + instead of a *)
                (?:                   # pre release
                    [-_\.]?
                    (a|b|c|rc|alpha|beta|pre|preview)
                    [-_\.]?
                    [0-9]*
                )?
                (?:                                   # post release
                    (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
                )?
                (?:[-_\.]?dev[-_\.]?[0-9]*)?          # dev release
            )
            |
            (?:
                # All other operators only allow a sub set of what the
                # (non)equality operators do. Specifically they do not allow
                # local versions to be specified nor do they allow the prefix
                # matching wild cards.
                (?„óz/Specifier._compare_compatible..éÿÿÿÿú.*r]rZ)ÚjoinÚlistÚ	itertoolsÚ	takewhileÚ_version_splitrB)rrbr2ÚprefixrrrÚ_compare_compatiblevsþÿûÿ
ÿzSpecifier._compare_compatiblecCsp| d¡rPt|jƒ}t|dd…ƒ}tt|ƒƒ}|dt|ƒ…}t||ƒ\}}nt|ƒ}|jsht|jƒ}||kS)Nr~éþÿÿÿ)ÚendswithrZpublicrƒr7ÚlenÚ_pad_versionÚlocalrarrrrc‘s


zSpecifier._compare_equalcCs| ||¡Sr:)rcrarrrrd´szSpecifier._compare_not_equalcCs|t|ƒkSr:©rrarrrre¸sz"Specifier._compare_less_than_equalcCs|t|ƒkSr:r‹rarrrrf¼sz%Specifier._compare_greater_than_equalcCs<t|ƒ}||ksdS|js8|jr8t|jƒt|jƒkr8dSdS©NFT)rrKÚbase_versionrarrrrgÀszSpecifier._compare_less_thancCs^t|ƒ}||ksdS|js8|jr8t|jƒt|jƒkr8dS|jdk	rZt|jƒt|jƒkrZdSdSrŒ)rZis_postreleaser�rŠrarrrrhÙs
zSpecifier._compare_greater_thancCst|ƒ ¡t|ƒ ¡kSr:)r7ÚlowerrarrrÚ_compare_arbitraryøszSpecifier._compare_arbitrarycCsR|jdk	r|jS|j\}}|dkrN|dkr@| d¡r@|dd…}t|ƒjrNdSdS)N)rZr]r\rurvrZr~r†TF)r1r0r‡r
rK)rr)r*rrrrûs


zSpecifier.prereleasescCs
||_dSr:rFrrrrrsN)rr
rrirjrkrlrmr+r@rsr…rcrdrerfrgrhr�rPrr&rrrrrt
s<]ø

"





rtz^([0-9]+)((?:a|b|c|rc)[0-9]+)$cCs@g}| d¡D],}t |¡}|r0| | ¡¡q| |¡q|S)Nrw)ÚsplitÚ
_prefix_regexr,ÚextendÚgroupsrL)r*Úresultrr3rrrrƒs
rƒc
Csægg}}| tt dd„|¡ƒ¡| tt dd„|¡ƒ¡| |t|dƒd…¡| |t|dƒd…¡| ddgtdt|dƒt|dƒƒ¡| ddgtdt|dƒt|dƒƒ¡ttj|Žƒttj|ŽƒfS)NcSs| ¡Sr:©Úisdigitryrrrr{*r|z_pad_version..cSs| ¡Sr:r•ryrrrr{+r|rrÚ0)rLr€r�r‚rˆÚinsertÚmaxÚchain)ÚleftÚrightZ
left_splitZright_splitrrrr‰&s
,,r‰c@sŒeZdZddd„Zdd„Zdd„Zd	d
„Zdd„Zd
d„Zdd„Z	dd„Z
dd„Zedd„ƒZ
e
jdd„ƒZ
dd„Zddd„Zd dd„ZdS)!ÚSpecifierSetr(Nc	Csndd„| d¡Dƒ}tƒ}|D]:}z| t|ƒ¡Wqtk
rV| t|ƒ¡YqXqt|ƒ|_||_dS)NcSsg|]}| ¡r| ¡‘qSr)r/©Ú.0ÚsrrrÚ
<sz)SpecifierSet.__init__..ú,)	r�ÚsetÚaddrtrrQÚ	frozensetÚ_specsr1)rZ
specifiersrZparsedÚ	specifierrrrr49s
zSpecifierSet.__init__cCs*|jdk	rd |j¡nd}d t|ƒ|¡S)Nr5r(z)r1r-rr7r8rrrr9Ns
ÿýzSpecifierSet.__repr__cCsd tdd„|jDƒƒ¡S)Nr¢css|]}t|ƒVqdSr:)r7ržrrrÚ	Xsz'SpecifierSet.__str__..)rÚsortedr¦rrrrrWszSpecifierSet.__str__cCs
t|jƒSr:)r;r¦rrrrrZszSpecifierSet.__hash__cCs˜t|tƒrt|ƒ}nt|tƒs"tStƒ}t|j|jBƒ|_|jdkrX|jdk	rX|j|_n<|jdk	rv|jdkrv|j|_n|j|jkrŒ|j|_ntdƒ‚|S)NzFCannot combine SpecifierSets with True and False prerelease overrides.)r=rr�r>r¥r¦r1Ú
ValueError)rrr§rrrÚ__and__]s 





ÿzSpecifierSet.__and__cCsFt|tƒrt|ƒ}n&t|tƒr,tt|ƒƒ}nt|tƒs:tS|j|jkSr:©r=rr�r'r7r>r¦rrrrrts



zSpecifierSet.__eq__cCsFt|tƒrt|ƒ}n&t|tƒr,tt|ƒƒ}nt|tƒs:tS|j|jkSr:r¬rrrrr~s



zSpecifierSet.__ne__cCs
t|jƒSr:)rˆr¦rrrrÚ__len__ˆszSpecifierSet.__len__cCs
t|jƒSr:)Úiterr¦rrrrÚ__iter__‹szSpecifierSet.__iter__cCs.|jdk	r|jS|jsdStdd„|jDƒƒS)Ncss|]}|jVqdSr:©rržrrrr¨�sz+SpecifierSet.prereleases..)r1r¦ÚanyrrrrrŽs

zSpecifierSet.prereleasescCs
||_dSr:rFrrrrrŸscCs
| |¡Sr:rGrHrrrrI£szSpecifierSet.__contains__csLtˆttfƒstˆƒ‰ˆdkr$|j‰ˆs2ˆjr2dSt‡‡fdd„|jDƒƒS)NFc3s|]}|jˆˆd�VqdS)r°NrGrž©rrrrr¨¾sz(SpecifierSet.contains..)r=r	rr
rrKÚallr¦rrr²rr ¦s
zSpecifierSet.containscCs°|dkr|j}|jr6|jD]}|j|t|ƒd�}q|Sg}g}|D]P}t|ttfƒs^t|ƒ}n|}t|tƒrnqB|jrˆ|sˆ|s’| 	|¡qB| 	|¡qB|s¨|r¨|dkr¨|S|SdS)Nr°)
rr¦r"Úboolr=r	rr
rKrL)rr!rr2ZfilteredrMrrOrrrr"Às*



zSpecifierSet.filter)r(N)N)N)rr
rr4r9rrr«rrr­r¯rPrr&rIr r"rrrrr�8s 
	




r�)Z
__future__rrrr#rqr�rjZ_compatrrr*rr	r
rªrÚABCMetaÚobjectrr'rQrsrtrkr‘rƒr‰r�rrrrÚs&81

PKÓ¶N]k�•ˆˆ2site-packages/pip/_vendor/packaging/_structures.pynu„[µü¤# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function


class Infinity(object):
    def __repr__(self):
        return "Infinity"

    def __hash__(self):
        return hash(repr(self))

    def __lt__(self, other):
        return False

    def __le__(self, other):
        return False

    def __eq__(self, other):
        return isinstance(other, self.__class__)

    def __ne__(self, other):
        return not isinstance(other, self.__class__)

    def __gt__(self, other):
        return True

    def __ge__(self, other):
        return True

    def __neg__(self):
        return NegativeInfinity


Infinity = Infinity()


class NegativeInfinity(object):
    def __repr__(self):
        return "-Infinity"

    def __hash__(self):
        return hash(repr(self))

    def __lt__(self, other):
        return True

    def __le__(self, other):
        return True

    def __eq__(self, other):
        return isinstance(other, self.__class__)

    def __ne__(self, other):
        return not isinstance(other, self.__class__)

    def __gt__(self, other):
        return False

    def __ge__(self, other):
        return False

    def __neg__(self):
        return Infinity


NegativeInfinity = NegativeInfinity()
PKÓ¶N]fŠÚãaa.site-packages/pip/_vendor/packaging/_compat.pynu„[µü¤# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function

import sys


PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3

# flake8: noqa

if PY3:
    string_types = (str,)
else:
    string_types = (basestring,)


def with_metaclass(meta, *bases):
    """
    Create a base class with a metaclass.
    """
    # This requires a bit of explanation: the basic idea is to make a dummy
    # metaclass for one level of class instantiation that replaces itself with
    # the actual metaclass.
    class metaclass(meta):
        def __new__(cls, name, this_bases, d):
            return meta(name, bases, d)

    return type.__new__(metaclass, "temporary_class", (), {})
PKÓ¶N]a=­�ðð,site-packages/pip/_vendor/packaging/utils.pynu„[µü¤# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function

import re

from .version import InvalidVersion, Version


_canonicalize_regex = re.compile(r"[-_.]+")


def canonicalize_name(name):
    # This is taken from PEP 503.
    return _canonicalize_regex.sub("-", name).lower()


def canonicalize_version(version):
    """
    This is very similar to Version.__str__, but has one subtle differences
    with the way it handles the release segment.
    """

    try:
        version = Version(version)
    except InvalidVersion:
        # Legacy versions cannot be normalized
        return version

    parts = []

    # Epoch
    if version.epoch != 0:
        parts.append("{0}!".format(version.epoch))

    # Release segment
    # NB: This strips trailing '.0's to normalize
    parts.append(re.sub(r"(\.0)+$", "", ".".join(str(x) for x in version.release)))

    # Pre-release
    if version.pre is not None:
        parts.append("".join(str(x) for x in version.pre))

    # Post-release
    if version.post is not None:
        parts.append(".post{0}".format(version.post))

    # Development release
    if version.dev is not None:
        parts.append(".dev{0}".format(version.dev))

    # Local version segment
    if version.local is not None:
        parts.append("+{0}".format(version.local))

    return "".join(parts)
PKÓ¶N]Ržü\\3site-packages/pip/_vendor/packaging/requirements.pynu„[µü¤# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function

import string
import re

from pip._vendor.pyparsing import stringStart, stringEnd, originalTextFor, ParseException
from pip._vendor.pyparsing import ZeroOrMore, Word, Optional, Regex, Combine
from pip._vendor.pyparsing import Literal as L  # noqa
from pip._vendor.six.moves.urllib import parse as urlparse

from .markers import MARKER_EXPR, Marker
from .specifiers import LegacySpecifier, Specifier, SpecifierSet


class InvalidRequirement(ValueError):
    """
    An invalid requirement was found, users should refer to PEP 508.
    """


ALPHANUM = Word(string.ascii_letters + string.digits)

LBRACKET = L("[").suppress()
RBRACKET = L("]").suppress()
LPAREN = L("(").suppress()
RPAREN = L(")").suppress()
COMMA = L(",").suppress()
SEMICOLON = L(";").suppress()
AT = L("@").suppress()

PUNCTUATION = Word("-_.")
IDENTIFIER_END = ALPHANUM | (ZeroOrMore(PUNCTUATION) + ALPHANUM)
IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END))

NAME = IDENTIFIER("name")
EXTRA = IDENTIFIER

URI = Regex(r"[^ ]+")("url")
URL = AT + URI

EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA)
EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras")

VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE)
VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE)

VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY
VERSION_MANY = Combine(
    VERSION_ONE + ZeroOrMore(COMMA + VERSION_ONE), joinString=",", adjacent=False
)("_raw_spec")
_VERSION_SPEC = Optional(((LPAREN + VERSION_MANY + RPAREN) | VERSION_MANY))
_VERSION_SPEC.setParseAction(lambda s, l, t: t._raw_spec or "")

VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier")
VERSION_SPEC.setParseAction(lambda s, l, t: t[1])

MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker")
MARKER_EXPR.setParseAction(
    lambda s, l, t: Marker(s[t._original_start : t._original_end])
)
MARKER_SEPARATOR = SEMICOLON
MARKER = MARKER_SEPARATOR + MARKER_EXPR

VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER)
URL_AND_MARKER = URL + Optional(MARKER)

NAMED_REQUIREMENT = NAME + Optional(EXTRAS) + (URL_AND_MARKER | VERSION_AND_MARKER)

REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd
# pyparsing isn't thread safe during initialization, so we do it eagerly, see
# issue #104
REQUIREMENT.parseString("x[]")


class Requirement(object):
    """Parse a requirement.

    Parse a given requirement string into its parts, such as name, specifier,
    URL, and extras. Raises InvalidRequirement on a badly-formed requirement
    string.
    """

    # TODO: Can we test whether something is contained within a requirement?
    #       If so how do we do that? Do we need to test against the _name_ of
    #       the thing as well as the version? What about the markers?
    # TODO: Can we normalize the name and extra name?

    def __init__(self, requirement_string):
        try:
            req = REQUIREMENT.parseString(requirement_string)
        except ParseException as e:
            raise InvalidRequirement(
                'Parse error at "{0!r}": {1}'.format(
                    requirement_string[e.loc : e.loc + 8], e.msg
                )
            )

        self.name = req.name
        if req.url:
            parsed_url = urlparse.urlparse(req.url)
            if parsed_url.scheme == "file":
                if urlparse.urlunparse(parsed_url) != req.url:
                    raise InvalidRequirement("Invalid URL given")
            elif not (parsed_url.scheme and parsed_url.netloc) or (
                not parsed_url.scheme and not parsed_url.netloc
            ):
                raise InvalidRequirement("Invalid URL: {0}".format(req.url))
            self.url = req.url
        else:
            self.url = None
        self.extras = set(req.extras.asList() if req.extras else [])
        self.specifier = SpecifierSet(req.specifier)
        self.marker = req.marker if req.marker else None

    def __str__(self):
        parts = [self.name]

        if self.extras:
            parts.append("[{0}]".format(",".join(sorted(self.extras))))

        if self.specifier:
            parts.append(str(self.specifier))

        if self.url:
            parts.append("@ {0}".format(self.url))
            if self.marker:
                parts.append(" ")

        if self.marker:
            parts.append("; {0}".format(self.marker))

        return "".join(parts)

    def __repr__(self):
        return "".format(str(self))
PKÓ¶N]ñ3rëÊ.Ê..site-packages/pip/_vendor/packaging/version.pynu„[µü¤# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function

import collections
import itertools
import re

from ._structures import Infinity


__all__ = ["parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN"]


_Version = collections.namedtuple(
    "_Version", ["epoch", "release", "dev", "pre", "post", "local"]
)


def parse(version):
    """
    Parse the given version string and return either a :class:`Version` object
    or a :class:`LegacyVersion` object depending on if the given version is
    a valid PEP 440 version or a legacy version.
    """
    try:
        return Version(version)
    except InvalidVersion:
        return LegacyVersion(version)


class InvalidVersion(ValueError):
    """
    An invalid version was found, users should refer to PEP 440.
    """


class _BaseVersion(object):
    def __hash__(self):
        return hash(self._key)

    def __lt__(self, other):
        return self._compare(other, lambda s, o: s < o)

    def __le__(self, other):
        return self._compare(other, lambda s, o: s <= o)

    def __eq__(self, other):
        return self._compare(other, lambda s, o: s == o)

    def __ge__(self, other):
        return self._compare(other, lambda s, o: s >= o)

    def __gt__(self, other):
        return self._compare(other, lambda s, o: s > o)

    def __ne__(self, other):
        return self._compare(other, lambda s, o: s != o)

    def _compare(self, other, method):
        if not isinstance(other, _BaseVersion):
            return NotImplemented

        return method(self._key, other._key)


class LegacyVersion(_BaseVersion):
    def __init__(self, version):
        self._version = str(version)
        self._key = _legacy_cmpkey(self._version)

    def __str__(self):
        return self._version

    def __repr__(self):
        return "".format(repr(str(self)))

    @property
    def public(self):
        return self._version

    @property
    def base_version(self):
        return self._version

    @property
    def epoch(self):
        return -1

    @property
    def release(self):
        return None

    @property
    def pre(self):
        return None

    @property
    def post(self):
        return None

    @property
    def dev(self):
        return None

    @property
    def local(self):
        return None

    @property
    def is_prerelease(self):
        return False

    @property
    def is_postrelease(self):
        return False

    @property
    def is_devrelease(self):
        return False


_legacy_version_component_re = re.compile(r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE)

_legacy_version_replacement_map = {
    "pre": "c",
    "preview": "c",
    "-": "final-",
    "rc": "c",
    "dev": "@",
}


def _parse_version_parts(s):
    for part in _legacy_version_component_re.split(s):
        part = _legacy_version_replacement_map.get(part, part)

        if not part or part == ".":
            continue

        if part[:1] in "0123456789":
            # pad for numeric comparison
            yield part.zfill(8)
        else:
            yield "*" + part

    # ensure that alpha/beta/candidate are before final
    yield "*final"


def _legacy_cmpkey(version):
    # We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch
    # greater than or equal to 0. This will effectively put the LegacyVersion,
    # which uses the defacto standard originally implemented by setuptools,
    # as before all PEP 440 versions.
    epoch = -1

    # This scheme is taken from pkg_resources.parse_version setuptools prior to
    # it's adoption of the packaging library.
    parts = []
    for part in _parse_version_parts(version.lower()):
        if part.startswith("*"):
            # remove "-" before a prerelease tag
            if part < "*final":
                while parts and parts[-1] == "*final-":
                    parts.pop()

            # remove trailing zeros from each series of numeric parts
            while parts and parts[-1] == "00000000":
                parts.pop()

        parts.append(part)
    parts = tuple(parts)

    return epoch, parts


# Deliberately not anchored to the start and end of the string, to make it
# easier for 3rd party code to reuse
VERSION_PATTERN = r"""
    v?
    (?:
        (?:(?P[0-9]+)!)?                           # epoch
        (?P[0-9]+(?:\.[0-9]+)*)                  # release segment
        (?P
                                          # pre-release
            [-_\.]?
            (?P(a|b|c|rc|alpha|beta|pre|preview))
            [-_\.]?
            (?P[0-9]+)?
        )?
        (?P                                         # post release
            (?:-(?P[0-9]+))
            |
            (?:
                [-_\.]?
                (?Ppost|rev|r)
                [-_\.]?
                (?P[0-9]+)?
            )
        )?
        (?P                                          # dev release
            [-_\.]?
            (?Pdev)
            [-_\.]?
            (?P[0-9]+)?
        )?
    )
    (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
"""


class Version(_BaseVersion):

    _regex = re.compile(r"^\s*" + VERSION_PATTERN + r"\s*$", re.VERBOSE | re.IGNORECASE)

    def __init__(self, version):
        # Validate the version and parse it into pieces
        match = self._regex.search(version)
        if not match:
            raise InvalidVersion("Invalid version: '{0}'".format(version))

        # Store the parsed out pieces of the version
        self._version = _Version(
            epoch=int(match.group("epoch")) if match.group("epoch") else 0,
            release=tuple(int(i) for i in match.group("release").split(".")),
            pre=_parse_letter_version(match.group("pre_l"), match.group("pre_n")),
            post=_parse_letter_version(
                match.group("post_l"), match.group("post_n1") or match.group("post_n2")
            ),
            dev=_parse_letter_version(match.group("dev_l"), match.group("dev_n")),
            local=_parse_local_version(match.group("local")),
        )

        # Generate a key which will be used for sorting
        self._key = _cmpkey(
            self._version.epoch,
            self._version.release,
            self._version.pre,
            self._version.post,
            self._version.dev,
            self._version.local,
        )

    def __repr__(self):
        return "".format(repr(str(self)))

    def __str__(self):
        parts = []

        # Epoch
        if self.epoch != 0:
            parts.append("{0}!".format(self.epoch))

        # Release segment
        parts.append(".".join(str(x) for x in self.release))

        # Pre-release
        if self.pre is not None:
            parts.append("".join(str(x) for x in self.pre))

        # Post-release
        if self.post is not None:
            parts.append(".post{0}".format(self.post))

        # Development release
        if self.dev is not None:
            parts.append(".dev{0}".format(self.dev))

        # Local version segment
        if self.local is not None:
            parts.append("+{0}".format(self.local))

        return "".join(parts)

    @property
    def epoch(self):
        return self._version.epoch

    @property
    def release(self):
        return self._version.release

    @property
    def pre(self):
        return self._version.pre

    @property
    def post(self):
        return self._version.post[1] if self._version.post else None

    @property
    def dev(self):
        return self._version.dev[1] if self._version.dev else None

    @property
    def local(self):
        if self._version.local:
            return ".".join(str(x) for x in self._version.local)
        else:
            return None

    @property
    def public(self):
        return str(self).split("+", 1)[0]

    @property
    def base_version(self):
        parts = []

        # Epoch
        if self.epoch != 0:
            parts.append("{0}!".format(self.epoch))

        # Release segment
        parts.append(".".join(str(x) for x in self.release))

        return "".join(parts)

    @property
    def is_prerelease(self):
        return self.dev is not None or self.pre is not None

    @property
    def is_postrelease(self):
        return self.post is not None

    @property
    def is_devrelease(self):
        return self.dev is not None


def _parse_letter_version(letter, number):
    if letter:
        # We consider there to be an implicit 0 in a pre-release if there is
        # not a numeral associated with it.
        if number is None:
            number = 0

        # We normalize any letters to their lower case form
        letter = letter.lower()

        # We consider some words to be alternate spellings of other words and
        # in those cases we want to normalize the spellings to our preferred
        # spelling.
        if letter == "alpha":
            letter = "a"
        elif letter == "beta":
            letter = "b"
        elif letter in ["c", "pre", "preview"]:
            letter = "rc"
        elif letter in ["rev", "r"]:
            letter = "post"

        return letter, int(number)
    if not letter and number:
        # We assume if we are given a number, but we are not given a letter
        # then this is using the implicit post release syntax (e.g. 1.0-1)
        letter = "post"

        return letter, int(number)


_local_version_separators = re.compile(r"[\._-]")


def _parse_local_version(local):
    """
    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
    """
    if local is not None:
        return tuple(
            part.lower() if not part.isdigit() else int(part)
            for part in _local_version_separators.split(local)
        )


def _cmpkey(epoch, release, pre, post, dev, local):
    # When we compare a release version, we want to compare it with all of the
    # trailing zeros removed. So we'll use a reverse the list, drop all the now
    # leading zeros until we come to something non zero, then take the rest
    # re-reverse it back into the correct order and make it a tuple and use
    # that for our sorting key.
    release = tuple(
        reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release))))
    )

    # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
    # We'll do this by abusing the pre segment, but we _only_ want to do this
    # if there is not a pre or a post segment. If we have one of those then
    # the normal sorting rules will handle this case correctly.
    if pre is None and post is None and dev is not None:
        pre = -Infinity
    # Versions without a pre-release (except as noted above) should sort after
    # those with one.
    elif pre is None:
        pre = Infinity

    # Versions without a post segment should sort before those with one.
    if post is None:
        post = -Infinity

    # Versions without a development segment should sort after those with one.
    if dev is None:
        dev = Infinity

    if local is None:
        # Versions without a local segment should sort before those with one.
        local = -Infinity
    else:
        # Versions with a local segment need that segment parsed to implement
        # the sorting rules in PEP440.
        # - Alpha numeric segments sort before numeric segments
        # - Alpha numeric segments sort lexicographically
        # - Numeric segments sort numerically
        # - Shorter versions sort before longer versions when the prefixes
        #   match exactly
        local = tuple((i, "") if isinstance(i, int) else (-Infinity, i) for i in local)

    return epoch, release, pre, post, dev, local
PKÓ¶N]òˆFÓ‚l‚l1site-packages/pip/_vendor/packaging/specifiers.pynu„[µü¤# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function

import abc
import functools
import itertools
import re

from ._compat import string_types, with_metaclass
from .version import Version, LegacyVersion, parse


class InvalidSpecifier(ValueError):
    """
    An invalid specifier was found, users should refer to PEP 440.
    """


class BaseSpecifier(with_metaclass(abc.ABCMeta, object)):
    @abc.abstractmethod
    def __str__(self):
        """
        Returns the str representation of this Specifier like object. This
        should be representative of the Specifier itself.
        """

    @abc.abstractmethod
    def __hash__(self):
        """
        Returns a hash value for this Specifier like object.
        """

    @abc.abstractmethod
    def __eq__(self, other):
        """
        Returns a boolean representing whether or not the two Specifier like
        objects are equal.
        """

    @abc.abstractmethod
    def __ne__(self, other):
        """
        Returns a boolean representing whether or not the two Specifier like
        objects are not equal.
        """

    @abc.abstractproperty
    def prereleases(self):
        """
        Returns whether or not pre-releases as a whole are allowed by this
        specifier.
        """

    @prereleases.setter
    def prereleases(self, value):
        """
        Sets whether or not pre-releases as a whole are allowed by this
        specifier.
        """

    @abc.abstractmethod
    def contains(self, item, prereleases=None):
        """
        Determines if the given item is contained within this specifier.
        """

    @abc.abstractmethod
    def filter(self, iterable, prereleases=None):
        """
        Takes an iterable of items and filters them so that only items which
        are contained within this specifier are allowed in it.
        """


class _IndividualSpecifier(BaseSpecifier):

    _operators = {}

    def __init__(self, spec="", prereleases=None):
        match = self._regex.search(spec)
        if not match:
            raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec))

        self._spec = (match.group("operator").strip(), match.group("version").strip())

        # Store whether or not this Specifier should accept prereleases
        self._prereleases = prereleases

    def __repr__(self):
        pre = (
            ", prereleases={0!r}".format(self.prereleases)
            if self._prereleases is not None
            else ""
        )

        return "<{0}({1!r}{2})>".format(self.__class__.__name__, str(self), pre)

    def __str__(self):
        return "{0}{1}".format(*self._spec)

    def __hash__(self):
        return hash(self._spec)

    def __eq__(self, other):
        if isinstance(other, string_types):
            try:
                other = self.__class__(other)
            except InvalidSpecifier:
                return NotImplemented
        elif not isinstance(other, self.__class__):
            return NotImplemented

        return self._spec == other._spec

    def __ne__(self, other):
        if isinstance(other, string_types):
            try:
                other = self.__class__(other)
            except InvalidSpecifier:
                return NotImplemented
        elif not isinstance(other, self.__class__):
            return NotImplemented

        return self._spec != other._spec

    def _get_operator(self, op):
        return getattr(self, "_compare_{0}".format(self._operators[op]))

    def _coerce_version(self, version):
        if not isinstance(version, (LegacyVersion, Version)):
            version = parse(version)
        return version

    @property
    def operator(self):
        return self._spec[0]

    @property
    def version(self):
        return self._spec[1]

    @property
    def prereleases(self):
        return self._prereleases

    @prereleases.setter
    def prereleases(self, value):
        self._prereleases = value

    def __contains__(self, item):
        return self.contains(item)

    def contains(self, item, prereleases=None):
        # Determine if prereleases are to be allowed or not.
        if prereleases is None:
            prereleases = self.prereleases

        # Normalize item to a Version or LegacyVersion, this allows us to have
        # a shortcut for ``"2.0" in Specifier(">=2")
        item = self._coerce_version(item)

        # Determine if we should be supporting prereleases in this specifier
        # or not, if we do not support prereleases than we can short circuit
        # logic if this version is a prereleases.
        if item.is_prerelease and not prereleases:
            return False

        # Actually do the comparison to determine if this item is contained
        # within this Specifier or not.
        return self._get_operator(self.operator)(item, self.version)

    def filter(self, iterable, prereleases=None):
        yielded = False
        found_prereleases = []

        kw = {"prereleases": prereleases if prereleases is not None else True}

        # Attempt to iterate over all the values in the iterable and if any of
        # them match, yield them.
        for version in iterable:
            parsed_version = self._coerce_version(version)

            if self.contains(parsed_version, **kw):
                # If our version is a prerelease, and we were not set to allow
                # prereleases, then we'll store it for later incase nothing
                # else matches this specifier.
                if parsed_version.is_prerelease and not (
                    prereleases or self.prereleases
                ):
                    found_prereleases.append(version)
                # Either this is not a prerelease, or we should have been
                # accepting prereleases from the beginning.
                else:
                    yielded = True
                    yield version

        # Now that we've iterated over everything, determine if we've yielded
        # any values, and if we have not and we have any prereleases stored up
        # then we will go ahead and yield the prereleases.
        if not yielded and found_prereleases:
            for version in found_prereleases:
                yield version


class LegacySpecifier(_IndividualSpecifier):

    _regex_str = r"""
        (?P(==|!=|<=|>=|<|>))
        \s*
        (?P
            [^,;\s)]* # Since this is a "legacy" specifier, and the version
                      # string can be just about anything, we match everything
                      # except for whitespace, a semi-colon for marker support,
                      # a closing paren since versions can be enclosed in
                      # them, and a comma since it's a version separator.
        )
        """

    _regex = re.compile(r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE)

    _operators = {
        "==": "equal",
        "!=": "not_equal",
        "<=": "less_than_equal",
        ">=": "greater_than_equal",
        "<": "less_than",
        ">": "greater_than",
    }

    def _coerce_version(self, version):
        if not isinstance(version, LegacyVersion):
            version = LegacyVersion(str(version))
        return version

    def _compare_equal(self, prospective, spec):
        return prospective == self._coerce_version(spec)

    def _compare_not_equal(self, prospective, spec):
        return prospective != self._coerce_version(spec)

    def _compare_less_than_equal(self, prospective, spec):
        return prospective <= self._coerce_version(spec)

    def _compare_greater_than_equal(self, prospective, spec):
        return prospective >= self._coerce_version(spec)

    def _compare_less_than(self, prospective, spec):
        return prospective < self._coerce_version(spec)

    def _compare_greater_than(self, prospective, spec):
        return prospective > self._coerce_version(spec)


def _require_version_compare(fn):
    @functools.wraps(fn)
    def wrapped(self, prospective, spec):
        if not isinstance(prospective, Version):
            return False
        return fn(self, prospective, spec)

    return wrapped


class Specifier(_IndividualSpecifier):

    _regex_str = r"""
        (?P(~=|==|!=|<=|>=|<|>|===))
        (?P
            (?:
                # The identity operators allow for an escape hatch that will
                # do an exact string match of the version you wish to install.
                # This will not be parsed by PEP 440 and we cannot determine
                # any semantic meaning from it. This operator is discouraged
                # but included entirely as an escape hatch.
                (?<====)  # Only match for the identity operator
                \s*
                [^\s]*    # We just match everything, except for whitespace
                          # since we are only testing for strict identity.
            )
            |
            (?:
                # The (non)equality operators allow for wild card and local
                # versions to be specified so we have to define these two
                # operators separately to enable that.
                (?<===|!=)            # Only match for equals and not equals

                \s*
                v?
                (?:[0-9]+!)?          # epoch
                [0-9]+(?:\.[0-9]+)*   # release
                (?:                   # pre release
                    [-_\.]?
                    (a|b|c|rc|alpha|beta|pre|preview)
                    [-_\.]?
                    [0-9]*
                )?
                (?:                   # post release
                    (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
                )?

                # You cannot use a wild card and a dev or local version
                # together so group them with a | and make them optional.
                (?:
                    (?:[-_\.]?dev[-_\.]?[0-9]*)?         # dev release
                    (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local
                    |
                    \.\*  # Wild card syntax of .*
                )?
            )
            |
            (?:
                # The compatible operator requires at least two digits in the
                # release segment.
                (?<=~=)               # Only match for the compatible operator

                \s*
                v?
                (?:[0-9]+!)?          # epoch
                [0-9]+(?:\.[0-9]+)+   # release  (We have a + instead of a *)
                (?:                   # pre release
                    [-_\.]?
                    (a|b|c|rc|alpha|beta|pre|preview)
                    [-_\.]?
                    [0-9]*
                )?
                (?:                                   # post release
                    (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
                )?
                (?:[-_\.]?dev[-_\.]?[0-9]*)?          # dev release
            )
            |
            (?:
                # All other operators only allow a sub set of what the
                # (non)equality operators do. Specifically they do not allow
                # local versions to be specified nor do they allow the prefix
                # matching wild cards.
                (?=": "greater_than_equal",
        "<": "less_than",
        ">": "greater_than",
        "===": "arbitrary",
    }

    @_require_version_compare
    def _compare_compatible(self, prospective, spec):
        # Compatible releases have an equivalent combination of >= and ==. That
        # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to
        # implement this in terms of the other specifiers instead of
        # implementing it ourselves. The only thing we need to do is construct
        # the other specifiers.

        # We want everything but the last item in the version, but we want to
        # ignore post and dev releases and we want to treat the pre-release as
        # it's own separate segment.
        prefix = ".".join(
            list(
                itertools.takewhile(
                    lambda x: (not x.startswith("post") and not x.startswith("dev")),
                    _version_split(spec),
                )
            )[:-1]
        )

        # Add the prefix notation to the end of our string
        prefix += ".*"

        return self._get_operator(">=")(prospective, spec) and self._get_operator("==")(
            prospective, prefix
        )

    @_require_version_compare
    def _compare_equal(self, prospective, spec):
        # We need special logic to handle prefix matching
        if spec.endswith(".*"):
            # In the case of prefix matching we want to ignore local segment.
            prospective = Version(prospective.public)
            # Split the spec out by dots, and pretend that there is an implicit
            # dot in between a release segment and a pre-release segment.
            spec = _version_split(spec[:-2])  # Remove the trailing .*

            # Split the prospective version out by dots, and pretend that there
            # is an implicit dot in between a release segment and a pre-release
            # segment.
            prospective = _version_split(str(prospective))

            # Shorten the prospective version to be the same length as the spec
            # so that we can determine if the specifier is a prefix of the
            # prospective version or not.
            prospective = prospective[: len(spec)]

            # Pad out our two sides with zeros so that they both equal the same
            # length.
            spec, prospective = _pad_version(spec, prospective)
        else:
            # Convert our spec string into a Version
            spec = Version(spec)

            # If the specifier does not have a local segment, then we want to
            # act as if the prospective version also does not have a local
            # segment.
            if not spec.local:
                prospective = Version(prospective.public)

        return prospective == spec

    @_require_version_compare
    def _compare_not_equal(self, prospective, spec):
        return not self._compare_equal(prospective, spec)

    @_require_version_compare
    def _compare_less_than_equal(self, prospective, spec):
        return prospective <= Version(spec)

    @_require_version_compare
    def _compare_greater_than_equal(self, prospective, spec):
        return prospective >= Version(spec)

    @_require_version_compare
    def _compare_less_than(self, prospective, spec):
        # Convert our spec to a Version instance, since we'll want to work with
        # it as a version.
        spec = Version(spec)

        # Check to see if the prospective version is less than the spec
        # version. If it's not we can short circuit and just return False now
        # instead of doing extra unneeded work.
        if not prospective < spec:
            return False

        # This special case is here so that, unless the specifier itself
        # includes is a pre-release version, that we do not accept pre-release
        # versions for the version mentioned in the specifier (e.g. <3.1 should
        # not match 3.1.dev0, but should match 3.0.dev0).
        if not spec.is_prerelease and prospective.is_prerelease:
            if Version(prospective.base_version) == Version(spec.base_version):
                return False

        # If we've gotten to here, it means that prospective version is both
        # less than the spec version *and* it's not a pre-release of the same
        # version in the spec.
        return True

    @_require_version_compare
    def _compare_greater_than(self, prospective, spec):
        # Convert our spec to a Version instance, since we'll want to work with
        # it as a version.
        spec = Version(spec)

        # Check to see if the prospective version is greater than the spec
        # version. If it's not we can short circuit and just return False now
        # instead of doing extra unneeded work.
        if not prospective > spec:
            return False

        # This special case is here so that, unless the specifier itself
        # includes is a post-release version, that we do not accept
        # post-release versions for the version mentioned in the specifier
        # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0).
        if not spec.is_postrelease and prospective.is_postrelease:
            if Version(prospective.base_version) == Version(spec.base_version):
                return False

        # Ensure that we do not allow a local version of the version mentioned
        # in the specifier, which is technically greater than, to match.
        if prospective.local is not None:
            if Version(prospective.base_version) == Version(spec.base_version):
                return False

        # If we've gotten to here, it means that prospective version is both
        # greater than the spec version *and* it's not a pre-release of the
        # same version in the spec.
        return True

    def _compare_arbitrary(self, prospective, spec):
        return str(prospective).lower() == str(spec).lower()

    @property
    def prereleases(self):
        # If there is an explicit prereleases set for this, then we'll just
        # blindly use that.
        if self._prereleases is not None:
            return self._prereleases

        # Look at all of our specifiers and determine if they are inclusive
        # operators, and if they are if they are including an explicit
        # prerelease.
        operator, version = self._spec
        if operator in ["==", ">=", "<=", "~=", "==="]:
            # The == specifier can include a trailing .*, if it does we
            # want to remove before parsing.
            if operator == "==" and version.endswith(".*"):
                version = version[:-2]

            # Parse the version, and if it is a pre-release than this
            # specifier allows pre-releases.
            if parse(version).is_prerelease:
                return True

        return False

    @prereleases.setter
    def prereleases(self, value):
        self._prereleases = value


_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$")


def _version_split(version):
    result = []
    for item in version.split("."):
        match = _prefix_regex.search(item)
        if match:
            result.extend(match.groups())
        else:
            result.append(item)
    return result


def _pad_version(left, right):
    left_split, right_split = [], []

    # Get the release segment of our versions
    left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left)))
    right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right)))

    # Get the rest of our versions
    left_split.append(left[len(left_split[0]) :])
    right_split.append(right[len(right_split[0]) :])

    # Insert our padding
    left_split.insert(1, ["0"] * max(0, len(right_split[0]) - len(left_split[0])))
    right_split.insert(1, ["0"] * max(0, len(left_split[0]) - len(right_split[0])))

    return (list(itertools.chain(*left_split)), list(itertools.chain(*right_split)))


class SpecifierSet(BaseSpecifier):
    def __init__(self, specifiers="", prereleases=None):
        # Split on , to break each indidivual specifier into it's own item, and
        # strip each item to remove leading/trailing whitespace.
        specifiers = [s.strip() for s in specifiers.split(",") if s.strip()]

        # Parsed each individual specifier, attempting first to make it a
        # Specifier and falling back to a LegacySpecifier.
        parsed = set()
        for specifier in specifiers:
            try:
                parsed.add(Specifier(specifier))
            except InvalidSpecifier:
                parsed.add(LegacySpecifier(specifier))

        # Turn our parsed specifiers into a frozen set and save them for later.
        self._specs = frozenset(parsed)

        # Store our prereleases value so we can use it later to determine if
        # we accept prereleases or not.
        self._prereleases = prereleases

    def __repr__(self):
        pre = (
            ", prereleases={0!r}".format(self.prereleases)
            if self._prereleases is not None
            else ""
        )

        return "".format(str(self), pre)

    def __str__(self):
        return ",".join(sorted(str(s) for s in self._specs))

    def __hash__(self):
        return hash(self._specs)

    def __and__(self, other):
        if isinstance(other, string_types):
            other = SpecifierSet(other)
        elif not isinstance(other, SpecifierSet):
            return NotImplemented

        specifier = SpecifierSet()
        specifier._specs = frozenset(self._specs | other._specs)

        if self._prereleases is None and other._prereleases is not None:
            specifier._prereleases = other._prereleases
        elif self._prereleases is not None and other._prereleases is None:
            specifier._prereleases = self._prereleases
        elif self._prereleases == other._prereleases:
            specifier._prereleases = self._prereleases
        else:
            raise ValueError(
                "Cannot combine SpecifierSets with True and False prerelease "
                "overrides."
            )

        return specifier

    def __eq__(self, other):
        if isinstance(other, string_types):
            other = SpecifierSet(other)
        elif isinstance(other, _IndividualSpecifier):
            other = SpecifierSet(str(other))
        elif not isinstance(other, SpecifierSet):
            return NotImplemented

        return self._specs == other._specs

    def __ne__(self, other):
        if isinstance(other, string_types):
            other = SpecifierSet(other)
        elif isinstance(other, _IndividualSpecifier):
            other = SpecifierSet(str(other))
        elif not isinstance(other, SpecifierSet):
            return NotImplemented

        return self._specs != other._specs

    def __len__(self):
        return len(self._specs)

    def __iter__(self):
        return iter(self._specs)

    @property
    def prereleases(self):
        # If we have been given an explicit prerelease modifier, then we'll
        # pass that through here.
        if self._prereleases is not None:
            return self._prereleases

        # If we don't have any specifiers, and we don't have a forced value,
        # then we'll just return None since we don't know if this should have
        # pre-releases or not.
        if not self._specs:
            return None

        # Otherwise we'll see if any of the given specifiers accept
        # prereleases, if any of them do we'll return True, otherwise False.
        return any(s.prereleases for s in self._specs)

    @prereleases.setter
    def prereleases(self, value):
        self._prereleases = value

    def __contains__(self, item):
        return self.contains(item)

    def contains(self, item, prereleases=None):
        # Ensure that our item is a Version or LegacyVersion instance.
        if not isinstance(item, (LegacyVersion, Version)):
            item = parse(item)

        # Determine if we're forcing a prerelease or not, if we're not forcing
        # one for this particular filter call, then we'll use whatever the
        # SpecifierSet thinks for whether or not we should support prereleases.
        if prereleases is None:
            prereleases = self.prereleases

        # We can determine if we're going to allow pre-releases by looking to
        # see if any of the underlying items supports them. If none of them do
        # and this item is a pre-release then we do not allow it and we can
        # short circuit that here.
        # Note: This means that 1.0.dev1 would not be contained in something
        #       like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0
        if not prereleases and item.is_prerelease:
            return False

        # We simply dispatch to the underlying specs here to make sure that the
        # given version is contained within all of them.
        # Note: This use of all() here means that an empty set of specifiers
        #       will always return True, this is an explicit design decision.
        return all(s.contains(item, prereleases=prereleases) for s in self._specs)

    def filter(self, iterable, prereleases=None):
        # Determine if we're forcing a prerelease or not, if we're not forcing
        # one for this particular filter call, then we'll use whatever the
        # SpecifierSet thinks for whether or not we should support prereleases.
        if prereleases is None:
            prereleases = self.prereleases

        # If we have any specifiers, then we want to wrap our iterable in the
        # filter method for each one, this will act as a logical AND amongst
        # each specifier.
        if self._specs:
            for spec in self._specs:
                iterable = spec.filter(iterable, prereleases=bool(prereleases))
            return iterable
        # If we do not have any specifiers, then we need to have a rough filter
        # which will filter out any pre-releases, unless there are no final
        # releases, and which will filter out LegacyVersion in general.
        else:
            filtered = []
            found_prereleases = []

            for item in iterable:
                # Ensure that we some kind of Version class for this item.
                if not isinstance(item, (LegacyVersion, Version)):
                    parsed_version = parse(item)
                else:
                    parsed_version = item

                # Filter out any item which is parsed as a LegacyVersion
                if isinstance(parsed_version, LegacyVersion):
                    continue

                # Store any item which is a pre-release for later unless we've
                # already found a final version or we are accepting prereleases
                if parsed_version.is_prerelease and not prereleases:
                    if not filtered:
                        found_prereleases.append(item)
                else:
                    filtered.append(item)

            # If we've found no items except for pre-releases, then we'll go
            # ahead and use the pre-releases
            if not filtered and found_prereleases and prereleases is None:
                return found_prereleases

            return filtered
PKÓ¶N]Š×Ðèè0site-packages/pip/_vendor/packaging/__about__.pynu„[µü¤# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function

__all__ = [
    "__title__",
    "__summary__",
    "__uri__",
    "__version__",
    "__author__",
    "__email__",
    "__license__",
    "__copyright__",
]

__title__ = "packaging"
__summary__ = "Core utilities for Python packages"
__uri__ = "https://github.com/pypa/packaging"

__version__ = "19.2"

__author__ = "Donald Stufft and individual contributors"
__email__ = "donald@stufft.io"

__license__ = "BSD or Apache License, Version 2.0"
__copyright__ = "Copyright 2014-2019 %s" % __author__
PKÓ¶N]²è×: : .site-packages/pip/_vendor/packaging/markers.pynu„[µü¤# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function

import operator
import os
import platform
import sys

from pip._vendor.pyparsing import ParseException, ParseResults, stringStart, stringEnd
from pip._vendor.pyparsing import ZeroOrMore, Group, Forward, QuotedString
from pip._vendor.pyparsing import Literal as L  # noqa

from ._compat import string_types
from .specifiers import Specifier, InvalidSpecifier


__all__ = [
    "InvalidMarker",
    "UndefinedComparison",
    "UndefinedEnvironmentName",
    "Marker",
    "default_environment",
]


class InvalidMarker(ValueError):
    """
    An invalid marker was found, users should refer to PEP 508.
    """


class UndefinedComparison(ValueError):
    """
    An invalid operation was attempted on a value that doesn't support it.
    """


class UndefinedEnvironmentName(ValueError):
    """
    A name was attempted to be used that does not exist inside of the
    environment.
    """


class Node(object):
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return str(self.value)

    def __repr__(self):
        return "<{0}({1!r})>".format(self.__class__.__name__, str(self))

    def serialize(self):
        raise NotImplementedError


class Variable(Node):
    def serialize(self):
        return str(self)


class Value(Node):
    def serialize(self):
        return '"{0}"'.format(self)


class Op(Node):
    def serialize(self):
        return str(self)


VARIABLE = (
    L("implementation_version")
    | L("platform_python_implementation")
    | L("implementation_name")
    | L("python_full_version")
    | L("platform_release")
    | L("platform_version")
    | L("platform_machine")
    | L("platform_system")
    | L("python_version")
    | L("sys_platform")
    | L("os_name")
    | L("os.name")
    | L("sys.platform")  # PEP-345
    | L("platform.version")  # PEP-345
    | L("platform.machine")  # PEP-345
    | L("platform.python_implementation")  # PEP-345
    | L("python_implementation")  # PEP-345
    | L("extra")  # undocumented setuptools legacy
)
ALIASES = {
    "os.name": "os_name",
    "sys.platform": "sys_platform",
    "platform.version": "platform_version",
    "platform.machine": "platform_machine",
    "platform.python_implementation": "platform_python_implementation",
    "python_implementation": "platform_python_implementation",
}
VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0])))

VERSION_CMP = (
    L("===") | L("==") | L(">=") | L("<=") | L("!=") | L("~=") | L(">") | L("<")
)

MARKER_OP = VERSION_CMP | L("not in") | L("in")
MARKER_OP.setParseAction(lambda s, l, t: Op(t[0]))

MARKER_VALUE = QuotedString("'") | QuotedString('"')
MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0]))

BOOLOP = L("and") | L("or")

MARKER_VAR = VARIABLE | MARKER_VALUE

MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR)
MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0]))

LPAREN = L("(").suppress()
RPAREN = L(")").suppress()

MARKER_EXPR = Forward()
MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN)
MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR)

MARKER = stringStart + MARKER_EXPR + stringEnd


def _coerce_parse_result(results):
    if isinstance(results, ParseResults):
        return [_coerce_parse_result(i) for i in results]
    else:
        return results


def _format_marker(marker, first=True):
    assert isinstance(marker, (list, tuple, string_types))

    # Sometimes we have a structure like [[...]] which is a single item list
    # where the single item is itself it's own list. In that case we want skip
    # the rest of this function so that we don't get extraneous () on the
    # outside.
    if (
        isinstance(marker, list)
        and len(marker) == 1
        and isinstance(marker[0], (list, tuple))
    ):
        return _format_marker(marker[0])

    if isinstance(marker, list):
        inner = (_format_marker(m, first=False) for m in marker)
        if first:
            return " ".join(inner)
        else:
            return "(" + " ".join(inner) + ")"
    elif isinstance(marker, tuple):
        return " ".join([m.serialize() for m in marker])
    else:
        return marker


_operators = {
    "in": lambda lhs, rhs: lhs in rhs,
    "not in": lambda lhs, rhs: lhs not in rhs,
    "<": operator.lt,
    "<=": operator.le,
    "==": operator.eq,
    "!=": operator.ne,
    ">=": operator.ge,
    ">": operator.gt,
}


def _eval_op(lhs, op, rhs):
    try:
        spec = Specifier("".join([op.serialize(), rhs]))
    except InvalidSpecifier:
        pass
    else:
        return spec.contains(lhs)

    oper = _operators.get(op.serialize())
    if oper is None:
        raise UndefinedComparison(
            "Undefined {0!r} on {1!r} and {2!r}.".format(op, lhs, rhs)
        )

    return oper(lhs, rhs)


_undefined = object()


def _get_env(environment, name):
    value = environment.get(name, _undefined)

    if value is _undefined:
        raise UndefinedEnvironmentName(
            "{0!r} does not exist in evaluation environment.".format(name)
        )

    return value


def _evaluate_markers(markers, environment):
    groups = [[]]

    for marker in markers:
        assert isinstance(marker, (list, tuple, string_types))

        if isinstance(marker, list):
            groups[-1].append(_evaluate_markers(marker, environment))
        elif isinstance(marker, tuple):
            lhs, op, rhs = marker

            if isinstance(lhs, Variable):
                lhs_value = _get_env(environment, lhs.value)
                rhs_value = rhs.value
            else:
                lhs_value = lhs.value
                rhs_value = _get_env(environment, rhs.value)

            groups[-1].append(_eval_op(lhs_value, op, rhs_value))
        else:
            assert marker in ["and", "or"]
            if marker == "or":
                groups.append([])

    return any(all(item) for item in groups)


def format_full_version(info):
    version = "{0.major}.{0.minor}.{0.micro}".format(info)
    kind = info.releaselevel
    if kind != "final":
        version += kind[0] + str(info.serial)
    return version


def default_environment():
    if hasattr(sys, "implementation"):
        iver = format_full_version(sys.implementation.version)
        implementation_name = sys.implementation.name
    else:
        iver = "0"
        implementation_name = ""

    return {
        "implementation_name": implementation_name,
        "implementation_version": iver,
        "os_name": os.name,
        "platform_machine": platform.machine(),
        "platform_release": platform.release(),
        "platform_system": platform.system(),
        "platform_version": platform.version(),
        "python_full_version": platform.python_version(),
        "platform_python_implementation": platform.python_implementation(),
        "python_version": ".".join(platform.python_version_tuple()[:2]),
        "sys_platform": sys.platform,
    }


class Marker(object):
    def __init__(self, marker):
        try:
            self._markers = _coerce_parse_result(MARKER.parseString(marker))
        except ParseException as e:
            err_str = "Invalid marker: {0!r}, parse error at {1!r}".format(
                marker, marker[e.loc : e.loc + 8]
            )
            raise InvalidMarker(err_str)

    def __str__(self):
        return _format_marker(self._markers)

    def __repr__(self):
        return "".format(str(self))

    def evaluate(self, environment=None):
        """Evaluate a marker.

        Return the boolean from evaluating the given marker against the
        environment. environment is an optional argument to override all or
        part of the determined environment.

        The environment is determined from the current Python process.
        """
        current_environment = default_environment()
        if environment is not None:
            current_environment.update(environment)

        return _evaluate_markers(self._markers, current_environment)
PKÓ¶N]óö‡ÿ…2…2+site-packages/pip/_vendor/packaging/tags.pynu„[µü¤# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.

from __future__ import absolute_import

import distutils.util

try:
    from importlib.machinery import EXTENSION_SUFFIXES
except ImportError:  # pragma: no cover
    import imp

    EXTENSION_SUFFIXES = [x[0] for x in imp.get_suffixes()]
    del imp
import platform
import re
import sys
import sysconfig
import warnings


INTERPRETER_SHORT_NAMES = {
    "python": "py",  # Generic.
    "cpython": "cp",
    "pypy": "pp",
    "ironpython": "ip",
    "jython": "jy",
}


_32_BIT_INTERPRETER = sys.maxsize <= 2 ** 32


class Tag(object):

    __slots__ = ["_interpreter", "_abi", "_platform"]

    def __init__(self, interpreter, abi, platform):
        self._interpreter = interpreter.lower()
        self._abi = abi.lower()
        self._platform = platform.lower()

    @property
    def interpreter(self):
        return self._interpreter

    @property
    def abi(self):
        return self._abi

    @property
    def platform(self):
        return self._platform

    def __eq__(self, other):
        return (
            (self.platform == other.platform)
            and (self.abi == other.abi)
            and (self.interpreter == other.interpreter)
        )

    def __hash__(self):
        return hash((self._interpreter, self._abi, self._platform))

    def __str__(self):
        return "{}-{}-{}".format(self._interpreter, self._abi, self._platform)

    def __repr__(self):
        return "<{self} @ {self_id}>".format(self=self, self_id=id(self))


def parse_tag(tag):
    tags = set()
    interpreters, abis, platforms = tag.split("-")
    for interpreter in interpreters.split("."):
        for abi in abis.split("."):
            for platform_ in platforms.split("."):
                tags.add(Tag(interpreter, abi, platform_))
    return frozenset(tags)


def _normalize_string(string):
    return string.replace(".", "_").replace("-", "_")


def _cpython_interpreter(py_version):
    # TODO: Is using py_version_nodot for interpreter version critical?
    return "cp{major}{minor}".format(major=py_version[0], minor=py_version[1])


def _cpython_abis(py_version):
    abis = []
    version = "{}{}".format(*py_version[:2])
    debug = pymalloc = ucs4 = ""
    with_debug = sysconfig.get_config_var("Py_DEBUG")
    has_refcount = hasattr(sys, "gettotalrefcount")
    # Windows doesn't set Py_DEBUG, so checking for support of debug-compiled
    # extension modules is the best option.
    # https://github.com/pypa/pip/issues/3383#issuecomment-173267692
    has_ext = "_d.pyd" in EXTENSION_SUFFIXES
    if with_debug or (with_debug is None and (has_refcount or has_ext)):
        debug = "d"
    if py_version < (3, 8):
        with_pymalloc = sysconfig.get_config_var("WITH_PYMALLOC")
        if with_pymalloc or with_pymalloc is None:
            pymalloc = "m"
        if py_version < (3, 3):
            unicode_size = sysconfig.get_config_var("Py_UNICODE_SIZE")
            if unicode_size == 4 or (
                unicode_size is None and sys.maxunicode == 0x10FFFF
            ):
                ucs4 = "u"
    elif debug:
        # Debug builds can also load "normal" extension modules.
        # We can also assume no UCS-4 or pymalloc requirement.
        abis.append("cp{version}".format(version=version))
    abis.insert(
        0,
        "cp{version}{debug}{pymalloc}{ucs4}".format(
            version=version, debug=debug, pymalloc=pymalloc, ucs4=ucs4
        ),
    )
    return abis


def _cpython_tags(py_version, interpreter, abis, platforms):
    for abi in abis:
        for platform_ in platforms:
            yield Tag(interpreter, abi, platform_)
    for tag in (Tag(interpreter, "abi3", platform_) for platform_ in platforms):
        yield tag
    for tag in (Tag(interpreter, "none", platform_) for platform_ in platforms):
        yield tag
    # PEP 384 was first implemented in Python 3.2.
    for minor_version in range(py_version[1] - 1, 1, -1):
        for platform_ in platforms:
            interpreter = "cp{major}{minor}".format(
                major=py_version[0], minor=minor_version
            )
            yield Tag(interpreter, "abi3", platform_)


def _pypy_interpreter():
    return "pp{py_major}{pypy_major}{pypy_minor}".format(
        py_major=sys.version_info[0],
        pypy_major=sys.pypy_version_info.major,
        pypy_minor=sys.pypy_version_info.minor,
    )


def _generic_abi():
    abi = sysconfig.get_config_var("SOABI")
    if abi:
        return _normalize_string(abi)
    else:
        return "none"


def _pypy_tags(py_version, interpreter, abi, platforms):
    for tag in (Tag(interpreter, abi, platform) for platform in platforms):
        yield tag
    for tag in (Tag(interpreter, "none", platform) for platform in platforms):
        yield tag


def _generic_tags(interpreter, py_version, abi, platforms):
    for tag in (Tag(interpreter, abi, platform) for platform in platforms):
        yield tag
    if abi != "none":
        tags = (Tag(interpreter, "none", platform_) for platform_ in platforms)
        for tag in tags:
            yield tag


def _py_interpreter_range(py_version):
    """
    Yield Python versions in descending order.

    After the latest version, the major-only version will be yielded, and then
    all following versions up to 'end'.
    """
    yield "py{major}{minor}".format(major=py_version[0], minor=py_version[1])
    yield "py{major}".format(major=py_version[0])
    for minor in range(py_version[1] - 1, -1, -1):
        yield "py{major}{minor}".format(major=py_version[0], minor=minor)


def _independent_tags(interpreter, py_version, platforms):
    """
    Return the sequence of tags that are consistent across implementations.

    The tags consist of:
    - py*-none-
    - -none-any
    - py*-none-any
    """
    for version in _py_interpreter_range(py_version):
        for platform_ in platforms:
            yield Tag(version, "none", platform_)
    yield Tag(interpreter, "none", "any")
    for version in _py_interpreter_range(py_version):
        yield Tag(version, "none", "any")


def _mac_arch(arch, is_32bit=_32_BIT_INTERPRETER):
    if not is_32bit:
        return arch

    if arch.startswith("ppc"):
        return "ppc"

    return "i386"


def _mac_binary_formats(version, cpu_arch):
    formats = [cpu_arch]
    if cpu_arch == "x86_64":
        if version < (10, 4):
            return []
        formats.extend(["intel", "fat64", "fat32"])

    elif cpu_arch == "i386":
        if version < (10, 4):
            return []
        formats.extend(["intel", "fat32", "fat"])

    elif cpu_arch == "ppc64":
        # TODO: Need to care about 32-bit PPC for ppc64 through 10.2?
        if version > (10, 5) or version < (10, 4):
            return []
        formats.append("fat64")

    elif cpu_arch == "ppc":
        if version > (10, 6):
            return []
        formats.extend(["fat32", "fat"])

    formats.append("universal")
    return formats


def _mac_platforms(version=None, arch=None):
    version_str, _, cpu_arch = platform.mac_ver()
    if version is None:
        version = tuple(map(int, version_str.split(".")[:2]))
    if arch is None:
        arch = _mac_arch(cpu_arch)
    platforms = []
    for minor_version in range(version[1], -1, -1):
        compat_version = version[0], minor_version
        binary_formats = _mac_binary_formats(compat_version, arch)
        for binary_format in binary_formats:
            platforms.append(
                "macosx_{major}_{minor}_{binary_format}".format(
                    major=compat_version[0],
                    minor=compat_version[1],
                    binary_format=binary_format,
                )
            )
    return platforms


# From PEP 513.
def _is_manylinux_compatible(name, glibc_version):
    # Check for presence of _manylinux module.
    try:
        import _manylinux

        return bool(getattr(_manylinux, name + "_compatible"))
    except (ImportError, AttributeError):
        # Fall through to heuristic check below.
        pass

    return _have_compatible_glibc(*glibc_version)


def _glibc_version_string():
    # Returns glibc version string, or None if not using glibc.
    import ctypes

    # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen
    # manpage says, "If filename is NULL, then the returned handle is for the
    # main program". This way we can let the linker do the work to figure out
    # which libc our process is actually using.
    process_namespace = ctypes.CDLL(None)
    try:
        gnu_get_libc_version = process_namespace.gnu_get_libc_version
    except AttributeError:
        # Symbol doesn't exist -> therefore, we are not linked to
        # glibc.
        return None

    # Call gnu_get_libc_version, which returns a string like "2.5"
    gnu_get_libc_version.restype = ctypes.c_char_p
    version_str = gnu_get_libc_version()
    # py2 / py3 compatibility:
    if not isinstance(version_str, str):
        version_str = version_str.decode("ascii")

    return version_str


# Separated out from have_compatible_glibc for easier unit testing.
def _check_glibc_version(version_str, required_major, minimum_minor):
    # Parse string and check against requested version.
    #
    # We use a regexp instead of str.split because we want to discard any
    # random junk that might come after the minor version -- this might happen
    # in patched/forked versions of glibc (e.g. Linaro's version of glibc
    # uses version strings like "2.20-2014.11"). See gh-3588.
    m = re.match(r"(?P[0-9]+)\.(?P[0-9]+)", version_str)
    if not m:
        warnings.warn(
            "Expected glibc version with 2 components major.minor,"
            " got: %s" % version_str,
            RuntimeWarning,
        )
        return False
    return (
        int(m.group("major")) == required_major
        and int(m.group("minor")) >= minimum_minor
    )


def _have_compatible_glibc(required_major, minimum_minor):
    version_str = _glibc_version_string()
    if version_str is None:
        return False
    return _check_glibc_version(version_str, required_major, minimum_minor)


def _linux_platforms(is_32bit=_32_BIT_INTERPRETER):
    linux = _normalize_string(distutils.util.get_platform())
    if linux == "linux_x86_64" and is_32bit:
        linux = "linux_i686"
    manylinux_support = (
        ("manylinux2014", (2, 17)),  # CentOS 7 w/ glibc 2.17 (PEP 599)
        ("manylinux2010", (2, 12)),  # CentOS 6 w/ glibc 2.12 (PEP 571)
        ("manylinux1", (2, 5)),  # CentOS 5 w/ glibc 2.5 (PEP 513)
    )
    manylinux_support_iter = iter(manylinux_support)
    for name, glibc_version in manylinux_support_iter:
        if _is_manylinux_compatible(name, glibc_version):
            platforms = [linux.replace("linux", name)]
            break
    else:
        platforms = []
    # Support for a later manylinux implies support for an earlier version.
    platforms += [linux.replace("linux", name) for name, _ in manylinux_support_iter]
    platforms.append(linux)
    return platforms


def _generic_platforms():
    platform = _normalize_string(distutils.util.get_platform())
    return [platform]


def _interpreter_name():
    name = platform.python_implementation().lower()
    return INTERPRETER_SHORT_NAMES.get(name) or name


def _generic_interpreter(name, py_version):
    version = sysconfig.get_config_var("py_version_nodot")
    if not version:
        version = "".join(map(str, py_version[:2]))
    return "{name}{version}".format(name=name, version=version)


def sys_tags():
    """
    Returns the sequence of tag triples for the running interpreter.

    The order of the sequence corresponds to priority order for the
    interpreter, from most to least important.
    """
    py_version = sys.version_info[:2]
    interpreter_name = _interpreter_name()
    if platform.system() == "Darwin":
        platforms = _mac_platforms()
    elif platform.system() == "Linux":
        platforms = _linux_platforms()
    else:
        platforms = _generic_platforms()

    if interpreter_name == "cp":
        interpreter = _cpython_interpreter(py_version)
        abis = _cpython_abis(py_version)
        for tag in _cpython_tags(py_version, interpreter, abis, platforms):
            yield tag
    elif interpreter_name == "pp":
        interpreter = _pypy_interpreter()
        abi = _generic_abi()
        for tag in _pypy_tags(py_version, interpreter, abi, platforms):
            yield tag
    else:
        interpreter = _generic_interpreter(interpreter_name, py_version)
        abi = _generic_abi()
        for tag in _generic_tags(interpreter, py_version, abi, platforms):
            yield tag
    for tag in _independent_tags(interpreter, py_version, platforms):
        yield tag
PKÓ¶N]¢(Öæ&&-site-packages/pip/_vendor/colorama/winterm.pynu„[µü¤# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
from . import win32


# from wincon.h
class WinColor(object):
    BLACK   = 0
    BLUE    = 1
    GREEN   = 2
    CYAN    = 3
    RED     = 4
    MAGENTA = 5
    YELLOW  = 6
    GREY    = 7

# from wincon.h
class WinStyle(object):
    NORMAL              = 0x00 # dim text, dim background
    BRIGHT              = 0x08 # bright text, dim background
    BRIGHT_BACKGROUND   = 0x80 # dim text, bright background

class WinTerm(object):

    def __init__(self):
        self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes
        self.set_attrs(self._default)
        self._default_fore = self._fore
        self._default_back = self._back
        self._default_style = self._style
        # In order to emulate LIGHT_EX in windows, we borrow the BRIGHT style.
        # So that LIGHT_EX colors and BRIGHT style do not clobber each other,
        # we track them separately, since LIGHT_EX is overwritten by Fore/Back
        # and BRIGHT is overwritten by Style codes.
        self._light = 0

    def get_attrs(self):
        return self._fore + self._back * 16 + (self._style | self._light)

    def set_attrs(self, value):
        self._fore = value & 7
        self._back = (value >> 4) & 7
        self._style = value & (WinStyle.BRIGHT | WinStyle.BRIGHT_BACKGROUND)

    def reset_all(self, on_stderr=None):
        self.set_attrs(self._default)
        self.set_console(attrs=self._default)
        self._light = 0

    def fore(self, fore=None, light=False, on_stderr=False):
        if fore is None:
            fore = self._default_fore
        self._fore = fore
        # Emulate LIGHT_EX with BRIGHT Style
        if light:
            self._light |= WinStyle.BRIGHT
        else:
            self._light &= ~WinStyle.BRIGHT
        self.set_console(on_stderr=on_stderr)

    def back(self, back=None, light=False, on_stderr=False):
        if back is None:
            back = self._default_back
        self._back = back
        # Emulate LIGHT_EX with BRIGHT_BACKGROUND Style
        if light:
            self._light |= WinStyle.BRIGHT_BACKGROUND
        else:
            self._light &= ~WinStyle.BRIGHT_BACKGROUND
        self.set_console(on_stderr=on_stderr)

    def style(self, style=None, on_stderr=False):
        if style is None:
            style = self._default_style
        self._style = style
        self.set_console(on_stderr=on_stderr)

    def set_console(self, attrs=None, on_stderr=False):
        if attrs is None:
            attrs = self.get_attrs()
        handle = win32.STDOUT
        if on_stderr:
            handle = win32.STDERR
        win32.SetConsoleTextAttribute(handle, attrs)

    def get_position(self, handle):
        position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition
        # Because Windows coordinates are 0-based,
        # and win32.SetConsoleCursorPosition expects 1-based.
        position.X += 1
        position.Y += 1
        return position

    def set_cursor_position(self, position=None, on_stderr=False):
        if position is None:
            # I'm not currently tracking the position, so there is no default.
            # position = self.get_position()
            return
        handle = win32.STDOUT
        if on_stderr:
            handle = win32.STDERR
        win32.SetConsoleCursorPosition(handle, position)

    def cursor_adjust(self, x, y, on_stderr=False):
        handle = win32.STDOUT
        if on_stderr:
            handle = win32.STDERR
        position = self.get_position(handle)
        adjusted_position = (position.Y + y, position.X + x)
        win32.SetConsoleCursorPosition(handle, adjusted_position, adjust=False)

    def erase_screen(self, mode=0, on_stderr=False):
        # 0 should clear from the cursor to the end of the screen.
        # 1 should clear from the cursor to the beginning of the screen.
        # 2 should clear the entire screen, and move cursor to (1,1)
        handle = win32.STDOUT
        if on_stderr:
            handle = win32.STDERR
        csbi = win32.GetConsoleScreenBufferInfo(handle)
        # get the number of character cells in the current buffer
        cells_in_screen = csbi.dwSize.X * csbi.dwSize.Y
        # get number of character cells before current cursor position
        cells_before_cursor = csbi.dwSize.X * csbi.dwCursorPosition.Y + csbi.dwCursorPosition.X
        if mode == 0:
            from_coord = csbi.dwCursorPosition
            cells_to_erase = cells_in_screen - cells_before_cursor
        elif mode == 1:
            from_coord = win32.COORD(0, 0)
            cells_to_erase = cells_before_cursor
        elif mode == 2:
            from_coord = win32.COORD(0, 0)
            cells_to_erase = cells_in_screen
        else:
            # invalid mode
            return
        # fill the entire screen with blanks
        win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord)
        # now set the buffer's attributes accordingly
        win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord)
        if mode == 2:
            # put the cursor where needed
            win32.SetConsoleCursorPosition(handle, (1, 1))

    def erase_line(self, mode=0, on_stderr=False):
        # 0 should clear from the cursor to the end of the line.
        # 1 should clear from the cursor to the beginning of the line.
        # 2 should clear the entire line.
        handle = win32.STDOUT
        if on_stderr:
            handle = win32.STDERR
        csbi = win32.GetConsoleScreenBufferInfo(handle)
        if mode == 0:
            from_coord = csbi.dwCursorPosition
            cells_to_erase = csbi.dwSize.X - csbi.dwCursorPosition.X
        elif mode == 1:
            from_coord = win32.COORD(0, csbi.dwCursorPosition.Y)
            cells_to_erase = csbi.dwCursorPosition.X
        elif mode == 2:
            from_coord = win32.COORD(0, csbi.dwCursorPosition.Y)
            cells_to_erase = csbi.dwSize.X
        else:
            # invalid mode
            return
        # fill the entire screen with blanks
        win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord)
        # now set the buffer's attributes accordingly
        win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord)

    def set_title(self, title):
        win32.SetConsoleTitle(title)
PKÓ¶N]mJ Óïï.site-packages/pip/_vendor/colorama/__init__.pynu„[µü¤# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
from .initialise import init, deinit, reinit, colorama_text
from .ansi import Fore, Back, Style, Cursor
from .ansitowin32 import AnsiToWin32

__version__ = '0.4.1'
PKÓ¶N]ÎÈݵOsite-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eÞ(ã@sŠddlZddlZddlZddlmZmZmZmZddlm	Z	m
Z
mZddlm
Z
mZdZe
dk	rfe	ƒZGdd„deƒZGdd	„d	eƒZdS)
éNé)ÚAnsiForeÚAnsiBackÚ	AnsiStyleÚStyle)ÚWinTermÚWinColorÚWinStyle)ÚwindllÚwinapi_testc@sLeZdZdZdd„Zdd„Zdd„Zdd	„Zd
d„Zdd
„Z	e
dd„ƒZdS)Ú
StreamWrapperz´
    Wraps a stream (such as stdout), acting as a transparent proxy for all
    attribute access apart from method 'write()', which is delegated to our
    Converter instance.
    cCs||_||_dS©N)Ú_StreamWrapper__wrappedÚ_StreamWrapper__convertor)ÚselfÚwrappedZ	converter©rúD/usr/lib/python3.8/site-packages/pip/_vendor/colorama/ansitowin32.pyÚ__init__szStreamWrapper.__init__cCst|j|ƒSr
)Úgetattrr)rÚnamerrrÚ__getattr__szStreamWrapper.__getattr__cOs|jj||ŽSr
)rÚ	__enter__©rÚargsÚkwargsrrrrszStreamWrapper.__enter__cOs|jj||ŽSr
)rÚ__exit__rrrrr%szStreamWrapper.__exit__cCs|j |¡dSr
)rÚwrite©rÚtextrrrr(szStreamWrapper.writecCs\|j}dtjkr0|dk	r0|tjks,|tjkr0dSz
|j}Wntk
rPYdSX|ƒSdS)NZPYCHARM_HOSTEDTF)rÚosÚenvironÚsysÚ
__stdout__Ú
__stderr__ÚisattyÚAttributeError)rÚstreamZ
stream_isattyrrrr%+s

zStreamWrapper.isattycCs*|j}z|jWStk
r$YdSXdS©NT)rÚclosedr&)rr'rrrr)7s
zStreamWrapper.closedN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rrrrrr%Úpropertyr)rrrrrsrc@s~eZdZdZe d¡Ze d¡Zddd„Zdd	„Z	d
d„Z
dd
„Zdd„Zdd„Z
dd„Zdd„Zdd„Zdd„Zdd„ZdS)ÚAnsiToWin32z¾
    Implements a 'write()' method which, on Windows, will strip ANSI character
    sequences from the text, and if outputting to a tty, will convert them into
    win32 function calls.
    z?\[((?:\d|;)*)([a-zA-Z])?z?\]((?:.|;)*?)()?NFcCs–||_||_t||ƒ|_tjdk}|o*tƒ}|dkrN|pL|jjoL|j ¡}||_	|dkrt|or|jjor|j ¡}||_
| ¡|_|jt
jk|_dS)NÚnt)rÚ	autoresetrr'r rrr)r%ÚstripÚconvertÚget_win32_callsÚwin32_callsr"ÚstderrÚ	on_stderr)rrr3r2r1Z
on_windowsZconversion_supportedrrrrIs


zAnsiToWin32.__init__cCs|jp|jp|jS)aj
        True if this class is actually needed. If false, then the output
        stream will not be affected, nor will win32 calls be issued, so
        wrapping stdout is not actually required. This will generally be
        False on non-Windows platforms, unless optional functionality like
        autoreset has been requested using kwargs to init()
        )r3r2r1©rrrrÚshould_wrapjszAnsiToWin32.should_wrapcNCs@|j�r:t�r:tjtjftjtjtjftjtjtj	ftj	tjtj	ft
jtjt
jft
jtjt
jft
jtjt
jft
jtjt
jft
jtjt
jft
jtjt
jft
jtjt
jft
jtjt
jft
jtjft
jtjt
jdft
jtjt
jdft
jtjt
jdft
jtjt
jdft
jtjt
jdft
jtjt
jdft
jtjt
jdft
jtjt
jdftjtj t
jftjtj t
jftjtj t
jftjtj t
jftjtj t
jftjtj t
jftjtj t
jftjtj t
jftjtj ftjtj t
jdftjtj t
jdftjtj t
jdftjtj t
jdftjtj t
jdftjtj t
jdftjtj t
jdftjtj t
jdfi&St!ƒSr()"r3ÚwintermrÚ	RESET_ALLÚ	reset_allZBRIGHTZstyler	ZDIMZNORMALrZBLACKZforerZREDZGREENZYELLOWZBLUEZMAGENTAZCYANZWHITEZGREYZRESETZ
LIGHTBLACK_EXZLIGHTRED_EXZ
LIGHTGREEN_EXZLIGHTYELLOW_EXZLIGHTBLUE_EXZLIGHTMAGENTA_EXZLIGHTCYAN_EXZ
LIGHTWHITE_EXrZbackÚdictr8rrrr4tsž


















Ú(zAnsiToWin32.get_win32_callscCs@|js|jr| |¡n|j |¡|j ¡|jr<| ¡dSr
)r2r3Úwrite_and_convertrrÚflushr1r<rrrrr s
zAnsiToWin32.writecCs4|jr| dd¡n|js0|jjs0|j tj¡dS)NÚm©r)	r3Ú
call_win32r2r'r)rrrr;r8rrrr<ªszAnsiToWin32.reset_allcCsbd}| |¡}|j |¡D]0}| ¡\}}| |||¡|j| ¡Ž|}q| ||t|ƒ¡dS)zª
        Write the given text to our wrapped stream, stripping any ANSI
        sequences from the text, and optionally converting them into win32
        calls.
        rN)Úconvert_oscÚANSI_CSI_REÚfinditerÚspanÚwrite_plain_textÚconvert_ansiÚgroupsÚlen)rrZcursorÚmatchÚstartÚendrrrr>±s
zAnsiToWin32.write_and_convertcCs*||kr&|j |||…¡|j ¡dSr
)rrr?)rrrLrMrrrrGÁszAnsiToWin32.write_plain_textcCs"|jr| ||¡}| ||¡dSr
)r3Úextract_paramsrB)rÚparamstringÚcommandÚparamsrrrrHÇszAnsiToWin32.convert_ansicCsz|dkr8tdd„| d¡Dƒƒ}t|ƒdkrv|d}q n>tdd„| d¡Dƒƒ}t|ƒdkrv|d	krjd
}n|dkrvd}|S)NÚHfcss&|]}t|ƒdkrt|ƒndVqdS)rrN©rJÚint©Ú.0ÚprrrÚ	Ïsz-AnsiToWin32.extract_params..ú;é)rcss"|]}t|ƒdkrt|ƒVqdS)rNrSrUrrrrXÔsrZJKmrAÚABCD)ÚtupleÚsplitrJ)rrPrOrQrrrrNÍszAnsiToWin32.extract_paramscCsø|dkrR|D]B}||jkr|j|}|d}|dd…}t|jd�}|||Žqn¢|dkrptj|d|jd�n„|dkrŽtj|d|jd�nf|dkr¨tj||jd�nL|dkrô|d}d|fd|f|df|dfd	œ|\}	}
tj|	|
|jd�dS)
Nr@rr)r7ÚJÚKrRr[)ÚAÚBÚCÚD)r5r=r7r:Zerase_screenZ
erase_lineZset_cursor_positionZ
cursor_adjust)rrPrQZparamZ	func_argsÚfuncrrÚnÚxÚyrrrrBßs$

*zAnsiToWin32.call_win32cCsr|j |¡D]`}| ¡\}}|d|…||d…}| ¡\}}|dkr| d¡}|ddkrt |d¡q|S)NúrYrZ02r)ÚANSI_OSC_RErErFrIr]r:Z	set_title)rrrKrLrMrOrPrQrrrrCõs
zAnsiToWin32.convert_osc)NNF)r*r+r,r-ÚreÚcompilerDrirr9r4rr<r>rGrHrNrBrCrrrrr/@s


!
,
r/)rjr"r Úansirrrrr:rrr	Zwin32r
rÚobjectrr/rrrrÚs0PKÓ¶N]º[pxxHsite-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eÜ	ã@s dZdZdZdZdd„Zdd„Zdd	d
„Zddd„ZGd
d„deƒZ	Gdd„deƒZ
Gdd„de	ƒZGdd„de	ƒZGdd„de	ƒZ
eƒZeƒZe
ƒZe
ƒZdS)z€
This module generates ANSI character codes to printing colors to terminals.
See: http://en.wikipedia.org/wiki/ANSI_escape_code
z]úcCstt|ƒdS)NÚm©ÚCSIÚstr)Úcode©rú=/usr/lib/python3.8/site-packages/pip/_vendor/colorama/ansi.pyÚ
code_to_charssr	cCstd|tS)Nz2;)ÚOSCÚBEL)ÚtitlerrrÚ	set_titlesr
écCstt|ƒdS)NÚJr©ÚmoderrrÚclear_screensrcCstt|ƒdS)NÚKrrrrrÚ
clear_linesrc@seZdZdd„ZdS)Ú	AnsiCodescCs6t|ƒD](}| d¡st||ƒ}t||t|ƒƒqdS)NÚ_)ÚdirÚ
startswithÚgetattrÚsetattrr	)ÚselfÚnameÚvaluerrrÚ__init__s

zAnsiCodes.__init__N)Ú__name__Ú
__module__Ú__qualname__rrrrrrsrc@s>eZdZd
dd„Zddd„Zddd„Zddd	„Zdd
d„ZdS)Ú
AnsiCursorécCstt|ƒdS)NÚAr©rÚnrrrÚUP%sz
AnsiCursor.UPcCstt|ƒdS)NÚBrr%rrrÚDOWN'szAnsiCursor.DOWNcCstt|ƒdS)NÚCrr%rrrÚFORWARD)szAnsiCursor.FORWARDcCstt|ƒdS)NÚDrr%rrrÚBACK+szAnsiCursor.BACKcCstt|ƒdt|ƒdS)Nú;ÚHr)rÚxÚyrrrÚPOS-szAnsiCursor.POSN)r#)r#)r#)r#)r#r#)rr r!r'r)r+r-r2rrrrr"$s




r"c@sPeZdZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZ
dZd
ZdZdZdZdZdS)ÚAnsiForeééé é!é"é#é$é%é'éZé[é\é]é^é_é`éaN©rr r!ZBLACKZREDZGREENZYELLOWZBLUEZMAGENTAZCYANZWHITEZRESETZ
LIGHTBLACK_EXZLIGHTRED_EXZ
LIGHTGREEN_EXZLIGHTYELLOW_EXZLIGHTBLUE_EXZLIGHTMAGENTA_EXZLIGHTCYAN_EXZ
LIGHTWHITE_EXrrrrr31s"r3c@sPeZdZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZ
dZd
ZdZdZdZdZdS)ÚAnsiBacké(é)é*é+é,é-é.é/é1édéeéfégéhéiéjékNrErrrrrFGs"rFc@seZdZdZdZdZdZdS)Ú	AnsiStyler#rééN)rr r!ZBRIGHTZDIMZNORMALZ	RESET_ALLrrrrrX]srXN)r)r)Ú__doc__rr
rr	r
rrÚobjectrr"r3rFrXZForeZBackZStyleZCursorrrrrÚs 


PKÓ¶N]?Î=ùEsite-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-38.pycnu„[µü¤U

ÀÒ.e&ã@s@ddlmZGdd„deƒZGdd„deƒZGdd„deƒZdS)	é)Úwin32c@s,eZdZdZdZdZdZdZdZdZ	dZ
d	S)
ÚWinColorérééééééN)Ú__name__Ú
__module__Ú__qualname__ZBLACKZBLUEZGREENZCYANZREDZMAGENTAZYELLOWZGREY©rrú@/usr/lib/python3.8/site-packages/pip/_vendor/colorama/winterm.pyrsrc@seZdZdZdZdZdS)ÚWinStyleréé€N)rrr
ZNORMALÚBRIGHTÚBRIGHT_BACKGROUNDrrrrrsrc@sŽeZdZdd„Zdd„Zdd„Zd dd	„Zd!dd„Zd"d
d„Zd#dd„Z	d$dd„Z
dd„Zd%dd„Zd&dd„Z
d'dd„Zd(dd„Zdd„ZdS))ÚWinTermcCs>t tj¡j|_| |j¡|j|_|j|_	|j
|_d|_dS)Nr)
rÚGetConsoleScreenBufferInfoÚSTDOUTZwAttributesÚ_defaultÚ	set_attrsÚ_foreÚ
_default_foreÚ_backÚ
_default_backÚ_styleÚ_default_styleÚ_light©ÚselfrrrÚ__init__szWinTerm.__init__cCs|j|jd|j|jBS)Né)rrrr r!rrrÚ	get_attrs$szWinTerm.get_attrscCs.|d@|_|d?d@|_|tjtjB@|_dS)Nr
r)rrrrrr)r"Úvaluerrrr's
zWinTerm.set_attrsNcCs$| |j¡|j|jd�d|_dS)N)Úattrsr)rrÚset_consoler )r"Ú	on_stderrrrrÚ	reset_all,szWinTerm.reset_allFcCsL|dkr|j}||_|r*|jtjO_n|jtjM_|j|d�dS©N)r))rrr rrr()r"ÚforeÚlightr)rrrr,1szWinTerm.forecCsL|dkr|j}||_|r*|jtjO_n|jtjM_|j|d�dSr+)rrr rrr()r"Úbackr-r)rrrr.<szWinTerm.backcCs$|dkr|j}||_|j|d�dSr+)rrr()r"Ústyler)rrrr/Gsz
WinTerm.stylecCs0|dkr| ¡}tj}|r tj}t ||¡dS©N)r%rrÚSTDERRZSetConsoleTextAttribute)r"r'r)Úhandlerrrr(MszWinTerm.set_consolecCs,t |¡j}|jd7_|jd7_|S)Nr)rrÚdwCursorPositionÚXÚY)r"r2ÚpositionrrrÚget_positionUszWinTerm.get_positioncCs,|dkrdStj}|rtj}t ||¡dSr0)rrr1ÚSetConsoleCursorPosition)r"r6r)r2rrrÚset_cursor_position]szWinTerm.set_cursor_positioncCsBtj}|rtj}| |¡}|j||j|f}tj||dd�dS)NF)Zadjust)rrr1r7r5r4r8)r"ÚxÚyr)r2r6Zadjusted_positionrrrÚ
cursor_adjustgs
zWinTerm.cursor_adjustrc	CsÎtj}|rtj}t |¡}|jj|jj}|jj|jj|jj}|dkrZ|j}||}n8|dkrtt dd¡}|}n|dkrŽt dd¡}|}ndSt 	|d||¡t 
|| ¡||¡|dkrÊt |d¡dS)Nrrrú )rr)
rrr1rÚdwSizer4r5r3ÚCOORDÚFillConsoleOutputCharacterÚFillConsoleOutputAttributer%r8)	r"Úmoder)r2ÚcsbiZcells_in_screenZcells_before_cursorÚ
from_coordÚcells_to_eraserrrÚerase_screenos(

zWinTerm.erase_screencCsªtj}|rtj}t |¡}|dkr:|j}|jj|jj}nH|dkr\t d|jj¡}|jj}n&|dkr~t d|jj¡}|jj}ndSt 	|d||¡t 
|| ¡||¡dS)Nrrrr=)rrr1rr3r>r4r?r5r@rAr%)r"rBr)r2rCrDrErrrÚ
erase_line�s 


zWinTerm.erase_linecCst |¡dSr0)rZSetConsoleTitle)r"ÚtitlerrrÚ	set_title¨szWinTerm.set_title)N)NFF)NFF)NF)NF)NF)F)rF)rF)rrr
r#r%rr*r,r.r/r(r7r9r<rFrGrIrrrrrs








 
rN)ÚrÚobjectrrrrrrrÚsPKÓ¶N]3´G——Lsite-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eïã@sDddlmZmZmZmZddlmZmZmZm	Z	ddl
mZdZdS)é)ÚinitÚdeinitÚreinitÚ
colorama_text)ÚForeÚBackÚStyleÚCursor)ÚAnsiToWin32z0.4.1N)
Z
initialiserrrrÚansirrrr	Zansitowin32r
Ú__version__©r
r
úA/usr/lib/python3.8/site-packages/pip/_vendor/colorama/__init__.pyÚsPKÓ¶N]?Î=ùKsite-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.e&ã@s@ddlmZGdd„deƒZGdd„deƒZGdd„deƒZdS)	é)Úwin32c@s,eZdZdZdZdZdZdZdZdZ	dZ
d	S)
ÚWinColorérééééééN)Ú__name__Ú
__module__Ú__qualname__ZBLACKZBLUEZGREENZCYANZREDZMAGENTAZYELLOWZGREY©rrú@/usr/lib/python3.8/site-packages/pip/_vendor/colorama/winterm.pyrsrc@seZdZdZdZdZdS)ÚWinStyleréé€N)rrr
ZNORMALÚBRIGHTÚBRIGHT_BACKGROUNDrrrrrsrc@sŽeZdZdd„Zdd„Zdd„Zd dd	„Zd!dd„Zd"d
d„Zd#dd„Z	d$dd„Z
dd„Zd%dd„Zd&dd„Z
d'dd„Zd(dd„Zdd„ZdS))ÚWinTermcCs>t tj¡j|_| |j¡|j|_|j|_	|j
|_d|_dS)Nr)
rÚGetConsoleScreenBufferInfoÚSTDOUTZwAttributesÚ_defaultÚ	set_attrsÚ_foreÚ
_default_foreÚ_backÚ
_default_backÚ_styleÚ_default_styleÚ_light©ÚselfrrrÚ__init__szWinTerm.__init__cCs|j|jd|j|jBS)Né)rrrr r!rrrÚ	get_attrs$szWinTerm.get_attrscCs.|d@|_|d?d@|_|tjtjB@|_dS)Nr
r)rrrrrr)r"Úvaluerrrr's
zWinTerm.set_attrsNcCs$| |j¡|j|jd�d|_dS)N)Úattrsr)rrÚset_consoler )r"Ú	on_stderrrrrÚ	reset_all,szWinTerm.reset_allFcCsL|dkr|j}||_|r*|jtjO_n|jtjM_|j|d�dS©N)r))rrr rrr()r"ÚforeÚlightr)rrrr,1szWinTerm.forecCsL|dkr|j}||_|r*|jtjO_n|jtjM_|j|d�dSr+)rrr rrr()r"Úbackr-r)rrrr.<szWinTerm.backcCs$|dkr|j}||_|j|d�dSr+)rrr()r"Ústyler)rrrr/Gsz
WinTerm.stylecCs0|dkr| ¡}tj}|r tj}t ||¡dS©N)r%rrÚSTDERRZSetConsoleTextAttribute)r"r'r)Úhandlerrrr(MszWinTerm.set_consolecCs,t |¡j}|jd7_|jd7_|S)Nr)rrÚdwCursorPositionÚXÚY)r"r2ÚpositionrrrÚget_positionUszWinTerm.get_positioncCs,|dkrdStj}|rtj}t ||¡dSr0)rrr1ÚSetConsoleCursorPosition)r"r6r)r2rrrÚset_cursor_position]szWinTerm.set_cursor_positioncCsBtj}|rtj}| |¡}|j||j|f}tj||dd�dS)NF)Zadjust)rrr1r7r5r4r8)r"ÚxÚyr)r2r6Zadjusted_positionrrrÚ
cursor_adjustgs
zWinTerm.cursor_adjustrc	CsÎtj}|rtj}t |¡}|jj|jj}|jj|jj|jj}|dkrZ|j}||}n8|dkrtt dd¡}|}n|dkrŽt dd¡}|}ndSt 	|d||¡t 
|| ¡||¡|dkrÊt |d¡dS)Nrrrú )rr)
rrr1rÚdwSizer4r5r3ÚCOORDÚFillConsoleOutputCharacterÚFillConsoleOutputAttributer%r8)	r"Úmoder)r2ÚcsbiZcells_in_screenZcells_before_cursorÚ
from_coordÚcells_to_eraserrrÚerase_screenos(

zWinTerm.erase_screencCsªtj}|rtj}t |¡}|dkr:|j}|jj|jj}nH|dkr\t d|jj¡}|jj}n&|dkr~t d|jj¡}|jj}ndSt 	|d||¡t 
|| ¡||¡dS)Nrrrr=)rrr1rr3r>r4r?r5r@rAr%)r"rBr)r2rCrDrErrrÚ
erase_line�s 


zWinTerm.erase_linecCst |¡dSr0)rZSetConsoleTitle)r"ÚtitlerrrÚ	set_title¨szWinTerm.set_title)N)NFF)NFF)NF)NF)NF)F)rF)rF)rrr
r#r%rr*r,r.r/r(r7r9r<rFrGrIrrrrrs








 
rN)ÚrÚobjectrrrrrrrÚsPKÓ¶N])”„„Nsite-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.e{ã@stddlZddlZddlZddlmZdadadadada	dd„Z
ddd	„Zd
d„Zej
dd
„ƒZdd„Zdd„ZdS)éNé)ÚAnsiToWin32FcCstdk	rttƒ ¡dS©N)rÚorig_stdoutÚ	reset_all©rrúC/usr/lib/python3.8/site-packages/pip/_vendor/colorama/initialise.pyrsrTcCsˆ|st|||gƒrtdƒ‚tjatjatjdkr6dantt||||ƒt_atjdkr\da	ntt||||ƒt_a	t
s„t t
¡da
dS)Nz,wrap=False conflicts with any other arg=TrueT)ÚanyÚ
ValueErrorÚsysÚstdoutrÚstderrÚorig_stderrÚwrapped_stdoutÚwrap_streamÚwrapped_stderrÚatexit_doneÚatexitÚregisterr)Ú	autoresetÚconvertÚstripÚwraprrrÚinits
ÿ
ÿ
rcCs tdk	rtt_tdk	rtt_dSr)rrrrr
rrrrÚdeinit3srcos"t||Žz
dVW5tƒXdSr)rr)ÚargsÚkwargsrrrÚ
colorama_text:s

rcCs tdk	rtt_tdk	rtt_dSr)rrrrr
rrrrÚreinitCsrcCs&|r"t||||d�}| ¡r"|j}|S)N)rrr)rZshould_wrapÚstream)rrrrrÚwrapperrrrrJsÿr)FNNT)rÚ
contextlibrZansitowin32rrrrrrrrrÚcontextmanagerrrrrrrrÚs

PKÓ¶N]wGÂ%hhCsite-packages/pip/_vendor/colorama/__pycache__/win32.cpython-38.pycnu„[µü¤U

ÀÒ.eã	@sÂdZdZz.ddlZddlmZeejƒZddlmZWn.eefk
rddZdd„Z	dd„Z
Y�nZXdd	lmZmZm
Z
mZejZGd
d„deƒZejjZejge_eje_ejjZejeeƒge_eje_ejj	Zejejge_eje_ejjZejege_eje_ejj Z!eje
ejeeejƒge!_eje!_ejj"Z#ejejejeeejƒge#_eje#_ejj$Z%ej&ge%_eje%_dd
„Z'dd„Z
efdd„Zdd„Z	ddd„Zdd„Z(dd„Z"dd„Z)dS)iõÿÿÿiôÿÿÿéN)Ú
LibraryLoader)ÚwintypescGsdS©N©©Ú_rrú>/usr/lib/python3.8/site-packages/pip/_vendor/colorama/win32.pyÚór	cGsdSrrrrrrr	r
)ÚbyrefÚ	StructureÚc_charÚPOINTERc@s>eZdZdZdefdefdejfdejfdefgZdd„Z	d	S)
ÚCONSOLE_SCREEN_BUFFER_INFOzstruct in wincon.h.ÚdwSizeÚdwCursorPositionÚwAttributesÚsrWindowÚdwMaximumWindowSizecCsHd|jj|jj|jj|jj|j|jj|jj|jj|jj	|j
j|j
jfS)Nz"(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d))rÚYÚXrrrÚTopÚLeftZBottomZRightr)ÚselfrrrÚ__str__sûz"CONSOLE_SCREEN_BUFFER_INFO.__str__N)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚCOORDrÚWORDZ
SMALL_RECTZ_fields_rrrrrrsûrcCstƒ}t|t|ƒƒ}t|ƒSr)rÚ_GetConsoleScreenBufferInforÚbool)ÚhandleÚcsbiÚsuccessrrrÚ_winapi_test\sÿr&cCstdd„ttƒttƒfDƒƒS)Ncss|]}t|ƒVqdSr)r&)Ú.0ÚhrrrÚ	cszwinapi_test..)ÚanyÚ
_GetStdHandleÚSTDOUTÚSTDERRrrrrÚwinapi_testbsÿr.cCs t|ƒ}tƒ}t|t|ƒƒ}|Sr)r+rr!r)Ú	stream_idr#r$r%rrrÚGetConsoleScreenBufferInfofsÿr0cCst|ƒ}t||ƒSr)r+Ú_SetConsoleTextAttribute)r/Zattrsr#rrrÚSetConsoleTextAttributemsr2TcCsvt|Ž}|jdks|jdkr dSt|jd|jdƒ}|rdttƒj}|j|j7_|j|j7_t|ƒ}t	||ƒS)Nré)
rrrr0r,rrrr+Ú_SetConsoleCursorPosition)r/ZpositionZadjustZadjusted_positionÚsrr#rrrÚSetConsoleCursorPositionqs
r6cCsBt|ƒ}t| ¡ƒ}t |¡}t d¡}t||||t|ƒƒ}|jS)Nr)r+r
ÚencoderÚDWORDÚ_FillConsoleOutputCharacterArÚvalue)r/ÚcharÚlengthÚstartr#Únum_writtenr%rrrÚFillConsoleOutputCharacterƒs

ÿr?cCs:t|ƒ}t |¡}t |¡}t d¡}t||||t|ƒƒS)za FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )r)r+rr r8Ú_FillConsoleOutputAttributer)r/Úattrr<r=r#Z	attributer>rrrÚFillConsoleOutputAttribute�s


ÿrBcCst|ƒSr)Ú_SetConsoleTitleW)ÚtitlerrrÚSetConsoleTitle—srE)T)*r,r-ZctypesrZWinDLLZwindllrÚAttributeErrorÚImportErrorr2r.rrr
rZ_COORDrrZkernel32ZGetStdHandler+r8ZargtypesZHANDLEZrestyper0r!ZBOOLr1r r6r4ZFillConsoleOutputCharacterAr9rBr@ZSetConsoleTitleWrCZLPCWSTRr&r?rErrrrÚsx
ÿþþþûûÿ


PKÓ¶N]ÎÈݵIsite-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-38.pycnu„[µü¤U

ÀÒ.eÞ(ã@sŠddlZddlZddlZddlmZmZmZmZddlm	Z	m
Z
mZddlm
Z
mZdZe
dk	rfe	ƒZGdd„deƒZGdd	„d	eƒZdS)
éNé)ÚAnsiForeÚAnsiBackÚ	AnsiStyleÚStyle)ÚWinTermÚWinColorÚWinStyle)ÚwindllÚwinapi_testc@sLeZdZdZdd„Zdd„Zdd„Zdd	„Zd
d„Zdd
„Z	e
dd„ƒZdS)Ú
StreamWrapperz´
    Wraps a stream (such as stdout), acting as a transparent proxy for all
    attribute access apart from method 'write()', which is delegated to our
    Converter instance.
    cCs||_||_dS©N)Ú_StreamWrapper__wrappedÚ_StreamWrapper__convertor)ÚselfÚwrappedZ	converter©rúD/usr/lib/python3.8/site-packages/pip/_vendor/colorama/ansitowin32.pyÚ__init__szStreamWrapper.__init__cCst|j|ƒSr
)Úgetattrr)rÚnamerrrÚ__getattr__szStreamWrapper.__getattr__cOs|jj||ŽSr
)rÚ	__enter__©rÚargsÚkwargsrrrrszStreamWrapper.__enter__cOs|jj||ŽSr
)rÚ__exit__rrrrr%szStreamWrapper.__exit__cCs|j |¡dSr
)rÚwrite©rÚtextrrrr(szStreamWrapper.writecCs\|j}dtjkr0|dk	r0|tjks,|tjkr0dSz
|j}Wntk
rPYdSX|ƒSdS)NZPYCHARM_HOSTEDTF)rÚosÚenvironÚsysÚ
__stdout__Ú
__stderr__ÚisattyÚAttributeError)rÚstreamZ
stream_isattyrrrr%+s

zStreamWrapper.isattycCs*|j}z|jWStk
r$YdSXdS©NT)rÚclosedr&)rr'rrrr)7s
zStreamWrapper.closedN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rrrrrr%Úpropertyr)rrrrrsrc@s~eZdZdZe d¡Ze d¡Zddd„Zdd	„Z	d
d„Z
dd
„Zdd„Zdd„Z
dd„Zdd„Zdd„Zdd„Zdd„ZdS)ÚAnsiToWin32z¾
    Implements a 'write()' method which, on Windows, will strip ANSI character
    sequences from the text, and if outputting to a tty, will convert them into
    win32 function calls.
    z?\[((?:\d|;)*)([a-zA-Z])?z?\]((?:.|;)*?)()?NFcCs–||_||_t||ƒ|_tjdk}|o*tƒ}|dkrN|pL|jjoL|j ¡}||_	|dkrt|or|jjor|j ¡}||_
| ¡|_|jt
jk|_dS)NÚnt)rÚ	autoresetrr'r rrr)r%ÚstripÚconvertÚget_win32_callsÚwin32_callsr"ÚstderrÚ	on_stderr)rrr3r2r1Z
on_windowsZconversion_supportedrrrrIs


zAnsiToWin32.__init__cCs|jp|jp|jS)aj
        True if this class is actually needed. If false, then the output
        stream will not be affected, nor will win32 calls be issued, so
        wrapping stdout is not actually required. This will generally be
        False on non-Windows platforms, unless optional functionality like
        autoreset has been requested using kwargs to init()
        )r3r2r1©rrrrÚshould_wrapjszAnsiToWin32.should_wrapcNCs@|j�r:t�r:tjtjftjtjtjftjtjtj	ftj	tjtj	ft
jtjt
jft
jtjt
jft
jtjt
jft
jtjt
jft
jtjt
jft
jtjt
jft
jtjt
jft
jtjt
jft
jtjft
jtjt
jdft
jtjt
jdft
jtjt
jdft
jtjt
jdft
jtjt
jdft
jtjt
jdft
jtjt
jdft
jtjt
jdftjtj t
jftjtj t
jftjtj t
jftjtj t
jftjtj t
jftjtj t
jftjtj t
jftjtj t
jftjtj ftjtj t
jdftjtj t
jdftjtj t
jdftjtj t
jdftjtj t
jdftjtj t
jdftjtj t
jdftjtj t
jdfi&St!ƒSr()"r3ÚwintermrÚ	RESET_ALLÚ	reset_allZBRIGHTZstyler	ZDIMZNORMALrZBLACKZforerZREDZGREENZYELLOWZBLUEZMAGENTAZCYANZWHITEZGREYZRESETZ
LIGHTBLACK_EXZLIGHTRED_EXZ
LIGHTGREEN_EXZLIGHTYELLOW_EXZLIGHTBLUE_EXZLIGHTMAGENTA_EXZLIGHTCYAN_EXZ
LIGHTWHITE_EXrZbackÚdictr8rrrr4tsž


















Ú(zAnsiToWin32.get_win32_callscCs@|js|jr| |¡n|j |¡|j ¡|jr<| ¡dSr
)r2r3Úwrite_and_convertrrÚflushr1r<rrrrr s
zAnsiToWin32.writecCs4|jr| dd¡n|js0|jjs0|j tj¡dS)NÚm©r)	r3Ú
call_win32r2r'r)rrrr;r8rrrr<ªszAnsiToWin32.reset_allcCsbd}| |¡}|j |¡D]0}| ¡\}}| |||¡|j| ¡Ž|}q| ||t|ƒ¡dS)zª
        Write the given text to our wrapped stream, stripping any ANSI
        sequences from the text, and optionally converting them into win32
        calls.
        rN)Úconvert_oscÚANSI_CSI_REÚfinditerÚspanÚwrite_plain_textÚconvert_ansiÚgroupsÚlen)rrZcursorÚmatchÚstartÚendrrrr>±s
zAnsiToWin32.write_and_convertcCs*||kr&|j |||…¡|j ¡dSr
)rrr?)rrrLrMrrrrGÁszAnsiToWin32.write_plain_textcCs"|jr| ||¡}| ||¡dSr
)r3Úextract_paramsrB)rÚparamstringÚcommandÚparamsrrrrHÇszAnsiToWin32.convert_ansicCsz|dkr8tdd„| d¡Dƒƒ}t|ƒdkrv|d}q n>tdd„| d¡Dƒƒ}t|ƒdkrv|d	krjd
}n|dkrvd}|S)NÚHfcss&|]}t|ƒdkrt|ƒndVqdS)rrN©rJÚint©Ú.0ÚprrrÚ	Ïsz-AnsiToWin32.extract_params..ú;é)rcss"|]}t|ƒdkrt|ƒVqdS)rNrSrUrrrrXÔsrZJKmrAÚABCD)ÚtupleÚsplitrJ)rrPrOrQrrrrNÍszAnsiToWin32.extract_paramscCsø|dkrR|D]B}||jkr|j|}|d}|dd…}t|jd�}|||Žqn¢|dkrptj|d|jd�n„|dkrŽtj|d|jd�nf|dkr¨tj||jd�nL|dkrô|d}d|fd|f|df|dfd	œ|\}	}
tj|	|
|jd�dS)
Nr@rr)r7ÚJÚKrRr[)ÚAÚBÚCÚD)r5r=r7r:Zerase_screenZ
erase_lineZset_cursor_positionZ
cursor_adjust)rrPrQZparamZ	func_argsÚfuncrrÚnÚxÚyrrrrBßs$

*zAnsiToWin32.call_win32cCsr|j |¡D]`}| ¡\}}|d|…||d…}| ¡\}}|dkr| d¡}|ddkrt |d¡q|S)NúrYrZ02r)ÚANSI_OSC_RErErFrIr]r:Z	set_title)rrrKrLrMrOrPrQrrrrCõs
zAnsiToWin32.convert_osc)NNF)r*r+r,r-ÚreÚcompilerDrirr9r4rr<r>rGrHrNrBrCrrrrr/@s


!
,
r/)rjr"r Úansirrrrr:rrr	Zwin32r
rÚobjectrr/rrrrÚs0PKÓ¶N])”„„Hsite-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-38.pycnu„[µü¤U

ÀÒ.e{ã@stddlZddlZddlZddlmZdadadadada	dd„Z
ddd	„Zd
d„Zej
dd
„ƒZdd„Zdd„ZdS)éNé)ÚAnsiToWin32FcCstdk	rttƒ ¡dS©N)rÚorig_stdoutÚ	reset_all©rrúC/usr/lib/python3.8/site-packages/pip/_vendor/colorama/initialise.pyrsrTcCsˆ|st|||gƒrtdƒ‚tjatjatjdkr6dantt||||ƒt_atjdkr\da	ntt||||ƒt_a	t
s„t t
¡da
dS)Nz,wrap=False conflicts with any other arg=TrueT)ÚanyÚ
ValueErrorÚsysÚstdoutrÚstderrÚorig_stderrÚwrapped_stdoutÚwrap_streamÚwrapped_stderrÚatexit_doneÚatexitÚregisterr)Ú	autoresetÚconvertÚstripÚwraprrrÚinits
ÿ
ÿ
rcCs tdk	rtt_tdk	rtt_dSr)rrrrr
rrrrÚdeinit3srcos"t||Žz
dVW5tƒXdSr)rr)ÚargsÚkwargsrrrÚ
colorama_text:s

rcCs tdk	rtt_tdk	rtt_dSr)rrrrr
rrrrÚreinitCsrcCs&|r"t||||d�}| ¡r"|j}|S)N)rrr)rZshould_wrapÚstream)rrrrrÚwrapperrrrrJsÿr)FNNT)rÚ
contextlibrZansitowin32rrrrrrrrrÚcontextmanagerrrrrrrrÚs

PKÓ¶N]3´G——Fsite-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-38.pycnu„[µü¤U

ÀÒ.eïã@sDddlmZmZmZmZddlmZmZmZm	Z	ddl
mZdZdS)é)ÚinitÚdeinitÚreinitÚ
colorama_text)ÚForeÚBackÚStyleÚCursor)ÚAnsiToWin32z0.4.1N)
Z
initialiserrrrÚansirrrr	Zansitowin32r
Ú__version__©r
r
úA/usr/lib/python3.8/site-packages/pip/_vendor/colorama/__init__.pyÚsPKÓ¶N]º[pxxBsite-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-38.pycnu„[µü¤U

ÀÒ.eÜ	ã@s dZdZdZdZdd„Zdd„Zdd	d
„Zddd„ZGd
d„deƒZ	Gdd„deƒZ
Gdd„de	ƒZGdd„de	ƒZGdd„de	ƒZ
eƒZeƒZe
ƒZe
ƒZdS)z€
This module generates ANSI character codes to printing colors to terminals.
See: http://en.wikipedia.org/wiki/ANSI_escape_code
z]úcCstt|ƒdS)NÚm©ÚCSIÚstr)Úcode©rú=/usr/lib/python3.8/site-packages/pip/_vendor/colorama/ansi.pyÚ
code_to_charssr	cCstd|tS)Nz2;)ÚOSCÚBEL)ÚtitlerrrÚ	set_titlesr
écCstt|ƒdS)NÚJr©ÚmoderrrÚclear_screensrcCstt|ƒdS)NÚKrrrrrÚ
clear_linesrc@seZdZdd„ZdS)Ú	AnsiCodescCs6t|ƒD](}| d¡st||ƒ}t||t|ƒƒqdS)NÚ_)ÚdirÚ
startswithÚgetattrÚsetattrr	)ÚselfÚnameÚvaluerrrÚ__init__s

zAnsiCodes.__init__N)Ú__name__Ú
__module__Ú__qualname__rrrrrrsrc@s>eZdZd
dd„Zddd„Zddd„Zddd	„Zdd
d„ZdS)Ú
AnsiCursorécCstt|ƒdS)NÚAr©rÚnrrrÚUP%sz
AnsiCursor.UPcCstt|ƒdS)NÚBrr%rrrÚDOWN'szAnsiCursor.DOWNcCstt|ƒdS)NÚCrr%rrrÚFORWARD)szAnsiCursor.FORWARDcCstt|ƒdS)NÚDrr%rrrÚBACK+szAnsiCursor.BACKcCstt|ƒdt|ƒdS)Nú;ÚHr)rÚxÚyrrrÚPOS-szAnsiCursor.POSN)r#)r#)r#)r#)r#r#)rr r!r'r)r+r-r2rrrrr"$s




r"c@sPeZdZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZ
dZd
ZdZdZdZdZdS)ÚAnsiForeééé é!é"é#é$é%é'éZé[é\é]é^é_é`éaN©rr r!ZBLACKZREDZGREENZYELLOWZBLUEZMAGENTAZCYANZWHITEZRESETZ
LIGHTBLACK_EXZLIGHTRED_EXZ
LIGHTGREEN_EXZLIGHTYELLOW_EXZLIGHTBLUE_EXZLIGHTMAGENTA_EXZLIGHTCYAN_EXZ
LIGHTWHITE_EXrrrrr31s"r3c@sPeZdZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZ
dZd
ZdZdZdZdZdS)ÚAnsiBacké(é)é*é+é,é-é.é/é1édéeéfégéhéiéjékNrErrrrrFGs"rFc@seZdZdZdZdZdZdS)Ú	AnsiStyler#rééN)rr r!ZBRIGHTZDIMZNORMALZ	RESET_ALLrrrrrX]srXN)r)r)Ú__doc__rr
rr	r
rrÚobjectrr"r3rFrXZForeZBackZStyleZCursorrrrrÚs 


PKÓ¶N]wGÂ%hhIsite-packages/pip/_vendor/colorama/__pycache__/win32.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eã	@sÂdZdZz.ddlZddlmZeejƒZddlmZWn.eefk
rddZdd„Z	dd„Z
Y�nZXdd	lmZmZm
Z
mZejZGd
d„deƒZejjZejge_eje_ejjZejeeƒge_eje_ejj	Zejejge_eje_ejjZejege_eje_ejj Z!eje
ejeeejƒge!_eje!_ejj"Z#ejejejeeejƒge#_eje#_ejj$Z%ej&ge%_eje%_dd
„Z'dd„Z
efdd„Zdd„Z	ddd„Zdd„Z(dd„Z"dd„Z)dS)iõÿÿÿiôÿÿÿéN)Ú
LibraryLoader)ÚwintypescGsdS©N©©Ú_rrú>/usr/lib/python3.8/site-packages/pip/_vendor/colorama/win32.pyÚór	cGsdSrrrrrrr	r
)ÚbyrefÚ	StructureÚc_charÚPOINTERc@s>eZdZdZdefdefdejfdejfdefgZdd„Z	d	S)
ÚCONSOLE_SCREEN_BUFFER_INFOzstruct in wincon.h.ÚdwSizeÚdwCursorPositionÚwAttributesÚsrWindowÚdwMaximumWindowSizecCsHd|jj|jj|jj|jj|j|jj|jj|jj|jj	|j
j|j
jfS)Nz"(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d))rÚYÚXrrrÚTopÚLeftZBottomZRightr)ÚselfrrrÚ__str__sûz"CONSOLE_SCREEN_BUFFER_INFO.__str__N)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚCOORDrÚWORDZ
SMALL_RECTZ_fields_rrrrrrsûrcCstƒ}t|t|ƒƒ}t|ƒSr)rÚ_GetConsoleScreenBufferInforÚbool)ÚhandleÚcsbiÚsuccessrrrÚ_winapi_test\sÿr&cCstdd„ttƒttƒfDƒƒS)Ncss|]}t|ƒVqdSr)r&)Ú.0ÚhrrrÚ	cszwinapi_test..)ÚanyÚ
_GetStdHandleÚSTDOUTÚSTDERRrrrrÚwinapi_testbsÿr.cCs t|ƒ}tƒ}t|t|ƒƒ}|Sr)r+rr!r)Ú	stream_idr#r$r%rrrÚGetConsoleScreenBufferInfofsÿr0cCst|ƒ}t||ƒSr)r+Ú_SetConsoleTextAttribute)r/Zattrsr#rrrÚSetConsoleTextAttributemsr2TcCsvt|Ž}|jdks|jdkr dSt|jd|jdƒ}|rdttƒj}|j|j7_|j|j7_t|ƒ}t	||ƒS)Nré)
rrrr0r,rrrr+Ú_SetConsoleCursorPosition)r/ZpositionZadjustZadjusted_positionÚsrr#rrrÚSetConsoleCursorPositionqs
r6cCsBt|ƒ}t| ¡ƒ}t |¡}t d¡}t||||t|ƒƒ}|jS)Nr)r+r
ÚencoderÚDWORDÚ_FillConsoleOutputCharacterArÚvalue)r/ÚcharÚlengthÚstartr#Únum_writtenr%rrrÚFillConsoleOutputCharacterƒs

ÿr?cCs:t|ƒ}t |¡}t |¡}t d¡}t||||t|ƒƒS)za FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )r)r+rr r8Ú_FillConsoleOutputAttributer)r/Úattrr<r=r#Z	attributer>rrrÚFillConsoleOutputAttribute�s


ÿrBcCst|ƒSr)Ú_SetConsoleTitleW)ÚtitlerrrÚSetConsoleTitle—srE)T)*r,r-ZctypesrZWinDLLZwindllrÚAttributeErrorÚImportErrorr2r.rrr
rZ_COORDrrZkernel32ZGetStdHandler+r8ZargtypesZHANDLEZrestyper0r!ZBOOLr1r r6r4ZFillConsoleOutputCharacterAr9rBr@ZSetConsoleTitleWrCZLPCWSTRr&r?rErrrrÚsx
ÿþþþûûÿ


PKÓ¶N]oEr{{0site-packages/pip/_vendor/colorama/initialise.pynu„[µü¤# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
import atexit
import contextlib
import sys

from .ansitowin32 import AnsiToWin32


orig_stdout = None
orig_stderr = None

wrapped_stdout = None
wrapped_stderr = None

atexit_done = False


def reset_all():
    if AnsiToWin32 is not None:    # Issue #74: objects might become None at exit
        AnsiToWin32(orig_stdout).reset_all()


def init(autoreset=False, convert=None, strip=None, wrap=True):

    if not wrap and any([autoreset, convert, strip]):
        raise ValueError('wrap=False conflicts with any other arg=True')

    global wrapped_stdout, wrapped_stderr
    global orig_stdout, orig_stderr

    orig_stdout = sys.stdout
    orig_stderr = sys.stderr

    if sys.stdout is None:
        wrapped_stdout = None
    else:
        sys.stdout = wrapped_stdout = \
            wrap_stream(orig_stdout, convert, strip, autoreset, wrap)
    if sys.stderr is None:
        wrapped_stderr = None
    else:
        sys.stderr = wrapped_stderr = \
            wrap_stream(orig_stderr, convert, strip, autoreset, wrap)

    global atexit_done
    if not atexit_done:
        atexit.register(reset_all)
        atexit_done = True


def deinit():
    if orig_stdout is not None:
        sys.stdout = orig_stdout
    if orig_stderr is not None:
        sys.stderr = orig_stderr


@contextlib.contextmanager
def colorama_text(*args, **kwargs):
    init(*args, **kwargs)
    try:
        yield
    finally:
        deinit()


def reinit():
    if wrapped_stdout is not None:
        sys.stdout = wrapped_stdout
    if wrapped_stderr is not None:
        sys.stderr = wrapped_stderr


def wrap_stream(stream, convert, strip, autoreset, wrap):
    if wrap:
        wrapper = AnsiToWin32(stream,
            convert=convert, strip=strip, autoreset=autoreset)
        if wrapper.should_wrap():
            stream = wrapper.stream
    return stream
PKÓ¶N]#ðlsÞ(Þ(1site-packages/pip/_vendor/colorama/ansitowin32.pynu„[µü¤# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
import re
import sys
import os

from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style
from .winterm import WinTerm, WinColor, WinStyle
from .win32 import windll, winapi_test


winterm = None
if windll is not None:
    winterm = WinTerm()


class StreamWrapper(object):
    '''
    Wraps a stream (such as stdout), acting as a transparent proxy for all
    attribute access apart from method 'write()', which is delegated to our
    Converter instance.
    '''
    def __init__(self, wrapped, converter):
        # double-underscore everything to prevent clashes with names of
        # attributes on the wrapped stream object.
        self.__wrapped = wrapped
        self.__convertor = converter

    def __getattr__(self, name):
        return getattr(self.__wrapped, name)

    def __enter__(self, *args, **kwargs):
        # special method lookup bypasses __getattr__/__getattribute__, see
        # https://stackoverflow.com/questions/12632894/why-doesnt-getattr-work-with-exit
        # thus, contextlib magic methods are not proxied via __getattr__
        return self.__wrapped.__enter__(*args, **kwargs)

    def __exit__(self, *args, **kwargs):
        return self.__wrapped.__exit__(*args, **kwargs)

    def write(self, text):
        self.__convertor.write(text)

    def isatty(self):
        stream = self.__wrapped
        if 'PYCHARM_HOSTED' in os.environ:
            if stream is not None and (stream is sys.__stdout__ or stream is sys.__stderr__):
                return True
        try:
            stream_isatty = stream.isatty
        except AttributeError:
            return False
        else:
            return stream_isatty()

    @property
    def closed(self):
        stream = self.__wrapped
        try:
            return stream.closed
        except AttributeError:
            return True


class AnsiToWin32(object):
    '''
    Implements a 'write()' method which, on Windows, will strip ANSI character
    sequences from the text, and if outputting to a tty, will convert them into
    win32 function calls.
    '''
    ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?')   # Control Sequence Introducer
    ANSI_OSC_RE = re.compile('\001?\033\\]((?:.|;)*?)(\x07)\002?')        # Operating System Command

    def __init__(self, wrapped, convert=None, strip=None, autoreset=False):
        # The wrapped stream (normally sys.stdout or sys.stderr)
        self.wrapped = wrapped

        # should we reset colors to defaults after every .write()
        self.autoreset = autoreset

        # create the proxy wrapping our output stream
        self.stream = StreamWrapper(wrapped, self)

        on_windows = os.name == 'nt'
        # We test if the WinAPI works, because even if we are on Windows
        # we may be using a terminal that doesn't support the WinAPI
        # (e.g. Cygwin Terminal). In this case it's up to the terminal
        # to support the ANSI codes.
        conversion_supported = on_windows and winapi_test()

        # should we strip ANSI sequences from our output?
        if strip is None:
            strip = conversion_supported or (not self.stream.closed and not self.stream.isatty())
        self.strip = strip

        # should we should convert ANSI sequences into win32 calls?
        if convert is None:
            convert = conversion_supported and not self.stream.closed and self.stream.isatty()
        self.convert = convert

        # dict of ansi codes to win32 functions and parameters
        self.win32_calls = self.get_win32_calls()

        # are we wrapping stderr?
        self.on_stderr = self.wrapped is sys.stderr

    def should_wrap(self):
        '''
        True if this class is actually needed. If false, then the output
        stream will not be affected, nor will win32 calls be issued, so
        wrapping stdout is not actually required. This will generally be
        False on non-Windows platforms, unless optional functionality like
        autoreset has been requested using kwargs to init()
        '''
        return self.convert or self.strip or self.autoreset

    def get_win32_calls(self):
        if self.convert and winterm:
            return {
                AnsiStyle.RESET_ALL: (winterm.reset_all, ),
                AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT),
                AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL),
                AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL),
                AnsiFore.BLACK: (winterm.fore, WinColor.BLACK),
                AnsiFore.RED: (winterm.fore, WinColor.RED),
                AnsiFore.GREEN: (winterm.fore, WinColor.GREEN),
                AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW),
                AnsiFore.BLUE: (winterm.fore, WinColor.BLUE),
                AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA),
                AnsiFore.CYAN: (winterm.fore, WinColor.CYAN),
                AnsiFore.WHITE: (winterm.fore, WinColor.GREY),
                AnsiFore.RESET: (winterm.fore, ),
                AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True),
                AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True),
                AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True),
                AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True),
                AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True),
                AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True),
                AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True),
                AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True),
                AnsiBack.BLACK: (winterm.back, WinColor.BLACK),
                AnsiBack.RED: (winterm.back, WinColor.RED),
                AnsiBack.GREEN: (winterm.back, WinColor.GREEN),
                AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW),
                AnsiBack.BLUE: (winterm.back, WinColor.BLUE),
                AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA),
                AnsiBack.CYAN: (winterm.back, WinColor.CYAN),
                AnsiBack.WHITE: (winterm.back, WinColor.GREY),
                AnsiBack.RESET: (winterm.back, ),
                AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True),
                AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True),
                AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True),
                AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True),
                AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True),
                AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True),
                AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True),
                AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True),
            }
        return dict()

    def write(self, text):
        if self.strip or self.convert:
            self.write_and_convert(text)
        else:
            self.wrapped.write(text)
            self.wrapped.flush()
        if self.autoreset:
            self.reset_all()


    def reset_all(self):
        if self.convert:
            self.call_win32('m', (0,))
        elif not self.strip and not self.stream.closed:
            self.wrapped.write(Style.RESET_ALL)


    def write_and_convert(self, text):
        '''
        Write the given text to our wrapped stream, stripping any ANSI
        sequences from the text, and optionally converting them into win32
        calls.
        '''
        cursor = 0
        text = self.convert_osc(text)
        for match in self.ANSI_CSI_RE.finditer(text):
            start, end = match.span()
            self.write_plain_text(text, cursor, start)
            self.convert_ansi(*match.groups())
            cursor = end
        self.write_plain_text(text, cursor, len(text))


    def write_plain_text(self, text, start, end):
        if start < end:
            self.wrapped.write(text[start:end])
            self.wrapped.flush()


    def convert_ansi(self, paramstring, command):
        if self.convert:
            params = self.extract_params(command, paramstring)
            self.call_win32(command, params)


    def extract_params(self, command, paramstring):
        if command in 'Hf':
            params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';'))
            while len(params) < 2:
                # defaults:
                params = params + (1,)
        else:
            params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0)
            if len(params) == 0:
                # defaults:
                if command in 'JKm':
                    params = (0,)
                elif command in 'ABCD':
                    params = (1,)

        return params


    def call_win32(self, command, params):
        if command == 'm':
            for param in params:
                if param in self.win32_calls:
                    func_args = self.win32_calls[param]
                    func = func_args[0]
                    args = func_args[1:]
                    kwargs = dict(on_stderr=self.on_stderr)
                    func(*args, **kwargs)
        elif command in 'J':
            winterm.erase_screen(params[0], on_stderr=self.on_stderr)
        elif command in 'K':
            winterm.erase_line(params[0], on_stderr=self.on_stderr)
        elif command in 'Hf':     # cursor position - absolute
            winterm.set_cursor_position(params, on_stderr=self.on_stderr)
        elif command in 'ABCD':   # cursor position - relative
            n = params[0]
            # A - up, B - down, C - forward, D - back
            x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command]
            winterm.cursor_adjust(x, y, on_stderr=self.on_stderr)


    def convert_osc(self, text):
        for match in self.ANSI_OSC_RE.finditer(text):
            start, end = match.span()
            text = text[:start] + text[end:]
            paramstring, command = match.groups()
            if command in '\x07':       # \x07 = BEL
                params = paramstring.split(";")
                # 0 - change title and icon (we will only change title)
                # 1 - change icon (we don't support this)
                # 2 - change title
                if params[0] in '02':
                    winterm.set_title(params[1])
        return text
PKÔ¶N]>§_Ü	Ü	*site-packages/pip/_vendor/colorama/ansi.pynu„[µü¤# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
'''
This module generates ANSI character codes to printing colors to terminals.
See: http://en.wikipedia.org/wiki/ANSI_escape_code
'''

CSI = '\033['
OSC = '\033]'
BEL = '\007'


def code_to_chars(code):
    return CSI + str(code) + 'm'

def set_title(title):
    return OSC + '2;' + title + BEL

def clear_screen(mode=2):
    return CSI + str(mode) + 'J'

def clear_line(mode=2):
    return CSI + str(mode) + 'K'


class AnsiCodes(object):
    def __init__(self):
        # the subclasses declare class attributes which are numbers.
        # Upon instantiation we define instance attributes, which are the same
        # as the class attributes but wrapped with the ANSI escape sequence
        for name in dir(self):
            if not name.startswith('_'):
                value = getattr(self, name)
                setattr(self, name, code_to_chars(value))


class AnsiCursor(object):
    def UP(self, n=1):
        return CSI + str(n) + 'A'
    def DOWN(self, n=1):
        return CSI + str(n) + 'B'
    def FORWARD(self, n=1):
        return CSI + str(n) + 'C'
    def BACK(self, n=1):
        return CSI + str(n) + 'D'
    def POS(self, x=1, y=1):
        return CSI + str(y) + ';' + str(x) + 'H'


class AnsiFore(AnsiCodes):
    BLACK           = 30
    RED             = 31
    GREEN           = 32
    YELLOW          = 33
    BLUE            = 34
    MAGENTA         = 35
    CYAN            = 36
    WHITE           = 37
    RESET           = 39

    # These are fairly well supported, but not part of the standard.
    LIGHTBLACK_EX   = 90
    LIGHTRED_EX     = 91
    LIGHTGREEN_EX   = 92
    LIGHTYELLOW_EX  = 93
    LIGHTBLUE_EX    = 94
    LIGHTMAGENTA_EX = 95
    LIGHTCYAN_EX    = 96
    LIGHTWHITE_EX   = 97


class AnsiBack(AnsiCodes):
    BLACK           = 40
    RED             = 41
    GREEN           = 42
    YELLOW          = 43
    BLUE            = 44
    MAGENTA         = 45
    CYAN            = 46
    WHITE           = 47
    RESET           = 49

    # These are fairly well supported, but not part of the standard.
    LIGHTBLACK_EX   = 100
    LIGHTRED_EX     = 101
    LIGHTGREEN_EX   = 102
    LIGHTYELLOW_EX  = 103
    LIGHTBLUE_EX    = 104
    LIGHTMAGENTA_EX = 105
    LIGHTCYAN_EX    = 106
    LIGHTWHITE_EX   = 107


class AnsiStyle(AnsiCodes):
    BRIGHT    = 1
    DIM       = 2
    NORMAL    = 22
    RESET_ALL = 0

Fore   = AnsiFore()
Back   = AnsiBack()
Style  = AnsiStyle()
Cursor = AnsiCursor()
PKÔ¶N]+site-packages/pip/_vendor/colorama/win32.pynu„[µü¤# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.

# from winbase.h
STDOUT = -11
STDERR = -12

try:
    import ctypes
    from ctypes import LibraryLoader
    windll = LibraryLoader(ctypes.WinDLL)
    from ctypes import wintypes
except (AttributeError, ImportError):
    windll = None
    SetConsoleTextAttribute = lambda *_: None
    winapi_test = lambda *_: None
else:
    from ctypes import byref, Structure, c_char, POINTER

    COORD = wintypes._COORD

    class CONSOLE_SCREEN_BUFFER_INFO(Structure):
        """struct in wincon.h."""
        _fields_ = [
            ("dwSize", COORD),
            ("dwCursorPosition", COORD),
            ("wAttributes", wintypes.WORD),
            ("srWindow", wintypes.SMALL_RECT),
            ("dwMaximumWindowSize", COORD),
        ]
        def __str__(self):
            return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % (
                self.dwSize.Y, self.dwSize.X
                , self.dwCursorPosition.Y, self.dwCursorPosition.X
                , self.wAttributes
                , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right
                , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X
            )

    _GetStdHandle = windll.kernel32.GetStdHandle
    _GetStdHandle.argtypes = [
        wintypes.DWORD,
    ]
    _GetStdHandle.restype = wintypes.HANDLE

    _GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo
    _GetConsoleScreenBufferInfo.argtypes = [
        wintypes.HANDLE,
        POINTER(CONSOLE_SCREEN_BUFFER_INFO),
    ]
    _GetConsoleScreenBufferInfo.restype = wintypes.BOOL

    _SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute
    _SetConsoleTextAttribute.argtypes = [
        wintypes.HANDLE,
        wintypes.WORD,
    ]
    _SetConsoleTextAttribute.restype = wintypes.BOOL

    _SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition
    _SetConsoleCursorPosition.argtypes = [
        wintypes.HANDLE,
        COORD,
    ]
    _SetConsoleCursorPosition.restype = wintypes.BOOL

    _FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA
    _FillConsoleOutputCharacterA.argtypes = [
        wintypes.HANDLE,
        c_char,
        wintypes.DWORD,
        COORD,
        POINTER(wintypes.DWORD),
    ]
    _FillConsoleOutputCharacterA.restype = wintypes.BOOL

    _FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute
    _FillConsoleOutputAttribute.argtypes = [
        wintypes.HANDLE,
        wintypes.WORD,
        wintypes.DWORD,
        COORD,
        POINTER(wintypes.DWORD),
    ]
    _FillConsoleOutputAttribute.restype = wintypes.BOOL

    _SetConsoleTitleW = windll.kernel32.SetConsoleTitleW
    _SetConsoleTitleW.argtypes = [
        wintypes.LPCWSTR
    ]
    _SetConsoleTitleW.restype = wintypes.BOOL

    def _winapi_test(handle):
        csbi = CONSOLE_SCREEN_BUFFER_INFO()
        success = _GetConsoleScreenBufferInfo(
            handle, byref(csbi))
        return bool(success)

    def winapi_test():
        return any(_winapi_test(h) for h in
                   (_GetStdHandle(STDOUT), _GetStdHandle(STDERR)))

    def GetConsoleScreenBufferInfo(stream_id=STDOUT):
        handle = _GetStdHandle(stream_id)
        csbi = CONSOLE_SCREEN_BUFFER_INFO()
        success = _GetConsoleScreenBufferInfo(
            handle, byref(csbi))
        return csbi

    def SetConsoleTextAttribute(stream_id, attrs):
        handle = _GetStdHandle(stream_id)
        return _SetConsoleTextAttribute(handle, attrs)

    def SetConsoleCursorPosition(stream_id, position, adjust=True):
        position = COORD(*position)
        # If the position is out of range, do nothing.
        if position.Y <= 0 or position.X <= 0:
            return
        # Adjust for Windows' SetConsoleCursorPosition:
        #    1. being 0-based, while ANSI is 1-based.
        #    2. expecting (x,y), while ANSI uses (y,x).
        adjusted_position = COORD(position.Y - 1, position.X - 1)
        if adjust:
            # Adjust for viewport's scroll position
            sr = GetConsoleScreenBufferInfo(STDOUT).srWindow
            adjusted_position.Y += sr.Top
            adjusted_position.X += sr.Left
        # Resume normal processing
        handle = _GetStdHandle(stream_id)
        return _SetConsoleCursorPosition(handle, adjusted_position)

    def FillConsoleOutputCharacter(stream_id, char, length, start):
        handle = _GetStdHandle(stream_id)
        char = c_char(char.encode())
        length = wintypes.DWORD(length)
        num_written = wintypes.DWORD(0)
        # Note that this is hard-coded for ANSI (vs wide) bytes.
        success = _FillConsoleOutputCharacterA(
            handle, char, length, start, byref(num_written))
        return num_written.value

    def FillConsoleOutputAttribute(stream_id, attr, length, start):
        ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )'''
        handle = _GetStdHandle(stream_id)
        attribute = wintypes.WORD(attr)
        length = wintypes.DWORD(length)
        num_written = wintypes.DWORD(0)
        # Note that this is hard-coded for ANSI (vs wide) bytes.
        return _FillConsoleOutputAttribute(
            handle, attribute, length, start, byref(num_written))

    def SetConsoleTitle(title):
        return _SetConsoleTitleW(title)
PKÔ¶N]/àݺdd-site-packages/pip/_vendor/progress/spinner.pynu„[µü¤# -*- coding: utf-8 -*-

# Copyright (c) 2012 Giorgos Verigakis 
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

from __future__ import unicode_literals
from . import Infinite


class Spinner(Infinite):
    phases = ('-', '\\', '|', '/')
    hide_cursor = True

    def update(self):
        i = self.index % len(self.phases)
        self.write(self.phases[i])


class PieSpinner(Spinner):
    phases = ['â—·', 'â—¶', 'â—µ', 'â—´']


class MoonSpinner(Spinner):
    phases = ['â—‘', 'â—’', 'â—�', 'â—“']


class LineSpinner(Spinner):
    phases = ['⎺', '⎻', '⎼', '⎽', '⎼', '⎻']


class PixelSpinner(Spinner):
    phases = ['⣾', '⣷', '⣯', '⣟', '⡿', '⢿', '⣻', '⣽']
PKÔ¶N]—̵¸&&)site-packages/pip/_vendor/progress/bar.pynu„[µü¤# -*- coding: utf-8 -*-

# Copyright (c) 2012 Giorgos Verigakis 
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

from __future__ import unicode_literals

import sys

from . import Progress


class Bar(Progress):
    width = 32
    suffix = '%(index)d/%(max)d'
    bar_prefix = ' |'
    bar_suffix = '| '
    empty_fill = ' '
    fill = '#'

    def update(self):
        filled_length = int(self.width * self.progress)
        empty_length = self.width - filled_length

        message = self.message % self
        bar = self.fill * filled_length
        empty = self.empty_fill * empty_length
        suffix = self.suffix % self
        line = ''.join([message, self.bar_prefix, bar, empty, self.bar_suffix,
                        suffix])
        self.writeln(line)


class ChargingBar(Bar):
    suffix = '%(percent)d%%'
    bar_prefix = ' '
    bar_suffix = ' '
    empty_fill = '∙'
    fill = 'â–ˆ'


class FillingSquaresBar(ChargingBar):
    empty_fill = 'â–¢'
    fill = 'â–£'


class FillingCirclesBar(ChargingBar):
    empty_fill = 'â—¯'
    fill = 'â—‰'


class IncrementalBar(Bar):
    if sys.platform.startswith('win'):
        phases = (u' ', u'▌', u'█')
    else:
        phases = (' ', '�', '▎', '�', '▌', '▋', '▊', '▉', '█')

    def update(self):
        nphases = len(self.phases)
        filled_len = self.width * self.progress
        nfull = int(filled_len)                      # Number of full chars
        phase = int((filled_len - nfull) * nphases)  # Phase of last char
        nempty = self.width - nfull                  # Number of empty chars

        message = self.message % self
        bar = self.phases[-1] * nfull
        current = self.phases[phase] if phase > 0 else ''
        empty = self.empty_fill * max(0, nempty - len(current))
        suffix = self.suffix % self
        line = ''.join([message, self.bar_prefix, bar, current, empty,
                        self.bar_suffix, suffix])
        self.writeln(line)


class PixelBar(IncrementalBar):
    phases = ('⡀', '⡄', '⡆', '⡇', '⣇', '⣧', '⣷', '⣿')


class ShadyBar(IncrementalBar):
    phases = (' ', 'â–‘', 'â–’', 'â–“', 'â–ˆ')
PKÔ¶N]BiKùù.site-packages/pip/_vendor/progress/__init__.pynu„[µü¤# Copyright (c) 2012 Giorgos Verigakis 
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

from __future__ import division, print_function

from collections import deque
from datetime import timedelta
from math import ceil
from sys import stderr
try:
    from time import monotonic
except ImportError:
    from time import time as monotonic


__version__ = '1.5'

HIDE_CURSOR = '\x1b[?25l'
SHOW_CURSOR = '\x1b[?25h'


class Infinite(object):
    file = stderr
    sma_window = 10         # Simple Moving Average window
    check_tty = True
    hide_cursor = True

    def __init__(self, message='', **kwargs):
        self.index = 0
        self.start_ts = monotonic()
        self.avg = 0
        self._avg_update_ts = self.start_ts
        self._ts = self.start_ts
        self._xput = deque(maxlen=self.sma_window)
        for key, val in kwargs.items():
            setattr(self, key, val)

        self._width = 0
        self.message = message

        if self.file and self.is_tty():
            if self.hide_cursor:
                print(HIDE_CURSOR, end='', file=self.file)
            print(self.message, end='', file=self.file)
            self.file.flush()

    def __getitem__(self, key):
        if key.startswith('_'):
            return None
        return getattr(self, key, None)

    @property
    def elapsed(self):
        return int(monotonic() - self.start_ts)

    @property
    def elapsed_td(self):
        return timedelta(seconds=self.elapsed)

    def update_avg(self, n, dt):
        if n > 0:
            xput_len = len(self._xput)
            self._xput.append(dt / n)
            now = monotonic()
            # update when we're still filling _xput, then after every second
            if (xput_len < self.sma_window or
                    now - self._avg_update_ts > 1):
                self.avg = sum(self._xput) / len(self._xput)
                self._avg_update_ts = now

    def update(self):
        pass

    def start(self):
        pass

    def clearln(self):
        if self.file and self.is_tty():
            print('\r\x1b[K', end='', file=self.file)

    def write(self, s):
        if self.file and self.is_tty():
            line = self.message + s.ljust(self._width)
            print('\r' + line, end='', file=self.file)
            self._width = max(self._width, len(s))
            self.file.flush()

    def writeln(self, line):
        if self.file and self.is_tty():
            self.clearln()
            print(line, end='', file=self.file)
            self.file.flush()

    def finish(self):
        if self.file and self.is_tty():
            print(file=self.file)
            if self.hide_cursor:
                print(SHOW_CURSOR, end='', file=self.file)

    def is_tty(self):
        return self.file.isatty() if self.check_tty else True

    def next(self, n=1):
        now = monotonic()
        dt = now - self._ts
        self.update_avg(n, dt)
        self._ts = now
        self.index = self.index + n
        self.update()

    def iter(self, it):
        with self:
            for x in it:
                yield x
                self.next()

    def __enter__(self):
        self.start()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.finish()


class Progress(Infinite):
    def __init__(self, *args, **kwargs):
        super(Progress, self).__init__(*args, **kwargs)
        self.max = kwargs.get('max', 100)

    @property
    def eta(self):
        return int(ceil(self.avg * self.remaining))

    @property
    def eta_td(self):
        return timedelta(seconds=self.eta)

    @property
    def percent(self):
        return self.progress * 100

    @property
    def progress(self):
        return min(1, self.index / self.max)

    @property
    def remaining(self):
        return max(self.max - self.index, 0)

    def start(self):
        self.update()

    def goto(self, index):
        incr = index - self.index
        self.next(incr)

    def iter(self, it):
        try:
            self.max = len(it)
        except TypeError:
            pass

        with self:
            for x in it:
                yield x
                self.next()
PKÔ¶N]Xð��Esite-packages/pip/_vendor/progress/__pycache__/counter.cpython-38.pycnu„[µü¤U

ÀÒ.e\ã@s`ddlmZddlmZmZGdd„deƒZGdd„deƒZGdd	„d	eƒZGd
d„deƒZdS)
é)Úunicode_literalsé)ÚInfiniteÚProgressc@seZdZdd„ZdS)ÚCountercCs| t|jƒ¡dS©N)ÚwriteÚstrÚindex©Úself©r
ú@/usr/lib/python3.8/site-packages/pip/_vendor/progress/counter.pyÚupdateszCounter.updateN©Ú__name__Ú
__module__Ú__qualname__rr
r
r
rrsrc@seZdZdd„ZdS)Ú	CountdowncCs| t|jƒ¡dSr)rr	Z	remainingrr
r
rrszCountdown.updateNrr
r
r
rrsrc@seZdZdZdd„ZdS)ÚStack)	ú uâ–�uâ–‚uâ–ƒuâ–„uâ–…uâ–†uâ–‡uâ–ˆcCs6t|jƒ}t|dt|j|ƒƒ}| |j|¡dS)Nr)ÚlenÚphasesÚminÚintZprogressr)rZnphasesÚir
r
rr"s
zStack.updateN)rrrrrr
r
r
rrsrc@seZdZdZdS)ÚPie)uâ—‹uâ—”uâ—‘uâ—•uâ—�N)rrrrr
r
r
rr(srN)	Z
__future__rÚrrrrrrr
r
r
rÚs
	PKÔ¶N]	Á ÍÍLsite-packages/pip/_vendor/progress/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eùã@s¢ddlmZmZddlmZddlmZddlmZddl	m
Z
zddlmZWn e
k
rpddlmZYnXdZd	Zd
ZGdd„deƒZGd
d„deƒZdS)é)ÚdivisionÚprint_function)Údeque)Ú	timedelta)Úceil)Ústderr)Ú	monotonic)Útimez1.5z[?25lz[?25hc@s¨eZdZeZdZdZdZd&dd„Zdd„Z	e
dd	„ƒZe
d
d„ƒZdd
„Z
dd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zd'dd„Zdd „Zd!d"„Zd#d$„Zd%S)(ÚInfiniteé
TÚcKs d|_tƒ|_d|_|j|_|j|_t|jd�|_| 	¡D]\}}t
|||ƒq:d|_||_|j
rœ| ¡rœ|jr€ttd|j
d�t|jd|j
d�|j
 ¡dS)Nr)Úmaxlenr©ÚendÚfile)ÚindexrÚstart_tsÚavgÚ_avg_update_tsÚ_tsrÚ
sma_windowÚ_xputÚitemsÚsetattrÚ_widthÚmessagerÚis_ttyÚhide_cursorÚprintÚHIDE_CURSORÚflush)ÚselfrÚkwargsÚkeyÚval©r%úA/usr/lib/python3.8/site-packages/pip/_vendor/progress/__init__.pyÚ__init__'szInfinite.__init__cCs| d¡rdSt||dƒS)NÚ_)Ú
startswithÚgetattr)r!r#r%r%r&Ú__getitem__:s
zInfinite.__getitem__cCsttƒ|jƒS©N)Úintrr©r!r%r%r&Úelapsed?szInfinite.elapsedcCst|jd�S©N)Zseconds)rr/r.r%r%r&Ú
elapsed_tdCszInfinite.elapsed_tdcCs`|dkr\t|jƒ}|j ||¡tƒ}||jks@||jdkr\t|jƒt|jƒ|_||_dS)Nré)ÚlenrÚappendrrrÚsumr)r!ÚnÚdtZxput_lenÚnowr%r%r&Ú
update_avgGs

ÿzInfinite.update_avgcCsdSr,r%r.r%r%r&ÚupdateRszInfinite.updatecCsdSr,r%r.r%r%r&ÚstartUszInfinite.startcCs"|jr| ¡rtdd|jd�dS)Nz
rr)rrrr.r%r%r&ÚclearlnXszInfinite.clearlncCsT|jrP| ¡rP|j| |j¡}td|d|jd�t|jt|ƒƒ|_|j ¡dS)Nú
rr)	rrrÚljustrrÚmaxr3r )r!ÚsÚliner%r%r&Úwrite\s
zInfinite.writecCs4|jr0| ¡r0| ¡t|d|jd�|j ¡dS)Nrr)rrr<rr )r!rAr%r%r&ÚwritelncszInfinite.writelncCs4|jr0| ¡r0t|jd�|jr0ttd|jd�dS)N)rrr)rrrrÚSHOW_CURSORr.r%r%r&ÚfinishiszInfinite.finishcCs|jr|j ¡SdS)NT)Ú	check_ttyrÚisattyr.r%r%r&roszInfinite.is_ttyr2cCs:tƒ}||j}| ||¡||_|j||_| ¡dSr,)rrr9rr:)r!r6r8r7r%r%r&Únextrs
z
Infinite.nextc	cs,|�|D]}|V| ¡q
W5QRXdSr,)rH©r!ÚitÚxr%r%r&Úiterzsz
Infinite.itercCs| ¡|Sr,)r;r.r%r%r&Ú	__enter__€szInfinite.__enter__cCs| ¡dSr,)rE)r!Úexc_typeZexc_valZexc_tbr%r%r&Ú__exit__„szInfinite.__exit__N)r)r2)Ú__name__Ú
__module__Ú__qualname__rrrrFrr'r+Úpropertyr/r1r9r:r;r<rBrCrErrHrLrMrOr%r%r%r&r
!s,



r
cspeZdZ‡fdd„Zedd„ƒZedd„ƒZedd„ƒZed	d
„ƒZedd„ƒZ	d
d„Z
dd„Zdd„Z‡Z
S)ÚProgresscs$tt|ƒj||Ž| dd¡|_dS)Nr?éd)ÚsuperrTr'Úgetr?)r!Úargsr"©Ú	__class__r%r&r'‰szProgress.__init__cCstt|j|jƒƒSr,)r-rrÚ	remainingr.r%r%r&Úeta�szProgress.etacCst|jd�Sr0)rr\r.r%r%r&Úeta_td‘szProgress.eta_tdcCs
|jdS)NrU)Úprogressr.r%r%r&Úpercent•szProgress.percentcCstd|j|jƒS)Nr2)Úminrr?r.r%r%r&r^™szProgress.progresscCst|j|jdƒS)Nr)r?rr.r%r%r&r[�szProgress.remainingcCs| ¡dSr,)r:r.r%r%r&r;¡szProgress.startcCs||j}| |¡dSr,)rrH)r!rZincrr%r%r&Úgoto¤s
z
Progress.gotoc	csPzt|ƒ|_Wntk
r"YnX|�|D]}|V| ¡q.W5QRXdSr,)r3r?Ú	TypeErrorrHrIr%r%r&rL¨sz
Progress.iter)rPrQrRr'rSr\r]r_r^r[r;rarLÚ
__classcell__r%r%rYr&rTˆs




rTN)Z
__future__rrÚcollectionsrZdatetimerZmathrÚsysrr	rÚImportErrorÚ__version__rrDÚobjectr
rTr%r%r%r&ÚsgPKÔ¶N]ûBTTKsite-packages/pip/_vendor/progress/__pycache__/spinner.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.edã@slddlmZddlmZGdd„deƒZGdd„deƒZGdd	„d	eƒZGd
d„deƒZGdd
„d
eƒZdS)é)Úunicode_literalsé)ÚInfinitec@seZdZdZdZdd„ZdS)ÚSpinner)ú-ú\ú|ú/TcCs$|jt|jƒ}| |j|¡dS)N)ÚindexÚlenÚphasesÚwrite)ÚselfÚi©rú@/usr/lib/python3.8/site-packages/pip/_vendor/progress/spinner.pyÚupdateszSpinner.updateN)Ú__name__Ú
__module__Ú__qualname__rZhide_cursorrrrrrrsrc@seZdZddddgZdS)Ú
PieSpinneruâ—·uâ—¶uâ—µuâ—´N©rrrrrrrrrsrc@seZdZddddgZdS)ÚMoonSpinneruâ—‘uâ—’uâ—�uâ—“Nrrrrrr"src@seZdZddddddgZdS)ÚLineSpinneru⎺u⎻u⎼u⎽Nrrrrrr&src@s eZdZddddddddgZd	S)
ÚPixelSpinneru⣾u⣷u⣯u⣟uâ¡¿u⢿u⣻u⣽Nrrrrrr*srN)	Z
__future__rÚrrrrrrrrrrÚs	PKÔ¶N]Xð��Ksite-packages/pip/_vendor/progress/__pycache__/counter.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.e\ã@s`ddlmZddlmZmZGdd„deƒZGdd„deƒZGdd	„d	eƒZGd
d„deƒZdS)
é)Úunicode_literalsé)ÚInfiniteÚProgressc@seZdZdd„ZdS)ÚCountercCs| t|jƒ¡dS©N)ÚwriteÚstrÚindex©Úself©r
ú@/usr/lib/python3.8/site-packages/pip/_vendor/progress/counter.pyÚupdateszCounter.updateN©Ú__name__Ú
__module__Ú__qualname__rr
r
r
rrsrc@seZdZdd„ZdS)Ú	CountdowncCs| t|jƒ¡dSr)rr	Z	remainingrr
r
rrszCountdown.updateNrr
r
r
rrsrc@seZdZdZdd„ZdS)ÚStack)	ú uâ–�uâ–‚uâ–ƒuâ–„uâ–…uâ–†uâ–‡uâ–ˆcCs6t|jƒ}t|dt|j|ƒƒ}| |j|¡dS)Nr)ÚlenÚphasesÚminÚintZprogressr)rZnphasesÚir
r
rr"s
zStack.updateN)rrrrrr
r
r
rrsrc@seZdZdZdS)ÚPie)uâ—‹uâ—”uâ—‘uâ—•uâ—�N)rrrrr
r
r
rr(srN)	Z
__future__rÚrrrrrrr
r
r
rÚs
	PKÔ¶N]ûBTTEsite-packages/pip/_vendor/progress/__pycache__/spinner.cpython-38.pycnu„[µü¤U

ÀÒ.edã@slddlmZddlmZGdd„deƒZGdd„deƒZGdd	„d	eƒZGd
d„deƒZGdd
„d
eƒZdS)é)Úunicode_literalsé)ÚInfinitec@seZdZdZdZdd„ZdS)ÚSpinner)ú-ú\ú|ú/TcCs$|jt|jƒ}| |j|¡dS)N)ÚindexÚlenÚphasesÚwrite)ÚselfÚi©rú@/usr/lib/python3.8/site-packages/pip/_vendor/progress/spinner.pyÚupdateszSpinner.updateN)Ú__name__Ú
__module__Ú__qualname__rZhide_cursorrrrrrrsrc@seZdZddddgZdS)Ú
PieSpinneruâ—·uâ—¶uâ—µuâ—´N©rrrrrrrrrsrc@seZdZddddgZdS)ÚMoonSpinneruâ—‘uâ—’uâ—�uâ—“Nrrrrrr"src@seZdZddddddgZdS)ÚLineSpinneru⎺u⎻u⎼u⎽Nrrrrrr&src@s eZdZddddddddgZd	S)
ÚPixelSpinneru⣾u⣷u⣯u⣟uâ¡¿u⢿u⣻u⣽Nrrrrrr*srN)	Z
__future__rÚrrrrrrrrrrÚs	PKÔ¶N]	Á ÍÍFsite-packages/pip/_vendor/progress/__pycache__/__init__.cpython-38.pycnu„[µü¤U

ÀÒ.eùã@s¢ddlmZmZddlmZddlmZddlmZddl	m
Z
zddlmZWn e
k
rpddlmZYnXdZd	Zd
ZGdd„deƒZGd
d„deƒZdS)é)ÚdivisionÚprint_function)Údeque)Ú	timedelta)Úceil)Ústderr)Ú	monotonic)Útimez1.5z[?25lz[?25hc@s¨eZdZeZdZdZdZd&dd„Zdd„Z	e
dd	„ƒZe
d
d„ƒZdd
„Z
dd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zd'dd„Zdd „Zd!d"„Zd#d$„Zd%S)(ÚInfiniteé
TÚcKs d|_tƒ|_d|_|j|_|j|_t|jd�|_| 	¡D]\}}t
|||ƒq:d|_||_|j
rœ| ¡rœ|jr€ttd|j
d�t|jd|j
d�|j
 ¡dS)Nr)Úmaxlenr©ÚendÚfile)ÚindexrÚstart_tsÚavgÚ_avg_update_tsÚ_tsrÚ
sma_windowÚ_xputÚitemsÚsetattrÚ_widthÚmessagerÚis_ttyÚhide_cursorÚprintÚHIDE_CURSORÚflush)ÚselfrÚkwargsÚkeyÚval©r%úA/usr/lib/python3.8/site-packages/pip/_vendor/progress/__init__.pyÚ__init__'szInfinite.__init__cCs| d¡rdSt||dƒS)NÚ_)Ú
startswithÚgetattr)r!r#r%r%r&Ú__getitem__:s
zInfinite.__getitem__cCsttƒ|jƒS©N)Úintrr©r!r%r%r&Úelapsed?szInfinite.elapsedcCst|jd�S©N)Zseconds)rr/r.r%r%r&Ú
elapsed_tdCszInfinite.elapsed_tdcCs`|dkr\t|jƒ}|j ||¡tƒ}||jks@||jdkr\t|jƒt|jƒ|_||_dS)Nré)ÚlenrÚappendrrrÚsumr)r!ÚnÚdtZxput_lenÚnowr%r%r&Ú
update_avgGs

ÿzInfinite.update_avgcCsdSr,r%r.r%r%r&ÚupdateRszInfinite.updatecCsdSr,r%r.r%r%r&ÚstartUszInfinite.startcCs"|jr| ¡rtdd|jd�dS)Nz
rr)rrrr.r%r%r&ÚclearlnXszInfinite.clearlncCsT|jrP| ¡rP|j| |j¡}td|d|jd�t|jt|ƒƒ|_|j ¡dS)Nú
rr)	rrrÚljustrrÚmaxr3r )r!ÚsÚliner%r%r&Úwrite\s
zInfinite.writecCs4|jr0| ¡r0| ¡t|d|jd�|j ¡dS)Nrr)rrr<rr )r!rAr%r%r&ÚwritelncszInfinite.writelncCs4|jr0| ¡r0t|jd�|jr0ttd|jd�dS)N)rrr)rrrrÚSHOW_CURSORr.r%r%r&ÚfinishiszInfinite.finishcCs|jr|j ¡SdS)NT)Ú	check_ttyrÚisattyr.r%r%r&roszInfinite.is_ttyr2cCs:tƒ}||j}| ||¡||_|j||_| ¡dSr,)rrr9rr:)r!r6r8r7r%r%r&Únextrs
z
Infinite.nextc	cs,|�|D]}|V| ¡q
W5QRXdSr,)rH©r!ÚitÚxr%r%r&Úiterzsz
Infinite.itercCs| ¡|Sr,)r;r.r%r%r&Ú	__enter__€szInfinite.__enter__cCs| ¡dSr,)rE)r!Úexc_typeZexc_valZexc_tbr%r%r&Ú__exit__„szInfinite.__exit__N)r)r2)Ú__name__Ú
__module__Ú__qualname__rrrrFrr'r+Úpropertyr/r1r9r:r;r<rBrCrErrHrLrMrOr%r%r%r&r
!s,



r
cspeZdZ‡fdd„Zedd„ƒZedd„ƒZedd„ƒZed	d
„ƒZedd„ƒZ	d
d„Z
dd„Zdd„Z‡Z
S)ÚProgresscs$tt|ƒj||Ž| dd¡|_dS)Nr?éd)ÚsuperrTr'Úgetr?)r!Úargsr"©Ú	__class__r%r&r'‰szProgress.__init__cCstt|j|jƒƒSr,)r-rrÚ	remainingr.r%r%r&Úeta�szProgress.etacCst|jd�Sr0)rr\r.r%r%r&Úeta_td‘szProgress.eta_tdcCs
|jdS)NrU)Úprogressr.r%r%r&Úpercent•szProgress.percentcCstd|j|jƒS)Nr2)Úminrr?r.r%r%r&r^™szProgress.progresscCst|j|jdƒS)Nr)r?rr.r%r%r&r[�szProgress.remainingcCs| ¡dSr,)r:r.r%r%r&r;¡szProgress.startcCs||j}| |¡dSr,)rrH)r!rZincrr%r%r&Úgoto¤s
z
Progress.gotoc	csPzt|ƒ|_Wntk
r"YnX|�|D]}|V| ¡q.W5QRXdSr,)r3r?Ú	TypeErrorrHrIr%r%r&rL¨sz
Progress.iter)rPrQrRr'rSr\r]r_r^r[r;rarLÚ
__classcell__r%r%rYr&rTˆs




rTN)Z
__future__rrÚcollectionsrZdatetimerZmathrÚsysrr	rÚImportErrorÚ__version__rrDÚobjectr
rTr%r%r%r&ÚsgPKÔ¶N]üîá-
-
Asite-packages/pip/_vendor/progress/__pycache__/bar.cpython-38.pycnu„[µü¤U

ÀÒ.e&ã@s”ddlmZddlZddlmZGdd„deƒZGdd„deƒZGd	d
„d
eƒZGdd„deƒZGd
d„deƒZ	Gdd„de	ƒZ
Gdd„de	ƒZdS)é)Úunicode_literalsNé)ÚProgressc@s,eZdZdZdZdZdZdZdZdd„Z	d	S)
ÚBaré z%(index)d/%(max)dz |z| ú ú#cCsjt|j|jƒ}|j|}|j|}|j|}|j|}|j|}d ||j|||j	|g¡}| 
|¡dS)NÚ)ÚintÚwidthÚprogressÚmessageÚfillÚ
empty_fillÚsuffixÚjoinÚ
bar_prefixÚ
bar_suffixÚwriteln)ÚselfZ
filled_lengthZempty_lengthr
ÚbarÚemptyrÚline©rúsPKÔ¶N]üîá-
-
Gsite-packages/pip/_vendor/progress/__pycache__/bar.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.e&ã@s”ddlmZddlZddlmZGdd„deƒZGdd„deƒZGd	d
„d
eƒZGdd„deƒZGd
d„deƒZ	Gdd„de	ƒZ
Gdd„de	ƒZdS)é)Úunicode_literalsNé)ÚProgressc@s,eZdZdZdZdZdZdZdZdd„Z	d	S)
ÚBaré z%(index)d/%(max)dz |z| ú ú#cCsjt|j|jƒ}|j|}|j|}|j|}|j|}|j|}d ||j|||j	|g¡}| 
|¡dS)NÚ)ÚintÚwidthÚprogressÚmessageÚfillÚ
empty_fillÚsuffixÚjoinÚ
bar_prefixÚ
bar_suffixÚwriteln)ÚselfZ
filled_lengthZempty_lengthr
ÚbarÚemptyrÚline©rúsPKÔ¶N]xà¹�\\-site-packages/pip/_vendor/progress/counter.pynu„[µü¤# -*- coding: utf-8 -*-

# Copyright (c) 2012 Giorgos Verigakis 
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

from __future__ import unicode_literals
from . import Infinite, Progress


class Counter(Infinite):
    def update(self):
        self.write(str(self.index))


class Countdown(Progress):
    def update(self):
        self.write(str(self.remaining))


class Stack(Progress):
    phases = (' ', 'â–�', 'â–‚', 'â–ƒ', 'â–„', 'â–…', 'â–†', 'â–‡', 'â–ˆ')

    def update(self):
        nphases = len(self.phases)
        i = min(nphases - 1, int(self.progress * nphases))
        self.write(self.phases[i])


class Pie(Stack):
    phases = ('â—‹', 'â—”', 'â—‘', 'â—•', 'â—�')
PKÔ¶N]h¿\ÑÄ~Ä~ site-packages/pip/_vendor/six.pynu„[µü¤# Copyright (c) 2010-2018 Benjamin Peterson
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

"""Utilities for writing code that runs on Python 2 and 3"""

from __future__ import absolute_import

import functools
import itertools
import operator
import sys
import types

__author__ = "Benjamin Peterson "
__version__ = "1.12.0"


# Useful for very coarse version differentiation.
PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3
PY34 = sys.version_info[0:2] >= (3, 4)

if PY3:
    string_types = str,
    integer_types = int,
    class_types = type,
    text_type = str
    binary_type = bytes

    MAXSIZE = sys.maxsize
else:
    string_types = basestring,
    integer_types = (int, long)
    class_types = (type, types.ClassType)
    text_type = unicode
    binary_type = str

    if sys.platform.startswith("java"):
        # Jython always uses 32 bits.
        MAXSIZE = int((1 << 31) - 1)
    else:
        # It's possible to have sizeof(long) != sizeof(Py_ssize_t).
        class X(object):

            def __len__(self):
                return 1 << 31
        try:
            len(X())
        except OverflowError:
            # 32-bit
            MAXSIZE = int((1 << 31) - 1)
        else:
            # 64-bit
            MAXSIZE = int((1 << 63) - 1)
        del X


def _add_doc(func, doc):
    """Add documentation to a function."""
    func.__doc__ = doc


def _import_module(name):
    """Import module, returning the module after the last dot."""
    __import__(name)
    return sys.modules[name]


class _LazyDescr(object):

    def __init__(self, name):
        self.name = name

    def __get__(self, obj, tp):
        result = self._resolve()
        setattr(obj, self.name, result)  # Invokes __set__.
        try:
            # This is a bit ugly, but it avoids running this again by
            # removing this descriptor.
            delattr(obj.__class__, self.name)
        except AttributeError:
            pass
        return result


class MovedModule(_LazyDescr):

    def __init__(self, name, old, new=None):
        super(MovedModule, self).__init__(name)
        if PY3:
            if new is None:
                new = name
            self.mod = new
        else:
            self.mod = old

    def _resolve(self):
        return _import_module(self.mod)

    def __getattr__(self, attr):
        _module = self._resolve()
        value = getattr(_module, attr)
        setattr(self, attr, value)
        return value


class _LazyModule(types.ModuleType):

    def __init__(self, name):
        super(_LazyModule, self).__init__(name)
        self.__doc__ = self.__class__.__doc__

    def __dir__(self):
        attrs = ["__doc__", "__name__"]
        attrs += [attr.name for attr in self._moved_attributes]
        return attrs

    # Subclasses should override this
    _moved_attributes = []


class MovedAttribute(_LazyDescr):

    def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
        super(MovedAttribute, self).__init__(name)
        if PY3:
            if new_mod is None:
                new_mod = name
            self.mod = new_mod
            if new_attr is None:
                if old_attr is None:
                    new_attr = name
                else:
                    new_attr = old_attr
            self.attr = new_attr
        else:
            self.mod = old_mod
            if old_attr is None:
                old_attr = name
            self.attr = old_attr

    def _resolve(self):
        module = _import_module(self.mod)
        return getattr(module, self.attr)


class _SixMetaPathImporter(object):

    """
    A meta path importer to import six.moves and its submodules.

    This class implements a PEP302 finder and loader. It should be compatible
    with Python 2.5 and all existing versions of Python3
    """

    def __init__(self, six_module_name):
        self.name = six_module_name
        self.known_modules = {}

    def _add_module(self, mod, *fullnames):
        for fullname in fullnames:
            self.known_modules[self.name + "." + fullname] = mod

    def _get_module(self, fullname):
        return self.known_modules[self.name + "." + fullname]

    def find_module(self, fullname, path=None):
        if fullname in self.known_modules:
            return self
        return None

    def __get_module(self, fullname):
        try:
            return self.known_modules[fullname]
        except KeyError:
            raise ImportError("This loader does not know module " + fullname)

    def load_module(self, fullname):
        try:
            # in case of a reload
            return sys.modules[fullname]
        except KeyError:
            pass
        mod = self.__get_module(fullname)
        if isinstance(mod, MovedModule):
            mod = mod._resolve()
        else:
            mod.__loader__ = self
        sys.modules[fullname] = mod
        return mod

    def is_package(self, fullname):
        """
        Return true, if the named module is a package.

        We need this method to get correct spec objects with
        Python 3.4 (see PEP451)
        """
        return hasattr(self.__get_module(fullname), "__path__")

    def get_code(self, fullname):
        """Return None

        Required, if is_package is implemented"""
        self.__get_module(fullname)  # eventually raises ImportError
        return None
    get_source = get_code  # same as get_code

_importer = _SixMetaPathImporter(__name__)


class _MovedItems(_LazyModule):

    """Lazy loading of moved objects"""
    __path__ = []  # mark as package


_moved_attributes = [
    MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
    MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
    MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"),
    MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
    MovedAttribute("intern", "__builtin__", "sys"),
    MovedAttribute("map", "itertools", "builtins", "imap", "map"),
    MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"),
    MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"),
    MovedAttribute("getoutput", "commands", "subprocess"),
    MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
    MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"),
    MovedAttribute("reduce", "__builtin__", "functools"),
    MovedAttribute("shlex_quote", "pipes", "shlex", "quote"),
    MovedAttribute("StringIO", "StringIO", "io"),
    MovedAttribute("UserDict", "UserDict", "collections"),
    MovedAttribute("UserList", "UserList", "collections"),
    MovedAttribute("UserString", "UserString", "collections"),
    MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
    MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
    MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"),
    MovedModule("builtins", "__builtin__"),
    MovedModule("configparser", "ConfigParser"),
    MovedModule("copyreg", "copy_reg"),
    MovedModule("dbm_gnu", "gdbm", "dbm.gnu"),
    MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"),
    MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
    MovedModule("http_cookies", "Cookie", "http.cookies"),
    MovedModule("html_entities", "htmlentitydefs", "html.entities"),
    MovedModule("html_parser", "HTMLParser", "html.parser"),
    MovedModule("http_client", "httplib", "http.client"),
    MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
    MovedModule("email_mime_image", "email.MIMEImage", "email.mime.image"),
    MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
    MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"),
    MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
    MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
    MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
    MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
    MovedModule("cPickle", "cPickle", "pickle"),
    MovedModule("queue", "Queue"),
    MovedModule("reprlib", "repr"),
    MovedModule("socketserver", "SocketServer"),
    MovedModule("_thread", "thread", "_thread"),
    MovedModule("tkinter", "Tkinter"),
    MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
    MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
    MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
    MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
    MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
    MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"),
    MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
    MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
    MovedModule("tkinter_colorchooser", "tkColorChooser",
                "tkinter.colorchooser"),
    MovedModule("tkinter_commondialog", "tkCommonDialog",
                "tkinter.commondialog"),
    MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
    MovedModule("tkinter_font", "tkFont", "tkinter.font"),
    MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
    MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
                "tkinter.simpledialog"),
    MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
    MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
    MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
    MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
    MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"),
    MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"),
]
# Add windows specific modules.
if sys.platform == "win32":
    _moved_attributes += [
        MovedModule("winreg", "_winreg"),
    ]

for attr in _moved_attributes:
    setattr(_MovedItems, attr.name, attr)
    if isinstance(attr, MovedModule):
        _importer._add_module(attr, "moves." + attr.name)
del attr

_MovedItems._moved_attributes = _moved_attributes

moves = _MovedItems(__name__ + ".moves")
_importer._add_module(moves, "moves")


class Module_six_moves_urllib_parse(_LazyModule):

    """Lazy loading of moved objects in six.moves.urllib_parse"""


_urllib_parse_moved_attributes = [
    MovedAttribute("ParseResult", "urlparse", "urllib.parse"),
    MovedAttribute("SplitResult", "urlparse", "urllib.parse"),
    MovedAttribute("parse_qs", "urlparse", "urllib.parse"),
    MovedAttribute("parse_qsl", "urlparse", "urllib.parse"),
    MovedAttribute("urldefrag", "urlparse", "urllib.parse"),
    MovedAttribute("urljoin", "urlparse", "urllib.parse"),
    MovedAttribute("urlparse", "urlparse", "urllib.parse"),
    MovedAttribute("urlsplit", "urlparse", "urllib.parse"),
    MovedAttribute("urlunparse", "urlparse", "urllib.parse"),
    MovedAttribute("urlunsplit", "urlparse", "urllib.parse"),
    MovedAttribute("quote", "urllib", "urllib.parse"),
    MovedAttribute("quote_plus", "urllib", "urllib.parse"),
    MovedAttribute("unquote", "urllib", "urllib.parse"),
    MovedAttribute("unquote_plus", "urllib", "urllib.parse"),
    MovedAttribute("unquote_to_bytes", "urllib", "urllib.parse", "unquote", "unquote_to_bytes"),
    MovedAttribute("urlencode", "urllib", "urllib.parse"),
    MovedAttribute("splitquery", "urllib", "urllib.parse"),
    MovedAttribute("splittag", "urllib", "urllib.parse"),
    MovedAttribute("splituser", "urllib", "urllib.parse"),
    MovedAttribute("splitvalue", "urllib", "urllib.parse"),
    MovedAttribute("uses_fragment", "urlparse", "urllib.parse"),
    MovedAttribute("uses_netloc", "urlparse", "urllib.parse"),
    MovedAttribute("uses_params", "urlparse", "urllib.parse"),
    MovedAttribute("uses_query", "urlparse", "urllib.parse"),
    MovedAttribute("uses_relative", "urlparse", "urllib.parse"),
]
for attr in _urllib_parse_moved_attributes:
    setattr(Module_six_moves_urllib_parse, attr.name, attr)
del attr

Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes

_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"),
                      "moves.urllib_parse", "moves.urllib.parse")


class Module_six_moves_urllib_error(_LazyModule):

    """Lazy loading of moved objects in six.moves.urllib_error"""


_urllib_error_moved_attributes = [
    MovedAttribute("URLError", "urllib2", "urllib.error"),
    MovedAttribute("HTTPError", "urllib2", "urllib.error"),
    MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
]
for attr in _urllib_error_moved_attributes:
    setattr(Module_six_moves_urllib_error, attr.name, attr)
del attr

Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes

_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"),
                      "moves.urllib_error", "moves.urllib.error")


class Module_six_moves_urllib_request(_LazyModule):

    """Lazy loading of moved objects in six.moves.urllib_request"""


_urllib_request_moved_attributes = [
    MovedAttribute("urlopen", "urllib2", "urllib.request"),
    MovedAttribute("install_opener", "urllib2", "urllib.request"),
    MovedAttribute("build_opener", "urllib2", "urllib.request"),
    MovedAttribute("pathname2url", "urllib", "urllib.request"),
    MovedAttribute("url2pathname", "urllib", "urllib.request"),
    MovedAttribute("getproxies", "urllib", "urllib.request"),
    MovedAttribute("Request", "urllib2", "urllib.request"),
    MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
    MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
    MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
    MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
    MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
    MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
    MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
    MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
    MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
    MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
    MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
    MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
    MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
    MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
    MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
    MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
    MovedAttribute("FileHandler", "urllib2", "urllib.request"),
    MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
    MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
    MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
    MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
    MovedAttribute("urlretrieve", "urllib", "urllib.request"),
    MovedAttribute("urlcleanup", "urllib", "urllib.request"),
    MovedAttribute("URLopener", "urllib", "urllib.request"),
    MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
    MovedAttribute("proxy_bypass", "urllib", "urllib.request"),
    MovedAttribute("parse_http_list", "urllib2", "urllib.request"),
    MovedAttribute("parse_keqv_list", "urllib2", "urllib.request"),
]
for attr in _urllib_request_moved_attributes:
    setattr(Module_six_moves_urllib_request, attr.name, attr)
del attr

Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes

_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"),
                      "moves.urllib_request", "moves.urllib.request")


class Module_six_moves_urllib_response(_LazyModule):

    """Lazy loading of moved objects in six.moves.urllib_response"""


_urllib_response_moved_attributes = [
    MovedAttribute("addbase", "urllib", "urllib.response"),
    MovedAttribute("addclosehook", "urllib", "urllib.response"),
    MovedAttribute("addinfo", "urllib", "urllib.response"),
    MovedAttribute("addinfourl", "urllib", "urllib.response"),
]
for attr in _urllib_response_moved_attributes:
    setattr(Module_six_moves_urllib_response, attr.name, attr)
del attr

Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes

_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"),
                      "moves.urllib_response", "moves.urllib.response")


class Module_six_moves_urllib_robotparser(_LazyModule):

    """Lazy loading of moved objects in six.moves.urllib_robotparser"""


_urllib_robotparser_moved_attributes = [
    MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
]
for attr in _urllib_robotparser_moved_attributes:
    setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
del attr

Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes

_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"),
                      "moves.urllib_robotparser", "moves.urllib.robotparser")


class Module_six_moves_urllib(types.ModuleType):

    """Create a six.moves.urllib namespace that resembles the Python 3 namespace"""
    __path__ = []  # mark as package
    parse = _importer._get_module("moves.urllib_parse")
    error = _importer._get_module("moves.urllib_error")
    request = _importer._get_module("moves.urllib_request")
    response = _importer._get_module("moves.urllib_response")
    robotparser = _importer._get_module("moves.urllib_robotparser")

    def __dir__(self):
        return ['parse', 'error', 'request', 'response', 'robotparser']

_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"),
                      "moves.urllib")


def add_move(move):
    """Add an item to six.moves."""
    setattr(_MovedItems, move.name, move)


def remove_move(name):
    """Remove item from six.moves."""
    try:
        delattr(_MovedItems, name)
    except AttributeError:
        try:
            del moves.__dict__[name]
        except KeyError:
            raise AttributeError("no such move, %r" % (name,))


if PY3:
    _meth_func = "__func__"
    _meth_self = "__self__"

    _func_closure = "__closure__"
    _func_code = "__code__"
    _func_defaults = "__defaults__"
    _func_globals = "__globals__"
else:
    _meth_func = "im_func"
    _meth_self = "im_self"

    _func_closure = "func_closure"
    _func_code = "func_code"
    _func_defaults = "func_defaults"
    _func_globals = "func_globals"


try:
    advance_iterator = next
except NameError:
    def advance_iterator(it):
        return it.next()
next = advance_iterator


try:
    callable = callable
except NameError:
    def callable(obj):
        return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)


if PY3:
    def get_unbound_function(unbound):
        return unbound

    create_bound_method = types.MethodType

    def create_unbound_method(func, cls):
        return func

    Iterator = object
else:
    def get_unbound_function(unbound):
        return unbound.im_func

    def create_bound_method(func, obj):
        return types.MethodType(func, obj, obj.__class__)

    def create_unbound_method(func, cls):
        return types.MethodType(func, None, cls)

    class Iterator(object):

        def next(self):
            return type(self).__next__(self)

    callable = callable
_add_doc(get_unbound_function,
         """Get the function out of a possibly unbound function""")


get_method_function = operator.attrgetter(_meth_func)
get_method_self = operator.attrgetter(_meth_self)
get_function_closure = operator.attrgetter(_func_closure)
get_function_code = operator.attrgetter(_func_code)
get_function_defaults = operator.attrgetter(_func_defaults)
get_function_globals = operator.attrgetter(_func_globals)


if PY3:
    def iterkeys(d, **kw):
        return iter(d.keys(**kw))

    def itervalues(d, **kw):
        return iter(d.values(**kw))

    def iteritems(d, **kw):
        return iter(d.items(**kw))

    def iterlists(d, **kw):
        return iter(d.lists(**kw))

    viewkeys = operator.methodcaller("keys")

    viewvalues = operator.methodcaller("values")

    viewitems = operator.methodcaller("items")
else:
    def iterkeys(d, **kw):
        return d.iterkeys(**kw)

    def itervalues(d, **kw):
        return d.itervalues(**kw)

    def iteritems(d, **kw):
        return d.iteritems(**kw)

    def iterlists(d, **kw):
        return d.iterlists(**kw)

    viewkeys = operator.methodcaller("viewkeys")

    viewvalues = operator.methodcaller("viewvalues")

    viewitems = operator.methodcaller("viewitems")

_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.")
_add_doc(itervalues, "Return an iterator over the values of a dictionary.")
_add_doc(iteritems,
         "Return an iterator over the (key, value) pairs of a dictionary.")
_add_doc(iterlists,
         "Return an iterator over the (key, [values]) pairs of a dictionary.")


if PY3:
    def b(s):
        return s.encode("latin-1")

    def u(s):
        return s
    unichr = chr
    import struct
    int2byte = struct.Struct(">B").pack
    del struct
    byte2int = operator.itemgetter(0)
    indexbytes = operator.getitem
    iterbytes = iter
    import io
    StringIO = io.StringIO
    BytesIO = io.BytesIO
    _assertCountEqual = "assertCountEqual"
    if sys.version_info[1] <= 1:
        _assertRaisesRegex = "assertRaisesRegexp"
        _assertRegex = "assertRegexpMatches"
    else:
        _assertRaisesRegex = "assertRaisesRegex"
        _assertRegex = "assertRegex"
else:
    def b(s):
        return s
    # Workaround for standalone backslash

    def u(s):
        return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
    unichr = unichr
    int2byte = chr

    def byte2int(bs):
        return ord(bs[0])

    def indexbytes(buf, i):
        return ord(buf[i])
    iterbytes = functools.partial(itertools.imap, ord)
    import StringIO
    StringIO = BytesIO = StringIO.StringIO
    _assertCountEqual = "assertItemsEqual"
    _assertRaisesRegex = "assertRaisesRegexp"
    _assertRegex = "assertRegexpMatches"
_add_doc(b, """Byte literal""")
_add_doc(u, """Text literal""")


def assertCountEqual(self, *args, **kwargs):
    return getattr(self, _assertCountEqual)(*args, **kwargs)


def assertRaisesRegex(self, *args, **kwargs):
    return getattr(self, _assertRaisesRegex)(*args, **kwargs)


def assertRegex(self, *args, **kwargs):
    return getattr(self, _assertRegex)(*args, **kwargs)


if PY3:
    exec_ = getattr(moves.builtins, "exec")

    def reraise(tp, value, tb=None):
        try:
            if value is None:
                value = tp()
            if value.__traceback__ is not tb:
                raise value.with_traceback(tb)
            raise value
        finally:
            value = None
            tb = None

else:
    def exec_(_code_, _globs_=None, _locs_=None):
        """Execute code in a namespace."""
        if _globs_ is None:
            frame = sys._getframe(1)
            _globs_ = frame.f_globals
            if _locs_ is None:
                _locs_ = frame.f_locals
            del frame
        elif _locs_ is None:
            _locs_ = _globs_
        exec("""exec _code_ in _globs_, _locs_""")

    exec_("""def reraise(tp, value, tb=None):
    try:
        raise tp, value, tb
    finally:
        tb = None
""")


if sys.version_info[:2] == (3, 2):
    exec_("""def raise_from(value, from_value):
    try:
        if from_value is None:
            raise value
        raise value from from_value
    finally:
        value = None
""")
elif sys.version_info[:2] > (3, 2):
    exec_("""def raise_from(value, from_value):
    try:
        raise value from from_value
    finally:
        value = None
""")
else:
    def raise_from(value, from_value):
        raise value


print_ = getattr(moves.builtins, "print", None)
if print_ is None:
    def print_(*args, **kwargs):
        """The new-style print function for Python 2.4 and 2.5."""
        fp = kwargs.pop("file", sys.stdout)
        if fp is None:
            return

        def write(data):
            if not isinstance(data, basestring):
                data = str(data)
            # If the file has an encoding, encode unicode with it.
            if (isinstance(fp, file) and
                    isinstance(data, unicode) and
                    fp.encoding is not None):
                errors = getattr(fp, "errors", None)
                if errors is None:
                    errors = "strict"
                data = data.encode(fp.encoding, errors)
            fp.write(data)
        want_unicode = False
        sep = kwargs.pop("sep", None)
        if sep is not None:
            if isinstance(sep, unicode):
                want_unicode = True
            elif not isinstance(sep, str):
                raise TypeError("sep must be None or a string")
        end = kwargs.pop("end", None)
        if end is not None:
            if isinstance(end, unicode):
                want_unicode = True
            elif not isinstance(end, str):
                raise TypeError("end must be None or a string")
        if kwargs:
            raise TypeError("invalid keyword arguments to print()")
        if not want_unicode:
            for arg in args:
                if isinstance(arg, unicode):
                    want_unicode = True
                    break
        if want_unicode:
            newline = unicode("\n")
            space = unicode(" ")
        else:
            newline = "\n"
            space = " "
        if sep is None:
            sep = space
        if end is None:
            end = newline
        for i, arg in enumerate(args):
            if i:
                write(sep)
            write(arg)
        write(end)
if sys.version_info[:2] < (3, 3):
    _print = print_

    def print_(*args, **kwargs):
        fp = kwargs.get("file", sys.stdout)
        flush = kwargs.pop("flush", False)
        _print(*args, **kwargs)
        if flush and fp is not None:
            fp.flush()

_add_doc(reraise, """Reraise an exception.""")

if sys.version_info[0:2] < (3, 4):
    def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS,
              updated=functools.WRAPPER_UPDATES):
        def wrapper(f):
            f = functools.wraps(wrapped, assigned, updated)(f)
            f.__wrapped__ = wrapped
            return f
        return wrapper
else:
    wraps = functools.wraps


def with_metaclass(meta, *bases):
    """Create a base class with a metaclass."""
    # This requires a bit of explanation: the basic idea is to make a dummy
    # metaclass for one level of class instantiation that replaces itself with
    # the actual metaclass.
    class metaclass(type):

        def __new__(cls, name, this_bases, d):
            return meta(name, bases, d)

        @classmethod
        def __prepare__(cls, name, this_bases):
            return meta.__prepare__(name, bases)
    return type.__new__(metaclass, 'temporary_class', (), {})


def add_metaclass(metaclass):
    """Class decorator for creating a class with a metaclass."""
    def wrapper(cls):
        orig_vars = cls.__dict__.copy()
        slots = orig_vars.get('__slots__')
        if slots is not None:
            if isinstance(slots, str):
                slots = [slots]
            for slots_var in slots:
                orig_vars.pop(slots_var)
        orig_vars.pop('__dict__', None)
        orig_vars.pop('__weakref__', None)
        if hasattr(cls, '__qualname__'):
            orig_vars['__qualname__'] = cls.__qualname__
        return metaclass(cls.__name__, cls.__bases__, orig_vars)
    return wrapper


def ensure_binary(s, encoding='utf-8', errors='strict'):
    """Coerce **s** to six.binary_type.

    For Python 2:
      - `unicode` -> encoded to `str`
      - `str` -> `str`

    For Python 3:
      - `str` -> encoded to `bytes`
      - `bytes` -> `bytes`
    """
    if isinstance(s, text_type):
        return s.encode(encoding, errors)
    elif isinstance(s, binary_type):
        return s
    else:
        raise TypeError("not expecting type '%s'" % type(s))


def ensure_str(s, encoding='utf-8', errors='strict'):
    """Coerce *s* to `str`.

    For Python 2:
      - `unicode` -> encoded to `str`
      - `str` -> `str`

    For Python 3:
      - `str` -> `str`
      - `bytes` -> decoded to `str`
    """
    if not isinstance(s, (text_type, binary_type)):
        raise TypeError("not expecting type '%s'" % type(s))
    if PY2 and isinstance(s, text_type):
        s = s.encode(encoding, errors)
    elif PY3 and isinstance(s, binary_type):
        s = s.decode(encoding, errors)
    return s


def ensure_text(s, encoding='utf-8', errors='strict'):
    """Coerce *s* to six.text_type.

    For Python 2:
      - `unicode` -> `unicode`
      - `str` -> `unicode`

    For Python 3:
      - `str` -> `str`
      - `bytes` -> decoded to `str`
    """
    if isinstance(s, binary_type):
        return s.decode(encoding, errors)
    elif isinstance(s, text_type):
        return s
    else:
        raise TypeError("not expecting type '%s'" % type(s))



def python_2_unicode_compatible(klass):
    """
    A decorator that defines __unicode__ and __str__ methods under Python 2.
    Under Python 3 it does nothing.

    To support Python 2 and 3 with a single code base, define a __str__ method
    returning text and apply this decorator to the class.
    """
    if PY2:
        if '__str__' not in klass.__dict__:
            raise ValueError("@python_2_unicode_compatible cannot be applied "
                             "to %s because it doesn't define __str__()." %
                             klass.__name__)
        klass.__unicode__ = klass.__str__
        klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
    return klass


# Complete the moves implementation.
# This code is at the end of this module to speed up module loading.
# Turn this module into a package.
__path__ = []  # required for PEP 302 and PEP 451
__package__ = __name__  # see PEP 366 @ReservedAssignment
if globals().get("__spec__") is not None:
    __spec__.submodule_search_locations = []  # PEP 451 @UndefinedVariable
# Remove other six meta path importers, since they cause problems. This can
# happen if six is removed from sys.modules and then reloaded. (Setuptools does
# this for some reason.)
if sys.meta_path:
    for i, importer in enumerate(sys.meta_path):
        # Here's some real nastiness: Another "instance" of the six module might
        # be floating around. Therefore, we can't use isinstance() to check for
        # the six meta path importer, since the other six instance will have
        # inserted an importer with different class.
        if (type(importer).__name__ == "_SixMetaPathImporter" and
                importer.name == __name__):
            del sys.meta_path[i]
            break
    del i, importer
# Finally, add the importer to the meta path import hook.
sys.meta_path.append(_importer)
PKÔ¶N]g8p§££/site-packages/pip/_vendor/webencodings/tests.pynu„[µü¤# coding: utf-8
"""

    webencodings.tests
    ~~~~~~~~~~~~~~~~~~

    A basic test suite for Encoding.

    :copyright: Copyright 2012 by Simon Sapin
    :license: BSD, see LICENSE for details.

"""

from __future__ import unicode_literals

from . import (lookup, LABELS, decode, encode, iter_decode, iter_encode,
               IncrementalDecoder, IncrementalEncoder, UTF8)


def assert_raises(exception, function, *args, **kwargs):
    try:
        function(*args, **kwargs)
    except exception:
        return
    else:  # pragma: no cover
        raise AssertionError('Did not raise %s.' % exception)


def test_labels():
    assert lookup('utf-8').name == 'utf-8'
    assert lookup('Utf-8').name == 'utf-8'
    assert lookup('UTF-8').name == 'utf-8'
    assert lookup('utf8').name == 'utf-8'
    assert lookup('utf8').name == 'utf-8'
    assert lookup('utf8 ').name == 'utf-8'
    assert lookup(' \r\nutf8\t').name == 'utf-8'
    assert lookup('u8') is None  # Python label.
    assert lookup('utf-8 ') is None  # Non-ASCII white space.

    assert lookup('US-ASCII').name == 'windows-1252'
    assert lookup('iso-8859-1').name == 'windows-1252'
    assert lookup('latin1').name == 'windows-1252'
    assert lookup('LATIN1').name == 'windows-1252'
    assert lookup('latin-1') is None
    assert lookup('LATİN1') is None  # ASCII-only case insensitivity.


def test_all_labels():
    for label in LABELS:
        assert decode(b'', label) == ('', lookup(label))
        assert encode('', label) == b''
        for repeat in [0, 1, 12]:
            output, _ = iter_decode([b''] * repeat, label)
            assert list(output) == []
            assert list(iter_encode([''] * repeat, label)) == []
        decoder = IncrementalDecoder(label)
        assert decoder.decode(b'') == ''
        assert decoder.decode(b'', final=True) == ''
        encoder = IncrementalEncoder(label)
        assert encoder.encode('') == b''
        assert encoder.encode('', final=True) == b''
    # All encoding names are valid labels too:
    for name in set(LABELS.values()):
        assert lookup(name).name == name


def test_invalid_label():
    assert_raises(LookupError, decode, b'\xEF\xBB\xBF\xc3\xa9', 'invalid')
    assert_raises(LookupError, encode, 'é', 'invalid')
    assert_raises(LookupError, iter_decode, [], 'invalid')
    assert_raises(LookupError, iter_encode, [], 'invalid')
    assert_raises(LookupError, IncrementalDecoder, 'invalid')
    assert_raises(LookupError, IncrementalEncoder, 'invalid')


def test_decode():
    assert decode(b'\x80', 'latin1') == ('€', lookup('latin1'))
    assert decode(b'\x80', lookup('latin1')) == ('€', lookup('latin1'))
    assert decode(b'\xc3\xa9', 'utf8') == ('é', lookup('utf8'))
    assert decode(b'\xc3\xa9', UTF8) == ('é', lookup('utf8'))
    assert decode(b'\xc3\xa9', 'ascii') == ('é', lookup('ascii'))
    assert decode(b'\xEF\xBB\xBF\xc3\xa9', 'ascii') == ('é', lookup('utf8'))  # UTF-8 with BOM

    assert decode(b'\xFE\xFF\x00\xe9', 'ascii') == ('é', lookup('utf-16be'))  # UTF-16-BE with BOM
    assert decode(b'\xFF\xFE\xe9\x00', 'ascii') == ('é', lookup('utf-16le'))  # UTF-16-LE with BOM
    assert decode(b'\xFE\xFF\xe9\x00', 'ascii') == ('\ue900', lookup('utf-16be'))
    assert decode(b'\xFF\xFE\x00\xe9', 'ascii') == ('\ue900', lookup('utf-16le'))

    assert decode(b'\x00\xe9', 'UTF-16BE') == ('é', lookup('utf-16be'))
    assert decode(b'\xe9\x00', 'UTF-16LE') == ('é', lookup('utf-16le'))
    assert decode(b'\xe9\x00', 'UTF-16') == ('é', lookup('utf-16le'))

    assert decode(b'\xe9\x00', 'UTF-16BE') == ('\ue900', lookup('utf-16be'))
    assert decode(b'\x00\xe9', 'UTF-16LE') == ('\ue900', lookup('utf-16le'))
    assert decode(b'\x00\xe9', 'UTF-16') == ('\ue900', lookup('utf-16le'))


def test_encode():
    assert encode('é', 'latin1') == b'\xe9'
    assert encode('é', 'utf8') == b'\xc3\xa9'
    assert encode('é', 'utf8') == b'\xc3\xa9'
    assert encode('é', 'utf-16') == b'\xe9\x00'
    assert encode('é', 'utf-16le') == b'\xe9\x00'
    assert encode('é', 'utf-16be') == b'\x00\xe9'


def test_iter_decode():
    def iter_decode_to_string(input, fallback_encoding):
        output, _encoding = iter_decode(input, fallback_encoding)
        return ''.join(output)
    assert iter_decode_to_string([], 'latin1') == ''
    assert iter_decode_to_string([b''], 'latin1') == ''
    assert iter_decode_to_string([b'\xe9'], 'latin1') == 'é'
    assert iter_decode_to_string([b'hello'], 'latin1') == 'hello'
    assert iter_decode_to_string([b'he', b'llo'], 'latin1') == 'hello'
    assert iter_decode_to_string([b'hell', b'o'], 'latin1') == 'hello'
    assert iter_decode_to_string([b'\xc3\xa9'], 'latin1') == 'é'
    assert iter_decode_to_string([b'\xEF\xBB\xBF\xc3\xa9'], 'latin1') == 'é'
    assert iter_decode_to_string([
        b'\xEF\xBB\xBF', b'\xc3', b'\xa9'], 'latin1') == 'é'
    assert iter_decode_to_string([
        b'\xEF\xBB\xBF', b'a', b'\xc3'], 'latin1') == 'a\uFFFD'
    assert iter_decode_to_string([
        b'', b'\xEF', b'', b'', b'\xBB\xBF\xc3', b'\xa9'], 'latin1') == 'é'
    assert iter_decode_to_string([b'\xEF\xBB\xBF'], 'latin1') == ''
    assert iter_decode_to_string([b'\xEF\xBB'], 'latin1') == 'ï»'
    assert iter_decode_to_string([b'\xFE\xFF\x00\xe9'], 'latin1') == 'é'
    assert iter_decode_to_string([b'\xFF\xFE\xe9\x00'], 'latin1') == 'é'
    assert iter_decode_to_string([
        b'', b'\xFF', b'', b'', b'\xFE\xe9', b'\x00'], 'latin1') == 'é'
    assert iter_decode_to_string([
        b'', b'h\xe9', b'llo'], 'x-user-defined') == 'h\uF7E9llo'


def test_iter_encode():
    assert b''.join(iter_encode([], 'latin1')) == b''
    assert b''.join(iter_encode([''], 'latin1')) == b''
    assert b''.join(iter_encode(['é'], 'latin1')) == b'\xe9'
    assert b''.join(iter_encode(['', 'é', '', ''], 'latin1')) == b'\xe9'
    assert b''.join(iter_encode(['', 'é', '', ''], 'utf-16')) == b'\xe9\x00'
    assert b''.join(iter_encode(['', 'é', '', ''], 'utf-16le')) == b'\xe9\x00'
    assert b''.join(iter_encode(['', 'é', '', ''], 'utf-16be')) == b'\x00\xe9'
    assert b''.join(iter_encode([
        '', 'h\uF7E9', '', 'llo'], 'x-user-defined')) == b'h\xe9llo'


def test_x_user_defined():
    encoded = b'2,\x0c\x0b\x1aO\xd9#\xcb\x0f\xc9\xbbt\xcf\xa8\xca'
    decoded = '2,\x0c\x0b\x1aO\uf7d9#\uf7cb\x0f\uf7c9\uf7bbt\uf7cf\uf7a8\uf7ca'
    encoded = b'aa'
    decoded = 'aa'
    assert decode(encoded, 'x-user-defined') == (decoded, lookup('x-user-defined'))
    assert encode(decoded, 'x-user-defined') == encoded
PKÔ¶N]xÐqS)S)2site-packages/pip/_vendor/webencodings/__init__.pynu„[µü¤# coding: utf-8
"""

    webencodings
    ~~~~~~~~~~~~

    This is a Python implementation of the `WHATWG Encoding standard
    `. See README for details.

    :copyright: Copyright 2012 by Simon Sapin
    :license: BSD, see LICENSE for details.

"""

from __future__ import unicode_literals

import codecs

from .labels import LABELS


VERSION = '0.5.1'


# Some names in Encoding are not valid Python aliases. Remap these.
PYTHON_NAMES = {
    'iso-8859-8-i': 'iso-8859-8',
    'x-mac-cyrillic': 'mac-cyrillic',
    'macintosh': 'mac-roman',
    'windows-874': 'cp874'}

CACHE = {}


def ascii_lower(string):
    r"""Transform (only) ASCII letters to lower case: A-Z is mapped to a-z.

    :param string: An Unicode string.
    :returns: A new Unicode string.

    This is used for `ASCII case-insensitive
    `_
    matching of encoding labels.
    The same matching is also used, among other things,
    for `CSS keywords `_.

    This is different from the :meth:`~py:str.lower` method of Unicode strings
    which also affect non-ASCII characters,
    sometimes mapping them into the ASCII range:

        >>> keyword = u'Bac\N{KELVIN SIGN}ground'
        >>> assert keyword.lower() == u'background'
        >>> assert ascii_lower(keyword) != keyword.lower()
        >>> assert ascii_lower(keyword) == u'bac\N{KELVIN SIGN}ground'

    """
    # This turns out to be faster than unicode.translate()
    return string.encode('utf8').lower().decode('utf8')


def lookup(label):
    """
    Look for an encoding by its label.
    This is the spec’s `get an encoding
    `_ algorithm.
    Supported labels are listed there.

    :param label: A string.
    :returns:
        An :class:`Encoding` object, or :obj:`None` for an unknown label.

    """
    # Only strip ASCII whitespace: U+0009, U+000A, U+000C, U+000D, and U+0020.
    label = ascii_lower(label.strip('\t\n\f\r '))
    name = LABELS.get(label)
    if name is None:
        return None
    encoding = CACHE.get(name)
    if encoding is None:
        if name == 'x-user-defined':
            from .x_user_defined import codec_info
        else:
            python_name = PYTHON_NAMES.get(name, name)
            # Any python_name value that gets to here should be valid.
            codec_info = codecs.lookup(python_name)
        encoding = Encoding(name, codec_info)
        CACHE[name] = encoding
    return encoding


def _get_encoding(encoding_or_label):
    """
    Accept either an encoding object or label.

    :param encoding: An :class:`Encoding` object or a label string.
    :returns: An :class:`Encoding` object.
    :raises: :exc:`~exceptions.LookupError` for an unknown label.

    """
    if hasattr(encoding_or_label, 'codec_info'):
        return encoding_or_label

    encoding = lookup(encoding_or_label)
    if encoding is None:
        raise LookupError('Unknown encoding label: %r' % encoding_or_label)
    return encoding


class Encoding(object):
    """Reresents a character encoding such as UTF-8,
    that can be used for decoding or encoding.

    .. attribute:: name

        Canonical name of the encoding

    .. attribute:: codec_info

        The actual implementation of the encoding,
        a stdlib :class:`~codecs.CodecInfo` object.
        See :func:`codecs.register`.

    """
    def __init__(self, name, codec_info):
        self.name = name
        self.codec_info = codec_info

    def __repr__(self):
        return '' % self.name


#: The UTF-8 encoding. Should be used for new content and formats.
UTF8 = lookup('utf-8')

_UTF16LE = lookup('utf-16le')
_UTF16BE = lookup('utf-16be')


def decode(input, fallback_encoding, errors='replace'):
    """
    Decode a single string.

    :param input: A byte string
    :param fallback_encoding:
        An :class:`Encoding` object or a label string.
        The encoding to use if :obj:`input` does note have a BOM.
    :param errors: Type of error handling. See :func:`codecs.register`.
    :raises: :exc:`~exceptions.LookupError` for an unknown encoding label.
    :return:
        A ``(output, encoding)`` tuple of an Unicode string
        and an :obj:`Encoding`.

    """
    # Fail early if `encoding` is an invalid label.
    fallback_encoding = _get_encoding(fallback_encoding)
    bom_encoding, input = _detect_bom(input)
    encoding = bom_encoding or fallback_encoding
    return encoding.codec_info.decode(input, errors)[0], encoding


def _detect_bom(input):
    """Return (bom_encoding, input), with any BOM removed from the input."""
    if input.startswith(b'\xFF\xFE'):
        return _UTF16LE, input[2:]
    if input.startswith(b'\xFE\xFF'):
        return _UTF16BE, input[2:]
    if input.startswith(b'\xEF\xBB\xBF'):
        return UTF8, input[3:]
    return None, input


def encode(input, encoding=UTF8, errors='strict'):
    """
    Encode a single string.

    :param input: An Unicode string.
    :param encoding: An :class:`Encoding` object or a label string.
    :param errors: Type of error handling. See :func:`codecs.register`.
    :raises: :exc:`~exceptions.LookupError` for an unknown encoding label.
    :return: A byte string.

    """
    return _get_encoding(encoding).codec_info.encode(input, errors)[0]


def iter_decode(input, fallback_encoding, errors='replace'):
    """
    "Pull"-based decoder.

    :param input:
        An iterable of byte strings.

        The input is first consumed just enough to determine the encoding
        based on the precense of a BOM,
        then consumed on demand when the return value is.
    :param fallback_encoding:
        An :class:`Encoding` object or a label string.
        The encoding to use if :obj:`input` does note have a BOM.
    :param errors: Type of error handling. See :func:`codecs.register`.
    :raises: :exc:`~exceptions.LookupError` for an unknown encoding label.
    :returns:
        An ``(output, encoding)`` tuple.
        :obj:`output` is an iterable of Unicode strings,
        :obj:`encoding` is the :obj:`Encoding` that is being used.

    """

    decoder = IncrementalDecoder(fallback_encoding, errors)
    generator = _iter_decode_generator(input, decoder)
    encoding = next(generator)
    return generator, encoding


def _iter_decode_generator(input, decoder):
    """Return a generator that first yields the :obj:`Encoding`,
    then yields output chukns as Unicode strings.

    """
    decode = decoder.decode
    input = iter(input)
    for chunck in input:
        output = decode(chunck)
        if output:
            assert decoder.encoding is not None
            yield decoder.encoding
            yield output
            break
    else:
        # Input exhausted without determining the encoding
        output = decode(b'', final=True)
        assert decoder.encoding is not None
        yield decoder.encoding
        if output:
            yield output
        return

    for chunck in input:
        output = decode(chunck)
        if output:
            yield output
    output = decode(b'', final=True)
    if output:
        yield output


def iter_encode(input, encoding=UTF8, errors='strict'):
    """
    “Pull�-based encoder.

    :param input: An iterable of Unicode strings.
    :param encoding: An :class:`Encoding` object or a label string.
    :param errors: Type of error handling. See :func:`codecs.register`.
    :raises: :exc:`~exceptions.LookupError` for an unknown encoding label.
    :returns: An iterable of byte strings.

    """
    # Fail early if `encoding` is an invalid label.
    encode = IncrementalEncoder(encoding, errors).encode
    return _iter_encode_generator(input, encode)


def _iter_encode_generator(input, encode):
    for chunck in input:
        output = encode(chunck)
        if output:
            yield output
    output = encode('', final=True)
    if output:
        yield output


class IncrementalDecoder(object):
    """
    “Push�-based decoder.

    :param fallback_encoding:
        An :class:`Encoding` object or a label string.
        The encoding to use if :obj:`input` does note have a BOM.
    :param errors: Type of error handling. See :func:`codecs.register`.
    :raises: :exc:`~exceptions.LookupError` for an unknown encoding label.

    """
    def __init__(self, fallback_encoding, errors='replace'):
        # Fail early if `encoding` is an invalid label.
        self._fallback_encoding = _get_encoding(fallback_encoding)
        self._errors = errors
        self._buffer = b''
        self._decoder = None
        #: The actual :class:`Encoding` that is being used,
        #: or :obj:`None` if that is not determined yet.
        #: (Ie. if there is not enough input yet to determine
        #: if there is a BOM.)
        self.encoding = None  # Not known yet.

    def decode(self, input, final=False):
        """Decode one chunk of the input.

        :param input: A byte string.
        :param final:
            Indicate that no more input is available.
            Must be :obj:`True` if this is the last call.
        :returns: An Unicode string.

        """
        decoder = self._decoder
        if decoder is not None:
            return decoder(input, final)

        input = self._buffer + input
        encoding, input = _detect_bom(input)
        if encoding is None:
            if len(input) < 3 and not final:  # Not enough data yet.
                self._buffer = input
                return ''
            else:  # No BOM
                encoding = self._fallback_encoding
        decoder = encoding.codec_info.incrementaldecoder(self._errors).decode
        self._decoder = decoder
        self.encoding = encoding
        return decoder(input, final)


class IncrementalEncoder(object):
    """
    “Push�-based encoder.

    :param encoding: An :class:`Encoding` object or a label string.
    :param errors: Type of error handling. See :func:`codecs.register`.
    :raises: :exc:`~exceptions.LookupError` for an unknown encoding label.

    .. method:: encode(input, final=False)

        :param input: An Unicode string.
        :param final:
            Indicate that no more input is available.
            Must be :obj:`True` if this is the last call.
        :returns: A byte string.

    """
    def __init__(self, encoding=UTF8, errors='strict'):
        encoding = _get_encoding(encoding)
        self.encode = encoding.codec_info.incrementalencoder(errors).encode
PKÔ¶N]£à7CCPsite-packages/pip/_vendor/webencodings/__pycache__/mklabels.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eã@sfdZddlZzddlmZWn ek
r<ddlmZYnXdd„Zdd„Zedkrbe	ed	ƒƒdS)
zÂ

    webencodings.mklabels
    ~~~~~~~~~~~~~~~~~~~~~

    Regenarate the webencodings.labels module.

    :copyright: Copyright 2012 by Simon Sapin
    :license: BSD, see LICENSE for details.

éN)ÚurlopencCs|S©N©)ÚstringrrúE/usr/lib/python3.8/site-packages/pip/_vendor/webencodings/mklabels.pyÚassert_lowersrcsfdg}dd„t t|ƒ ¡ d¡¡Dƒ}tdd„|Dƒƒ‰| ‡fdd„|Dƒ¡| d¡d	 |¡S)
Na"""

    webencodings.labels
    ~~~~~~~~~~~~~~~~~~~

    Map encoding labels to their name.

    :copyright: Copyright 2012 by Simon Sapin
    :license: BSD, see LICENSE for details.

"""

# XXX Do not edit!
# This file is automatically generated by mklabels.py

LABELS = {
cSsLg|]D}|dD]6}|dD](}tt|ƒƒ d¡t|dƒ d¡f‘qqqS)Z	encodingsÚlabelsÚuÚname)ÚreprrÚlstrip)Ú.0ÚcategoryÚencodingÚlabelrrrÚ
,s

üÿzgenerate..Úasciicss|]\}}t|ƒVqdSr©Úlen©r
rr
rrrÚ	2szgenerate..c3s,|]$\}}d|dˆt|ƒ|fVqdS)z    %s:%s %s,
ú Nrr©Zmax_lenrrr3sÿÚ}Ú)	ÚjsonÚloadsrÚreadÚdecodeÚmaxÚextendÚappendÚjoin)ZurlÚpartsrrrrÚgeneratesýþ
r$Ú__main__z.http://encoding.spec.whatwg.org/encodings.json)
Ú__doc__rZurllibrÚImportErrorZurllib.requestrr$Ú__name__ÚprintrrrrÚs!PKÔ¶N]F�Å÷iiJsite-packages/pip/_vendor/webencodings/__pycache__/mklabels.cpython-38.pycnu„[µü¤U

ÀÒ.eã@sfdZddlZzddlmZWn ek
r<ddlmZYnXdd„Zdd„Zedkrbe	ed	ƒƒdS)
zÂ

    webencodings.mklabels
    ~~~~~~~~~~~~~~~~~~~~~

    Regenarate the webencodings.labels module.

    :copyright: Copyright 2012 by Simon Sapin
    :license: BSD, see LICENSE for details.

éN)ÚurlopencCs|| ¡kst‚|S©N)ÚlowerÚAssertionError)Ústring©rúE/usr/lib/python3.8/site-packages/pip/_vendor/webencodings/mklabels.pyÚassert_lowersr	csfdg}dd„t t|ƒ ¡ d¡¡Dƒ}tdd„|Dƒƒ‰| ‡fdd„|Dƒ¡| d¡d	 |¡S)
Na"""

    webencodings.labels
    ~~~~~~~~~~~~~~~~~~~

    Map encoding labels to their name.

    :copyright: Copyright 2012 by Simon Sapin
    :license: BSD, see LICENSE for details.

"""

# XXX Do not edit!
# This file is automatically generated by mklabels.py

LABELS = {
cSsLg|]D}|dD]6}|dD](}tt|ƒƒ d¡t|dƒ d¡f‘qqqS)Z	encodingsÚlabelsÚuÚname)Úreprr	Úlstrip)Ú.0ÚcategoryÚencodingÚlabelrrrÚ
,s

üÿzgenerate..Úasciicss|]\}}t|ƒVqdSr©Úlen©rrrrrrÚ	2szgenerate..c3s,|]$\}}d|dˆt|ƒ|fVqdS)z    %s:%s %s,
ú Nrr©Zmax_lenrrr3sÿÚ}Ú)	ÚjsonÚloadsrÚreadÚdecodeÚmaxÚextendÚappendÚjoin)ZurlÚpartsr
rrrÚgeneratesýþ
r&Ú__main__z.http://encoding.spec.whatwg.org/encodings.json)
Ú__doc__rZurllibrÚImportErrorZurllib.requestr	r&Ú__name__ÚprintrrrrÚs!PKÔ¶N]òÏ‘·%·%Psite-packages/pip/_vendor/webencodings/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eS)ã@sædZddlmZddlZddlmZdZddd	d
dœZiZdd
„Z	dd„Z
dd„ZGdd„deƒZ
e
dƒZe
dƒZe
dƒZd+dd„Zdd„Zedfdd„Zd,dd „Zd!d"„Zedfd#d$„Zd%d&„ZGd'd(„d(eƒZGd)d*„d*eƒZdS)-a

    webencodings
    ~~~~~~~~~~~~

    This is a Python implementation of the `WHATWG Encoding standard
    `. See README for details.

    :copyright: Copyright 2012 by Simon Sapin
    :license: BSD, see LICENSE for details.

é)Úunicode_literalsNé)ÚLABELSz0.5.1z
iso-8859-8zmac-cyrillicz	mac-romanZcp874)ziso-8859-8-izx-mac-cyrillicÚ	macintoshzwindows-874cCs| d¡ ¡ d¡S)a9Transform (only) ASCII letters to lower case: A-Z is mapped to a-z.

    :param string: An Unicode string.
    :returns: A new Unicode string.

    This is used for `ASCII case-insensitive
    `_
    matching of encoding labels.
    The same matching is also used, among other things,
    for `CSS keywords `_.

    This is different from the :meth:`~py:str.lower` method of Unicode strings
    which also affect non-ASCII characters,
    sometimes mapping them into the ASCII range:

        >>> keyword = u'Bac\N{KELVIN SIGN}ground'
        >>> assert keyword.lower() == u'background'
        >>> assert ascii_lower(keyword) != keyword.lower()
        >>> assert ascii_lower(keyword) == u'bac\N{KELVIN SIGN}ground'

    Úutf8)ÚencodeÚlowerÚdecode)Ústring©rúE/usr/lib/python3.8/site-packages/pip/_vendor/webencodings/__init__.pyÚascii_lower#sr
cCsxt| d¡ƒ}t |¡}|dkr$dSt |¡}|dkrt|dkrLddlm}nt ||¡}t 	|¡}t
||ƒ}|t|<|S)u<
    Look for an encoding by its label.
    This is the spec’s `get an encoding
    `_ algorithm.
    Supported labels are listed there.

    :param label: A string.
    :returns:
        An :class:`Encoding` object, or :obj:`None` for an unknown label.

    z	

 Nzx-user-definedr)Ú
codec_info)r
ÚstriprÚgetÚCACHEZx_user_definedrÚPYTHON_NAMESÚcodecsÚlookupÚEncoding)ZlabelÚnameÚencodingrZpython_namerrrr=s




rcCs.t|dƒr|St|ƒ}|dkr*td|ƒ‚|S)zç
    Accept either an encoding object or label.

    :param encoding: An :class:`Encoding` object or a label string.
    :returns: An :class:`Encoding` object.
    :raises: :exc:`~exceptions.LookupError` for an unknown label.

    rNzUnknown encoding label: %r)ÚhasattrrÚLookupError)Zencoding_or_labelrrrrÚ
_get_encoding[s	
rc@s eZdZdZdd„Zdd„ZdS)raOReresents a character encoding such as UTF-8,
    that can be used for decoding or encoding.

    .. attribute:: name

        Canonical name of the encoding

    .. attribute:: codec_info

        The actual implementation of the encoding,
        a stdlib :class:`~codecs.CodecInfo` object.
        See :func:`codecs.register`.

    cCs||_||_dS©N)rr)ÚselfrrrrrÚ__init__|szEncoding.__init__cCs
d|jS)Nz
)r)rrrrÚ__repr__€szEncoding.__repr__N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rrrrrrrmsrzutf-8zutf-16lezutf-16beÚreplacecCs2t|ƒ}t|ƒ\}}|p|}|j ||¡d|fS)aÖ
    Decode a single string.

    :param input: A byte string
    :param fallback_encoding:
        An :class:`Encoding` object or a label string.
        The encoding to use if :obj:`input` does note have a BOM.
    :param errors: Type of error handling. See :func:`codecs.register`.
    :raises: :exc:`~exceptions.LookupError` for an unknown encoding label.
    :return:
        A ``(output, encoding)`` tuple of an Unicode string
        and an :obj:`Encoding`.

    r)rÚ_detect_bomrr	)ÚinputÚfallback_encodingÚerrorsZbom_encodingrrrrr	‹sr	cCsV| d¡rt|dd…fS| d¡r4t|dd…fS| d¡rNt|dd…fSd|fS)zBReturn (bom_encoding, input), with any BOM removed from the input.sÿþéNsþÿsé)Ú
startswithÚ_UTF16LEÚ_UTF16BEÚUTF8)r%rrrr$¡s


r$ÚstrictcCst|ƒj ||¡dS)a;
    Encode a single string.

    :param input: An Unicode string.
    :param encoding: An :class:`Encoding` object or a label string.
    :param errors: Type of error handling. See :func:`codecs.register`.
    :raises: :exc:`~exceptions.LookupError` for an unknown encoding label.
    :return: A byte string.

    r)rrr)r%rr'rrrr¬srcCs$t||ƒ}t||ƒ}t|ƒ}||fS)aâ
    "Pull"-based decoder.

    :param input:
        An iterable of byte strings.

        The input is first consumed just enough to determine the encoding
        based on the precense of a BOM,
        then consumed on demand when the return value is.
    :param fallback_encoding:
        An :class:`Encoding` object or a label string.
        The encoding to use if :obj:`input` does note have a BOM.
    :param errors: Type of error handling. See :func:`codecs.register`.
    :raises: :exc:`~exceptions.LookupError` for an unknown encoding label.
    :returns:
        An ``(output, encoding)`` tuple.
        :obj:`output` is an iterable of Unicode strings,
        :obj:`encoding` is the :obj:`Encoding` that is being used.

    )ÚIncrementalDecoderÚ_iter_decode_generatorÚnext)r%r&r'ÚdecoderÚ	generatorrrrrÚiter_decodeºs

r4ccsŽ|j}t|ƒ}|D]"}||ƒ}|r|jV|VqXq|ddd�}|jV|rT|VdS|D]}||ƒ}|r\|Vq\|ddd�}|rŠ|VdS)zqReturn a generator that first yields the :obj:`Encoding`,
    then yields output chukns as Unicode strings.

    óT©ÚfinalN)r	Úiterr)r%r2r	ÚchunckÚoutputrrrr0Ös(r0cCst||ƒj}t||ƒS)uY
    “Pull�-based encoder.

    :param input: An iterable of Unicode strings.
    :param encoding: An :class:`Encoding` object or a label string.
    :param errors: Type of error handling. See :func:`codecs.register`.
    :raises: :exc:`~exceptions.LookupError` for an unknown encoding label.
    :returns: An iterable of byte strings.

    )ÚIncrementalEncoderrÚ_iter_encode_generator)r%rr'rrrrÚiter_encodeösr=ccs6|D]}||ƒ}|r|Vq|ddd�}|r2|VdS)NÚTr6r)r%rr9r:rrrr<sr<c@s$eZdZdZd	dd„Zd
dd„ZdS)r/uO
    “Push�-based decoder.

    :param fallback_encoding:
        An :class:`Encoding` object or a label string.
        The encoding to use if :obj:`input` does note have a BOM.
    :param errors: Type of error handling. See :func:`codecs.register`.
    :raises: :exc:`~exceptions.LookupError` for an unknown encoding label.

    r#cCs&t|ƒ|_||_d|_d|_d|_dS)Nr5)rÚ_fallback_encodingÚ_errorsÚ_bufferÚ_decoderr)rr&r'rrrrs

zIncrementalDecoder.__init__FcCs||j}|dk	r|||ƒS|j|}t|ƒ\}}|dkrVt|ƒdkrP|sP||_dS|j}|j |j¡j}||_||_	|||ƒS)zùDecode one chunk of the input.

        :param input: A byte string.
        :param final:
            Indicate that no more input is available.
            Must be :obj:`True` if this is the last call.
        :returns: An Unicode string.

        Nr)r>)
rBrAr$Úlenr?rÚincrementaldecoderr@r	r)rr%r7r2rrrrr	's


zIncrementalDecoder.decodeN)r#)F)rr r!r"rr	rrrrr/s

r/c@seZdZdZedfdd„ZdS)r;uù
    “Push�-based encoder.

    :param encoding: An :class:`Encoding` object or a label string.
    :param errors: Type of error handling. See :func:`codecs.register`.
    :raises: :exc:`~exceptions.LookupError` for an unknown encoding label.

    .. method:: encode(input, final=False)

        :param input: An Unicode string.
        :param final:
            Indicate that no more input is available.
            Must be :obj:`True` if this is the last call.
        :returns: A byte string.

    r.cCst|ƒ}|j |¡j|_dSr)rrÚincrementalencoderr)rrr'rrrrTszIncrementalEncoder.__init__N)rr r!r"r-rrrrrr;Csr;)r#)r#)r"Z
__future__rrÚlabelsrZVERSIONrrr
rrÚobjectrr-r+r,r	r$rr4r0r=r<r/r;rrrrÚs4
ü

 
3PKÔ¶N]Ô½­ÂG
G
Vsite-packages/pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eÓã	@s¨dZddlmZddlZGdd„dejƒZGdd„dejƒZGdd	„d	ejƒZGd
d„deejƒZGdd
„d
eejƒZej	deƒj
eƒjeeeed�ZdZ
e e
¡ZdS)zÕ

    webencodings.x_user_defined
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~

    An implementation of the x-user-defined encoding.

    :copyright: Copyright 2012 by Simon Sapin
    :license: BSD, see LICENSE for details.

é)Úunicode_literalsNc@s eZdZddd„Zddd„ZdS)	ÚCodecÚstrictcCst ||t¡S©N)ÚcodecsÚcharmap_encodeÚencoding_table©ÚselfÚinputÚerrors©r
úK/usr/lib/python3.8/site-packages/pip/_vendor/webencodings/x_user_defined.pyÚencodeszCodec.encodecCst ||t¡Sr)rÚcharmap_decodeÚdecoding_tabler	r
r
rÚdecodeszCodec.decodeN)r)r)Ú__name__Ú
__module__Ú__qualname__rrr
r
r
rrs
rc@seZdZddd„ZdS)ÚIncrementalEncoderFcCst ||jt¡dS©Nr)rrrr©r
rÚfinalr
r
rrszIncrementalEncoder.encodeN)F)rrrrr
r
r
rrsrc@seZdZddd„ZdS)ÚIncrementalDecoderFcCst ||jt¡dSr)rrrrrr
r
rr$szIncrementalDecoder.decodeN)F)rrrrr
r
r
rr#src@seZdZdS)ÚStreamWriterN©rrrr
r
r
rr(src@seZdZdS)ÚStreamReaderNrr
r
r
rr,srzx-user-defined)ÚnamerrÚincrementalencoderÚincrementaldecoderÚstreamreaderÚstreamwriteru	

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ïž�ïž�ïž�ïž�ïž�ïŸ�ïŸ�ïŸ�ïŸ�ïŸ�)Ú__doc__Z
__future__rrrrrrrÚ	CodecInforrZ
codec_inforÚ
charmap_buildrr
r
r
rÚs*	ùÿPKÔ¶N]ÒТYÇÇGsite-packages/pip/_vendor/webencodings/__pycache__/tests.cpython-38.pycnu„[µü¤U

ÀÒ.e£ã@sˆdZddlmZddlmZmZmZmZmZm	Z	m
Z
mZmZdd„Z
dd„Zd	d
„Zdd„Zd
d„Zdd„Zdd„Zdd„Zdd„ZdS)z²

    webencodings.tests
    ~~~~~~~~~~~~~~~~~~

    A basic test suite for Encoding.

    :copyright: Copyright 2012 by Simon Sapin
    :license: BSD, see LICENSE for details.

é)Úunicode_literalsé)	ÚlookupÚLABELSÚdecodeÚencodeÚiter_decodeÚiter_encodeÚIncrementalDecoderÚIncrementalEncoderÚUTF8cOs6z|||ŽWn|k
r$YdSXtd|ƒ‚dS)NzDid not raise %s.©ÚAssertionError)Z	exceptionZfunctionÚargsÚkwargs©rúB/usr/lib/python3.8/site-packages/pip/_vendor/webencodings/tests.pyÚ
assert_raisess
rcCstdƒjdkst‚tdƒjdks$t‚tdƒjdks6t‚tdƒjdksHt‚tdƒjdksZt‚tdƒjdkslt‚tdƒjdks~t‚tdƒdksŽt‚tdƒdksžt‚td	ƒjd
ks°t‚tdƒjd
ksÂt‚tdƒjd
ksÔt‚td
ƒjd
ksæt‚tdƒdksöt‚tdƒdk�st‚dS)Nzutf-8zUtf-8zUTF-8Úutf8zutf8 z 
utf8	Úu8uutf-8 zUS-ASCIIzwindows-1252z
iso-8859-1Úlatin1ZLATIN1zlatin-1uLATİN1)rÚnamerrrrrÚtest_labelssrcCstD]Ú}td|ƒdt|ƒfks"t‚td|ƒdks4t‚dD]D}tdg||ƒ\}}t|ƒgks`t‚ttdg||ƒƒgks8t‚q8t|ƒ}| d¡dks˜t‚|jddd�dks®t‚t	|ƒ}| d¡dksÈt‚|jddd�dkst‚qt
t ¡ƒD]}t|ƒj|ksìt‚qìdS)NóÚ)rréT)Úfinal)
rrrrrrÚlistr	r
rÚsetÚvaluesr)ZlabelÚrepeatÚoutputÚ_ÚdecoderÚencoderrrrrÚtest_all_labels0sr%cCsTtttddƒtttddƒtttgdƒtttgdƒtttdƒtttdƒdS)NóéZinvalidõé)rÚLookupErrorrrrr	r
rrrrrÚtest_invalid_labelCsr)cCs¶tddƒdtdƒfkst‚tdtdƒƒdtdƒfks8t‚tddƒdtdƒfksRt‚tdtƒdtdƒfkslt‚tddƒdtdƒfks†t‚td	dƒdtdƒfks t‚td
dƒdtdƒfksºt‚tddƒdtd
ƒfksÔt‚tddƒdtdƒfksît‚tddƒdtd
ƒfk�s
t‚tddƒdtdƒfk�s&t‚tddƒdtd
ƒfk�sBt‚tddƒdtd
ƒfk�s^t‚tddƒdtdƒfk�szt‚tddƒdtd
ƒfk�s–t‚tddƒdtd
ƒfk�s²t‚dS)Nó€ru€óérr'Úasciiõér&óþÿéúutf-16beóÿþéúutf-16lesþÿéusÿþéóézUTF-16BEóézUTF-16LEzUTF-16)rrrrrrrrÚtest_decodeLs r4cCsptddƒdkst‚tddƒdks$t‚tddƒdks6t‚tddƒdksHt‚tddƒdksZt‚tdd	ƒd
kslt‚dS)Nr'róérr+úutf-16r3r1r/r2)rrrrrrÚtest_encodebsr7cCsŽdd„}|gdƒdkst‚|dgdƒdks.t‚|dgdƒdksBt‚|dgdƒd	ksVt‚|d
dgdƒd	kslt‚|dd
gdƒd	ks‚t‚|dgdƒdks–t‚|dgdƒdksªt‚|dddgdƒdksÂt‚|dddgdƒdksÚt‚|ddddddgdƒdksøt‚|dgdƒdk�st‚|dgdƒdk�s$t‚|dgdƒdk�s:t‚|dgdƒdk�sPt‚|ddddddgdƒdk�spt‚|dddgd ƒd!k�sŠt‚dS)"NcSst||ƒ\}}d |¡S)Nr)rÚjoin)ÚinputZfallback_encodingr!Z	_encodingrrrÚiter_decode_to_stringlsz/test_iter_decode..iter_decode_to_stringrrrr5r'shelloZhellosheslloshellóor+r-r&sóÃó©óaua�óïs»¿Ãsï»uï»r.r0óÿsþéóshéúx-user-defineduhllor
)r:rrrÚtest_iter_decodeks€ÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿrCcCsðd tgdƒ¡dkst‚d tdgdƒ¡dks2t‚d tdgdƒ¡dksLt‚d tddddgdƒ¡dkslt‚d tddddgdƒ¡dksŒt‚d tddddgdƒ¡dks¬t‚d tddddgd	ƒ¡d
ksÌt‚d tddddgd
ƒ¡dksìt‚dS)Nrrrr'r5r6r3r1r/r2uhZllorBshéllo)r8r	rrrrrÚtest_iter_encode‡s"    ÿÿÿrDcCs@d}d}d}d}t|dƒ|tdƒfks*t‚t|dƒ|kss,			PKÔ¶N]Ô½­ÂG
G
Psite-packages/pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-38.pycnu„[µü¤U

ÀÒ.eÓã	@s¨dZddlmZddlZGdd„dejƒZGdd„dejƒZGdd	„d	ejƒZGd
d„deejƒZGdd
„d
eejƒZej	deƒj
eƒjeeeed�ZdZ
e e
¡ZdS)zÕ

    webencodings.x_user_defined
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~

    An implementation of the x-user-defined encoding.

    :copyright: Copyright 2012 by Simon Sapin
    :license: BSD, see LICENSE for details.

é)Úunicode_literalsNc@s eZdZddd„Zddd„ZdS)	ÚCodecÚstrictcCst ||t¡S©N)ÚcodecsÚcharmap_encodeÚencoding_table©ÚselfÚinputÚerrors©r
úK/usr/lib/python3.8/site-packages/pip/_vendor/webencodings/x_user_defined.pyÚencodeszCodec.encodecCst ||t¡Sr)rÚcharmap_decodeÚdecoding_tabler	r
r
rÚdecodeszCodec.decodeN)r)r)Ú__name__Ú
__module__Ú__qualname__rrr
r
r
rrs
rc@seZdZddd„ZdS)ÚIncrementalEncoderFcCst ||jt¡dS©Nr)rrrr©r
rÚfinalr
r
rrszIncrementalEncoder.encodeN)F)rrrrr
r
r
rrsrc@seZdZddd„ZdS)ÚIncrementalDecoderFcCst ||jt¡dSr)rrrrrr
r
rr$szIncrementalDecoder.decodeN)F)rrrrr
r
r
rr#src@seZdZdS)ÚStreamWriterN©rrrr
r
r
rr(src@seZdZdS)ÚStreamReaderNrr
r
r
rr,srzx-user-defined)ÚnamerrÚincrementalencoderÚincrementaldecoderÚstreamreaderÚstreamwriteru	

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ïž�ïž�ïž�ïž�ïž�ïŸ�ïŸ�ïŸ�ïŸ�ïŸ�)Ú__doc__Z
__future__rrrrrrrÚ	CodecInforrZ
codec_inforÚ
charmap_buildrr
r
r
rÚs*	ùÿPKÔ¶N]àO¶ØÙÙHsite-packages/pip/_vendor/webencodings/__pycache__/labels.cpython-38.pycnu„[µü¤U

ÀÒ.e#ã×@sºdZddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd	d	d	d	d	d	d	d	d	d	d	d
d
d
ddddddddddd
d
d
dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd d!d!d!d!d!d"d"d"d#d#d$d$d$d$d$d$d$d%d%d%d%d%d%d%d%d%d%d&d&d'd(d(d)d*œÖZd+S),z¶

    webencodings.labels
    ~~~~~~~~~~~~~~~~~~~

    Map encoding labels to their name.

    :copyright: Copyright 2012 by Simon Sapin
    :license: BSD, see LICENSE for details.

úutf-8Úibm866ú
iso-8859-2ú
iso-8859-3ú
iso-8859-4ú
iso-8859-5ú
iso-8859-6ú
iso-8859-7ú
iso-8859-8úiso-8859-8-iúiso-8859-10úiso-8859-13úiso-8859-14úiso-8859-15úiso-8859-16úkoi8-rúkoi8-uÚ	macintoshúwindows-874úwindows-1250úwindows-1251úwindows-1252úwindows-1253úwindows-1254úwindows-1255úwindows-1256úwindows-1257úwindows-1258úx-mac-cyrillicÚgbkÚgb18030ú
hz-gb-2312Úbig5úeuc-jpúiso-2022-jpÚ	shift_jisúeuc-krúiso-2022-krúutf-16beúutf-16leúx-user-defined)Özunicode-1-1-utf-8rÚutf8Ú866Úcp866Úcsibm866rÚcsisolatin2rz
iso-ir-101z	iso8859-2Ziso88592z
iso_8859-2ziso_8859-2:1987Úl2Úlatin2Úcsisolatin3rz
iso-ir-109z	iso8859-3Ziso88593z
iso_8859-3ziso_8859-3:1988Úl3Úlatin3Úcsisolatin4rz
iso-ir-110z	iso8859-4Ziso88594z
iso_8859-4ziso_8859-4:1988Úl4Úlatin4ÚcsisolatincyrillicÚcyrillicrz
iso-ir-144z	iso8859-5Ziso88595z
iso_8859-5ziso_8859-5:1988Úarabiczasmo-708Zcsiso88596eZcsiso88596iÚcsisolatinarabiczecma-114rziso-8859-6-eziso-8859-6-iz
iso-ir-127z	iso8859-6Ziso88596z
iso_8859-6ziso_8859-6:1987Úcsisolatingreekzecma-118Úelot_928ÚgreekÚgreek8rz
iso-ir-126z	iso8859-7Ziso88597z
iso_8859-7ziso_8859-7:1987Zsun_eu_greekZcsiso88598eÚcsisolatinhebrewÚhebrewr	ziso-8859-8-ez
iso-ir-138z	iso8859-8Ziso88598z
iso_8859-8ziso_8859-8:1988ZvisualZcsiso88598ir
ZlogicalÚcsisolatin6rz
iso-ir-157z
iso8859-10Z	iso885910Úl6Úlatin6rz
iso8859-13Z	iso885913r
z
iso8859-14Z	iso885914Zcsisolatin9rz
iso8859-15Z	iso885915ziso_8859-15Úl9rÚcskoi8rZkoiZkoi8rÚkoi8_rrZcsmacintoshZmacrzx-mac-romanzdos-874ziso-8859-11z
iso8859-11Z	iso885911ztis-620rÚcp1250rzx-cp1250Úcp1251rzx-cp1251zansi_x3.4-1968ÚasciiÚcp1252Úcp819Úcsisolatin1Úibm819z
iso-8859-1z
iso-ir-100z	iso8859-1Ziso88591z
iso_8859-1ziso_8859-1:1987Úl1Úlatin1zus-asciirzx-cp1252Úcp1253rzx-cp1253Úcp1254Úcsisolatin5z
iso-8859-9z
iso-ir-148z	iso8859-9Ziso88599z
iso_8859-9ziso_8859-9:1989Úl5Úlatin5rzx-cp1254Úcp1255rzx-cp1255Úcp1256rzx-cp1256Úcp1257rzx-cp1257Úcp1258rzx-cp1258rzx-mac-ukrainianÚchineseZcsgb2312Úcsiso58gb231280Úgb2312Zgb_2312z
gb_2312-80rz	iso-ir-58zx-gbkrr r!z
big5-hkscszcn-big5Úcsbig5zx-x-big5Zcseucpkdfmtjapaneser"zx-euc-jpÚcsiso2022jpr#Ú
csshiftjisÚms_kanjiz	shift-jisr$Úsjiszwindows-31jzx-sjisZcseuckrZ
csksc56011987r%z
iso-ir-149Úkoreanzks_c_5601-1987zks_c_5601-1989Úksc5601Zksc_5601zwindows-949Úcsiso2022krr&r'zutf-16r(r)N)Ú__doc__ZLABELS©rereúC/usr/lib/python3.8/site-packages/pip/_vendor/webencodings/labels.pyÚs°€ªPKÔ¶N]¥(/g	g	Msite-packages/pip/_vendor/webencodings/__pycache__/tests.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.e£ã@sˆdZddlmZddlmZmZmZmZmZm	Z	m
Z
mZmZdd„Z
dd„Zd	d
„Zdd„Zd
d„Zdd„Zdd„Zdd„Zdd„ZdS)z²

    webencodings.tests
    ~~~~~~~~~~~~~~~~~~

    A basic test suite for Encoding.

    :copyright: Copyright 2012 by Simon Sapin
    :license: BSD, see LICENSE for details.

é)Úunicode_literalsé)	ÚlookupÚLABELSÚdecodeÚencodeÚiter_decodeÚiter_encodeÚIncrementalDecoderÚIncrementalEncoderÚUTF8cOs6z|||ŽWn|k
r$YdSXtd|ƒ‚dS)NzDid not raise %s.)ÚAssertionError)Z	exceptionZfunctionÚargsÚkwargs©rúB/usr/lib/python3.8/site-packages/pip/_vendor/webencodings/tests.pyÚ
assert_raisess
rcCsdS©NrrrrrÚtest_labelssrcCsNtD]2}dD]}tdg||ƒ\}}qt|ƒ}t|ƒ}qtt ¡ƒD]}qDdS)N)rréó)rrr
rÚsetÚvalues)ZlabelÚrepeatÚoutputÚ_ÚdecoderÚencoderÚnamerrrÚtest_all_labels0srcCsTtttddƒtttddƒtttgdƒtttgdƒtttdƒtttdƒdS)NséZinvalidõé)rÚLookupErrorrrrr	r
rrrrrÚtest_invalid_labelCsr"cCsdSrrrrrrÚtest_decodeLsr#cCsdSrrrrrrÚtest_encodebsr$cCsdd„}dS)NcSst||ƒ\}}d |¡S)NÚ)rÚjoin)ÚinputZfallback_encodingrZ	_encodingrrrÚiter_decode_to_stringlsz/test_iter_decode..iter_decode_to_stringr)r(rrrÚtest_iter_decodeksr)cCsdSrrrrrrÚtest_iter_encode‡sr*cCsd}d}d}d}dS)Ns2,OÙ#ËÉ»tϨÊu2,O#tïŸ�saaZaar)ZencodedZdecodedrrrÚtest_x_user_defined“s
r+N)Ú__doc__Z
__future__rr%rrrrrr	r
rrrrrr"r#r$r)r*r+rrrrÚs,			PKÔ¶N]ª3äç%ç%Jsite-packages/pip/_vendor/webencodings/__pycache__/__init__.cpython-38.pycnu„[µü¤U

ÀÒ.eS)ã@sædZddlmZddlZddlmZdZddd	d
dœZiZdd
„Z	dd„Z
dd„ZGdd„deƒZ
e
dƒZe
dƒZe
dƒZd+dd„Zdd„Zedfdd„Zd,dd „Zd!d"„Zedfd#d$„Zd%d&„ZGd'd(„d(eƒZGd)d*„d*eƒZdS)-a

    webencodings
    ~~~~~~~~~~~~

    This is a Python implementation of the `WHATWG Encoding standard
    `. See README for details.

    :copyright: Copyright 2012 by Simon Sapin
    :license: BSD, see LICENSE for details.

é)Úunicode_literalsNé)ÚLABELSz0.5.1z
iso-8859-8zmac-cyrillicz	mac-romanZcp874)ziso-8859-8-izx-mac-cyrillicÚ	macintoshzwindows-874cCs| d¡ ¡ d¡S)a9Transform (only) ASCII letters to lower case: A-Z is mapped to a-z.

    :param string: An Unicode string.
    :returns: A new Unicode string.

    This is used for `ASCII case-insensitive
    `_
    matching of encoding labels.
    The same matching is also used, among other things,
    for `CSS keywords `_.

    This is different from the :meth:`~py:str.lower` method of Unicode strings
    which also affect non-ASCII characters,
    sometimes mapping them into the ASCII range:

        >>> keyword = u'Bac\N{KELVIN SIGN}ground'
        >>> assert keyword.lower() == u'background'
        >>> assert ascii_lower(keyword) != keyword.lower()
        >>> assert ascii_lower(keyword) == u'bac\N{KELVIN SIGN}ground'

    Úutf8)ÚencodeÚlowerÚdecode)Ústring©rúE/usr/lib/python3.8/site-packages/pip/_vendor/webencodings/__init__.pyÚascii_lower#sr
cCsxt| d¡ƒ}t |¡}|dkr$dSt |¡}|dkrt|dkrLddlm}nt ||¡}t 	|¡}t
||ƒ}|t|<|S)u<
    Look for an encoding by its label.
    This is the spec’s `get an encoding
    `_ algorithm.
    Supported labels are listed there.

    :param label: A string.
    :returns:
        An :class:`Encoding` object, or :obj:`None` for an unknown label.

    z	

 Nzx-user-definedr)Ú
codec_info)r
ÚstriprÚgetÚCACHEZx_user_definedrÚPYTHON_NAMESÚcodecsÚlookupÚEncoding)ZlabelÚnameÚencodingrZpython_namerrrr=s




rcCs.t|dƒr|St|ƒ}|dkr*td|ƒ‚|S)zç
    Accept either an encoding object or label.

    :param encoding: An :class:`Encoding` object or a label string.
    :returns: An :class:`Encoding` object.
    :raises: :exc:`~exceptions.LookupError` for an unknown label.

    rNzUnknown encoding label: %r)ÚhasattrrÚLookupError)Zencoding_or_labelrrrrÚ
_get_encoding[s	
rc@s eZdZdZdd„Zdd„ZdS)raOReresents a character encoding such as UTF-8,
    that can be used for decoding or encoding.

    .. attribute:: name

        Canonical name of the encoding

    .. attribute:: codec_info

        The actual implementation of the encoding,
        a stdlib :class:`~codecs.CodecInfo` object.
        See :func:`codecs.register`.

    cCs||_||_dS©N)rr)ÚselfrrrrrÚ__init__|szEncoding.__init__cCs
d|jS)Nz
)r)rrrrÚ__repr__€szEncoding.__repr__N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rrrrrrrmsrzutf-8zutf-16lezutf-16beÚreplacecCs2t|ƒ}t|ƒ\}}|p|}|j ||¡d|fS)aÖ
    Decode a single string.

    :param input: A byte string
    :param fallback_encoding:
        An :class:`Encoding` object or a label string.
        The encoding to use if :obj:`input` does note have a BOM.
    :param errors: Type of error handling. See :func:`codecs.register`.
    :raises: :exc:`~exceptions.LookupError` for an unknown encoding label.
    :return:
        A ``(output, encoding)`` tuple of an Unicode string
        and an :obj:`Encoding`.

    r)rÚ_detect_bomrr	)ÚinputÚfallback_encodingÚerrorsZbom_encodingrrrrr	‹sr	cCsV| d¡rt|dd…fS| d¡r4t|dd…fS| d¡rNt|dd…fSd|fS)zBReturn (bom_encoding, input), with any BOM removed from the input.sÿþéNsþÿsé)Ú
startswithÚ_UTF16LEÚ_UTF16BEÚUTF8)r%rrrr$¡s


r$ÚstrictcCst|ƒj ||¡dS)a;
    Encode a single string.

    :param input: An Unicode string.
    :param encoding: An :class:`Encoding` object or a label string.
    :param errors: Type of error handling. See :func:`codecs.register`.
    :raises: :exc:`~exceptions.LookupError` for an unknown encoding label.
    :return: A byte string.

    r)rrr)r%rr'rrrr¬srcCs$t||ƒ}t||ƒ}t|ƒ}||fS)aâ
    "Pull"-based decoder.

    :param input:
        An iterable of byte strings.

        The input is first consumed just enough to determine the encoding
        based on the precense of a BOM,
        then consumed on demand when the return value is.
    :param fallback_encoding:
        An :class:`Encoding` object or a label string.
        The encoding to use if :obj:`input` does note have a BOM.
    :param errors: Type of error handling. See :func:`codecs.register`.
    :raises: :exc:`~exceptions.LookupError` for an unknown encoding label.
    :returns:
        An ``(output, encoding)`` tuple.
        :obj:`output` is an iterable of Unicode strings,
        :obj:`encoding` is the :obj:`Encoding` that is being used.

    )ÚIncrementalDecoderÚ_iter_decode_generatorÚnext)r%r&r'ÚdecoderÚ	generatorrrrrÚiter_decodeºs

r4ccsª|j}t|ƒ}|D]0}||ƒ}|r|jdk	s0t‚|jV|Vqtq|ddd�}|jdk	s^t‚|jV|rp|VdS|D]}||ƒ}|rx|Vqx|ddd�}|r¦|VdS)zqReturn a generator that first yields the :obj:`Encoding`,
    then yields output chukns as Unicode strings.

    NóT©Úfinal)r	ÚiterrÚAssertionError)r%r2r	ÚchunckÚoutputrrrr0Ös,r0cCst||ƒj}t||ƒS)uY
    “Pull�-based encoder.

    :param input: An iterable of Unicode strings.
    :param encoding: An :class:`Encoding` object or a label string.
    :param errors: Type of error handling. See :func:`codecs.register`.
    :raises: :exc:`~exceptions.LookupError` for an unknown encoding label.
    :returns: An iterable of byte strings.

    )ÚIncrementalEncoderrÚ_iter_encode_generator)r%rr'rrrrÚiter_encodeösr>ccs6|D]}||ƒ}|r|Vq|ddd�}|r2|VdS)NÚTr6r)r%rr:r;rrrr=sr=c@s$eZdZdZd	dd„Zd
dd„ZdS)r/uO
    “Push�-based decoder.

    :param fallback_encoding:
        An :class:`Encoding` object or a label string.
        The encoding to use if :obj:`input` does note have a BOM.
    :param errors: Type of error handling. See :func:`codecs.register`.
    :raises: :exc:`~exceptions.LookupError` for an unknown encoding label.

    r#cCs&t|ƒ|_||_d|_d|_d|_dS)Nr5)rÚ_fallback_encodingÚ_errorsÚ_bufferÚ_decoderr)rr&r'rrrrs

zIncrementalDecoder.__init__FcCs||j}|dk	r|||ƒS|j|}t|ƒ\}}|dkrVt|ƒdkrP|sP||_dS|j}|j |j¡j}||_||_	|||ƒS)zùDecode one chunk of the input.

        :param input: A byte string.
        :param final:
            Indicate that no more input is available.
            Must be :obj:`True` if this is the last call.
        :returns: An Unicode string.

        Nr)r?)
rCrBr$Úlenr@rÚincrementaldecoderrAr	r)rr%r7r2rrrrr	's


zIncrementalDecoder.decodeN)r#)F)rr r!r"rr	rrrrr/s

r/c@seZdZdZedfdd„ZdS)r<uù
    “Push�-based encoder.

    :param encoding: An :class:`Encoding` object or a label string.
    :param errors: Type of error handling. See :func:`codecs.register`.
    :raises: :exc:`~exceptions.LookupError` for an unknown encoding label.

    .. method:: encode(input, final=False)

        :param input: An Unicode string.
        :param final:
            Indicate that no more input is available.
            Must be :obj:`True` if this is the last call.
        :returns: A byte string.

    r.cCst|ƒ}|j |¡j|_dSr)rrÚincrementalencoderr)rrr'rrrrTszIncrementalEncoder.__init__N)rr r!r"r-rrrrrr<Csr<)r#)r#)r"Z
__future__rrÚlabelsrZVERSIONrrr
rrÚobjectrr-r+r,r	r$rr4r0r>r=r/r<rrrrÚs4
ü

 
3PKÔ¶N]àO¶ØÙÙNsite-packages/pip/_vendor/webencodings/__pycache__/labels.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.e#ã×@sºdZddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd	d	d	d	d	d	d	d	d	d	d	d
d
d
ddddddddddd
d
d
dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd d!d!d!d!d!d"d"d"d#d#d$d$d$d$d$d$d$d%d%d%d%d%d%d%d%d%d%d&d&d'd(d(d)d*œÖZd+S),z¶

    webencodings.labels
    ~~~~~~~~~~~~~~~~~~~

    Map encoding labels to their name.

    :copyright: Copyright 2012 by Simon Sapin
    :license: BSD, see LICENSE for details.

úutf-8Úibm866ú
iso-8859-2ú
iso-8859-3ú
iso-8859-4ú
iso-8859-5ú
iso-8859-6ú
iso-8859-7ú
iso-8859-8úiso-8859-8-iúiso-8859-10úiso-8859-13úiso-8859-14úiso-8859-15úiso-8859-16úkoi8-rúkoi8-uÚ	macintoshúwindows-874úwindows-1250úwindows-1251úwindows-1252úwindows-1253úwindows-1254úwindows-1255úwindows-1256úwindows-1257úwindows-1258úx-mac-cyrillicÚgbkÚgb18030ú
hz-gb-2312Úbig5úeuc-jpúiso-2022-jpÚ	shift_jisúeuc-krúiso-2022-krúutf-16beúutf-16leúx-user-defined)Özunicode-1-1-utf-8rÚutf8Ú866Úcp866Úcsibm866rÚcsisolatin2rz
iso-ir-101z	iso8859-2Ziso88592z
iso_8859-2ziso_8859-2:1987Úl2Úlatin2Úcsisolatin3rz
iso-ir-109z	iso8859-3Ziso88593z
iso_8859-3ziso_8859-3:1988Úl3Úlatin3Úcsisolatin4rz
iso-ir-110z	iso8859-4Ziso88594z
iso_8859-4ziso_8859-4:1988Úl4Úlatin4ÚcsisolatincyrillicÚcyrillicrz
iso-ir-144z	iso8859-5Ziso88595z
iso_8859-5ziso_8859-5:1988Úarabiczasmo-708Zcsiso88596eZcsiso88596iÚcsisolatinarabiczecma-114rziso-8859-6-eziso-8859-6-iz
iso-ir-127z	iso8859-6Ziso88596z
iso_8859-6ziso_8859-6:1987Úcsisolatingreekzecma-118Úelot_928ÚgreekÚgreek8rz
iso-ir-126z	iso8859-7Ziso88597z
iso_8859-7ziso_8859-7:1987Zsun_eu_greekZcsiso88598eÚcsisolatinhebrewÚhebrewr	ziso-8859-8-ez
iso-ir-138z	iso8859-8Ziso88598z
iso_8859-8ziso_8859-8:1988ZvisualZcsiso88598ir
ZlogicalÚcsisolatin6rz
iso-ir-157z
iso8859-10Z	iso885910Úl6Úlatin6rz
iso8859-13Z	iso885913r
z
iso8859-14Z	iso885914Zcsisolatin9rz
iso8859-15Z	iso885915ziso_8859-15Úl9rÚcskoi8rZkoiZkoi8rÚkoi8_rrZcsmacintoshZmacrzx-mac-romanzdos-874ziso-8859-11z
iso8859-11Z	iso885911ztis-620rÚcp1250rzx-cp1250Úcp1251rzx-cp1251zansi_x3.4-1968ÚasciiÚcp1252Úcp819Úcsisolatin1Úibm819z
iso-8859-1z
iso-ir-100z	iso8859-1Ziso88591z
iso_8859-1ziso_8859-1:1987Úl1Úlatin1zus-asciirzx-cp1252Úcp1253rzx-cp1253Úcp1254Úcsisolatin5z
iso-8859-9z
iso-ir-148z	iso8859-9Ziso88599z
iso_8859-9ziso_8859-9:1989Úl5Úlatin5rzx-cp1254Úcp1255rzx-cp1255Úcp1256rzx-cp1256Úcp1257rzx-cp1257Úcp1258rzx-cp1258rzx-mac-ukrainianÚchineseZcsgb2312Úcsiso58gb231280Úgb2312Zgb_2312z
gb_2312-80rz	iso-ir-58zx-gbkrr r!z
big5-hkscszcn-big5Úcsbig5zx-x-big5Zcseucpkdfmtjapaneser"zx-euc-jpÚcsiso2022jpr#Ú
csshiftjisÚms_kanjiz	shift-jisr$Úsjiszwindows-31jzx-sjisZcseuckrZ
csksc56011987r%z
iso-ir-149Úkoreanzks_c_5601-1987zks_c_5601-1989Úksc5601Zksc_5601zwindows-949Úcsiso2022krr&r'zutf-16r(r)N)Ú__doc__ZLABELS©rereúC/usr/lib/python3.8/site-packages/pip/_vendor/webencodings/labels.pyÚs°€ªPKÔ¶N]Ç­‹##0site-packages/pip/_vendor/webencodings/labels.pynu„[µü¤"""

    webencodings.labels
    ~~~~~~~~~~~~~~~~~~~

    Map encoding labels to their name.

    :copyright: Copyright 2012 by Simon Sapin
    :license: BSD, see LICENSE for details.

"""

# XXX Do not edit!
# This file is automatically generated by mklabels.py

LABELS = {
    'unicode-1-1-utf-8':   'utf-8',
    'utf-8':               'utf-8',
    'utf8':                'utf-8',
    '866':                 'ibm866',
    'cp866':               'ibm866',
    'csibm866':            'ibm866',
    'ibm866':              'ibm866',
    'csisolatin2':         'iso-8859-2',
    'iso-8859-2':          'iso-8859-2',
    'iso-ir-101':          'iso-8859-2',
    'iso8859-2':           'iso-8859-2',
    'iso88592':            'iso-8859-2',
    'iso_8859-2':          'iso-8859-2',
    'iso_8859-2:1987':     'iso-8859-2',
    'l2':                  'iso-8859-2',
    'latin2':              'iso-8859-2',
    'csisolatin3':         'iso-8859-3',
    'iso-8859-3':          'iso-8859-3',
    'iso-ir-109':          'iso-8859-3',
    'iso8859-3':           'iso-8859-3',
    'iso88593':            'iso-8859-3',
    'iso_8859-3':          'iso-8859-3',
    'iso_8859-3:1988':     'iso-8859-3',
    'l3':                  'iso-8859-3',
    'latin3':              'iso-8859-3',
    'csisolatin4':         'iso-8859-4',
    'iso-8859-4':          'iso-8859-4',
    'iso-ir-110':          'iso-8859-4',
    'iso8859-4':           'iso-8859-4',
    'iso88594':            'iso-8859-4',
    'iso_8859-4':          'iso-8859-4',
    'iso_8859-4:1988':     'iso-8859-4',
    'l4':                  'iso-8859-4',
    'latin4':              'iso-8859-4',
    'csisolatincyrillic':  'iso-8859-5',
    'cyrillic':            'iso-8859-5',
    'iso-8859-5':          'iso-8859-5',
    'iso-ir-144':          'iso-8859-5',
    'iso8859-5':           'iso-8859-5',
    'iso88595':            'iso-8859-5',
    'iso_8859-5':          'iso-8859-5',
    'iso_8859-5:1988':     'iso-8859-5',
    'arabic':              'iso-8859-6',
    'asmo-708':            'iso-8859-6',
    'csiso88596e':         'iso-8859-6',
    'csiso88596i':         'iso-8859-6',
    'csisolatinarabic':    'iso-8859-6',
    'ecma-114':            'iso-8859-6',
    'iso-8859-6':          'iso-8859-6',
    'iso-8859-6-e':        'iso-8859-6',
    'iso-8859-6-i':        'iso-8859-6',
    'iso-ir-127':          'iso-8859-6',
    'iso8859-6':           'iso-8859-6',
    'iso88596':            'iso-8859-6',
    'iso_8859-6':          'iso-8859-6',
    'iso_8859-6:1987':     'iso-8859-6',
    'csisolatingreek':     'iso-8859-7',
    'ecma-118':            'iso-8859-7',
    'elot_928':            'iso-8859-7',
    'greek':               'iso-8859-7',
    'greek8':              'iso-8859-7',
    'iso-8859-7':          'iso-8859-7',
    'iso-ir-126':          'iso-8859-7',
    'iso8859-7':           'iso-8859-7',
    'iso88597':            'iso-8859-7',
    'iso_8859-7':          'iso-8859-7',
    'iso_8859-7:1987':     'iso-8859-7',
    'sun_eu_greek':        'iso-8859-7',
    'csiso88598e':         'iso-8859-8',
    'csisolatinhebrew':    'iso-8859-8',
    'hebrew':              'iso-8859-8',
    'iso-8859-8':          'iso-8859-8',
    'iso-8859-8-e':        'iso-8859-8',
    'iso-ir-138':          'iso-8859-8',
    'iso8859-8':           'iso-8859-8',
    'iso88598':            'iso-8859-8',
    'iso_8859-8':          'iso-8859-8',
    'iso_8859-8:1988':     'iso-8859-8',
    'visual':              'iso-8859-8',
    'csiso88598i':         'iso-8859-8-i',
    'iso-8859-8-i':        'iso-8859-8-i',
    'logical':             'iso-8859-8-i',
    'csisolatin6':         'iso-8859-10',
    'iso-8859-10':         'iso-8859-10',
    'iso-ir-157':          'iso-8859-10',
    'iso8859-10':          'iso-8859-10',
    'iso885910':           'iso-8859-10',
    'l6':                  'iso-8859-10',
    'latin6':              'iso-8859-10',
    'iso-8859-13':         'iso-8859-13',
    'iso8859-13':          'iso-8859-13',
    'iso885913':           'iso-8859-13',
    'iso-8859-14':         'iso-8859-14',
    'iso8859-14':          'iso-8859-14',
    'iso885914':           'iso-8859-14',
    'csisolatin9':         'iso-8859-15',
    'iso-8859-15':         'iso-8859-15',
    'iso8859-15':          'iso-8859-15',
    'iso885915':           'iso-8859-15',
    'iso_8859-15':         'iso-8859-15',
    'l9':                  'iso-8859-15',
    'iso-8859-16':         'iso-8859-16',
    'cskoi8r':             'koi8-r',
    'koi':                 'koi8-r',
    'koi8':                'koi8-r',
    'koi8-r':              'koi8-r',
    'koi8_r':              'koi8-r',
    'koi8-u':              'koi8-u',
    'csmacintosh':         'macintosh',
    'mac':                 'macintosh',
    'macintosh':           'macintosh',
    'x-mac-roman':         'macintosh',
    'dos-874':             'windows-874',
    'iso-8859-11':         'windows-874',
    'iso8859-11':          'windows-874',
    'iso885911':           'windows-874',
    'tis-620':             'windows-874',
    'windows-874':         'windows-874',
    'cp1250':              'windows-1250',
    'windows-1250':        'windows-1250',
    'x-cp1250':            'windows-1250',
    'cp1251':              'windows-1251',
    'windows-1251':        'windows-1251',
    'x-cp1251':            'windows-1251',
    'ansi_x3.4-1968':      'windows-1252',
    'ascii':               'windows-1252',
    'cp1252':              'windows-1252',
    'cp819':               'windows-1252',
    'csisolatin1':         'windows-1252',
    'ibm819':              'windows-1252',
    'iso-8859-1':          'windows-1252',
    'iso-ir-100':          'windows-1252',
    'iso8859-1':           'windows-1252',
    'iso88591':            'windows-1252',
    'iso_8859-1':          'windows-1252',
    'iso_8859-1:1987':     'windows-1252',
    'l1':                  'windows-1252',
    'latin1':              'windows-1252',
    'us-ascii':            'windows-1252',
    'windows-1252':        'windows-1252',
    'x-cp1252':            'windows-1252',
    'cp1253':              'windows-1253',
    'windows-1253':        'windows-1253',
    'x-cp1253':            'windows-1253',
    'cp1254':              'windows-1254',
    'csisolatin5':         'windows-1254',
    'iso-8859-9':          'windows-1254',
    'iso-ir-148':          'windows-1254',
    'iso8859-9':           'windows-1254',
    'iso88599':            'windows-1254',
    'iso_8859-9':          'windows-1254',
    'iso_8859-9:1989':     'windows-1254',
    'l5':                  'windows-1254',
    'latin5':              'windows-1254',
    'windows-1254':        'windows-1254',
    'x-cp1254':            'windows-1254',
    'cp1255':              'windows-1255',
    'windows-1255':        'windows-1255',
    'x-cp1255':            'windows-1255',
    'cp1256':              'windows-1256',
    'windows-1256':        'windows-1256',
    'x-cp1256':            'windows-1256',
    'cp1257':              'windows-1257',
    'windows-1257':        'windows-1257',
    'x-cp1257':            'windows-1257',
    'cp1258':              'windows-1258',
    'windows-1258':        'windows-1258',
    'x-cp1258':            'windows-1258',
    'x-mac-cyrillic':      'x-mac-cyrillic',
    'x-mac-ukrainian':     'x-mac-cyrillic',
    'chinese':             'gbk',
    'csgb2312':            'gbk',
    'csiso58gb231280':     'gbk',
    'gb2312':              'gbk',
    'gb_2312':             'gbk',
    'gb_2312-80':          'gbk',
    'gbk':                 'gbk',
    'iso-ir-58':           'gbk',
    'x-gbk':               'gbk',
    'gb18030':             'gb18030',
    'hz-gb-2312':          'hz-gb-2312',
    'big5':                'big5',
    'big5-hkscs':          'big5',
    'cn-big5':             'big5',
    'csbig5':              'big5',
    'x-x-big5':            'big5',
    'cseucpkdfmtjapanese': 'euc-jp',
    'euc-jp':              'euc-jp',
    'x-euc-jp':            'euc-jp',
    'csiso2022jp':         'iso-2022-jp',
    'iso-2022-jp':         'iso-2022-jp',
    'csshiftjis':          'shift_jis',
    'ms_kanji':            'shift_jis',
    'shift-jis':           'shift_jis',
    'shift_jis':           'shift_jis',
    'sjis':                'shift_jis',
    'windows-31j':         'shift_jis',
    'x-sjis':              'shift_jis',
    'cseuckr':             'euc-kr',
    'csksc56011987':       'euc-kr',
    'euc-kr':              'euc-kr',
    'iso-ir-149':          'euc-kr',
    'korean':              'euc-kr',
    'ks_c_5601-1987':      'euc-kr',
    'ks_c_5601-1989':      'euc-kr',
    'ksc5601':             'euc-kr',
    'ksc_5601':            'euc-kr',
    'windows-949':         'euc-kr',
    'csiso2022kr':         'iso-2022-kr',
    'iso-2022-kr':         'iso-2022-kr',
    'utf-16be':            'utf-16be',
    'utf-16':              'utf-16le',
    'utf-16le':            'utf-16le',
    'x-user-defined':      'x-user-defined',
}
PKÔ¶N]P12site-packages/pip/_vendor/webencodings/mklabels.pynu„[µü¤"""

    webencodings.mklabels
    ~~~~~~~~~~~~~~~~~~~~~

    Regenarate the webencodings.labels module.

    :copyright: Copyright 2012 by Simon Sapin
    :license: BSD, see LICENSE for details.

"""

import json
try:
    from urllib import urlopen
except ImportError:
    from urllib.request import urlopen


def assert_lower(string):
    assert string == string.lower()
    return string


def generate(url):
    parts = ['''\
"""

    webencodings.labels
    ~~~~~~~~~~~~~~~~~~~

    Map encoding labels to their name.

    :copyright: Copyright 2012 by Simon Sapin
    :license: BSD, see LICENSE for details.

"""

# XXX Do not edit!
# This file is automatically generated by mklabels.py

LABELS = {
''']
    labels = [
        (repr(assert_lower(label)).lstrip('u'),
         repr(encoding['name']).lstrip('u'))
        for category in json.loads(urlopen(url).read().decode('ascii'))
        for encoding in category['encodings']
        for label in encoding['labels']]
    max_len = max(len(label) for label, name in labels)
    parts.extend(
        '    %s:%s %s,\n' % (label, ' ' * (max_len - len(label)), name)
        for label, name in labels)
    parts.append('}')
    return ''.join(parts)


if __name__ == '__main__':
    print(generate('http://encoding.spec.whatwg.org/encodings.json'))
PKÔ¶N]ÛüÖÓÓ8site-packages/pip/_vendor/webencodings/x_user_defined.pynu„[µü¤# coding: utf-8
"""

    webencodings.x_user_defined
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~

    An implementation of the x-user-defined encoding.

    :copyright: Copyright 2012 by Simon Sapin
    :license: BSD, see LICENSE for details.

"""

from __future__ import unicode_literals

import codecs


### Codec APIs

class Codec(codecs.Codec):

    def encode(self, input, errors='strict'):
        return codecs.charmap_encode(input, errors, encoding_table)

    def decode(self, input, errors='strict'):
        return codecs.charmap_decode(input, errors, decoding_table)


class IncrementalEncoder(codecs.IncrementalEncoder):
    def encode(self, input, final=False):
        return codecs.charmap_encode(input, self.errors, encoding_table)[0]


class IncrementalDecoder(codecs.IncrementalDecoder):
    def decode(self, input, final=False):
        return codecs.charmap_decode(input, self.errors, decoding_table)[0]


class StreamWriter(Codec, codecs.StreamWriter):
    pass


class StreamReader(Codec, codecs.StreamReader):
    pass


### encodings module API

codec_info = codecs.CodecInfo(
    name='x-user-defined',
    encode=Codec().encode,
    decode=Codec().decode,
    incrementalencoder=IncrementalEncoder,
    incrementaldecoder=IncrementalDecoder,
    streamreader=StreamReader,
    streamwriter=StreamWriter,
)


### Decoding Table

# Python 3:
# for c in range(256): print('    %r' % chr(c if c < 128 else c + 0xF700))
decoding_table = (
    '\x00'
    '\x01'
    '\x02'
    '\x03'
    '\x04'
    '\x05'
    '\x06'
    '\x07'
    '\x08'
    '\t'
    '\n'
    '\x0b'
    '\x0c'
    '\r'
    '\x0e'
    '\x0f'
    '\x10'
    '\x11'
    '\x12'
    '\x13'
    '\x14'
    '\x15'
    '\x16'
    '\x17'
    '\x18'
    '\x19'
    '\x1a'
    '\x1b'
    '\x1c'
    '\x1d'
    '\x1e'
    '\x1f'
    ' '
    '!'
    '"'
    '#'
    '$'
    '%'
    '&'
    "'"
    '('
    ')'
    '*'
    '+'
    ','
    '-'
    '.'
    '/'
    '0'
    '1'
    '2'
    '3'
    '4'
    '5'
    '6'
    '7'
    '8'
    '9'
    ':'
    ';'
    '<'
    '='
    '>'
    '?'
    '@'
    'A'
    'B'
    'C'
    'D'
    'E'
    'F'
    'G'
    'H'
    'I'
    'J'
    'K'
    'L'
    'M'
    'N'
    'O'
    'P'
    'Q'
    'R'
    'S'
    'T'
    'U'
    'V'
    'W'
    'X'
    'Y'
    'Z'
    '['
    '\\'
    ']'
    '^'
    '_'
    '`'
    'a'
    'b'
    'c'
    'd'
    'e'
    'f'
    'g'
    'h'
    'i'
    'j'
    'k'
    'l'
    'm'
    'n'
    'o'
    'p'
    'q'
    'r'
    's'
    't'
    'u'
    'v'
    'w'
    'x'
    'y'
    'z'
    '{'
    '|'
    '}'
    '~'
    '\x7f'
    '\uf780'
    '\uf781'
    '\uf782'
    '\uf783'
    '\uf784'
    '\uf785'
    '\uf786'
    '\uf787'
    '\uf788'
    '\uf789'
    '\uf78a'
    '\uf78b'
    '\uf78c'
    '\uf78d'
    '\uf78e'
    '\uf78f'
    '\uf790'
    '\uf791'
    '\uf792'
    '\uf793'
    '\uf794'
    '\uf795'
    '\uf796'
    '\uf797'
    '\uf798'
    '\uf799'
    '\uf79a'
    '\uf79b'
    '\uf79c'
    '\uf79d'
    '\uf79e'
    '\uf79f'
    '\uf7a0'
    '\uf7a1'
    '\uf7a2'
    '\uf7a3'
    '\uf7a4'
    '\uf7a5'
    '\uf7a6'
    '\uf7a7'
    '\uf7a8'
    '\uf7a9'
    '\uf7aa'
    '\uf7ab'
    '\uf7ac'
    '\uf7ad'
    '\uf7ae'
    '\uf7af'
    '\uf7b0'
    '\uf7b1'
    '\uf7b2'
    '\uf7b3'
    '\uf7b4'
    '\uf7b5'
    '\uf7b6'
    '\uf7b7'
    '\uf7b8'
    '\uf7b9'
    '\uf7ba'
    '\uf7bb'
    '\uf7bc'
    '\uf7bd'
    '\uf7be'
    '\uf7bf'
    '\uf7c0'
    '\uf7c1'
    '\uf7c2'
    '\uf7c3'
    '\uf7c4'
    '\uf7c5'
    '\uf7c6'
    '\uf7c7'
    '\uf7c8'
    '\uf7c9'
    '\uf7ca'
    '\uf7cb'
    '\uf7cc'
    '\uf7cd'
    '\uf7ce'
    '\uf7cf'
    '\uf7d0'
    '\uf7d1'
    '\uf7d2'
    '\uf7d3'
    '\uf7d4'
    '\uf7d5'
    '\uf7d6'
    '\uf7d7'
    '\uf7d8'
    '\uf7d9'
    '\uf7da'
    '\uf7db'
    '\uf7dc'
    '\uf7dd'
    '\uf7de'
    '\uf7df'
    '\uf7e0'
    '\uf7e1'
    '\uf7e2'
    '\uf7e3'
    '\uf7e4'
    '\uf7e5'
    '\uf7e6'
    '\uf7e7'
    '\uf7e8'
    '\uf7e9'
    '\uf7ea'
    '\uf7eb'
    '\uf7ec'
    '\uf7ed'
    '\uf7ee'
    '\uf7ef'
    '\uf7f0'
    '\uf7f1'
    '\uf7f2'
    '\uf7f3'
    '\uf7f4'
    '\uf7f5'
    '\uf7f6'
    '\uf7f7'
    '\uf7f8'
    '\uf7f9'
    '\uf7fa'
    '\uf7fb'
    '\uf7fc'
    '\uf7fd'
    '\uf7fe'
    '\uf7ff'
)

### Encoding table
encoding_table = codecs.charmap_build(decoding_table)
PKÔ¶N]òöÀ|BB(site-packages/pip/_vendor/contextlib2.pynu„[µü¤"""contextlib2 - backports and enhancements to the contextlib module"""

import abc
import sys
import warnings
from collections import deque
from functools import wraps

__all__ = ["contextmanager", "closing", "nullcontext",
           "AbstractContextManager",
           "ContextDecorator", "ExitStack",
           "redirect_stdout", "redirect_stderr", "suppress"]

# Backwards compatibility
__all__ += ["ContextStack"]


# Backport abc.ABC
if sys.version_info[:2] >= (3, 4):
    _abc_ABC = abc.ABC
else:
    _abc_ABC = abc.ABCMeta('ABC', (object,), {'__slots__': ()})


# Backport classic class MRO
def _classic_mro(C, result):
    if C in result:
        return
    result.append(C)
    for B in C.__bases__:
        _classic_mro(B, result)
    return result


# Backport _collections_abc._check_methods
def _check_methods(C, *methods):
    try:
        mro = C.__mro__
    except AttributeError:
        mro = tuple(_classic_mro(C, []))

    for method in methods:
        for B in mro:
            if method in B.__dict__:
                if B.__dict__[method] is None:
                    return NotImplemented
                break
        else:
            return NotImplemented
    return True


class AbstractContextManager(_abc_ABC):
    """An abstract base class for context managers."""

    def __enter__(self):
        """Return `self` upon entering the runtime context."""
        return self

    @abc.abstractmethod
    def __exit__(self, exc_type, exc_value, traceback):
        """Raise any exception triggered within the runtime context."""
        return None

    @classmethod
    def __subclasshook__(cls, C):
        """Check whether subclass is considered a subclass of this ABC."""
        if cls is AbstractContextManager:
            return _check_methods(C, "__enter__", "__exit__")
        return NotImplemented


class ContextDecorator(object):
    """A base class or mixin that enables context managers to work as decorators."""

    def refresh_cm(self):
        """Returns the context manager used to actually wrap the call to the
        decorated function.

        The default implementation just returns *self*.

        Overriding this method allows otherwise one-shot context managers
        like _GeneratorContextManager to support use as decorators via
        implicit recreation.

        DEPRECATED: refresh_cm was never added to the standard library's
                    ContextDecorator API
        """
        warnings.warn("refresh_cm was never added to the standard library",
                      DeprecationWarning)
        return self._recreate_cm()

    def _recreate_cm(self):
        """Return a recreated instance of self.

        Allows an otherwise one-shot context manager like
        _GeneratorContextManager to support use as
        a decorator via implicit recreation.

        This is a private interface just for _GeneratorContextManager.
        See issue #11647 for details.
        """
        return self

    def __call__(self, func):
        @wraps(func)
        def inner(*args, **kwds):
            with self._recreate_cm():
                return func(*args, **kwds)
        return inner


class _GeneratorContextManager(ContextDecorator):
    """Helper for @contextmanager decorator."""

    def __init__(self, func, args, kwds):
        self.gen = func(*args, **kwds)
        self.func, self.args, self.kwds = func, args, kwds
        # Issue 19330: ensure context manager instances have good docstrings
        doc = getattr(func, "__doc__", None)
        if doc is None:
            doc = type(self).__doc__
        self.__doc__ = doc
        # Unfortunately, this still doesn't provide good help output when
        # inspecting the created context manager instances, since pydoc
        # currently bypasses the instance docstring and shows the docstring
        # for the class instead.
        # See http://bugs.python.org/issue19404 for more details.

    def _recreate_cm(self):
        # _GCM instances are one-shot context managers, so the
        # CM must be recreated each time a decorated function is
        # called
        return self.__class__(self.func, self.args, self.kwds)

    def __enter__(self):
        try:
            return next(self.gen)
        except StopIteration:
            raise RuntimeError("generator didn't yield")

    def __exit__(self, type, value, traceback):
        if type is None:
            try:
                next(self.gen)
            except StopIteration:
                return
            else:
                raise RuntimeError("generator didn't stop")
        else:
            if value is None:
                # Need to force instantiation so we can reliably
                # tell if we get the same exception back
                value = type()
            try:
                self.gen.throw(type, value, traceback)
                raise RuntimeError("generator didn't stop after throw()")
            except StopIteration as exc:
                # Suppress StopIteration *unless* it's the same exception that
                # was passed to throw().  This prevents a StopIteration
                # raised inside the "with" statement from being suppressed.
                return exc is not value
            except RuntimeError as exc:
                # Don't re-raise the passed in exception
                if exc is value:
                    return False
                # Likewise, avoid suppressing if a StopIteration exception
                # was passed to throw() and later wrapped into a RuntimeError
                # (see PEP 479).
                if _HAVE_EXCEPTION_CHAINING and exc.__cause__ is value:
                    return False
                raise
            except:
                # only re-raise if it's *not* the exception that was
                # passed to throw(), because __exit__() must not raise
                # an exception unless __exit__() itself failed.  But throw()
                # has to raise the exception to signal propagation, so this
                # fixes the impedance mismatch between the throw() protocol
                # and the __exit__() protocol.
                #
                if sys.exc_info()[1] is not value:
                    raise


def contextmanager(func):
    """@contextmanager decorator.

    Typical usage:

        @contextmanager
        def some_generator():
            
            try:
                yield 
            finally:
                

    This makes this:

        with some_generator() as :
            

    equivalent to this:

        
        try:
             = 
            
        finally:
            

    """
    @wraps(func)
    def helper(*args, **kwds):
        return _GeneratorContextManager(func, args, kwds)
    return helper


class closing(object):
    """Context to automatically close something at the end of a block.

    Code like this:

        with closing(.open()) as f:
            

    is equivalent to this:

        f = .open()
        try:
            
        finally:
            f.close()

    """
    def __init__(self, thing):
        self.thing = thing

    def __enter__(self):
        return self.thing

    def __exit__(self, *exc_info):
        self.thing.close()


class _RedirectStream(object):

    _stream = None

    def __init__(self, new_target):
        self._new_target = new_target
        # We use a list of old targets to make this CM re-entrant
        self._old_targets = []

    def __enter__(self):
        self._old_targets.append(getattr(sys, self._stream))
        setattr(sys, self._stream, self._new_target)
        return self._new_target

    def __exit__(self, exctype, excinst, exctb):
        setattr(sys, self._stream, self._old_targets.pop())


class redirect_stdout(_RedirectStream):
    """Context manager for temporarily redirecting stdout to another file.

        # How to send help() to stderr
        with redirect_stdout(sys.stderr):
            help(dir)

        # How to write help() to a file
        with open('help.txt', 'w') as f:
            with redirect_stdout(f):
                help(pow)
    """

    _stream = "stdout"


class redirect_stderr(_RedirectStream):
    """Context manager for temporarily redirecting stderr to another file."""

    _stream = "stderr"


class suppress(object):
    """Context manager to suppress specified exceptions

    After the exception is suppressed, execution proceeds with the next
    statement following the with statement.

         with suppress(FileNotFoundError):
             os.remove(somefile)
         # Execution still resumes here if the file was already removed
    """

    def __init__(self, *exceptions):
        self._exceptions = exceptions

    def __enter__(self):
        pass

    def __exit__(self, exctype, excinst, exctb):
        # Unlike isinstance and issubclass, CPython exception handling
        # currently only looks at the concrete type hierarchy (ignoring
        # the instance and subclass checking hooks). While Guido considers
        # that a bug rather than a feature, it's a fairly hard one to fix
        # due to various internal implementation details. suppress provides
        # the simpler issubclass based semantics, rather than trying to
        # exactly reproduce the limitations of the CPython interpreter.
        #
        # See http://bugs.python.org/issue12029 for more details
        return exctype is not None and issubclass(exctype, self._exceptions)


# Context manipulation is Python 3 only
_HAVE_EXCEPTION_CHAINING = sys.version_info[0] >= 3
if _HAVE_EXCEPTION_CHAINING:
    def _make_context_fixer(frame_exc):
        def _fix_exception_context(new_exc, old_exc):
            # Context may not be correct, so find the end of the chain
            while 1:
                exc_context = new_exc.__context__
                if exc_context is old_exc:
                    # Context is already set correctly (see issue 20317)
                    return
                if exc_context is None or exc_context is frame_exc:
                    break
                new_exc = exc_context
            # Change the end of the chain to point to the exception
            # we expect it to reference
            new_exc.__context__ = old_exc
        return _fix_exception_context

    def _reraise_with_existing_context(exc_details):
        try:
            # bare "raise exc_details[1]" replaces our carefully
            # set-up context
            fixed_ctx = exc_details[1].__context__
            raise exc_details[1]
        except BaseException:
            exc_details[1].__context__ = fixed_ctx
            raise
else:
    # No exception context in Python 2
    def _make_context_fixer(frame_exc):
        return lambda new_exc, old_exc: None

    # Use 3 argument raise in Python 2,
    # but use exec to avoid SyntaxError in Python 3
    def _reraise_with_existing_context(exc_details):
        exc_type, exc_value, exc_tb = exc_details
        exec("raise exc_type, exc_value, exc_tb")

# Handle old-style classes if they exist
try:
    from types import InstanceType
except ImportError:
    # Python 3 doesn't have old-style classes
    _get_type = type
else:
    # Need to handle old-style context managers on Python 2
    def _get_type(obj):
        obj_type = type(obj)
        if obj_type is InstanceType:
            return obj.__class__  # Old-style class
        return obj_type  # New-style class


# Inspired by discussions on http://bugs.python.org/issue13585
class ExitStack(object):
    """Context manager for dynamic management of a stack of exit callbacks

    For example:

        with ExitStack() as stack:
            files = [stack.enter_context(open(fname)) for fname in filenames]
            # All opened files will automatically be closed at the end of
            # the with statement, even if attempts to open files later
            # in the list raise an exception

    """
    def __init__(self):
        self._exit_callbacks = deque()

    def pop_all(self):
        """Preserve the context stack by transferring it to a new instance"""
        new_stack = type(self)()
        new_stack._exit_callbacks = self._exit_callbacks
        self._exit_callbacks = deque()
        return new_stack

    def _push_cm_exit(self, cm, cm_exit):
        """Helper to correctly register callbacks to __exit__ methods"""
        def _exit_wrapper(*exc_details):
            return cm_exit(cm, *exc_details)
        _exit_wrapper.__self__ = cm
        self.push(_exit_wrapper)

    def push(self, exit):
        """Registers a callback with the standard __exit__ method signature

        Can suppress exceptions the same way __exit__ methods can.

        Also accepts any object with an __exit__ method (registering a call
        to the method instead of the object itself)
        """
        # We use an unbound method rather than a bound method to follow
        # the standard lookup behaviour for special methods
        _cb_type = _get_type(exit)
        try:
            exit_method = _cb_type.__exit__
        except AttributeError:
            # Not a context manager, so assume its a callable
            self._exit_callbacks.append(exit)
        else:
            self._push_cm_exit(exit, exit_method)
        return exit # Allow use as a decorator

    def callback(self, callback, *args, **kwds):
        """Registers an arbitrary callback and arguments.

        Cannot suppress exceptions.
        """
        def _exit_wrapper(exc_type, exc, tb):
            callback(*args, **kwds)
        # We changed the signature, so using @wraps is not appropriate, but
        # setting __wrapped__ may still help with introspection
        _exit_wrapper.__wrapped__ = callback
        self.push(_exit_wrapper)
        return callback # Allow use as a decorator

    def enter_context(self, cm):
        """Enters the supplied context manager

        If successful, also pushes its __exit__ method as a callback and
        returns the result of the __enter__ method.
        """
        # We look up the special methods on the type to match the with statement
        _cm_type = _get_type(cm)
        _exit = _cm_type.__exit__
        result = _cm_type.__enter__(cm)
        self._push_cm_exit(cm, _exit)
        return result

    def close(self):
        """Immediately unwind the context stack"""
        self.__exit__(None, None, None)

    def __enter__(self):
        return self

    def __exit__(self, *exc_details):
        received_exc = exc_details[0] is not None

        # We manipulate the exception state so it behaves as though
        # we were actually nesting multiple with statements
        frame_exc = sys.exc_info()[1]
        _fix_exception_context = _make_context_fixer(frame_exc)

        # Callbacks are invoked in LIFO order to match the behaviour of
        # nested context managers
        suppressed_exc = False
        pending_raise = False
        while self._exit_callbacks:
            cb = self._exit_callbacks.pop()
            try:
                if cb(*exc_details):
                    suppressed_exc = True
                    pending_raise = False
                    exc_details = (None, None, None)
            except:
                new_exc_details = sys.exc_info()
                # simulate the stack of exceptions by setting the context
                _fix_exception_context(new_exc_details[1], exc_details[1])
                pending_raise = True
                exc_details = new_exc_details
        if pending_raise:
            _reraise_with_existing_context(exc_details)
        return received_exc and suppressed_exc


# Preserve backwards compatibility
class ContextStack(ExitStack):
    """Backwards compatibility alias for ExitStack"""

    def __init__(self):
        warnings.warn("ContextStack has been renamed to ExitStack",
                      DeprecationWarning)
        super(ContextStack, self).__init__()

    def register_exit(self, callback):
        return self.push(callback)

    def register(self, callback, *args, **kwds):
        return self.callback(callback, *args, **kwds)

    def preserve(self):
        return self.pop_all()


class nullcontext(AbstractContextManager):
    """Context manager that does no additional processing.
    Used as a stand-in for a normal context manager, when a particular
    block of code is only sometimes used with a normal context manager:
    cm = optional_cm if condition else nullcontext()
    with cm:
        # Perform operation, using optional_cm if condition is True
    """

    def __init__(self, enter_result=None):
        self.enter_result = enter_result

    def __enter__(self):
        return self.enter_result

    def __exit__(self, *excinfo):
        pass
PKÔ¶N];;�Ó99/site-packages/pip/_vendor/msgpack/exceptions.pynu„[µü¤class UnpackException(Exception):
    """Base class for some exceptions raised while unpacking.

    NOTE: unpack may raise exception other than subclass of
    UnpackException.  If you want to catch all error, catch
    Exception instead.
    """


class BufferFull(UnpackException):
    pass


class OutOfData(UnpackException):
    pass


class FormatError(ValueError, UnpackException):
    """Invalid msgpack format"""


class StackError(ValueError, UnpackException):
    """Too nested"""


# Deprecated.  Use ValueError instead
UnpackValueError = ValueError


class ExtraData(UnpackValueError):
    """ExtraData is raised when there is trailing data.

    This exception is raised while only one-shot (not streaming)
    unpack.
    """

    def __init__(self, unpacked, extra):
        self.unpacked = unpacked
        self.extra = extra

    def __str__(self):
        return "unpack(b) received extra data."


# Deprecated.  Use Exception instead to catch all exception during packing.
PackException = Exception
PackValueError = ValueError
PackOverflowError = OverflowError
PKÔ¶N])ݶÕÿÿ-site-packages/pip/_vendor/msgpack/__init__.pynu„[µü¤# coding: utf-8
from ._version import version
from .exceptions import *

from collections import namedtuple


class ExtType(namedtuple('ExtType', 'code data')):
    """ExtType represents ext type in msgpack."""
    def __new__(cls, code, data):
        if not isinstance(code, int):
            raise TypeError("code must be int")
        if not isinstance(data, bytes):
            raise TypeError("data must be bytes")
        if not 0 <= code <= 127:
            raise ValueError("code must be 0~127")
        return super(ExtType, cls).__new__(cls, code, data)


import os
if os.environ.get('MSGPACK_PUREPYTHON'):
    from .fallback import Packer, unpackb, Unpacker
else:
    try:
        from ._cmsgpack import Packer, unpackb, Unpacker
    except ImportError:
        from .fallback import Packer, unpackb, Unpacker


def pack(o, stream, **kwargs):
    """
    Pack object `o` and write it to `stream`

    See :class:`Packer` for options.
    """
    packer = Packer(**kwargs)
    stream.write(packer.pack(o))


def packb(o, **kwargs):
    """
    Pack object `o` and return packed bytes

    See :class:`Packer` for options.
    """
    return Packer(**kwargs).pack(o)


def unpack(stream, **kwargs):
    """
    Unpack an object from `stream`.

    Raises `ExtraData` when `stream` contains extra bytes.
    See :class:`Unpacker` for options.
    """
    data = stream.read()
    return unpackb(data, **kwargs)


# alias for compatibility to simplejson/marshal/pickle.
load = unpack
loads = unpackb

dump = pack
dumps = packb
PKÔ¶N]ý>QÀ~~Ksite-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eÿã@sÎddlmZddlTddlmZGdd„deddƒƒZddlZej d	¡r`dd
l	m
Z
mZmZnBzdd
l
m
Z
mZmZWn(ek
r dd
l	m
Z
mZmZYnXdd„Zd
d„Zdd„ZeZeZeZeZdS)é)Úversion)Ú*é)Ú
namedtuplecs eZdZdZ‡fdd„Z‡ZS)ÚExtTypez'ExtType represents ext type in msgpack.csVt|tƒstdƒ‚t|tƒs$tdƒ‚d|kr8dksBntdƒ‚tt|ƒ |||¡S)Nzcode must be intzdata must be bytesrézcode must be 0~127)Ú
isinstanceÚintÚ	TypeErrorÚbytesÚ
ValueErrorÚsuperrÚ__new__)ÚclsÚcodeÚdata©Ú	__class__©ú@/usr/lib/python3.8/site-packages/pip/_vendor/msgpack/__init__.pyr
s

zExtType.__new__)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rÚ
__classcell__rrrrrsrz	code dataNZMSGPACK_PUREPYTHON)ÚPackerÚunpackbÚUnpackercKstf|Ž}| | |¡¡dS)zX
    Pack object `o` and write it to `stream`

    See :class:`Packer` for options.
    N)rÚwriteÚpack)ÚoÚstreamÚkwargsZpackerrrrrs
rcKstf|Ž |¡S)zW
    Pack object `o` and return packed bytes

    See :class:`Packer` for options.
    )rr)r r"rrrÚpackb(sr#cKs| ¡}t|f|ŽS)zŒ
    Unpack an object from `stream`.

    Raises `ExtraData` when `stream` contains extra bytes.
    See :class:`Unpacker` for options.
    )Úreadr)r!r"rrrrÚunpack1sr%)Z_versionrÚ
exceptionsÚcollectionsrrÚosÚenvironÚgetZfallbackrrrZ	_cmsgpackÚImportErrorrr#r%ÚloadÚloadsÚdumpÚdumpsrrrrÚs"
	PKÔ¶N]Gz	¶¶Esite-packages/pip/_vendor/msgpack/__pycache__/_version.cpython-38.pycnu„[µü¤U

ÀÒ.eã@sdZdS))éééN)Úversion©rrú@/usr/lib/python3.8/site-packages/pip/_vendor/msgpack/_version.pyÚóPKÔ¶N]q³ÒÙffKsite-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eN’ã@sªdZddlZddlZddlZejddkr@dZeefZdd„Z	ndZeZe
ZeZ
dd„Z	ejd	krpeZd
d„Zndd„Zeed
ƒrÖddlmZzddlmZWn ek
r¾ddlmZYnXdZGdd„deƒZndZddlmZdd„ZddlmZmZm Z m!Z!m"Z"ddl#m$Z$dZ%dZ&dZ'dZ(dZ)dZ*dZ+dZ,dZ-dZ.dZ/e0e1fdd„Z2dd „Z3d!d"„Z4d#d$„Z5ejd%k�r€d,d&d'„Z6nej7Z6Gd(d)„d)eƒZ8Gd*d+„d+eƒZ9dS)-z.Fallback pure Python implementation of msgpackéNéTcCs| ¡S©N)Z	iteritems©Úd©rú@/usr/lib/python3.8/site-packages/pip/_vendor/msgpack/fallback.pyÚdict_iteritemssrFcCs| ¡Sr)Úitemsrrrrrs)éécCs.t|jƒdko,t|jdtƒo,|jd d¡S)Nérz maximum recursion depth exceeded)ÚlenÚargsÚ
isinstanceÚstrÚ
startswith©ÚerrrÚ_is_recursionerrorsÿrcCsdS)NTrrrrrrsZpypy_version_info)Únewlist_hint)ÚBytesBuilder)Ú
StringBuilderc@s&eZdZd	dd„Zdd„Zdd„ZdS)
ÚStringIOócCs,|r tt|ƒƒ|_|j |¡ntƒ|_dSr)rr
ÚbuilderÚappend©ÚselfÚsrrrÚ__init__*szStringIO.__init__cCs6t|tƒr| ¡}nt|tƒr&t|ƒ}|j |¡dSr)rÚ
memoryviewÚtobytesÚ	bytearrayÚbytesrrrrrrÚwrite0s



zStringIO.writecCs
|j ¡Sr)rZbuild©rrrrÚgetvalue6szStringIO.getvalueN)r)Ú__name__Ú
__module__Ú__qualname__rr$r&rrrrr)s
r)ÚBytesIOcCsgSrr)ÚsizerrrÚ;rr,r)Ú
BufferFullÚ	OutOfDataÚ	ExtraDataÚFormatErrorÚ
StackError)ÚExtTyper
ériÿcCs(||ƒ|kr||ƒ|kS||ƒ|kSdSrr)ÚobjÚtÚtypeÚtuplerrrÚ_check_type_strictXsr8cCsdzt|ƒ}Wn@tk
rLtrFtt|ƒƒ}tjdt|ƒtdd�n‚YnX|jdkr`t	dƒ‚|S)Nz‚using old buffer interface to unpack %s; this leads to unpacking errors if slicing is used and will be removed in a future versionr
©Ú
stacklevelrz$cannot unpack from multi-byte object)
r Ú	TypeErrorÚPY2ÚbufferÚwarningsÚwarnr6ÚRuntimeWarningÚitemsizeÚ
ValueError)r4ÚviewrrrÚ_get_data_from_buffer_sþý
rDcKs$tjdtdd�| ¡}t|f|ŽS)NzbDirect calling implementation's unpack() is deprecated, Use msgpack.unpack() or unpackb() instead.rr9)r>r?ÚDeprecationWarningÚreadÚunpackb)ÚstreamÚkwargsÚdatarrrÚunpackqsþrKc
Ks’tddt|ƒi|—Ž}| |¡z| ¡}WnJtk
rHtdƒ‚Yn0tk
rv}zt|ƒrdt‚‚W5d}~XYnX| 	¡rŽt
|| ¡ƒ‚|S)aw
    Unpack an object from `packed`.

    Raises ``ExtraData`` when *packed* contains extra bytes.
    Raises ``ValueError`` when *packed* is incomplete.
    Raises ``FormatError`` when *packed* is not valid msgpack.
    Raises ``StackError`` when *packed* contains too nested.
    Other exceptions can be raised during unpacking.

    See :class:`Unpacker` for options.
    NÚmax_buffer_sizezUnpack failed: incomplete input)N)ÚUnpackerr
ÚfeedÚ_unpackr.rBÚRecursionErrorrr1Ú_got_extradatar/Ú_get_extradata)ZpackedrIZunpackerÚretrrrrrGys
rG)réécCst |t|ƒ|¡S)z.Explicit typcast for legacy struct.unpack_from)ÚstructÚunpack_fromr#)ÚfÚbÚorrrÚ_unpack_from•sr[c@sÈeZdZdZdddddddddddedddddfdd„Zd	d
„Zdd„Zd
d„Zdd„Z	dd„Z
dd„Zdd„Ze
fdd„Ze
fdd„Zdd„Zdd„ZeZdd „Zd!d"„Zd#d$„Zd%d&„Zd'd(„ZdS))rMaØ
Streaming unpacker.

    arguments:

    :param file_like:
        File-like object having `.read(n)` method.
        If specified, unpacker reads serialized data from it and :meth:`feed()` is not usable.

    :param int read_size:
        Used as `file_like.read(read_size)`. (default: `min(16*1024, max_buffer_size)`)

    :param bool use_list:
        If true, unpack msgpack array to Python list.
        Otherwise, unpack to Python tuple. (default: True)

    :param bool raw:
        If true, unpack msgpack raw to Python bytes (default).
        Otherwise, unpack to Python str (or unicode on Python 2) by decoding
        with UTF-8 encoding (recommended).
        Currently, the default is true, but it will be changed to false in
        near future.  So you must specify it explicitly for keeping backward
        compatibility.

        *encoding* option which is deprecated overrides this option.

    :param bool strict_map_key:
        If true, only str or bytes are accepted for map (dict) keys.
        It's False by default for backward-compatibility.
        But it will be True from msgpack 1.0.

    :param callable object_hook:
        When specified, it should be callable.
        Unpacker calls it with a dict argument after unpacking msgpack map.
        (See also simplejson)

    :param callable object_pairs_hook:
        When specified, it should be callable.
        Unpacker calls it with a list of key-value pairs after unpacking msgpack map.
        (See also simplejson)

    :param str encoding:
        Encoding used for decoding msgpack raw.
        If it is None (default), msgpack raw is deserialized to Python bytes.

    :param str unicode_errors:
        (deprecated) Used for decoding msgpack raw with *encoding*.
        (default: `'strict'`)

    :param int max_buffer_size:
        Limits size of data waiting unpacked.  0 means system's INT_MAX (default).
        Raises `BufferFull` exception when it is insufficient.
        You should set this parameter when unpacking data from untrusted source.

    :param int max_str_len:
        Deprecated, use *max_buffer_size* instead.
        Limits max length of str. (default: max_buffer_size or 1024*1024)

    :param int max_bin_len:
        Deprecated, use *max_buffer_size* instead.
        Limits max length of bin. (default: max_buffer_size or 1024*1024)

    :param int max_array_len:
        Limits max length of array.
        (default: max_buffer_size or 128*1024)

    :param int max_map_len:
        Limits max length of map.
        (default: max_buffer_size//2 or 32*1024)

    :param int max_ext_len:
        Deprecated, use *max_buffer_size* instead.
        Limits max size of ext type.  (default: max_buffer_size or 1024*1024)

    Example of streaming deserialize from file-like object::

        unpacker = Unpacker(file_like, raw=False, max_buffer_size=10*1024*1024)
        for o in unpacker:
            process(o)

    Example of streaming deserialize from socket::

        unpacker = Unpacker(raw=False, max_buffer_size=10*1024*1024)
        while True:
            buf = sock.recv(1024**2)
            if not buf:
                break
            unpacker.feed(buf)
            for o in unpacker:
                process(o)

    Raises ``ExtraData`` when *packed* contains extra bytes.
    Raises ``OutOfData`` when *packed* is incomplete.
    Raises ``FormatError`` when *packed* is not valid msgpack.
    Raises ``StackError`` when *packed* contains too nested.
    Other exceptions can be raised during unpacking.
    NrTFéÿÿÿÿcCsÐ|	dk	rtjdtdd�|
dkr$d}
|dkr4d|_nt|jƒsFtdƒ‚||_d|_tƒ|_	d|_
d|_|
d	krv|ptd
}
|d	kr†|p„d
}|d	kr–|p”d}|d	krª|dp¨d}|d	krº|p¸d
}|pÀd
|_||jkrÖt
dƒ‚|pät|jdƒ|_t|ƒ|_t|ƒ|_|	|_|
|_||_||_||_||_||_|
|_||_||_||_||_d|_|dk	�rft|ƒ�sftdƒ‚|dk	�r‚t|ƒ�s‚tdƒ‚|dk	�ržt|ƒ�sžtdƒ‚|dk	�rº|dk	�rºtdƒ‚t|ƒ�sÌtdƒ‚dS)Nú.encoding is deprecated, Use raw=False instead.rr9ÚstrictTz!`file_like.read` must be callableFrr\iii€iÿÿÿz.read_size must be smaller than max_buffer_sizei@z`list_hook` is not callablez`object_hook` is not callablez#`object_pairs_hook` is not callablez8object_pairs_hook and object_hook are mutually exclusivez`ext_hook` is not callable) r>r?rEÚ_feedingÚcallablerFr;Ú	file_liker"Ú_bufferÚ_buff_iÚ_buf_checkpointÚ_max_buffer_sizerBÚminÚ
_read_sizeÚboolÚ_rawÚ_strict_map_keyÚ	_encodingÚ_unicode_errorsÚ	_use_listÚ
_list_hookÚ_object_hookÚ_object_pairs_hookÚ	_ext_hookÚ_max_str_lenÚ_max_bin_lenÚ_max_array_lenÚ_max_map_lenÚ_max_ext_lenÚ_stream_offset)rraZ	read_sizeZuse_listÚrawZstrict_map_keyZobject_hookZobject_pairs_hookZ	list_hookÚencodingÚunicode_errorsrLZext_hookZmax_str_lenZmax_bin_lenZ
max_array_lenZmax_map_lenZmax_ext_lenrrrrþsp	þ
	




zUnpacker.__init__cCsht|ƒ}t|jƒ|jt|ƒ|jkr*t‚|jdkrX|jd|j…=|j|j8_d|_|j |¡dS©Nr)rDr
rbrcrer-rdÚextend)rZ
next_bytesrCrrrrNPs
z
Unpacker.feedcCs"|j|j|j7_|j|_dS)z+ Gets rid of the used parts of the buffer. N)rwrcrdr%rrrÚ_consume_szUnpacker._consumecCs|jt|jƒkSr)rcr
rbr%rrrrQdszUnpacker._got_extradatacCs|j|jd…Sr)rbrcr%rrrrRgszUnpacker._get_extradatacCs
| |¡Sr)Ú_read©rÚnrrrÚ
read_bytesjszUnpacker.read_bytescCs,| |¡|j}|||_|j|||…Sr)Ú_reservercrb)rr€Úirrrr~ms

zUnpacker._readcCsÊt|jƒ|j|}|dkr dS|jr2|j|_t‚|jdkr`|jd|j…=|j|j8_d|_|}|dkr¨t|j|ƒ}|j 	|¡}|sŒq¨|j|7_|t|ƒ8}qft|jƒ||jkrÆd|_t‚dSr{)
r
rbrcr_rdr.ÚmaxrgrarF)rr€Zremain_bytesZ
to_read_bytesZ	read_datarrrr‚ts*
zUnpacker._reservecCs&
t}d}d}| d¡|j|j}|jd7_|d@dkrD|}�	nØ|d@dkr`d|dA}�	n¼|d@dkrž|d@}t}||jkr�td	||jƒ‚| |¡}�	n~|d
@dkrÒ|d@}t}||j	krÎtd
||j	ƒ‚�	nJ|d
@dk�r
|d@}t
}||jk�
rtd||jƒ‚�	n|dk�rd}�	n|dk�r.d}�nî|dk�r@d}�nÜ|dk�ržt}| d¡|j|j}|jd7_||j
k�r�td||j
fƒ‚| |¡}�n~|dk�rt}| d¡td|j|jƒd}|jd7_||j
k�rötd||j
fƒ‚| |¡}�n|dk�rjt}| d¡td|j|jƒd}|jd7_||j
k�r\td||j
fƒ‚| |¡}�n²|dk�rÐt}| d¡td|j|jƒ\}}|jd7_||jk�rÂtd||jfƒ‚| |¡}�nL|dk�r6t}| d ¡td!|j|jƒ\}}|jd 7_||jk�r(td||jfƒ‚| |¡}�næ|d"k�rœt}| d#¡td$|j|jƒ\}}|jd#7_||jk�rŽtd||jfƒ‚| |¡}�n€|d%k�rÖ| d¡td&|j|jƒd}|jd7_�nF|d'k�r| d(¡td)|j|jƒd}|jd(7_�n|d*k�rB| d¡|j|j}|jd7_�nÚ|d+k�r|| d¡td|j|jƒd}|jd7_�n |d,k�r¶| d¡td|j|jƒd}|jd7_�nf|d-k�rð| d(¡td.|j|jƒd}|jd(7_�n,|d/k�r*| d¡td0|j|jƒd}|jd7_�nò|d1k�rd| d¡td2|j|jƒd}|jd7_�n¸|d3k�rž| d¡td4|j|jƒd}|jd7_�n~|d5k�rØ| d(¡td6|j|jƒd}|jd(7_�nD|d7k�r4t}|jdk�rtdd|jfƒ‚| d¡td8|j|jƒ\}}|jd7_�nè|d9k�r�t}|jdk�r`tdd|jfƒ‚| d ¡td:|j|jƒ\}}|jd 7_�nŒ|d;k�rìt}|jdk�r¼tdd|jfƒ‚| d#¡td<|j|jƒ\}}|jd#7_�n0|d=k�rHt}|jd(k�rtdd(|jfƒ‚| d>¡td?|j|jƒ\}}|jd>7_�nÔ|d@k�r¤t}|jdAk�rttddA|jfƒ‚| dB¡tdC|j|jƒ\}}|jdB7_�nx|dDk�rþt}| d¡|j|j}|jd7_||jk�rðtd	||jƒ‚| |¡}�n|dEk�r^t}| d¡td|j|jƒ\}|jd7_||jk�rPtd	||jƒ‚| |¡}�n¾|dFk�r¾t}| d¡td|j|jƒ\}|jd7_||jk�r°td	||jƒ‚| |¡}�n^|dGk�	rt}| d¡td|j|jƒ\}|jd7_||j	k�
rtd
||j	ƒ‚�n|dHk�	rht}| d¡td|j|jƒ\}|jd7_||j	k�
rtd
||j	ƒ‚n´|dIk�	r¼| d¡td|j|jƒ\}|jd7_||jk�	r¶td||jƒ‚t
}n`|dJk�
r| d¡td|j|jƒ\}|jd7_||jk�
r
td||jƒ‚t
}ntdK|ƒ‚|||fS)LNrré€éàr\éÿé éz%s exceeds max_str_len(%s)éðé�éz%s exceeds max_array_len(%s)z%s exceeds max_map_len(%s)éÀéÂFéÃTéÄz%s exceeds max_bin_len(%s)éÅrú>HéÆr3ú>IéÇZBbz%s exceeds max_ext_len(%s)éÈr
z>HbéÉrz>IbéÊz>féËéz>déÌéÍéÎéÏz>QéÐrYéÑz>héÒz>iéÓz>qéÔZb1séÕZb2séÖZb4sé×é	Zb8séØééZb16séÙéÚéÛéÜéÝéÞéßzUnknown header: 0x%x)ÚTYPE_IMMEDIATEr‚rbrcÚTYPE_RAWrrrBr~Ú
TYPE_ARRAYrtÚTYPE_MAPruÚTYPE_BINrsr[ÚTYPE_EXTrvr0)rÚexecuteÚtypr€r4rYÚLrrrÚ_read_header”s¢





























































zUnpacker._read_headerc	sˆ |¡\}}}|tkr,|tkr(tdƒ‚|S|tkrH|tkrDtdƒ‚|S|tkrÀ|tkrtt|ƒD]}ˆ t¡q`dSt	|ƒ}t|ƒD]}| 
ˆ t¡¡q„ˆjdk	r®ˆ |¡}ˆj
r¸|St|ƒS|tk�r–|tkrøt|ƒD]}ˆ t¡ˆ t¡qÚdSˆjdk	�r"ˆ ‡fdd„t|ƒDƒ¡}npi}t|ƒD]L}ˆ t¡}ˆj�rjt|ƒttfk�rjtdtt|ƒƒƒ‚ˆ t¡||<�q.ˆjdk	�r’ˆ |¡}|S|tk�r¤dS|tk�rìˆjdk	�rÌ| ˆjˆj¡}nˆj�rÞt|ƒ}n
| d¡}|S|tk�rˆ |t|ƒ¡S|tk�rt|ƒS|S)NzExpected arrayzExpected mapc3s"|]}ˆ t¡ˆ t¡fVqdSr)rOÚEX_CONSTRUCT)Ú.0Ú_r%rrÚ	‰sþÿz#Unpacker._unpack..z%s is not allowed for map keyÚutf_8)r»ÚEX_READ_ARRAY_HEADERr´rBÚEX_READ_MAP_HEADERrµÚEX_SKIPÚxrangerOrrr¼rnrmr7rprjr6Úunicoder#rror³rkÚdecoderlrir·rqr¶)	rr¸r¹r€r4rƒrSr¾Úkeyrr%rrOhsj



ý








zUnpacker._unpackcCs|Srrr%rrrÚ__iter__¨szUnpacker.__iter__cCsTz| t¡}| ¡|WStk
r8| ¡t‚Yntk
rNt‚YnXdSr)rOr¼r}r.Ú
StopIterationrPr1©rrSrrrÚ__next__«s
zUnpacker.__next__cCs| t¡| ¡dSr)rOrÃr}r%rrrÚskip¸s
z
Unpacker.skipcCs4z| t¡}Wntk
r&t‚YnX| ¡|Sr)rOr¼rPr1r}rÊrrrrK¼s
zUnpacker.unpackcCs| t¡}| ¡|Sr)rOrÁr}rÊrrrÚread_array_headerÄs
zUnpacker.read_array_headercCs| t¡}| ¡|Sr)rOrÂr}rÊrrrÚread_map_headerÉs
zUnpacker.read_map_headercCs|jSr)rwr%rrrÚtellÎsz
Unpacker.tell)r'r(r)Ú__doc__r2rrNr}rQrRr�r~r‚r¼r»rOrÈrËÚnextrÌrKrÍrÎrÏrrrrrMœsBa
ø
R U@rMc@s–eZdZdZd#dd„Zeeefdd„Zd	d
„Z	dd„Z
d
d„Zdd„Zdd„Z
dd„Zdd„Zefdd„Zdd„Zdd„Zdd„Zdd „Zd!d"„ZdS)$ÚPackerah
    MessagePack Packer

    usage:

        packer = Packer()
        astream.write(packer.pack(a))
        astream.write(packer.pack(b))

    Packer's constructor has some keyword arguments:

    :param callable default:
        Convert user type to builtin type that Packer supports.
        See also simplejson's document.

    :param bool use_single_float:
        Use single precision float type for float. (default: False)

    :param bool autoreset:
        Reset buffer after each pack and return its content as `bytes`. (default: True).
        If set this to false, use `bytes()` to get content and `.reset()` to clear buffer.

    :param bool use_bin_type:
        Use bin type introduced in msgpack spec 2.0 for bytes.
        It also enables str8 type for unicode.

    :param bool strict_types:
        If set to true, types will be checked to be exact. Derived classes
        from serializeable types will not be serialized and will be
        treated as unsupported type and forwarded to default.
        Additionally tuples will not be serialized as lists.
        This is useful when trying to implement accurate serialization
        for python types.

    :param str encoding:
        (deprecated) Convert unicode to bytes with this encoding. (default: 'utf-8')

    :param str unicode_errors:
        Error handler for encoding unicode. (default: 'strict')
    NFTcCsx|dkrd}ntjdtdd�|dkr*d}||_||_||_||_||_||_t	ƒ|_
|dk	rnt|ƒsntdƒ‚||_
dS)NrÀr]rr9r^zdefault must be callable)r>r?rEÚ
_strict_typesÚ
_use_floatÚ
_autoresetÚ
_use_bin_typerkrlrrbr`r;Ú_default)rÚdefaultryrzZuse_single_floatZ	autoresetZuse_bin_typeZstrict_typesrrrrûs(þzPacker.__init__cCsdd}|jr|}t}nttf}|dkr,tdƒ‚|dkr@|j d¡S||tƒrf|rZ|j d¡S|j d¡S||tƒ�r€d|kr†dkržnn|j t 	d|¡¡Sd	|kr²dkrÊnn|j t 	d
|¡¡Sd|krÞdkrønn|j t 	dd
|¡¡Sd|k�rdk�r*nn|j t 	dd|¡¡Sd|k�rBdk�r\nn|j t 	dd|¡¡Sd|k�rtdk�rŽnn|j t 	dd|¡¡Sd|k�r¦dk�rÀnn|j t 	dd|¡¡Sd|k�rØdk�rònn|j t 	dd|¡¡Sd|k�r
dk�r$nn|j t 	dd|¡¡Sd |k�rBbrŸéÿÿú>BHrœi€ÿÿz>Bhr ìÿÿú>BIr�i€z>Bir¡lÿÿÿÿz>BQržlûÿÿÿz>Bqr¢TzInteger value out of rangeìz%s is too largez5Can't encode unicode string: no encoding is specifiedzString is too largezMemoryview is too largez>Bfr˜z>Bdr™róÔróÕr3óÖršó×r©óØú>BBr•r–r—zCannot serialize %r)%rÓÚlistr7rBrbr$rhÚ	int_typesrVÚpackr×Ú
OverflowErrorr#r"r
r6r'Ú_pack_bin_headerrÅrkr;ÚencoderlÚ_pack_raw_headerr rAÚfloatrÔr2ÚcoderJÚ_pack_array_headerrÄÚ_packÚdictÚ_pack_map_pairsr)rr4Ú
nest_limitZcheckZcheck_type_strictZdefault_usedZ
list_typesr€rðrJrºrƒrrrròsÎ



ÿ











ÿ
zPacker._packcCsFz| |¡Wntƒ|_‚YnX|jrB|j ¡}tƒ|_|SdSr)ròrrbrÕr&)rr4rSrrrrê‚s
zPacker.packcCs0| t|ƒ|¡|jr,|j ¡}tƒ|_|SdSr)rôr
rÕrbr&r)rÚpairsrSrrrÚpack_map_pairs�s

zPacker.pack_map_pairscCs6|dkrt‚| |¡|jr2|j ¡}tƒ|_|SdS©Nrá)rBrñrÕrbr&r©rr€rSrrrÚpack_array_header”s

zPacker.pack_array_headercCs6|dkrt‚| |¡|jr2|j ¡}tƒ|_|SdSrø)rBÚ_pack_map_headerrÕrbr&rrùrrrÚpack_map_header�s

zPacker.pack_map_headercCsJt|tƒstdƒ‚d|kr&dks0ntdƒ‚t|tƒsBtdƒ‚t|ƒ}|dkrZtdƒ‚|dkrp|j d	¡n¶|d
kr†|j d¡n |dkrœ|j d
¡nŠ|dkr²|j d¡nt|dkrÈ|j d¡n^|dkrê|j dt 	d|¡¡n<|dk�r|j dt 	d|¡¡n|j dt 	d|¡¡|j t 	d|¡¡|j |¡dS)Nztypecode must have int type.réztypecode should be 0-127zdata must have bytes typerßzToo large datarrârrãr3räršrår©rær‡óÇrÜrÝóÈr’óÉr”)
rÚintr;rBr#r
rbr$rVrê)rÚtypecoderJrºrrrÚ
pack_ext_type¦s4


zPacker.pack_ext_typecCsh|dkr |j t dd|¡¡S|dkr>|j t dd|¡¡S|dkr\|j t dd	|¡¡Std
ƒ‚dS)NrŒrÜr‹rÝrÞr®rßràr¯zArray is too large©rbr$rVrêrBrrrrrñÃszPacker._pack_array_headercCsh|dkr |j t dd|¡¡S|dkr>|j t dd|¡¡S|dkr\|j t dd	|¡¡Std
ƒ‚dS)NrŒrÜr…rÝrÞr°rßràr±zDict is too largerrrrrrûÌszPacker._pack_map_headercCs<| |¡|D](\}}| ||d¡| ||d¡qdS)Nr)rûrò)rr€rörõÚkÚvrrrrôÕs
zPacker._pack_map_pairscCs”|dkr"|j t dd|¡¡nn|jrH|dkrH|j t dd|¡¡nH|dkrh|j t dd	|¡¡n(|d
krˆ|j t dd|¡¡ntd
ƒ‚dS)Nr‰rÜrˆr‡rçr«rÝrÞr¬rßràr­zRaw is too large)rbr$rVrêrÖrBrrrrrîÛszPacker._pack_raw_headercCsv|js| |¡S|dkr.|j t dd|¡¡S|dkrL|j t dd|¡¡S|dkrj|j t dd	|¡¡Std
ƒ‚dS)Nr‡rçr�rÝrÞr‘rßràr“zBin is too large)rÖrîrbr$rVrêrBrrrrrìçs
zPacker._pack_bin_headercCs
|j ¡S)z/Return internal buffer contents as bytes object)rbr&r%rrrr#ószPacker.bytescCstƒ|_dS)zYReset internal buffer.

        This method is usaful only when autoreset=False.
        N)rrbr%rrrÚreset÷szPacker.resetcCs"tstrt| ¡ƒS|j ¡SdS)zReturn view of internal buffer.N)ÚUSING_STRINGBUILDERr<r r#rbÚ	getbufferr%rrrr	þszPacker.getbuffer)NNNFTFF)r'r(r)rÐrÚDEFAULT_RECURSE_LIMITrr8ròrêr÷rúrürrñrûrôrîrìr#rr	rrrrrÒÒs0(þ
ÿ
n				rÒ)r):rÐÚsysrVr>Úversion_infor<rZlongrérrrÅÚrangerÄÚRuntimeErrorrPrÚhasattrZ__pypy__rZ__pypy__.buildersrrÚImportErrorrÚobjectrÚior*Ú
exceptionsr-r.r/r0r1Úr2rÃr¼rÁrÂr²r´rµr³r¶r·r
r6r7r8rDrKrGr[rWrMrÒrrrrÚsj



:PKÔ¶N]Ïá]>Gsite-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-38.pycnu„[µü¤U

ÀÒ.e9ã@sxGdd„deƒZGdd„deƒZGdd„deƒZGdd„deeƒZGdd	„d	eeƒZeZGd
d„deƒZeZ	eZ
eZdS)
c@seZdZdZdS)ÚUnpackExceptionzËBase class for some exceptions raised while unpacking.

    NOTE: unpack may raise exception other than subclass of
    UnpackException.  If you want to catch all error, catch
    Exception instead.
    N©Ú__name__Ú
__module__Ú__qualname__Ú__doc__©rrúB/usr/lib/python3.8/site-packages/pip/_vendor/msgpack/exceptions.pyrsrc@seZdZdS)Ú
BufferFullN©rrrrrrrr	
sr	c@seZdZdS)Ú	OutOfDataNr
rrrrrsrc@seZdZdZdS)ÚFormatErrorzInvalid msgpack formatNrrrrrrsrc@seZdZdZdS)Ú
StackErrorz
Too nestedNrrrrrr
sr
c@s eZdZdZdd„Zdd„ZdS)Ú	ExtraDatazƒExtraData is raised when there is trailing data.

    This exception is raised while only one-shot (not streaming)
    unpack.
    cCs||_||_dS)N)ÚunpackedÚextra)ÚselfrrrrrÚ__init__%szExtraData.__init__cCsdS)Nzunpack(b) received extra data.r)rrrrÚ__str__)szExtraData.__str__N)rrrrrrrrrrrsrN)
Ú	Exceptionrr	rÚ
ValueErrorrr
ZUnpackValueErrorrZ
PackExceptionZPackValueErrorÚ
OverflowErrorZPackOverflowErrorrrrrÚs	PKÔ¶N]F½2Ñ¡f¡fEsite-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-38.pycnu„[µü¤U

ÀÒ.eN’ã@sªdZddlZddlZddlZejddkr@dZeefZdd„Z	ndZeZe
ZeZ
dd„Z	ejd	krpeZd
d„Zndd„Zeed
ƒrÖddlmZzddlmZWn ek
r¾ddlmZYnXdZGdd„deƒZndZddlmZdd„ZddlmZmZm Z m!Z!m"Z"ddl#m$Z$dZ%dZ&dZ'dZ(dZ)dZ*dZ+dZ,dZ-dZ.dZ/e0e1fdd„Z2dd „Z3d!d"„Z4d#d$„Z5ejd%k�r€d,d&d'„Z6nej7Z6Gd(d)„d)eƒZ8Gd*d+„d+eƒZ9dS)-z.Fallback pure Python implementation of msgpackéNéTcCs| ¡S©N)Z	iteritems©Úd©rú@/usr/lib/python3.8/site-packages/pip/_vendor/msgpack/fallback.pyÚdict_iteritemssrFcCs| ¡Sr)Úitemsrrrrrs)éécCs.t|jƒdko,t|jdtƒo,|jd d¡S)Nérz maximum recursion depth exceeded)ÚlenÚargsÚ
isinstanceÚstrÚ
startswith©ÚerrrÚ_is_recursionerrorsÿrcCsdS)NTrrrrrrsZpypy_version_info)Únewlist_hint)ÚBytesBuilder)Ú
StringBuilderc@s&eZdZd	dd„Zdd„Zdd„ZdS)
ÚStringIOócCs,|r tt|ƒƒ|_|j |¡ntƒ|_dSr)rr
ÚbuilderÚappend©ÚselfÚsrrrÚ__init__*szStringIO.__init__cCs6t|tƒr| ¡}nt|tƒr&t|ƒ}|j |¡dSr)rÚ
memoryviewÚtobytesÚ	bytearrayÚbytesrrrrrrÚwrite0s



zStringIO.writecCs
|j ¡Sr)rZbuild©rrrrÚgetvalue6szStringIO.getvalueN)r)Ú__name__Ú
__module__Ú__qualname__rr$r&rrrrr)s
r)ÚBytesIOcCsgSrr)ÚsizerrrÚ;rr,r)Ú
BufferFullÚ	OutOfDataÚ	ExtraDataÚFormatErrorÚ
StackError)ÚExtTyper
ériÿcCs(||ƒ|kr||ƒ|kS||ƒ|kSdSrr)ÚobjÚtÚtypeÚtuplerrrÚ_check_type_strictXsr8cCsdzt|ƒ}Wn@tk
rLtrFtt|ƒƒ}tjdt|ƒtdd�n‚YnX|jdkr`t	dƒ‚|S)Nz‚using old buffer interface to unpack %s; this leads to unpacking errors if slicing is used and will be removed in a future versionr
©Ú
stacklevelrz$cannot unpack from multi-byte object)
r Ú	TypeErrorÚPY2ÚbufferÚwarningsÚwarnr6ÚRuntimeWarningÚitemsizeÚ
ValueError)r4ÚviewrrrÚ_get_data_from_buffer_sþý
rDcKs$tjdtdd�| ¡}t|f|ŽS)NzbDirect calling implementation's unpack() is deprecated, Use msgpack.unpack() or unpackb() instead.rr9)r>r?ÚDeprecationWarningÚreadÚunpackb)ÚstreamÚkwargsÚdatarrrÚunpackqsþrKc
Ks’tddt|ƒi|—Ž}| |¡z| ¡}WnJtk
rHtdƒ‚Yn0tk
rv}zt|ƒrdt‚‚W5d}~XYnX| 	¡rŽt
|| ¡ƒ‚|S)aw
    Unpack an object from `packed`.

    Raises ``ExtraData`` when *packed* contains extra bytes.
    Raises ``ValueError`` when *packed* is incomplete.
    Raises ``FormatError`` when *packed* is not valid msgpack.
    Raises ``StackError`` when *packed* contains too nested.
    Other exceptions can be raised during unpacking.

    See :class:`Unpacker` for options.
    NÚmax_buffer_sizezUnpack failed: incomplete input)N)ÚUnpackerr
ÚfeedÚ_unpackr.rBÚRecursionErrorrr1Ú_got_extradatar/Ú_get_extradata)ZpackedrIZunpackerÚretrrrrrGys
rG)réécCst |t|ƒ|¡S)z.Explicit typcast for legacy struct.unpack_from)ÚstructÚunpack_fromr#)ÚfÚbÚorrrÚ_unpack_from•sr[c@sÈeZdZdZdddddddddddedddddfdd„Zd	d
„Zdd„Zd
d„Zdd„Z	dd„Z
dd„Zdd„Ze
fdd„Ze
fdd„Zdd„Zdd„ZeZdd „Zd!d"„Zd#d$„Zd%d&„Zd'd(„ZdS))rMaØ
Streaming unpacker.

    arguments:

    :param file_like:
        File-like object having `.read(n)` method.
        If specified, unpacker reads serialized data from it and :meth:`feed()` is not usable.

    :param int read_size:
        Used as `file_like.read(read_size)`. (default: `min(16*1024, max_buffer_size)`)

    :param bool use_list:
        If true, unpack msgpack array to Python list.
        Otherwise, unpack to Python tuple. (default: True)

    :param bool raw:
        If true, unpack msgpack raw to Python bytes (default).
        Otherwise, unpack to Python str (or unicode on Python 2) by decoding
        with UTF-8 encoding (recommended).
        Currently, the default is true, but it will be changed to false in
        near future.  So you must specify it explicitly for keeping backward
        compatibility.

        *encoding* option which is deprecated overrides this option.

    :param bool strict_map_key:
        If true, only str or bytes are accepted for map (dict) keys.
        It's False by default for backward-compatibility.
        But it will be True from msgpack 1.0.

    :param callable object_hook:
        When specified, it should be callable.
        Unpacker calls it with a dict argument after unpacking msgpack map.
        (See also simplejson)

    :param callable object_pairs_hook:
        When specified, it should be callable.
        Unpacker calls it with a list of key-value pairs after unpacking msgpack map.
        (See also simplejson)

    :param str encoding:
        Encoding used for decoding msgpack raw.
        If it is None (default), msgpack raw is deserialized to Python bytes.

    :param str unicode_errors:
        (deprecated) Used for decoding msgpack raw with *encoding*.
        (default: `'strict'`)

    :param int max_buffer_size:
        Limits size of data waiting unpacked.  0 means system's INT_MAX (default).
        Raises `BufferFull` exception when it is insufficient.
        You should set this parameter when unpacking data from untrusted source.

    :param int max_str_len:
        Deprecated, use *max_buffer_size* instead.
        Limits max length of str. (default: max_buffer_size or 1024*1024)

    :param int max_bin_len:
        Deprecated, use *max_buffer_size* instead.
        Limits max length of bin. (default: max_buffer_size or 1024*1024)

    :param int max_array_len:
        Limits max length of array.
        (default: max_buffer_size or 128*1024)

    :param int max_map_len:
        Limits max length of map.
        (default: max_buffer_size//2 or 32*1024)

    :param int max_ext_len:
        Deprecated, use *max_buffer_size* instead.
        Limits max size of ext type.  (default: max_buffer_size or 1024*1024)

    Example of streaming deserialize from file-like object::

        unpacker = Unpacker(file_like, raw=False, max_buffer_size=10*1024*1024)
        for o in unpacker:
            process(o)

    Example of streaming deserialize from socket::

        unpacker = Unpacker(raw=False, max_buffer_size=10*1024*1024)
        while True:
            buf = sock.recv(1024**2)
            if not buf:
                break
            unpacker.feed(buf)
            for o in unpacker:
                process(o)

    Raises ``ExtraData`` when *packed* contains extra bytes.
    Raises ``OutOfData`` when *packed* is incomplete.
    Raises ``FormatError`` when *packed* is not valid msgpack.
    Raises ``StackError`` when *packed* contains too nested.
    Other exceptions can be raised during unpacking.
    NrTFéÿÿÿÿcCsÐ|	dk	rtjdtdd�|
dkr$d}
|dkr4d|_nt|jƒsFtdƒ‚||_d|_tƒ|_	d|_
d|_|
d	krv|ptd
}
|d	kr†|p„d
}|d	kr–|p”d}|d	krª|dp¨d}|d	krº|p¸d
}|pÀd
|_||jkrÖt
dƒ‚|pät|jdƒ|_t|ƒ|_t|ƒ|_|	|_|
|_||_||_||_||_||_|
|_||_||_||_||_d|_|dk	�rft|ƒ�sftdƒ‚|dk	�r‚t|ƒ�s‚tdƒ‚|dk	�ržt|ƒ�sžtdƒ‚|dk	�rº|dk	�rºtdƒ‚t|ƒ�sÌtdƒ‚dS)Nú.encoding is deprecated, Use raw=False instead.rr9ÚstrictTz!`file_like.read` must be callableFrr\iii€iÿÿÿz.read_size must be smaller than max_buffer_sizei@z`list_hook` is not callablez`object_hook` is not callablez#`object_pairs_hook` is not callablez8object_pairs_hook and object_hook are mutually exclusivez`ext_hook` is not callable) r>r?rEÚ_feedingÚcallablerFr;Ú	file_liker"Ú_bufferÚ_buff_iÚ_buf_checkpointÚ_max_buffer_sizerBÚminÚ
_read_sizeÚboolÚ_rawÚ_strict_map_keyÚ	_encodingÚ_unicode_errorsÚ	_use_listÚ
_list_hookÚ_object_hookÚ_object_pairs_hookÚ	_ext_hookÚ_max_str_lenÚ_max_bin_lenÚ_max_array_lenÚ_max_map_lenÚ_max_ext_lenÚ_stream_offset)rraZ	read_sizeZuse_listÚrawZstrict_map_keyZobject_hookZobject_pairs_hookZ	list_hookÚencodingÚunicode_errorsrLZext_hookZmax_str_lenZmax_bin_lenZ
max_array_lenZmax_map_lenZmax_ext_lenrrrrþsp	þ
	




zUnpacker.__init__cCsr|js
t‚t|ƒ}t|jƒ|jt|ƒ|jkr4t‚|jdkrb|jd|j…=|j|j8_d|_|j 	|¡dS©Nr)
r_ÚAssertionErrorrDr
rbrcrer-rdÚextend)rZ
next_bytesrCrrrrNPs

z
Unpacker.feedcCs"|j|j|j7_|j|_dS)z+ Gets rid of the used parts of the buffer. N)rwrcrdr%rrrÚ_consume_szUnpacker._consumecCs|jt|jƒkSr)rcr
rbr%rrrrQdszUnpacker._got_extradatacCs|j|jd…Sr)rbrcr%rrrrRgszUnpacker._get_extradatacCs
| |¡Sr)Ú_read©rÚnrrrÚ
read_bytesjszUnpacker.read_bytescCs,| |¡|j}|||_|j|||…Sr)Ú_reservercrb)rr�Úirrrrms

zUnpacker._readcCsØt|jƒ|j|}|dkr dS|jr2|j|_t‚|jdkr`|jd|j…=|j|j8_d|_|}|dkr¶t|j|ƒ}|j 	|¡}|sŒq¶t
|tƒsšt‚|j|7_|t|ƒ8}qft|jƒ||jkrÔd|_t‚dSr{)
r
rbrcr_rdr.ÚmaxrgrarFrr#r|)rr�Zremain_bytesZ
to_read_bytesZ	read_datarrrrƒts,
zUnpacker._reservecCs&
t}d}d}| d¡|j|j}|jd7_|d@dkrD|}�	nØ|d@dkr`d|dA}�	n¼|d@dkrž|d@}t}||jkr�td	||jƒ‚| |¡}�	n~|d
@dkrÒ|d@}t}||j	krÎtd
||j	ƒ‚�	nJ|d
@dk�r
|d@}t
}||jk�
rtd||jƒ‚�	n|dk�rd}�	n|dk�r.d}�nî|dk�r@d}�nÜ|dk�ržt}| d¡|j|j}|jd7_||j
k�r�td||j
fƒ‚| |¡}�n~|dk�rt}| d¡td|j|jƒd}|jd7_||j
k�rötd||j
fƒ‚| |¡}�n|dk�rjt}| d¡td|j|jƒd}|jd7_||j
k�r\td||j
fƒ‚| |¡}�n²|dk�rÐt}| d¡td|j|jƒ\}}|jd7_||jk�rÂtd||jfƒ‚| |¡}�nL|dk�r6t}| d ¡td!|j|jƒ\}}|jd 7_||jk�r(td||jfƒ‚| |¡}�næ|d"k�rœt}| d#¡td$|j|jƒ\}}|jd#7_||jk�rŽtd||jfƒ‚| |¡}�n€|d%k�rÖ| d¡td&|j|jƒd}|jd7_�nF|d'k�r| d(¡td)|j|jƒd}|jd(7_�n|d*k�rB| d¡|j|j}|jd7_�nÚ|d+k�r|| d¡td|j|jƒd}|jd7_�n |d,k�r¶| d¡td|j|jƒd}|jd7_�nf|d-k�rð| d(¡td.|j|jƒd}|jd(7_�n,|d/k�r*| d¡td0|j|jƒd}|jd7_�nò|d1k�rd| d¡td2|j|jƒd}|jd7_�n¸|d3k�rž| d¡td4|j|jƒd}|jd7_�n~|d5k�rØ| d(¡td6|j|jƒd}|jd(7_�nD|d7k�r4t}|jdk�rtdd|jfƒ‚| d¡td8|j|jƒ\}}|jd7_�nè|d9k�r�t}|jdk�r`tdd|jfƒ‚| d ¡td:|j|jƒ\}}|jd 7_�nŒ|d;k�rìt}|jdk�r¼tdd|jfƒ‚| d#¡td<|j|jƒ\}}|jd#7_�n0|d=k�rHt}|jd(k�rtdd(|jfƒ‚| d>¡td?|j|jƒ\}}|jd>7_�nÔ|d@k�r¤t}|jdAk�rttddA|jfƒ‚| dB¡tdC|j|jƒ\}}|jdB7_�nx|dDk�rþt}| d¡|j|j}|jd7_||jk�rðtd	||jƒ‚| |¡}�n|dEk�r^t}| d¡td|j|jƒ\}|jd7_||jk�rPtd	||jƒ‚| |¡}�n¾|dFk�r¾t}| d¡td|j|jƒ\}|jd7_||jk�r°td	||jƒ‚| |¡}�n^|dGk�	rt}| d¡td|j|jƒ\}|jd7_||j	k�
rtd
||j	ƒ‚�n|dHk�	rht}| d¡td|j|jƒ\}|jd7_||j	k�
rtd
||j	ƒ‚n´|dIk�	r¼| d¡td|j|jƒ\}|jd7_||jk�	r¶td||jƒ‚t
}n`|dJk�
r| d¡td|j|jƒ\}|jd7_||jk�
r
td||jƒ‚t
}ntdK|ƒ‚|||fS)LNrré€éàr\éÿé éz%s exceeds max_str_len(%s)éðé�éz%s exceeds max_array_len(%s)z%s exceeds max_map_len(%s)éÀéÂFéÃTéÄz%s exceeds max_bin_len(%s)éÅrú>HéÆr3ú>IéÇZBbz%s exceeds max_ext_len(%s)éÈr
z>HbéÉrz>IbéÊz>féËéz>déÌéÍéÎéÏz>QéÐrYéÑz>héÒz>iéÓz>qéÔZb1séÕZb2séÖZb4sé×é	Zb8séØééZb16séÙéÚéÛéÜéÝéÞéßzUnknown header: 0x%x)ÚTYPE_IMMEDIATErƒrbrcÚTYPE_RAWrrrBrÚ
TYPE_ARRAYrtÚTYPE_MAPruÚTYPE_BINrsr[ÚTYPE_EXTrvr0)rÚexecuteÚtypr�r4rYÚLrrrÚ_read_header”s¢





























































zUnpacker._read_headerc	s*ˆ |¡\}}}|tkr,|tkr(tdƒ‚|S|tkrH|tkrDtdƒ‚|S|tkrÀ|tkrtt|ƒD]}ˆ t¡q`dSt	|ƒ}t|ƒD]}| 
ˆ t¡¡q„ˆjdk	r®ˆ |¡}ˆj
r¸|St|ƒS|tk�r–|tkrøt|ƒD]}ˆ t¡ˆ t¡qÚdSˆjdk	�r"ˆ ‡fdd„t|ƒDƒ¡}npi}t|ƒD]L}ˆ t¡}ˆj�rjt|ƒttfk�rjtdtt|ƒƒƒ‚ˆ t¡||<�q.ˆjdk	�r’ˆ |¡}|S|tk�r¤dS|tk�rìˆjdk	�rÌ| ˆjˆj¡}nˆj�rÞt|ƒ}n
| d¡}|S|tk�rˆ |t|ƒ¡S|tk�rt|ƒS|tk�s&t‚|S)NzExpected arrayzExpected mapc3s"|]}ˆ t¡ˆ t¡fVqdSr)rOÚEX_CONSTRUCT)Ú.0Ú_r%rrÚ	‰sþÿz#Unpacker._unpack..z%s is not allowed for map keyÚutf_8) r¼ÚEX_READ_ARRAY_HEADERrµrBÚEX_READ_MAP_HEADERr¶ÚEX_SKIPÚxrangerOrrr½rnrmr7rprjr6Úunicoder#rror´rkÚdecoderlrir¸rqr·r³r|)	rr¹rºr�r4r„rSr¿Úkeyrr%rrOhsl



ý








zUnpacker._unpackcCs|Srrr%rrrÚ__iter__¨szUnpacker.__iter__cCsTz| t¡}| ¡|WStk
r8| ¡t‚Yntk
rNt‚YnXdSr)rOr½r~r.Ú
StopIterationrPr1©rrSrrrÚ__next__«s
zUnpacker.__next__cCs| t¡| ¡dSr)rOrÄr~r%rrrÚskip¸s
z
Unpacker.skipcCs4z| t¡}Wntk
r&t‚YnX| ¡|Sr)rOr½rPr1r~rËrrrrK¼s
zUnpacker.unpackcCs| t¡}| ¡|Sr)rOrÂr~rËrrrÚread_array_headerÄs
zUnpacker.read_array_headercCs| t¡}| ¡|Sr)rOrÃr~rËrrrÚread_map_headerÉs
zUnpacker.read_map_headercCs|jSr)rwr%rrrÚtellÎsz
Unpacker.tell)r'r(r)Ú__doc__r2rrNr~rQrRr‚rrƒr½r¼rOrÉrÌÚnextrÍrKrÎrÏrÐrrrrrMœsBa
ø
R U@rMc@s–eZdZdZd#dd„Zeeefdd„Zd	d
„Z	dd„Z
d
d„Zdd„Zdd„Z
dd„Zdd„Zefdd„Zdd„Zdd„Zdd„Zdd „Zd!d"„ZdS)$ÚPackerah
    MessagePack Packer

    usage:

        packer = Packer()
        astream.write(packer.pack(a))
        astream.write(packer.pack(b))

    Packer's constructor has some keyword arguments:

    :param callable default:
        Convert user type to builtin type that Packer supports.
        See also simplejson's document.

    :param bool use_single_float:
        Use single precision float type for float. (default: False)

    :param bool autoreset:
        Reset buffer after each pack and return its content as `bytes`. (default: True).
        If set this to false, use `bytes()` to get content and `.reset()` to clear buffer.

    :param bool use_bin_type:
        Use bin type introduced in msgpack spec 2.0 for bytes.
        It also enables str8 type for unicode.

    :param bool strict_types:
        If set to true, types will be checked to be exact. Derived classes
        from serializeable types will not be serialized and will be
        treated as unsupported type and forwarded to default.
        Additionally tuples will not be serialized as lists.
        This is useful when trying to implement accurate serialization
        for python types.

    :param str encoding:
        (deprecated) Convert unicode to bytes with this encoding. (default: 'utf-8')

    :param str unicode_errors:
        Error handler for encoding unicode. (default: 'strict')
    NFTcCsx|dkrd}ntjdtdd�|dkr*d}||_||_||_||_||_||_t	ƒ|_
|dk	rnt|ƒsntdƒ‚||_
dS)NrÁr]rr9r^zdefault must be callable)r>r?rEÚ
_strict_typesÚ
_use_floatÚ
_autoresetÚ
_use_bin_typerkrlrrbr`r;Ú_default)rÚdefaultryrzZuse_single_floatZ	autoresetZuse_bin_typeZstrict_typesrrrrûs(þzPacker.__init__cCs„d}|jr|}t}nttf}|dkr,tdƒ‚|dkr@|j d¡S||tƒrf|rZ|j d¡S|j d¡S||tƒ�r€d|kr†dkržnn|j t 	d|¡¡Sd	|kr²dkrÊnn|j t 	d
|¡¡Sd|krÞdkrønn|j t 	dd
|¡¡Sd|k�rdk�r*nn|j t 	dd|¡¡Sd|k�rBdk�r\nn|j t 	dd|¡¡Sd|k�rtdk�rŽnn|j t 	dd|¡¡Sd|k�r¦dk�rÀnn|j t 	dd|¡¡Sd|k�rØdk�rònn|j t 	dd|¡¡Sd|k�r
dk�r$nn|j t 	dd|¡¡Sd |k�rBbr éÿÿú>BHr�i€ÿÿz>Bhr¡ìÿÿú>BIrži€z>Bir¢lÿÿÿÿz>BQrŸlûÿÿÿz>Bqr£TzInteger value out of rangeìz%s is too largez5Can't encode unicode string: no encoding is specifiedzString is too largezMemoryview is too largez>Bfr™z>BdršróÔróÕr3óÖr›ó×rªóØú>BBr–r—r˜zCannot serialize %r)(rÔÚlistr7rBrbr$rhÚ	int_typesrVÚpackrØÚ
OverflowErrorr#r"r
r6r'Ú_pack_bin_headerrÆrkr;ÚencoderlÚ_pack_raw_headerr rAÚfloatrÕr2ÚcoderJrÚintr|Ú_pack_array_headerrÅÚ_packÚdictÚ_pack_map_pairsr)rr4Ú
nest_limitZcheckZcheck_type_strictZdefault_usedZ
list_typesr�rñrJr»r„rrrrôsÒ



ÿ











ÿ
zPacker._packcCsFz| |¡Wntƒ|_‚YnX|jrB|j ¡}tƒ|_|SdSr)rôrrbrÖr&)rr4rSrrrrë‚s
zPacker.packcCs0| t|ƒ|¡|jr,|j ¡}tƒ|_|SdSr)rör
rÖrbr&r)rÚpairsrSrrrÚpack_map_pairs�s

zPacker.pack_map_pairscCs6|dkrt‚| |¡|jr2|j ¡}tƒ|_|SdS©Nrâ)rBrórÖrbr&r©rr�rSrrrÚpack_array_header”s

zPacker.pack_array_headercCs6|dkrt‚| |¡|jr2|j ¡}tƒ|_|SdSrú)rBÚ_pack_map_headerrÖrbr&rrûrrrÚpack_map_header�s

zPacker.pack_map_headercCsJt|tƒstdƒ‚d|kr&dks0ntdƒ‚t|tƒsBtdƒ‚t|ƒ}|dkrZtdƒ‚|dkrp|j d	¡n¶|d
kr†|j d¡n |dkrœ|j d
¡nŠ|dkr²|j d¡nt|dkrÈ|j d¡n^|dkrê|j dt 	d|¡¡n<|dk�r|j dt 	d|¡¡n|j dt 	d|¡¡|j t 	d|¡¡|j |¡dS)Nztypecode must have int type.réztypecode should be 0-127zdata must have bytes typeràzToo large datarrãrrär3rår›rærªrçrˆóÇrÝrÞóÈr“óÉr•)
rròr;rBr#r
rbr$rVrë)rÚtypecoderJr»rrrÚ
pack_ext_type¦s4


zPacker.pack_ext_typecCsh|dkr |j t dd|¡¡S|dkr>|j t dd|¡¡S|dkr\|j t dd	|¡¡Std
ƒ‚dS)Nr�rÝrŒrÞrßr¯ràrár°zArray is too large©rbr$rVrërBr€rrrróÃszPacker._pack_array_headercCsh|dkr |j t dd|¡¡S|dkr>|j t dd|¡¡S|dkr\|j t dd	|¡¡Std
ƒ‚dS)Nr�rÝr†rÞrßr±ràrár²zDict is too largerr€rrrrýÌszPacker._pack_map_headercCs<| |¡|D](\}}| ||d¡| ||d¡qdS)Nr)rýrô)rr�rør÷ÚkÚvrrrröÕs
zPacker._pack_map_pairscCs”|dkr"|j t dd|¡¡nn|jrH|dkrH|j t dd|¡¡nH|dkrh|j t dd	|¡¡n(|d
krˆ|j t dd|¡¡ntd
ƒ‚dS)NrŠrÝr‰rˆrèr¬rÞrßr­ràrár®zRaw is too large)rbr$rVrër×rBr€rrrrïÛszPacker._pack_raw_headercCsv|js| |¡S|dkr.|j t dd|¡¡S|dkrL|j t dd|¡¡S|dkrj|j t dd	|¡¡Std
ƒ‚dS)Nrˆrèr‘rÞrßr’ràrár”zBin is too large)r×rïrbr$rVrërBr€rrrríçs
zPacker._pack_bin_headercCs
|j ¡S)z/Return internal buffer contents as bytes object)rbr&r%rrrr#ószPacker.bytescCstƒ|_dS)zYReset internal buffer.

        This method is usaful only when autoreset=False.
        N)rrbr%rrrÚreset÷szPacker.resetcCs"tstrt| ¡ƒS|j ¡SdS)zReturn view of internal buffer.N)ÚUSING_STRINGBUILDERr<r r#rbÚ	getbufferr%rrrr
þszPacker.getbuffer)NNNFTFF)r'r(r)rÑrÚDEFAULT_RECURSE_LIMITrr8rôrërùrürþrrórýrörïrír#rr
rrrrrÓÒs0(þ
ÿ
n				rÓ)r):rÑÚsysrVr>Úversion_infor<ròZlongrêrrrÆÚrangerÅÚRuntimeErrorrPrÚhasattrZ__pypy__rZ__pypy__.buildersrrÚImportErrorr	ÚobjectrÚior*Ú
exceptionsr-r.r/r0r1Úr2rÄr½rÂrÃr³rµr¶r´r·r¸rr6r7r8rDrKrGr[rWrMrÓrrrrÚsj



:PKÔ¶N]ý>QÀ~~Esite-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-38.pycnu„[µü¤U

ÀÒ.eÿã@sÎddlmZddlTddlmZGdd„deddƒƒZddlZej d	¡r`dd
l	m
Z
mZmZnBzdd
l
m
Z
mZmZWn(ek
r dd
l	m
Z
mZmZYnXdd„Zd
d„Zdd„ZeZeZeZeZdS)é)Úversion)Ú*é)Ú
namedtuplecs eZdZdZ‡fdd„Z‡ZS)ÚExtTypez'ExtType represents ext type in msgpack.csVt|tƒstdƒ‚t|tƒs$tdƒ‚d|kr8dksBntdƒ‚tt|ƒ |||¡S)Nzcode must be intzdata must be bytesrézcode must be 0~127)Ú
isinstanceÚintÚ	TypeErrorÚbytesÚ
ValueErrorÚsuperrÚ__new__)ÚclsÚcodeÚdata©Ú	__class__©ú@/usr/lib/python3.8/site-packages/pip/_vendor/msgpack/__init__.pyr
s

zExtType.__new__)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rÚ
__classcell__rrrrrsrz	code dataNZMSGPACK_PUREPYTHON)ÚPackerÚunpackbÚUnpackercKstf|Ž}| | |¡¡dS)zX
    Pack object `o` and write it to `stream`

    See :class:`Packer` for options.
    N)rÚwriteÚpack)ÚoÚstreamÚkwargsZpackerrrrrs
rcKstf|Ž |¡S)zW
    Pack object `o` and return packed bytes

    See :class:`Packer` for options.
    )rr)r r"rrrÚpackb(sr#cKs| ¡}t|f|ŽS)zŒ
    Unpack an object from `stream`.

    Raises `ExtraData` when `stream` contains extra bytes.
    See :class:`Unpacker` for options.
    )Úreadr)r!r"rrrrÚunpack1sr%)Z_versionrÚ
exceptionsÚcollectionsrrÚosÚenvironÚgetZfallbackrrrZ	_cmsgpackÚImportErrorrr#r%ÚloadÚloadsÚdumpÚdumpsrrrrÚs"
	PKÔ¶N]Ïá]>Msite-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.e9ã@sxGdd„deƒZGdd„deƒZGdd„deƒZGdd„deeƒZGdd	„d	eeƒZeZGd
d„deƒZeZ	eZ
eZdS)
c@seZdZdZdS)ÚUnpackExceptionzËBase class for some exceptions raised while unpacking.

    NOTE: unpack may raise exception other than subclass of
    UnpackException.  If you want to catch all error, catch
    Exception instead.
    N©Ú__name__Ú
__module__Ú__qualname__Ú__doc__©rrúB/usr/lib/python3.8/site-packages/pip/_vendor/msgpack/exceptions.pyrsrc@seZdZdS)Ú
BufferFullN©rrrrrrrr	
sr	c@seZdZdS)Ú	OutOfDataNr
rrrrrsrc@seZdZdZdS)ÚFormatErrorzInvalid msgpack formatNrrrrrrsrc@seZdZdZdS)Ú
StackErrorz
Too nestedNrrrrrr
sr
c@s eZdZdZdd„Zdd„ZdS)Ú	ExtraDatazƒExtraData is raised when there is trailing data.

    This exception is raised while only one-shot (not streaming)
    unpack.
    cCs||_||_dS)N)ÚunpackedÚextra)ÚselfrrrrrÚ__init__%szExtraData.__init__cCsdS)Nzunpack(b) received extra data.r)rrrrÚ__str__)szExtraData.__str__N)rrrrrrrrrrrsrN)
Ú	Exceptionrr	rÚ
ValueErrorrr
ZUnpackValueErrorrZ
PackExceptionZPackValueErrorÚ
OverflowErrorZPackOverflowErrorrrrrÚs	PKÔ¶N]Gz	¶¶Ksite-packages/pip/_vendor/msgpack/__pycache__/_version.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eã@sdZdS))éééN)Úversion©rrú@/usr/lib/python3.8/site-packages/pip/_vendor/msgpack/_version.pyÚóPKÔ¶N]Âw§ÑN’N’-site-packages/pip/_vendor/msgpack/fallback.pynu„[µü¤"""Fallback pure Python implementation of msgpack"""

import sys
import struct
import warnings


if sys.version_info[0] == 2:
    PY2 = True
    int_types = (int, long)
    def dict_iteritems(d):
        return d.iteritems()
else:
    PY2 = False
    int_types = int
    unicode = str
    xrange = range
    def dict_iteritems(d):
        return d.items()

if sys.version_info < (3, 5):
    # Ugly hack...
    RecursionError = RuntimeError

    def _is_recursionerror(e):
        return len(e.args) == 1 and isinstance(e.args[0], str) and \
            e.args[0].startswith('maximum recursion depth exceeded')
else:
    def _is_recursionerror(e):
        return True

if hasattr(sys, 'pypy_version_info'):
    # cStringIO is slow on PyPy, StringIO is faster.  However: PyPy's own
    # StringBuilder is fastest.
    from __pypy__ import newlist_hint
    try:
        from __pypy__.builders import BytesBuilder as StringBuilder
    except ImportError:
        from __pypy__.builders import StringBuilder
    USING_STRINGBUILDER = True
    class StringIO(object):
        def __init__(self, s=b''):
            if s:
                self.builder = StringBuilder(len(s))
                self.builder.append(s)
            else:
                self.builder = StringBuilder()
        def write(self, s):
            if isinstance(s, memoryview):
                s = s.tobytes()
            elif isinstance(s, bytearray):
                s = bytes(s)
            self.builder.append(s)
        def getvalue(self):
            return self.builder.build()
else:
    USING_STRINGBUILDER = False
    from io import BytesIO as StringIO
    newlist_hint = lambda size: []


from .exceptions import (
    BufferFull,
    OutOfData,
    ExtraData,
    FormatError,
    StackError,
)

from . import ExtType


EX_SKIP                 = 0
EX_CONSTRUCT            = 1
EX_READ_ARRAY_HEADER    = 2
EX_READ_MAP_HEADER      = 3

TYPE_IMMEDIATE          = 0
TYPE_ARRAY              = 1
TYPE_MAP                = 2
TYPE_RAW                = 3
TYPE_BIN                = 4
TYPE_EXT                = 5

DEFAULT_RECURSE_LIMIT = 511


def _check_type_strict(obj, t, type=type, tuple=tuple):
    if type(t) is tuple:
        return type(obj) in t
    else:
        return type(obj) is t


def _get_data_from_buffer(obj):
    try:
        view = memoryview(obj)
    except TypeError:
        # try to use legacy buffer protocol if 2.7, otherwise re-raise
        if PY2:
            view = memoryview(buffer(obj))
            warnings.warn("using old buffer interface to unpack %s; "
                          "this leads to unpacking errors if slicing is used and "
                          "will be removed in a future version" % type(obj),
                          RuntimeWarning, stacklevel=3)
        else:
            raise
    if view.itemsize != 1:
        raise ValueError("cannot unpack from multi-byte object")
    return view


def unpack(stream, **kwargs):
    warnings.warn(
        "Direct calling implementation's unpack() is deprecated, Use msgpack.unpack() or unpackb() instead.",
        DeprecationWarning, stacklevel=2)
    data = stream.read()
    return unpackb(data, **kwargs)


def unpackb(packed, **kwargs):
    """
    Unpack an object from `packed`.

    Raises ``ExtraData`` when *packed* contains extra bytes.
    Raises ``ValueError`` when *packed* is incomplete.
    Raises ``FormatError`` when *packed* is not valid msgpack.
    Raises ``StackError`` when *packed* contains too nested.
    Other exceptions can be raised during unpacking.

    See :class:`Unpacker` for options.
    """
    unpacker = Unpacker(None, max_buffer_size=len(packed), **kwargs)
    unpacker.feed(packed)
    try:
        ret = unpacker._unpack()
    except OutOfData:
        raise ValueError("Unpack failed: incomplete input")
    except RecursionError as e:
        if _is_recursionerror(e):
            raise StackError
        raise
    if unpacker._got_extradata():
        raise ExtraData(ret, unpacker._get_extradata())
    return ret


if sys.version_info < (2, 7, 6):
    def _unpack_from(f, b, o=0):
        """Explicit typcast for legacy struct.unpack_from"""
        return struct.unpack_from(f, bytes(b), o)
else:
    _unpack_from = struct.unpack_from


class Unpacker(object):
    """Streaming unpacker.

    arguments:

    :param file_like:
        File-like object having `.read(n)` method.
        If specified, unpacker reads serialized data from it and :meth:`feed()` is not usable.

    :param int read_size:
        Used as `file_like.read(read_size)`. (default: `min(16*1024, max_buffer_size)`)

    :param bool use_list:
        If true, unpack msgpack array to Python list.
        Otherwise, unpack to Python tuple. (default: True)

    :param bool raw:
        If true, unpack msgpack raw to Python bytes (default).
        Otherwise, unpack to Python str (or unicode on Python 2) by decoding
        with UTF-8 encoding (recommended).
        Currently, the default is true, but it will be changed to false in
        near future.  So you must specify it explicitly for keeping backward
        compatibility.

        *encoding* option which is deprecated overrides this option.

    :param bool strict_map_key:
        If true, only str or bytes are accepted for map (dict) keys.
        It's False by default for backward-compatibility.
        But it will be True from msgpack 1.0.

    :param callable object_hook:
        When specified, it should be callable.
        Unpacker calls it with a dict argument after unpacking msgpack map.
        (See also simplejson)

    :param callable object_pairs_hook:
        When specified, it should be callable.
        Unpacker calls it with a list of key-value pairs after unpacking msgpack map.
        (See also simplejson)

    :param str encoding:
        Encoding used for decoding msgpack raw.
        If it is None (default), msgpack raw is deserialized to Python bytes.

    :param str unicode_errors:
        (deprecated) Used for decoding msgpack raw with *encoding*.
        (default: `'strict'`)

    :param int max_buffer_size:
        Limits size of data waiting unpacked.  0 means system's INT_MAX (default).
        Raises `BufferFull` exception when it is insufficient.
        You should set this parameter when unpacking data from untrusted source.

    :param int max_str_len:
        Deprecated, use *max_buffer_size* instead.
        Limits max length of str. (default: max_buffer_size or 1024*1024)

    :param int max_bin_len:
        Deprecated, use *max_buffer_size* instead.
        Limits max length of bin. (default: max_buffer_size or 1024*1024)

    :param int max_array_len:
        Limits max length of array.
        (default: max_buffer_size or 128*1024)

    :param int max_map_len:
        Limits max length of map.
        (default: max_buffer_size//2 or 32*1024)

    :param int max_ext_len:
        Deprecated, use *max_buffer_size* instead.
        Limits max size of ext type.  (default: max_buffer_size or 1024*1024)

    Example of streaming deserialize from file-like object::

        unpacker = Unpacker(file_like, raw=False, max_buffer_size=10*1024*1024)
        for o in unpacker:
            process(o)

    Example of streaming deserialize from socket::

        unpacker = Unpacker(raw=False, max_buffer_size=10*1024*1024)
        while True:
            buf = sock.recv(1024**2)
            if not buf:
                break
            unpacker.feed(buf)
            for o in unpacker:
                process(o)

    Raises ``ExtraData`` when *packed* contains extra bytes.
    Raises ``OutOfData`` when *packed* is incomplete.
    Raises ``FormatError`` when *packed* is not valid msgpack.
    Raises ``StackError`` when *packed* contains too nested.
    Other exceptions can be raised during unpacking.
    """

    def __init__(self, file_like=None, read_size=0, use_list=True, raw=True, strict_map_key=False,
                 object_hook=None, object_pairs_hook=None, list_hook=None,
                 encoding=None, unicode_errors=None, max_buffer_size=0,
                 ext_hook=ExtType,
                 max_str_len=-1,
                 max_bin_len=-1,
                 max_array_len=-1,
                 max_map_len=-1,
                 max_ext_len=-1):
        if encoding is not None:
            warnings.warn(
                "encoding is deprecated, Use raw=False instead.",
                DeprecationWarning, stacklevel=2)

        if unicode_errors is None:
            unicode_errors = 'strict'

        if file_like is None:
            self._feeding = True
        else:
            if not callable(file_like.read):
                raise TypeError("`file_like.read` must be callable")
            self.file_like = file_like
            self._feeding = False

        #: array of bytes fed.
        self._buffer = bytearray()
        #: Which position we currently reads
        self._buff_i = 0

        # When Unpacker is used as an iterable, between the calls to next(),
        # the buffer is not "consumed" completely, for efficiency sake.
        # Instead, it is done sloppily.  To make sure we raise BufferFull at
        # the correct moments, we have to keep track of how sloppy we were.
        # Furthermore, when the buffer is incomplete (that is: in the case
        # we raise an OutOfData) we need to rollback the buffer to the correct
        # state, which _buf_checkpoint records.
        self._buf_checkpoint = 0

        if max_str_len == -1:
            max_str_len = max_buffer_size or 1024*1024
        if max_bin_len == -1:
            max_bin_len = max_buffer_size or 1024*1024
        if max_array_len == -1:
            max_array_len = max_buffer_size or 128*1024
        if max_map_len == -1:
            max_map_len = max_buffer_size//2 or 32*1024
        if max_ext_len == -1:
            max_ext_len = max_buffer_size or 1024*1024

        self._max_buffer_size = max_buffer_size or 2**31-1
        if read_size > self._max_buffer_size:
            raise ValueError("read_size must be smaller than max_buffer_size")
        self._read_size = read_size or min(self._max_buffer_size, 16*1024)
        self._raw = bool(raw)
        self._strict_map_key = bool(strict_map_key)
        self._encoding = encoding
        self._unicode_errors = unicode_errors
        self._use_list = use_list
        self._list_hook = list_hook
        self._object_hook = object_hook
        self._object_pairs_hook = object_pairs_hook
        self._ext_hook = ext_hook
        self._max_str_len = max_str_len
        self._max_bin_len = max_bin_len
        self._max_array_len = max_array_len
        self._max_map_len = max_map_len
        self._max_ext_len = max_ext_len
        self._stream_offset = 0

        if list_hook is not None and not callable(list_hook):
            raise TypeError('`list_hook` is not callable')
        if object_hook is not None and not callable(object_hook):
            raise TypeError('`object_hook` is not callable')
        if object_pairs_hook is not None and not callable(object_pairs_hook):
            raise TypeError('`object_pairs_hook` is not callable')
        if object_hook is not None and object_pairs_hook is not None:
            raise TypeError("object_pairs_hook and object_hook are mutually "
                            "exclusive")
        if not callable(ext_hook):
            raise TypeError("`ext_hook` is not callable")

    def feed(self, next_bytes):
        assert self._feeding
        view = _get_data_from_buffer(next_bytes)
        if (len(self._buffer) - self._buff_i + len(view) > self._max_buffer_size):
            raise BufferFull

        # Strip buffer before checkpoint before reading file.
        if self._buf_checkpoint > 0:
            del self._buffer[:self._buf_checkpoint]
            self._buff_i -= self._buf_checkpoint
            self._buf_checkpoint = 0

        # Use extend here: INPLACE_ADD += doesn't reliably typecast memoryview in jython
        self._buffer.extend(view)

    def _consume(self):
        """ Gets rid of the used parts of the buffer. """
        self._stream_offset += self._buff_i - self._buf_checkpoint
        self._buf_checkpoint = self._buff_i

    def _got_extradata(self):
        return self._buff_i < len(self._buffer)

    def _get_extradata(self):
        return self._buffer[self._buff_i:]

    def read_bytes(self, n):
        return self._read(n)

    def _read(self, n):
        # (int) -> bytearray
        self._reserve(n)
        i = self._buff_i
        self._buff_i = i+n
        return self._buffer[i:i+n]

    def _reserve(self, n):
        remain_bytes = len(self._buffer) - self._buff_i - n

        # Fast path: buffer has n bytes already
        if remain_bytes >= 0:
            return

        if self._feeding:
            self._buff_i = self._buf_checkpoint
            raise OutOfData

        # Strip buffer before checkpoint before reading file.
        if self._buf_checkpoint > 0:
            del self._buffer[:self._buf_checkpoint]
            self._buff_i -= self._buf_checkpoint
            self._buf_checkpoint = 0

        # Read from file
        remain_bytes = -remain_bytes
        while remain_bytes > 0:
            to_read_bytes = max(self._read_size, remain_bytes)
            read_data = self.file_like.read(to_read_bytes)
            if not read_data:
                break
            assert isinstance(read_data, bytes)
            self._buffer += read_data
            remain_bytes -= len(read_data)

        if len(self._buffer) < n + self._buff_i:
            self._buff_i = 0  # rollback
            raise OutOfData

    def _read_header(self, execute=EX_CONSTRUCT):
        typ = TYPE_IMMEDIATE
        n = 0
        obj = None
        self._reserve(1)
        b = self._buffer[self._buff_i]
        self._buff_i += 1
        if b & 0b10000000 == 0:
            obj = b
        elif b & 0b11100000 == 0b11100000:
            obj = -1 - (b ^ 0xff)
        elif b & 0b11100000 == 0b10100000:
            n = b & 0b00011111
            typ = TYPE_RAW
            if n > self._max_str_len:
                raise ValueError("%s exceeds max_str_len(%s)", n, self._max_str_len)
            obj = self._read(n)
        elif b & 0b11110000 == 0b10010000:
            n = b & 0b00001111
            typ = TYPE_ARRAY
            if n > self._max_array_len:
                raise ValueError("%s exceeds max_array_len(%s)", n, self._max_array_len)
        elif b & 0b11110000 == 0b10000000:
            n = b & 0b00001111
            typ = TYPE_MAP
            if n > self._max_map_len:
                raise ValueError("%s exceeds max_map_len(%s)", n, self._max_map_len)
        elif b == 0xc0:
            obj = None
        elif b == 0xc2:
            obj = False
        elif b == 0xc3:
            obj = True
        elif b == 0xc4:
            typ = TYPE_BIN
            self._reserve(1)
            n = self._buffer[self._buff_i]
            self._buff_i += 1
            if n > self._max_bin_len:
                raise ValueError("%s exceeds max_bin_len(%s)" % (n, self._max_bin_len))
            obj = self._read(n)
        elif b == 0xc5:
            typ = TYPE_BIN
            self._reserve(2)
            n = _unpack_from(">H", self._buffer, self._buff_i)[0]
            self._buff_i += 2
            if n > self._max_bin_len:
                raise ValueError("%s exceeds max_bin_len(%s)" % (n, self._max_bin_len))
            obj = self._read(n)
        elif b == 0xc6:
            typ = TYPE_BIN
            self._reserve(4)
            n = _unpack_from(">I", self._buffer, self._buff_i)[0]
            self._buff_i += 4
            if n > self._max_bin_len:
                raise ValueError("%s exceeds max_bin_len(%s)" % (n, self._max_bin_len))
            obj = self._read(n)
        elif b == 0xc7:  # ext 8
            typ = TYPE_EXT
            self._reserve(2)
            L, n = _unpack_from('Bb', self._buffer, self._buff_i)
            self._buff_i += 2
            if L > self._max_ext_len:
                raise ValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len))
            obj = self._read(L)
        elif b == 0xc8:  # ext 16
            typ = TYPE_EXT
            self._reserve(3)
            L, n = _unpack_from('>Hb', self._buffer, self._buff_i)
            self._buff_i += 3
            if L > self._max_ext_len:
                raise ValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len))
            obj = self._read(L)
        elif b == 0xc9:  # ext 32
            typ = TYPE_EXT
            self._reserve(5)
            L, n = _unpack_from('>Ib', self._buffer, self._buff_i)
            self._buff_i += 5
            if L > self._max_ext_len:
                raise ValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len))
            obj = self._read(L)
        elif b == 0xca:
            self._reserve(4)
            obj = _unpack_from(">f", self._buffer, self._buff_i)[0]
            self._buff_i += 4
        elif b == 0xcb:
            self._reserve(8)
            obj = _unpack_from(">d", self._buffer, self._buff_i)[0]
            self._buff_i += 8
        elif b == 0xcc:
            self._reserve(1)
            obj = self._buffer[self._buff_i]
            self._buff_i += 1
        elif b == 0xcd:
            self._reserve(2)
            obj = _unpack_from(">H", self._buffer, self._buff_i)[0]
            self._buff_i += 2
        elif b == 0xce:
            self._reserve(4)
            obj = _unpack_from(">I", self._buffer, self._buff_i)[0]
            self._buff_i += 4
        elif b == 0xcf:
            self._reserve(8)
            obj = _unpack_from(">Q", self._buffer, self._buff_i)[0]
            self._buff_i += 8
        elif b == 0xd0:
            self._reserve(1)
            obj = _unpack_from("b", self._buffer, self._buff_i)[0]
            self._buff_i += 1
        elif b == 0xd1:
            self._reserve(2)
            obj = _unpack_from(">h", self._buffer, self._buff_i)[0]
            self._buff_i += 2
        elif b == 0xd2:
            self._reserve(4)
            obj = _unpack_from(">i", self._buffer, self._buff_i)[0]
            self._buff_i += 4
        elif b == 0xd3:
            self._reserve(8)
            obj = _unpack_from(">q", self._buffer, self._buff_i)[0]
            self._buff_i += 8
        elif b == 0xd4:  # fixext 1
            typ = TYPE_EXT
            if self._max_ext_len < 1:
                raise ValueError("%s exceeds max_ext_len(%s)" % (1, self._max_ext_len))
            self._reserve(2)
            n, obj = _unpack_from("b1s", self._buffer, self._buff_i)
            self._buff_i += 2
        elif b == 0xd5:  # fixext 2
            typ = TYPE_EXT
            if self._max_ext_len < 2:
                raise ValueError("%s exceeds max_ext_len(%s)" % (2, self._max_ext_len))
            self._reserve(3)
            n, obj = _unpack_from("b2s", self._buffer, self._buff_i)
            self._buff_i += 3
        elif b == 0xd6:  # fixext 4
            typ = TYPE_EXT
            if self._max_ext_len < 4:
                raise ValueError("%s exceeds max_ext_len(%s)" % (4, self._max_ext_len))
            self._reserve(5)
            n, obj = _unpack_from("b4s", self._buffer, self._buff_i)
            self._buff_i += 5
        elif b == 0xd7:  # fixext 8
            typ = TYPE_EXT
            if self._max_ext_len < 8:
                raise ValueError("%s exceeds max_ext_len(%s)" % (8, self._max_ext_len))
            self._reserve(9)
            n, obj = _unpack_from("b8s", self._buffer, self._buff_i)
            self._buff_i += 9
        elif b == 0xd8:  # fixext 16
            typ = TYPE_EXT
            if self._max_ext_len < 16:
                raise ValueError("%s exceeds max_ext_len(%s)" % (16, self._max_ext_len))
            self._reserve(17)
            n, obj = _unpack_from("b16s", self._buffer, self._buff_i)
            self._buff_i += 17
        elif b == 0xd9:
            typ = TYPE_RAW
            self._reserve(1)
            n = self._buffer[self._buff_i]
            self._buff_i += 1
            if n > self._max_str_len:
                raise ValueError("%s exceeds max_str_len(%s)", n, self._max_str_len)
            obj = self._read(n)
        elif b == 0xda:
            typ = TYPE_RAW
            self._reserve(2)
            n, = _unpack_from(">H", self._buffer, self._buff_i)
            self._buff_i += 2
            if n > self._max_str_len:
                raise ValueError("%s exceeds max_str_len(%s)", n, self._max_str_len)
            obj = self._read(n)
        elif b == 0xdb:
            typ = TYPE_RAW
            self._reserve(4)
            n, = _unpack_from(">I", self._buffer, self._buff_i)
            self._buff_i += 4
            if n > self._max_str_len:
                raise ValueError("%s exceeds max_str_len(%s)", n, self._max_str_len)
            obj = self._read(n)
        elif b == 0xdc:
            typ = TYPE_ARRAY
            self._reserve(2)
            n, = _unpack_from(">H", self._buffer, self._buff_i)
            self._buff_i += 2
            if n > self._max_array_len:
                raise ValueError("%s exceeds max_array_len(%s)", n, self._max_array_len)
        elif b == 0xdd:
            typ = TYPE_ARRAY
            self._reserve(4)
            n, = _unpack_from(">I", self._buffer, self._buff_i)
            self._buff_i += 4
            if n > self._max_array_len:
                raise ValueError("%s exceeds max_array_len(%s)", n, self._max_array_len)
        elif b == 0xde:
            self._reserve(2)
            n, = _unpack_from(">H", self._buffer, self._buff_i)
            self._buff_i += 2
            if n > self._max_map_len:
                raise ValueError("%s exceeds max_map_len(%s)", n, self._max_map_len)
            typ = TYPE_MAP
        elif b == 0xdf:
            self._reserve(4)
            n, = _unpack_from(">I", self._buffer, self._buff_i)
            self._buff_i += 4
            if n > self._max_map_len:
                raise ValueError("%s exceeds max_map_len(%s)", n, self._max_map_len)
            typ = TYPE_MAP
        else:
            raise FormatError("Unknown header: 0x%x" % b)
        return typ, n, obj

    def _unpack(self, execute=EX_CONSTRUCT):
        typ, n, obj = self._read_header(execute)

        if execute == EX_READ_ARRAY_HEADER:
            if typ != TYPE_ARRAY:
                raise ValueError("Expected array")
            return n
        if execute == EX_READ_MAP_HEADER:
            if typ != TYPE_MAP:
                raise ValueError("Expected map")
            return n
        # TODO should we eliminate the recursion?
        if typ == TYPE_ARRAY:
            if execute == EX_SKIP:
                for i in xrange(n):
                    # TODO check whether we need to call `list_hook`
                    self._unpack(EX_SKIP)
                return
            ret = newlist_hint(n)
            for i in xrange(n):
                ret.append(self._unpack(EX_CONSTRUCT))
            if self._list_hook is not None:
                ret = self._list_hook(ret)
            # TODO is the interaction between `list_hook` and `use_list` ok?
            return ret if self._use_list else tuple(ret)
        if typ == TYPE_MAP:
            if execute == EX_SKIP:
                for i in xrange(n):
                    # TODO check whether we need to call hooks
                    self._unpack(EX_SKIP)
                    self._unpack(EX_SKIP)
                return
            if self._object_pairs_hook is not None:
                ret = self._object_pairs_hook(
                    (self._unpack(EX_CONSTRUCT),
                     self._unpack(EX_CONSTRUCT))
                    for _ in xrange(n))
            else:
                ret = {}
                for _ in xrange(n):
                    key = self._unpack(EX_CONSTRUCT)
                    if self._strict_map_key and type(key) not in (unicode, bytes):
                        raise ValueError("%s is not allowed for map key" % str(type(key)))
                    ret[key] = self._unpack(EX_CONSTRUCT)
                if self._object_hook is not None:
                    ret = self._object_hook(ret)
            return ret
        if execute == EX_SKIP:
            return
        if typ == TYPE_RAW:
            if self._encoding is not None:
                obj = obj.decode(self._encoding, self._unicode_errors)
            elif self._raw:
                obj = bytes(obj)
            else:
                obj = obj.decode('utf_8')
            return obj
        if typ == TYPE_EXT:
            return self._ext_hook(n, bytes(obj))
        if typ == TYPE_BIN:
            return bytes(obj)
        assert typ == TYPE_IMMEDIATE
        return obj

    def __iter__(self):
        return self

    def __next__(self):
        try:
            ret = self._unpack(EX_CONSTRUCT)
            self._consume()
            return ret
        except OutOfData:
            self._consume()
            raise StopIteration
        except RecursionError:
            raise StackError

    next = __next__

    def skip(self):
        self._unpack(EX_SKIP)
        self._consume()

    def unpack(self):
        try:
            ret = self._unpack(EX_CONSTRUCT)
        except RecursionError:
            raise StackError
        self._consume()
        return ret

    def read_array_header(self):
        ret = self._unpack(EX_READ_ARRAY_HEADER)
        self._consume()
        return ret

    def read_map_header(self):
        ret = self._unpack(EX_READ_MAP_HEADER)
        self._consume()
        return ret

    def tell(self):
        return self._stream_offset


class Packer(object):
    """
    MessagePack Packer

    usage:

        packer = Packer()
        astream.write(packer.pack(a))
        astream.write(packer.pack(b))

    Packer's constructor has some keyword arguments:

    :param callable default:
        Convert user type to builtin type that Packer supports.
        See also simplejson's document.

    :param bool use_single_float:
        Use single precision float type for float. (default: False)

    :param bool autoreset:
        Reset buffer after each pack and return its content as `bytes`. (default: True).
        If set this to false, use `bytes()` to get content and `.reset()` to clear buffer.

    :param bool use_bin_type:
        Use bin type introduced in msgpack spec 2.0 for bytes.
        It also enables str8 type for unicode.

    :param bool strict_types:
        If set to true, types will be checked to be exact. Derived classes
        from serializeable types will not be serialized and will be
        treated as unsupported type and forwarded to default.
        Additionally tuples will not be serialized as lists.
        This is useful when trying to implement accurate serialization
        for python types.

    :param str encoding:
        (deprecated) Convert unicode to bytes with this encoding. (default: 'utf-8')

    :param str unicode_errors:
        Error handler for encoding unicode. (default: 'strict')
    """
    def __init__(self, default=None, encoding=None, unicode_errors=None,
                 use_single_float=False, autoreset=True, use_bin_type=False,
                 strict_types=False):
        if encoding is None:
            encoding = 'utf_8'
        else:
            warnings.warn(
                "encoding is deprecated, Use raw=False instead.",
                DeprecationWarning, stacklevel=2)

        if unicode_errors is None:
            unicode_errors = 'strict'

        self._strict_types = strict_types
        self._use_float = use_single_float
        self._autoreset = autoreset
        self._use_bin_type = use_bin_type
        self._encoding = encoding
        self._unicode_errors = unicode_errors
        self._buffer = StringIO()
        if default is not None:
            if not callable(default):
                raise TypeError("default must be callable")
        self._default = default

    def _pack(self, obj, nest_limit=DEFAULT_RECURSE_LIMIT,
              check=isinstance, check_type_strict=_check_type_strict):
        default_used = False
        if self._strict_types:
            check = check_type_strict
            list_types = list
        else:
            list_types = (list, tuple)
        while True:
            if nest_limit < 0:
                raise ValueError("recursion limit exceeded")
            if obj is None:
                return self._buffer.write(b"\xc0")
            if check(obj, bool):
                if obj:
                    return self._buffer.write(b"\xc3")
                return self._buffer.write(b"\xc2")
            if check(obj, int_types):
                if 0 <= obj < 0x80:
                    return self._buffer.write(struct.pack("B", obj))
                if -0x20 <= obj < 0:
                    return self._buffer.write(struct.pack("b", obj))
                if 0x80 <= obj <= 0xff:
                    return self._buffer.write(struct.pack("BB", 0xcc, obj))
                if -0x80 <= obj < 0:
                    return self._buffer.write(struct.pack(">Bb", 0xd0, obj))
                if 0xff < obj <= 0xffff:
                    return self._buffer.write(struct.pack(">BH", 0xcd, obj))
                if -0x8000 <= obj < -0x80:
                    return self._buffer.write(struct.pack(">Bh", 0xd1, obj))
                if 0xffff < obj <= 0xffffffff:
                    return self._buffer.write(struct.pack(">BI", 0xce, obj))
                if -0x80000000 <= obj < -0x8000:
                    return self._buffer.write(struct.pack(">Bi", 0xd2, obj))
                if 0xffffffff < obj <= 0xffffffffffffffff:
                    return self._buffer.write(struct.pack(">BQ", 0xcf, obj))
                if -0x8000000000000000 <= obj < -0x80000000:
                    return self._buffer.write(struct.pack(">Bq", 0xd3, obj))
                if not default_used and self._default is not None:
                    obj = self._default(obj)
                    default_used = True
                    continue
                raise OverflowError("Integer value out of range")
            if check(obj, (bytes, bytearray)):
                n = len(obj)
                if n >= 2**32:
                    raise ValueError("%s is too large" % type(obj).__name__)
                self._pack_bin_header(n)
                return self._buffer.write(obj)
            if check(obj, unicode):
                if self._encoding is None:
                    raise TypeError(
                        "Can't encode unicode string: "
                        "no encoding is specified")
                obj = obj.encode(self._encoding, self._unicode_errors)
                n = len(obj)
                if n >= 2**32:
                    raise ValueError("String is too large")
                self._pack_raw_header(n)
                return self._buffer.write(obj)
            if check(obj, memoryview):
                n = len(obj) * obj.itemsize
                if n >= 2**32:
                    raise ValueError("Memoryview is too large")
                self._pack_bin_header(n)
                return self._buffer.write(obj)
            if check(obj, float):
                if self._use_float:
                    return self._buffer.write(struct.pack(">Bf", 0xca, obj))
                return self._buffer.write(struct.pack(">Bd", 0xcb, obj))
            if check(obj, ExtType):
                code = obj.code
                data = obj.data
                assert isinstance(code, int)
                assert isinstance(data, bytes)
                L = len(data)
                if L == 1:
                    self._buffer.write(b'\xd4')
                elif L == 2:
                    self._buffer.write(b'\xd5')
                elif L == 4:
                    self._buffer.write(b'\xd6')
                elif L == 8:
                    self._buffer.write(b'\xd7')
                elif L == 16:
                    self._buffer.write(b'\xd8')
                elif L <= 0xff:
                    self._buffer.write(struct.pack(">BB", 0xc7, L))
                elif L <= 0xffff:
                    self._buffer.write(struct.pack(">BH", 0xc8, L))
                else:
                    self._buffer.write(struct.pack(">BI", 0xc9, L))
                self._buffer.write(struct.pack("b", code))
                self._buffer.write(data)
                return
            if check(obj, list_types):
                n = len(obj)
                self._pack_array_header(n)
                for i in xrange(n):
                    self._pack(obj[i], nest_limit - 1)
                return
            if check(obj, dict):
                return self._pack_map_pairs(len(obj), dict_iteritems(obj),
                                               nest_limit - 1)
            if not default_used and self._default is not None:
                obj = self._default(obj)
                default_used = 1
                continue
            raise TypeError("Cannot serialize %r" % (obj, ))

    def pack(self, obj):
        try:
            self._pack(obj)
        except:
            self._buffer = StringIO()  # force reset
            raise
        if self._autoreset:
            ret = self._buffer.getvalue()
            self._buffer = StringIO()
            return ret

    def pack_map_pairs(self, pairs):
        self._pack_map_pairs(len(pairs), pairs)
        if self._autoreset:
            ret = self._buffer.getvalue()
            self._buffer = StringIO()
            return ret

    def pack_array_header(self, n):
        if n >= 2**32:
            raise ValueError
        self._pack_array_header(n)
        if self._autoreset:
            ret = self._buffer.getvalue()
            self._buffer = StringIO()
            return ret

    def pack_map_header(self, n):
        if n >= 2**32:
            raise ValueError
        self._pack_map_header(n)
        if self._autoreset:
            ret = self._buffer.getvalue()
            self._buffer = StringIO()
            return ret

    def pack_ext_type(self, typecode, data):
        if not isinstance(typecode, int):
            raise TypeError("typecode must have int type.")
        if not 0 <= typecode <= 127:
            raise ValueError("typecode should be 0-127")
        if not isinstance(data, bytes):
            raise TypeError("data must have bytes type")
        L = len(data)
        if L > 0xffffffff:
            raise ValueError("Too large data")
        if L == 1:
            self._buffer.write(b'\xd4')
        elif L == 2:
            self._buffer.write(b'\xd5')
        elif L == 4:
            self._buffer.write(b'\xd6')
        elif L == 8:
            self._buffer.write(b'\xd7')
        elif L == 16:
            self._buffer.write(b'\xd8')
        elif L <= 0xff:
            self._buffer.write(b'\xc7' + struct.pack('B', L))
        elif L <= 0xffff:
            self._buffer.write(b'\xc8' + struct.pack('>H', L))
        else:
            self._buffer.write(b'\xc9' + struct.pack('>I', L))
        self._buffer.write(struct.pack('B', typecode))
        self._buffer.write(data)

    def _pack_array_header(self, n):
        if n <= 0x0f:
            return self._buffer.write(struct.pack('B', 0x90 + n))
        if n <= 0xffff:
            return self._buffer.write(struct.pack(">BH", 0xdc, n))
        if n <= 0xffffffff:
            return self._buffer.write(struct.pack(">BI", 0xdd, n))
        raise ValueError("Array is too large")

    def _pack_map_header(self, n):
        if n <= 0x0f:
            return self._buffer.write(struct.pack('B', 0x80 + n))
        if n <= 0xffff:
            return self._buffer.write(struct.pack(">BH", 0xde, n))
        if n <= 0xffffffff:
            return self._buffer.write(struct.pack(">BI", 0xdf, n))
        raise ValueError("Dict is too large")

    def _pack_map_pairs(self, n, pairs, nest_limit=DEFAULT_RECURSE_LIMIT):
        self._pack_map_header(n)
        for (k, v) in pairs:
            self._pack(k, nest_limit - 1)
            self._pack(v, nest_limit - 1)

    def _pack_raw_header(self, n):
        if n <= 0x1f:
            self._buffer.write(struct.pack('B', 0xa0 + n))
        elif self._use_bin_type and n <= 0xff:
            self._buffer.write(struct.pack('>BB', 0xd9, n))
        elif n <= 0xffff:
            self._buffer.write(struct.pack(">BH", 0xda, n))
        elif n <= 0xffffffff:
            self._buffer.write(struct.pack(">BI", 0xdb, n))
        else:
            raise ValueError('Raw is too large')

    def _pack_bin_header(self, n):
        if not self._use_bin_type:
            return self._pack_raw_header(n)
        elif n <= 0xff:
            return self._buffer.write(struct.pack('>BB', 0xc4, n))
        elif n <= 0xffff:
            return self._buffer.write(struct.pack(">BH", 0xc5, n))
        elif n <= 0xffffffff:
            return self._buffer.write(struct.pack(">BI", 0xc6, n))
        else:
            raise ValueError('Bin is too large')

    def bytes(self):
        """Return internal buffer contents as bytes object"""
        return self._buffer.getvalue()

    def reset(self):
        """Reset internal buffer.

        This method is usaful only when autoreset=False.
        """
        self._buffer = StringIO()

    def getbuffer(self):
        """Return view of internal buffer."""
        if USING_STRINGBUILDER or PY2:
            return memoryview(self.bytes())
        else:
            return self._buffer.getbuffer()
PKÔ¶N]o�-site-packages/pip/_vendor/msgpack/_version.pynu„[µü¤version = (0, 6, 2)
PKÔ¶N]C\Uwøëøë)site-packages/pip/_vendor/distlib/util.pynu„[µü¤#
# Copyright (C) 2012-2017 The Python Software Foundation.
# See LICENSE.txt and CONTRIBUTORS.txt.
#
import codecs
from collections import deque
import contextlib
import csv
from glob import iglob as std_iglob
import io
import json
import logging
import os
import py_compile
import re
import socket
try:
    import ssl
except ImportError:  # pragma: no cover
    ssl = None
import subprocess
import sys
import tarfile
import tempfile
import textwrap

try:
    import threading
except ImportError:  # pragma: no cover
    import dummy_threading as threading
import time

from . import DistlibException
from .compat import (string_types, text_type, shutil, raw_input, StringIO,
                     cache_from_source, urlopen, urljoin, httplib, xmlrpclib,
                     splittype, HTTPHandler, BaseConfigurator, valid_ident,
                     Container, configparser, URLError, ZipFile, fsdecode,
                     unquote, urlparse)

logger = logging.getLogger(__name__)

#
# Requirement parsing code as per PEP 508
#

IDENTIFIER = re.compile(r'^([\w\.-]+)\s*')
VERSION_IDENTIFIER = re.compile(r'^([\w\.*+-]+)\s*')
COMPARE_OP = re.compile(r'^(<=?|>=?|={2,3}|[~!]=)\s*')
MARKER_OP = re.compile(r'^((<=?)|(>=?)|={2,3}|[~!]=|in|not\s+in)\s*')
OR = re.compile(r'^or\b\s*')
AND = re.compile(r'^and\b\s*')
NON_SPACE = re.compile(r'(\S+)\s*')
STRING_CHUNK = re.compile(r'([\s\w\.{}()*+#:;,/?!~`@$%^&=|<>\[\]-]+)')


def parse_marker(marker_string):
    """
    Parse a marker string and return a dictionary containing a marker expression.

    The dictionary will contain keys "op", "lhs" and "rhs" for non-terminals in
    the expression grammar, or strings. A string contained in quotes is to be
    interpreted as a literal string, and a string not contained in quotes is a
    variable (such as os_name).
    """
    def marker_var(remaining):
        # either identifier, or literal string
        m = IDENTIFIER.match(remaining)
        if m:
            result = m.groups()[0]
            remaining = remaining[m.end():]
        elif not remaining:
            raise SyntaxError('unexpected end of input')
        else:
            q = remaining[0]
            if q not in '\'"':
                raise SyntaxError('invalid expression: %s' % remaining)
            oq = '\'"'.replace(q, '')
            remaining = remaining[1:]
            parts = [q]
            while remaining:
                # either a string chunk, or oq, or q to terminate
                if remaining[0] == q:
                    break
                elif remaining[0] == oq:
                    parts.append(oq)
                    remaining = remaining[1:]
                else:
                    m = STRING_CHUNK.match(remaining)
                    if not m:
                        raise SyntaxError('error in string literal: %s' % remaining)
                    parts.append(m.groups()[0])
                    remaining = remaining[m.end():]
            else:
                s = ''.join(parts)
                raise SyntaxError('unterminated string: %s' % s)
            parts.append(q)
            result = ''.join(parts)
            remaining = remaining[1:].lstrip() # skip past closing quote
        return result, remaining

    def marker_expr(remaining):
        if remaining and remaining[0] == '(':
            result, remaining = marker(remaining[1:].lstrip())
            if remaining[0] != ')':
                raise SyntaxError('unterminated parenthesis: %s' % remaining)
            remaining = remaining[1:].lstrip()
        else:
            lhs, remaining = marker_var(remaining)
            while remaining:
                m = MARKER_OP.match(remaining)
                if not m:
                    break
                op = m.groups()[0]
                remaining = remaining[m.end():]
                rhs, remaining = marker_var(remaining)
                lhs = {'op': op, 'lhs': lhs, 'rhs': rhs}
            result = lhs
        return result, remaining

    def marker_and(remaining):
        lhs, remaining = marker_expr(remaining)
        while remaining:
            m = AND.match(remaining)
            if not m:
                break
            remaining = remaining[m.end():]
            rhs, remaining = marker_expr(remaining)
            lhs = {'op': 'and', 'lhs': lhs, 'rhs': rhs}
        return lhs, remaining

    def marker(remaining):
        lhs, remaining = marker_and(remaining)
        while remaining:
            m = OR.match(remaining)
            if not m:
                break
            remaining = remaining[m.end():]
            rhs, remaining = marker_and(remaining)
            lhs = {'op': 'or', 'lhs': lhs, 'rhs': rhs}
        return lhs, remaining

    return marker(marker_string)


def parse_requirement(req):
    """
    Parse a requirement passed in as a string. Return a Container
    whose attributes contain the various parts of the requirement.
    """
    remaining = req.strip()
    if not remaining or remaining.startswith('#'):
        return None
    m = IDENTIFIER.match(remaining)
    if not m:
        raise SyntaxError('name expected: %s' % remaining)
    distname = m.groups()[0]
    remaining = remaining[m.end():]
    extras = mark_expr = versions = uri = None
    if remaining and remaining[0] == '[':
        i = remaining.find(']', 1)
        if i < 0:
            raise SyntaxError('unterminated extra: %s' % remaining)
        s = remaining[1:i]
        remaining = remaining[i + 1:].lstrip()
        extras = []
        while s:
            m = IDENTIFIER.match(s)
            if not m:
                raise SyntaxError('malformed extra: %s' % s)
            extras.append(m.groups()[0])
            s = s[m.end():]
            if not s:
                break
            if s[0] != ',':
                raise SyntaxError('comma expected in extras: %s' % s)
            s = s[1:].lstrip()
        if not extras:
            extras = None
    if remaining:
        if remaining[0] == '@':
            # it's a URI
            remaining = remaining[1:].lstrip()
            m = NON_SPACE.match(remaining)
            if not m:
                raise SyntaxError('invalid URI: %s' % remaining)
            uri = m.groups()[0]
            t = urlparse(uri)
            # there are issues with Python and URL parsing, so this test
            # is a bit crude. See bpo-20271, bpo-23505. Python doesn't
            # always parse invalid URLs correctly - it should raise
            # exceptions for malformed URLs
            if not (t.scheme and t.netloc):
                raise SyntaxError('Invalid URL: %s' % uri)
            remaining = remaining[m.end():].lstrip()
        else:

            def get_versions(ver_remaining):
                """
                Return a list of operator, version tuples if any are
                specified, else None.
                """
                m = COMPARE_OP.match(ver_remaining)
                versions = None
                if m:
                    versions = []
                    while True:
                        op = m.groups()[0]
                        ver_remaining = ver_remaining[m.end():]
                        m = VERSION_IDENTIFIER.match(ver_remaining)
                        if not m:
                            raise SyntaxError('invalid version: %s' % ver_remaining)
                        v = m.groups()[0]
                        versions.append((op, v))
                        ver_remaining = ver_remaining[m.end():]
                        if not ver_remaining or ver_remaining[0] != ',':
                            break
                        ver_remaining = ver_remaining[1:].lstrip()
                        m = COMPARE_OP.match(ver_remaining)
                        if not m:
                            raise SyntaxError('invalid constraint: %s' % ver_remaining)
                    if not versions:
                        versions = None
                return versions, ver_remaining

            if remaining[0] != '(':
                versions, remaining = get_versions(remaining)
            else:
                i = remaining.find(')', 1)
                if i < 0:
                    raise SyntaxError('unterminated parenthesis: %s' % remaining)
                s = remaining[1:i]
                remaining = remaining[i + 1:].lstrip()
                # As a special diversion from PEP 508, allow a version number
                # a.b.c in parentheses as a synonym for ~= a.b.c (because this
                # is allowed in earlier PEPs)
                if COMPARE_OP.match(s):
                    versions, _ = get_versions(s)
                else:
                    m = VERSION_IDENTIFIER.match(s)
                    if not m:
                        raise SyntaxError('invalid constraint: %s' % s)
                    v = m.groups()[0]
                    s = s[m.end():].lstrip()
                    if s:
                        raise SyntaxError('invalid constraint: %s' % s)
                    versions = [('~=', v)]

    if remaining:
        if remaining[0] != ';':
            raise SyntaxError('invalid requirement: %s' % remaining)
        remaining = remaining[1:].lstrip()

        mark_expr, remaining = parse_marker(remaining)

    if remaining and remaining[0] != '#':
        raise SyntaxError('unexpected trailing data: %s' % remaining)

    if not versions:
        rs = distname
    else:
        rs = '%s %s' % (distname, ', '.join(['%s %s' % con for con in versions]))
    return Container(name=distname, extras=extras, constraints=versions,
                     marker=mark_expr, url=uri, requirement=rs)


def get_resources_dests(resources_root, rules):
    """Find destinations for resources files"""

    def get_rel_path(root, path):
        # normalizes and returns a lstripped-/-separated path
        root = root.replace(os.path.sep, '/')
        path = path.replace(os.path.sep, '/')
        assert path.startswith(root)
        return path[len(root):].lstrip('/')

    destinations = {}
    for base, suffix, dest in rules:
        prefix = os.path.join(resources_root, base)
        for abs_base in iglob(prefix):
            abs_glob = os.path.join(abs_base, suffix)
            for abs_path in iglob(abs_glob):
                resource_file = get_rel_path(resources_root, abs_path)
                if dest is None:  # remove the entry if it was here
                    destinations.pop(resource_file, None)
                else:
                    rel_path = get_rel_path(abs_base, abs_path)
                    rel_dest = dest.replace(os.path.sep, '/').rstrip('/')
                    destinations[resource_file] = rel_dest + '/' + rel_path
    return destinations


def in_venv():
    if hasattr(sys, 'real_prefix'):
        # virtualenv venvs
        result = True
    else:
        # PEP 405 venvs
        result = sys.prefix != getattr(sys, 'base_prefix', sys.prefix)
    return result


def get_executable():
# The __PYVENV_LAUNCHER__ dance is apparently no longer needed, as
# changes to the stub launcher mean that sys.executable always points
# to the stub on OS X
#    if sys.platform == 'darwin' and ('__PYVENV_LAUNCHER__'
#                                     in os.environ):
#        result =  os.environ['__PYVENV_LAUNCHER__']
#    else:
#        result = sys.executable
#    return result
    result = os.path.normcase(sys.executable)
    if not isinstance(result, text_type):
        result = fsdecode(result)
    return result


def proceed(prompt, allowed_chars, error_prompt=None, default=None):
    p = prompt
    while True:
        s = raw_input(p)
        p = prompt
        if not s and default:
            s = default
        if s:
            c = s[0].lower()
            if c in allowed_chars:
                break
            if error_prompt:
                p = '%c: %s\n%s' % (c, error_prompt, prompt)
    return c


def extract_by_key(d, keys):
    if isinstance(keys, string_types):
        keys = keys.split()
    result = {}
    for key in keys:
        if key in d:
            result[key] = d[key]
    return result

def read_exports(stream):
    if sys.version_info[0] >= 3:
        # needs to be a text stream
        stream = codecs.getreader('utf-8')(stream)
    # Try to load as JSON, falling back on legacy format
    data = stream.read()
    stream = StringIO(data)
    try:
        jdata = json.load(stream)
        result = jdata['extensions']['python.exports']['exports']
        for group, entries in result.items():
            for k, v in entries.items():
                s = '%s = %s' % (k, v)
                entry = get_export_entry(s)
                assert entry is not None
                entries[k] = entry
        return result
    except Exception:
        stream.seek(0, 0)

    def read_stream(cp, stream):
        if hasattr(cp, 'read_file'):
            cp.read_file(stream)
        else:
            cp.readfp(stream)

    cp = configparser.ConfigParser()
    try:
        read_stream(cp, stream)
    except configparser.MissingSectionHeaderError:
        stream.close()
        data = textwrap.dedent(data)
        stream = StringIO(data)
        read_stream(cp, stream)

    result = {}
    for key in cp.sections():
        result[key] = entries = {}
        for name, value in cp.items(key):
            s = '%s = %s' % (name, value)
            entry = get_export_entry(s)
            assert entry is not None
            #entry.dist = self
            entries[name] = entry
    return result


def write_exports(exports, stream):
    if sys.version_info[0] >= 3:
        # needs to be a text stream
        stream = codecs.getwriter('utf-8')(stream)
    cp = configparser.ConfigParser()
    for k, v in exports.items():
        # TODO check k, v for valid values
        cp.add_section(k)
        for entry in v.values():
            if entry.suffix is None:
                s = entry.prefix
            else:
                s = '%s:%s' % (entry.prefix, entry.suffix)
            if entry.flags:
                s = '%s [%s]' % (s, ', '.join(entry.flags))
            cp.set(k, entry.name, s)
    cp.write(stream)


@contextlib.contextmanager
def tempdir():
    td = tempfile.mkdtemp()
    try:
        yield td
    finally:
        shutil.rmtree(td)

@contextlib.contextmanager
def chdir(d):
    cwd = os.getcwd()
    try:
        os.chdir(d)
        yield
    finally:
        os.chdir(cwd)


@contextlib.contextmanager
def socket_timeout(seconds=15):
    cto = socket.getdefaulttimeout()
    try:
        socket.setdefaulttimeout(seconds)
        yield
    finally:
        socket.setdefaulttimeout(cto)


class cached_property(object):
    def __init__(self, func):
        self.func = func
        #for attr in ('__name__', '__module__', '__doc__'):
        #    setattr(self, attr, getattr(func, attr, None))

    def __get__(self, obj, cls=None):
        if obj is None:
            return self
        value = self.func(obj)
        object.__setattr__(obj, self.func.__name__, value)
        #obj.__dict__[self.func.__name__] = value = self.func(obj)
        return value

def convert_path(pathname):
    """Return 'pathname' as a name that will work on the native filesystem.

    The path is split on '/' and put back together again using the current
    directory separator.  Needed because filenames in the setup script are
    always supplied in Unix style, and have to be converted to the local
    convention before we can actually use them in the filesystem.  Raises
    ValueError on non-Unix-ish systems if 'pathname' either starts or
    ends with a slash.
    """
    if os.sep == '/':
        return pathname
    if not pathname:
        return pathname
    if pathname[0] == '/':
        raise ValueError("path '%s' cannot be absolute" % pathname)
    if pathname[-1] == '/':
        raise ValueError("path '%s' cannot end with '/'" % pathname)

    paths = pathname.split('/')
    while os.curdir in paths:
        paths.remove(os.curdir)
    if not paths:
        return os.curdir
    return os.path.join(*paths)


class FileOperator(object):
    def __init__(self, dry_run=False):
        self.dry_run = dry_run
        self.ensured = set()
        self._init_record()

    def _init_record(self):
        self.record = False
        self.files_written = set()
        self.dirs_created = set()

    def record_as_written(self, path):
        if self.record:
            self.files_written.add(path)

    def newer(self, source, target):
        """Tell if the target is newer than the source.

        Returns true if 'source' exists and is more recently modified than
        'target', or if 'source' exists and 'target' doesn't.

        Returns false if both exist and 'target' is the same age or younger
        than 'source'. Raise PackagingFileError if 'source' does not exist.

        Note that this test is not very accurate: files created in the same
        second will have the same "age".
        """
        if not os.path.exists(source):
            raise DistlibException("file '%r' does not exist" %
                                   os.path.abspath(source))
        if not os.path.exists(target):
            return True

        return os.stat(source).st_mtime > os.stat(target).st_mtime

    def copy_file(self, infile, outfile, check=True):
        """Copy a file respecting dry-run and force flags.
        """
        self.ensure_dir(os.path.dirname(outfile))
        logger.info('Copying %s to %s', infile, outfile)
        if not self.dry_run:
            msg = None
            if check:
                if os.path.islink(outfile):
                    msg = '%s is a symlink' % outfile
                elif os.path.exists(outfile) and not os.path.isfile(outfile):
                    msg = '%s is a non-regular file' % outfile
            if msg:
                raise ValueError(msg + ' which would be overwritten')
            shutil.copyfile(infile, outfile)
        self.record_as_written(outfile)

    def copy_stream(self, instream, outfile, encoding=None):
        assert not os.path.isdir(outfile)
        self.ensure_dir(os.path.dirname(outfile))
        logger.info('Copying stream %s to %s', instream, outfile)
        if not self.dry_run:
            if encoding is None:
                outstream = open(outfile, 'wb')
            else:
                outstream = codecs.open(outfile, 'w', encoding=encoding)
            try:
                shutil.copyfileobj(instream, outstream)
            finally:
                outstream.close()
        self.record_as_written(outfile)

    def write_binary_file(self, path, data):
        self.ensure_dir(os.path.dirname(path))
        if not self.dry_run:
            if os.path.exists(path):
                os.remove(path)
            with open(path, 'wb') as f:
                f.write(data)
        self.record_as_written(path)

    def write_text_file(self, path, data, encoding):
        self.write_binary_file(path, data.encode(encoding))

    def set_mode(self, bits, mask, files):
        if os.name == 'posix' or (os.name == 'java' and os._name == 'posix'):
            # Set the executable bits (owner, group, and world) on
            # all the files specified.
            for f in files:
                if self.dry_run:
                    logger.info("changing mode of %s", f)
                else:
                    mode = (os.stat(f).st_mode | bits) & mask
                    logger.info("changing mode of %s to %o", f, mode)
                    os.chmod(f, mode)

    set_executable_mode = lambda s, f: s.set_mode(0o555, 0o7777, f)

    def ensure_dir(self, path):
        path = os.path.abspath(path)
        if path not in self.ensured and not os.path.exists(path):
            self.ensured.add(path)
            d, f = os.path.split(path)
            self.ensure_dir(d)
            logger.info('Creating %s' % path)
            if not self.dry_run:
                os.mkdir(path)
            if self.record:
                self.dirs_created.add(path)

    def byte_compile(self, path, optimize=False, force=False, prefix=None, hashed_invalidation=False):
        dpath = cache_from_source(path, not optimize)
        logger.info('Byte-compiling %s to %s', path, dpath)
        if not self.dry_run:
            if force or self.newer(path, dpath):
                if not prefix:
                    diagpath = None
                else:
                    assert path.startswith(prefix)
                    diagpath = path[len(prefix):]
            compile_kwargs = {}
            if hashed_invalidation and hasattr(py_compile, 'PycInvalidationMode'):
                compile_kwargs['invalidation_mode'] = py_compile.PycInvalidationMode.CHECKED_HASH
            py_compile.compile(path, dpath, diagpath, True, **compile_kwargs)     # raise error
        self.record_as_written(dpath)
        return dpath

    def ensure_removed(self, path):
        if os.path.exists(path):
            if os.path.isdir(path) and not os.path.islink(path):
                logger.debug('Removing directory tree at %s', path)
                if not self.dry_run:
                    shutil.rmtree(path)
                if self.record:
                    if path in self.dirs_created:
                        self.dirs_created.remove(path)
            else:
                if os.path.islink(path):
                    s = 'link'
                else:
                    s = 'file'
                logger.debug('Removing %s %s', s, path)
                if not self.dry_run:
                    os.remove(path)
                if self.record:
                    if path in self.files_written:
                        self.files_written.remove(path)

    def is_writable(self, path):
        result = False
        while not result:
            if os.path.exists(path):
                result = os.access(path, os.W_OK)
                break
            parent = os.path.dirname(path)
            if parent == path:
                break
            path = parent
        return result

    def commit(self):
        """
        Commit recorded changes, turn off recording, return
        changes.
        """
        assert self.record
        result = self.files_written, self.dirs_created
        self._init_record()
        return result

    def rollback(self):
        if not self.dry_run:
            for f in list(self.files_written):
                if os.path.exists(f):
                    os.remove(f)
            # dirs should all be empty now, except perhaps for
            # __pycache__ subdirs
            # reverse so that subdirs appear before their parents
            dirs = sorted(self.dirs_created, reverse=True)
            for d in dirs:
                flist = os.listdir(d)
                if flist:
                    assert flist == ['__pycache__']
                    sd = os.path.join(d, flist[0])
                    os.rmdir(sd)
                os.rmdir(d)     # should fail if non-empty
        self._init_record()

def resolve(module_name, dotted_path):
    if module_name in sys.modules:
        mod = sys.modules[module_name]
    else:
        mod = __import__(module_name)
    if dotted_path is None:
        result = mod
    else:
        parts = dotted_path.split('.')
        result = getattr(mod, parts.pop(0))
        for p in parts:
            result = getattr(result, p)
    return result


class ExportEntry(object):
    def __init__(self, name, prefix, suffix, flags):
        self.name = name
        self.prefix = prefix
        self.suffix = suffix
        self.flags = flags

    @cached_property
    def value(self):
        return resolve(self.prefix, self.suffix)

    def __repr__(self):  # pragma: no cover
        return '' % (self.name, self.prefix,
                                                self.suffix, self.flags)

    def __eq__(self, other):
        if not isinstance(other, ExportEntry):
            result = False
        else:
            result = (self.name == other.name and
                      self.prefix == other.prefix and
                      self.suffix == other.suffix and
                      self.flags == other.flags)
        return result

    __hash__ = object.__hash__


ENTRY_RE = re.compile(r'''(?P(\w|[-.+])+)
                      \s*=\s*(?P(\w+)([:\.]\w+)*)
                      \s*(\[\s*(?P\w+(=\w+)?(,\s*\w+(=\w+)?)*)\s*\])?
                      ''', re.VERBOSE)

def get_export_entry(specification):
    m = ENTRY_RE.search(specification)
    if not m:
        result = None
        if '[' in specification or ']' in specification:
            raise DistlibException("Invalid specification "
                                   "'%s'" % specification)
    else:
        d = m.groupdict()
        name = d['name']
        path = d['callable']
        colons = path.count(':')
        if colons == 0:
            prefix, suffix = path, None
        else:
            if colons != 1:
                raise DistlibException("Invalid specification "
                                       "'%s'" % specification)
            prefix, suffix = path.split(':')
        flags = d['flags']
        if flags is None:
            if '[' in specification or ']' in specification:
                raise DistlibException("Invalid specification "
                                       "'%s'" % specification)
            flags = []
        else:
            flags = [f.strip() for f in flags.split(',')]
        result = ExportEntry(name, prefix, suffix, flags)
    return result


def get_cache_base(suffix=None):
    """
    Return the default base location for distlib caches. If the directory does
    not exist, it is created. Use the suffix provided for the base directory,
    and default to '.distlib' if it isn't provided.

    On Windows, if LOCALAPPDATA is defined in the environment, then it is
    assumed to be a directory, and will be the parent directory of the result.
    On POSIX, and on Windows if LOCALAPPDATA is not defined, the user's home
    directory - using os.expanduser('~') - will be the parent directory of
    the result.

    The result is just the directory '.distlib' in the parent directory as
    determined above, or with the name specified with ``suffix``.
    """
    if suffix is None:
        suffix = '.distlib'
    if os.name == 'nt' and 'LOCALAPPDATA' in os.environ:
        result = os.path.expandvars('$localappdata')
    else:
        # Assume posix, or old Windows
        result = os.path.expanduser('~')
    # we use 'isdir' instead of 'exists', because we want to
    # fail if there's a file with that name
    if os.path.isdir(result):
        usable = os.access(result, os.W_OK)
        if not usable:
            logger.warning('Directory exists but is not writable: %s', result)
    else:
        try:
            os.makedirs(result)
            usable = True
        except OSError:
            logger.warning('Unable to create %s', result, exc_info=True)
            usable = False
    if not usable:
        result = tempfile.mkdtemp()
        logger.warning('Default location unusable, using %s', result)
    return os.path.join(result, suffix)


def path_to_cache_dir(path):
    """
    Convert an absolute path to a directory name for use in a cache.

    The algorithm used is:

    #. On Windows, any ``':'`` in the drive is replaced with ``'---'``.
    #. Any occurrence of ``os.sep`` is replaced with ``'--'``.
    #. ``'.cache'`` is appended.
    """
    d, p = os.path.splitdrive(os.path.abspath(path))
    if d:
        d = d.replace(':', '---')
    p = p.replace(os.sep, '--')
    return d + p + '.cache'


def ensure_slash(s):
    if not s.endswith('/'):
        return s + '/'
    return s


def parse_credentials(netloc):
    username = password = None
    if '@' in netloc:
        prefix, netloc = netloc.rsplit('@', 1)
        if ':' not in prefix:
            username = prefix
        else:
            username, password = prefix.split(':', 1)
    if username:
        username = unquote(username)
    if password:
        password = unquote(password)
    return username, password, netloc


def get_process_umask():
    result = os.umask(0o22)
    os.umask(result)
    return result

def is_string_sequence(seq):
    result = True
    i = None
    for i, s in enumerate(seq):
        if not isinstance(s, string_types):
            result = False
            break
    assert i is not None
    return result

PROJECT_NAME_AND_VERSION = re.compile('([a-z0-9_]+([.-][a-z_][a-z0-9_]*)*)-'
                                      '([a-z0-9_.+-]+)', re.I)
PYTHON_VERSION = re.compile(r'-py(\d\.?\d?)')


def split_filename(filename, project_name=None):
    """
    Extract name, version, python version from a filename (no extension)

    Return name, version, pyver or None
    """
    result = None
    pyver = None
    filename = unquote(filename).replace(' ', '-')
    m = PYTHON_VERSION.search(filename)
    if m:
        pyver = m.group(1)
        filename = filename[:m.start()]
    if project_name and len(filename) > len(project_name) + 1:
        m = re.match(re.escape(project_name) + r'\b', filename)
        if m:
            n = m.end()
            result = filename[:n], filename[n + 1:], pyver
    if result is None:
        m = PROJECT_NAME_AND_VERSION.match(filename)
        if m:
            result = m.group(1), m.group(3), pyver
    return result

# Allow spaces in name because of legacy dists like "Twisted Core"
NAME_VERSION_RE = re.compile(r'(?P[\w .-]+)\s*'
                             r'\(\s*(?P[^\s)]+)\)$')

def parse_name_and_version(p):
    """
    A utility method used to get name and version from a string.

    From e.g. a Provides-Dist value.

    :param p: A value in a form 'foo (1.0)'
    :return: The name and version as a tuple.
    """
    m = NAME_VERSION_RE.match(p)
    if not m:
        raise DistlibException('Ill-formed name/version string: \'%s\'' % p)
    d = m.groupdict()
    return d['name'].strip().lower(), d['ver']

def get_extras(requested, available):
    result = set()
    requested = set(requested or [])
    available = set(available or [])
    if '*' in requested:
        requested.remove('*')
        result |= available
    for r in requested:
        if r == '-':
            result.add(r)
        elif r.startswith('-'):
            unwanted = r[1:]
            if unwanted not in available:
                logger.warning('undeclared extra: %s' % unwanted)
            if unwanted in result:
                result.remove(unwanted)
        else:
            if r not in available:
                logger.warning('undeclared extra: %s' % r)
            result.add(r)
    return result
#
# Extended metadata functionality
#

def _get_external_data(url):
    result = {}
    try:
        # urlopen might fail if it runs into redirections,
        # because of Python issue #13696. Fixed in locators
        # using a custom redirect handler.
        resp = urlopen(url)
        headers = resp.info()
        ct = headers.get('Content-Type')
        if not ct.startswith('application/json'):
            logger.debug('Unexpected response for JSON request: %s', ct)
        else:
            reader = codecs.getreader('utf-8')(resp)
            #data = reader.read().decode('utf-8')
            #result = json.loads(data)
            result = json.load(reader)
    except Exception as e:
        logger.exception('Failed to get external data for %s: %s', url, e)
    return result

_external_data_base_url = 'https://www.red-dove.com/pypi/projects/'

def get_project_data(name):
    url = '%s/%s/project.json' % (name[0].upper(), name)
    url = urljoin(_external_data_base_url, url)
    result = _get_external_data(url)
    return result

def get_package_data(name, version):
    url = '%s/%s/package-%s.json' % (name[0].upper(), name, version)
    url = urljoin(_external_data_base_url, url)
    return _get_external_data(url)


class Cache(object):
    """
    A class implementing a cache for resources that need to live in the file system
    e.g. shared libraries. This class was moved from resources to here because it
    could be used by other modules, e.g. the wheel module.
    """

    def __init__(self, base):
        """
        Initialise an instance.

        :param base: The base directory where the cache should be located.
        """
        # we use 'isdir' instead of 'exists', because we want to
        # fail if there's a file with that name
        if not os.path.isdir(base):  # pragma: no cover
            os.makedirs(base)
        if (os.stat(base).st_mode & 0o77) != 0:
            logger.warning('Directory \'%s\' is not private', base)
        self.base = os.path.abspath(os.path.normpath(base))

    def prefix_to_dir(self, prefix):
        """
        Converts a resource prefix to a directory name in the cache.
        """
        return path_to_cache_dir(prefix)

    def clear(self):
        """
        Clear the cache.
        """
        not_removed = []
        for fn in os.listdir(self.base):
            fn = os.path.join(self.base, fn)
            try:
                if os.path.islink(fn) or os.path.isfile(fn):
                    os.remove(fn)
                elif os.path.isdir(fn):
                    shutil.rmtree(fn)
            except Exception:
                not_removed.append(fn)
        return not_removed


class EventMixin(object):
    """
    A very simple publish/subscribe system.
    """
    def __init__(self):
        self._subscribers = {}

    def add(self, event, subscriber, append=True):
        """
        Add a subscriber for an event.

        :param event: The name of an event.
        :param subscriber: The subscriber to be added (and called when the
                           event is published).
        :param append: Whether to append or prepend the subscriber to an
                       existing subscriber list for the event.
        """
        subs = self._subscribers
        if event not in subs:
            subs[event] = deque([subscriber])
        else:
            sq = subs[event]
            if append:
                sq.append(subscriber)
            else:
                sq.appendleft(subscriber)

    def remove(self, event, subscriber):
        """
        Remove a subscriber for an event.

        :param event: The name of an event.
        :param subscriber: The subscriber to be removed.
        """
        subs = self._subscribers
        if event not in subs:
            raise ValueError('No subscribers: %r' % event)
        subs[event].remove(subscriber)

    def get_subscribers(self, event):
        """
        Return an iterator for the subscribers for an event.
        :param event: The event to return subscribers for.
        """
        return iter(self._subscribers.get(event, ()))

    def publish(self, event, *args, **kwargs):
        """
        Publish a event and return a list of values returned by its
        subscribers.

        :param event: The event to publish.
        :param args: The positional arguments to pass to the event's
                     subscribers.
        :param kwargs: The keyword arguments to pass to the event's
                       subscribers.
        """
        result = []
        for subscriber in self.get_subscribers(event):
            try:
                value = subscriber(event, *args, **kwargs)
            except Exception:
                logger.exception('Exception during event publication')
                value = None
            result.append(value)
        logger.debug('publish %s: args = %s, kwargs = %s, result = %s',
                     event, args, kwargs, result)
        return result

#
# Simple sequencing
#
class Sequencer(object):
    def __init__(self):
        self._preds = {}
        self._succs = {}
        self._nodes = set()     # nodes with no preds/succs

    def add_node(self, node):
        self._nodes.add(node)

    def remove_node(self, node, edges=False):
        if node in self._nodes:
            self._nodes.remove(node)
        if edges:
            for p in set(self._preds.get(node, ())):
                self.remove(p, node)
            for s in set(self._succs.get(node, ())):
                self.remove(node, s)
            # Remove empties
            for k, v in list(self._preds.items()):
                if not v:
                    del self._preds[k]
            for k, v in list(self._succs.items()):
                if not v:
                    del self._succs[k]

    def add(self, pred, succ):
        assert pred != succ
        self._preds.setdefault(succ, set()).add(pred)
        self._succs.setdefault(pred, set()).add(succ)

    def remove(self, pred, succ):
        assert pred != succ
        try:
            preds = self._preds[succ]
            succs = self._succs[pred]
        except KeyError:  # pragma: no cover
            raise ValueError('%r not a successor of anything' % succ)
        try:
            preds.remove(pred)
            succs.remove(succ)
        except KeyError:  # pragma: no cover
            raise ValueError('%r not a successor of %r' % (succ, pred))

    def is_step(self, step):
        return (step in self._preds or step in self._succs or
                step in self._nodes)

    def get_steps(self, final):
        if not self.is_step(final):
            raise ValueError('Unknown: %r' % final)
        result = []
        todo = []
        seen = set()
        todo.append(final)
        while todo:
            step = todo.pop(0)
            if step in seen:
                # if a step was already seen,
                # move it to the end (so it will appear earlier
                # when reversed on return) ... but not for the
                # final step, as that would be confusing for
                # users
                if step != final:
                    result.remove(step)
                    result.append(step)
            else:
                seen.add(step)
                result.append(step)
                preds = self._preds.get(step, ())
                todo.extend(preds)
        return reversed(result)

    @property
    def strong_connections(self):
        #http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
        index_counter = [0]
        stack = []
        lowlinks = {}
        index = {}
        result = []

        graph = self._succs

        def strongconnect(node):
            # set the depth index for this node to the smallest unused index
            index[node] = index_counter[0]
            lowlinks[node] = index_counter[0]
            index_counter[0] += 1
            stack.append(node)

            # Consider successors
            try:
                successors = graph[node]
            except Exception:
                successors = []
            for successor in successors:
                if successor not in lowlinks:
                    # Successor has not yet been visited
                    strongconnect(successor)
                    lowlinks[node] = min(lowlinks[node],lowlinks[successor])
                elif successor in stack:
                    # the successor is in the stack and hence in the current
                    # strongly connected component (SCC)
                    lowlinks[node] = min(lowlinks[node],index[successor])

            # If `node` is a root node, pop the stack and generate an SCC
            if lowlinks[node] == index[node]:
                connected_component = []

                while True:
                    successor = stack.pop()
                    connected_component.append(successor)
                    if successor == node: break
                component = tuple(connected_component)
                # storing the result
                result.append(component)

        for node in graph:
            if node not in lowlinks:
                strongconnect(node)

        return result

    @property
    def dot(self):
        result = ['digraph G {']
        for succ in self._preds:
            preds = self._preds[succ]
            for pred in preds:
                result.append('  %s -> %s;' % (pred, succ))
        for node in self._nodes:
            result.append('  %s;' % node)
        result.append('}')
        return '\n'.join(result)

#
# Unarchiving functionality for zip, tar, tgz, tbz, whl
#

ARCHIVE_EXTENSIONS = ('.tar.gz', '.tar.bz2', '.tar', '.zip',
                      '.tgz', '.tbz', '.whl')

def unarchive(archive_filename, dest_dir, format=None, check=True):

    def check_path(path):
        if not isinstance(path, text_type):
            path = path.decode('utf-8')
        p = os.path.abspath(os.path.join(dest_dir, path))
        if not p.startswith(dest_dir) or p[plen] != os.sep:
            raise ValueError('path outside destination: %r' % p)

    dest_dir = os.path.abspath(dest_dir)
    plen = len(dest_dir)
    archive = None
    if format is None:
        if archive_filename.endswith(('.zip', '.whl')):
            format = 'zip'
        elif archive_filename.endswith(('.tar.gz', '.tgz')):
            format = 'tgz'
            mode = 'r:gz'
        elif archive_filename.endswith(('.tar.bz2', '.tbz')):
            format = 'tbz'
            mode = 'r:bz2'
        elif archive_filename.endswith('.tar'):
            format = 'tar'
            mode = 'r'
        else:  # pragma: no cover
            raise ValueError('Unknown format for %r' % archive_filename)
    try:
        if format == 'zip':
            archive = ZipFile(archive_filename, 'r')
            if check:
                names = archive.namelist()
                for name in names:
                    check_path(name)
        else:
            archive = tarfile.open(archive_filename, mode)
            if check:
                names = archive.getnames()
                for name in names:
                    check_path(name)
        if format != 'zip' and sys.version_info[0] < 3:
            # See Python issue 17153. If the dest path contains Unicode,
            # tarfile extraction fails on Python 2.x if a member path name
            # contains non-ASCII characters - it leads to an implicit
            # bytes -> unicode conversion using ASCII to decode.
            for tarinfo in archive.getmembers():
                if not isinstance(tarinfo.name, text_type):
                    tarinfo.name = tarinfo.name.decode('utf-8')

        # Limit extraction of dangerous items, if this Python
        # allows it easily. If not, just trust the input.
        # See: https://docs.python.org/3/library/tarfile.html#extraction-filters
        def extraction_filter(member, path):
            """Run tarfile.tar_fillter, but raise the expected ValueError"""
            # This is only called if the current Python has tarfile filters
            try:
                return tarfile.tar_filter(member, path)
            except tarfile.FilterError as exc:
                raise ValueError(str(exc))
        archive.extraction_filter = extraction_filter

        archive.extractall(dest_dir)

    finally:
        if archive:
            archive.close()


def zip_dir(directory):
    """zip a directory tree into a BytesIO object"""
    result = io.BytesIO()
    dlen = len(directory)
    with ZipFile(result, "w") as zf:
        for root, dirs, files in os.walk(directory):
            for name in files:
                full = os.path.join(root, name)
                rel = root[dlen:]
                dest = os.path.join(rel, name)
                zf.write(full, dest)
    return result

#
# Simple progress bar
#

UNITS = ('', 'K', 'M', 'G','T','P')


class Progress(object):
    unknown = 'UNKNOWN'

    def __init__(self, minval=0, maxval=100):
        assert maxval is None or maxval >= minval
        self.min = self.cur = minval
        self.max = maxval
        self.started = None
        self.elapsed = 0
        self.done = False

    def update(self, curval):
        assert self.min <= curval
        assert self.max is None or curval <= self.max
        self.cur = curval
        now = time.time()
        if self.started is None:
            self.started = now
        else:
            self.elapsed = now - self.started

    def increment(self, incr):
        assert incr >= 0
        self.update(self.cur + incr)

    def start(self):
        self.update(self.min)
        return self

    def stop(self):
        if self.max is not None:
            self.update(self.max)
        self.done = True

    @property
    def maximum(self):
        return self.unknown if self.max is None else self.max

    @property
    def percentage(self):
        if self.done:
            result = '100 %'
        elif self.max is None:
            result = ' ?? %'
        else:
            v = 100.0 * (self.cur - self.min) / (self.max - self.min)
            result = '%3d %%' % v
        return result

    def format_duration(self, duration):
        if (duration <= 0) and self.max is None or self.cur == self.min:
            result = '??:??:??'
        #elif duration < 1:
        #    result = '--:--:--'
        else:
            result = time.strftime('%H:%M:%S', time.gmtime(duration))
        return result

    @property
    def ETA(self):
        if self.done:
            prefix = 'Done'
            t = self.elapsed
            #import pdb; pdb.set_trace()
        else:
            prefix = 'ETA '
            if self.max is None:
                t = -1
            elif self.elapsed == 0 or (self.cur == self.min):
                t = 0
            else:
                #import pdb; pdb.set_trace()
                t = float(self.max - self.min)
                t /= self.cur - self.min
                t = (t - 1) * self.elapsed
        return '%s: %s' % (prefix, self.format_duration(t))

    @property
    def speed(self):
        if self.elapsed == 0:
            result = 0.0
        else:
            result = (self.cur - self.min) / self.elapsed
        for unit in UNITS:
            if result < 1000:
                break
            result /= 1000.0
        return '%d %sB/s' % (result, unit)

#
# Glob functionality
#

RICH_GLOB = re.compile(r'\{([^}]*)\}')
_CHECK_RECURSIVE_GLOB = re.compile(r'[^/\\,{]\*\*|\*\*[^/\\,}]')
_CHECK_MISMATCH_SET = re.compile(r'^[^{]*\}|\{[^}]*$')


def iglob(path_glob):
    """Extended globbing function that supports ** and {opt1,opt2,opt3}."""
    if _CHECK_RECURSIVE_GLOB.search(path_glob):
        msg = """invalid glob %r: recursive glob "**" must be used alone"""
        raise ValueError(msg % path_glob)
    if _CHECK_MISMATCH_SET.search(path_glob):
        msg = """invalid glob %r: mismatching set marker '{' or '}'"""
        raise ValueError(msg % path_glob)
    return _iglob(path_glob)


def _iglob(path_glob):
    rich_path_glob = RICH_GLOB.split(path_glob, 1)
    if len(rich_path_glob) > 1:
        assert len(rich_path_glob) == 3, rich_path_glob
        prefix, set, suffix = rich_path_glob
        for item in set.split(','):
            for path in _iglob(''.join((prefix, item, suffix))):
                yield path
    else:
        if '**' not in path_glob:
            for item in std_iglob(path_glob):
                yield item
        else:
            prefix, radical = path_glob.split('**', 1)
            if prefix == '':
                prefix = '.'
            if radical == '':
                radical = '*'
            else:
                # we support both
                radical = radical.lstrip('/')
                radical = radical.lstrip('\\')
            for path, dir, files in os.walk(prefix):
                path = os.path.normpath(path)
                for fn in _iglob(os.path.join(path, radical)):
                    yield fn

if ssl:
    from .compat import (HTTPSHandler as BaseHTTPSHandler, match_hostname,
                         CertificateError)


#
# HTTPSConnection which verifies certificates/matches domains
#

    class HTTPSConnection(httplib.HTTPSConnection):
        ca_certs = None # set this to the path to the certs file (.pem)
        check_domain = True # only used if ca_certs is not None

        # noinspection PyPropertyAccess
        def connect(self):
            sock = socket.create_connection((self.host, self.port), self.timeout)
            if getattr(self, '_tunnel_host', False):
                self.sock = sock
                self._tunnel()

            if not hasattr(ssl, 'SSLContext'):
                # For 2.x
                if self.ca_certs:
                    cert_reqs = ssl.CERT_REQUIRED
                else:
                    cert_reqs = ssl.CERT_NONE
                self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
                                            cert_reqs=cert_reqs,
                                            ssl_version=ssl.PROTOCOL_SSLv23,
                                            ca_certs=self.ca_certs)
            else:  # pragma: no cover
                context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
                context.options |= ssl.OP_NO_SSLv2
                if self.cert_file:
                    context.load_cert_chain(self.cert_file, self.key_file)
                kwargs = {}
                if self.ca_certs:
                    context.verify_mode = ssl.CERT_REQUIRED
                    context.load_verify_locations(cafile=self.ca_certs)
                    if getattr(ssl, 'HAS_SNI', False):
                        kwargs['server_hostname'] = self.host
                self.sock = context.wrap_socket(sock, **kwargs)
            if self.ca_certs and self.check_domain:
                try:
                    match_hostname(self.sock.getpeercert(), self.host)
                    logger.debug('Host verified: %s', self.host)
                except CertificateError:  # pragma: no cover
                    self.sock.shutdown(socket.SHUT_RDWR)
                    self.sock.close()
                    raise

    class HTTPSHandler(BaseHTTPSHandler):
        def __init__(self, ca_certs, check_domain=True):
            BaseHTTPSHandler.__init__(self)
            self.ca_certs = ca_certs
            self.check_domain = check_domain

        def _conn_maker(self, *args, **kwargs):
            """
            This is called to create a connection instance. Normally you'd
            pass a connection class to do_open, but it doesn't actually check for
            a class, and just expects a callable. As long as we behave just as a
            constructor would have, we should be OK. If it ever changes so that
            we *must* pass a class, we'll create an UnsafeHTTPSConnection class
            which just sets check_domain to False in the class definition, and
            choose which one to pass to do_open.
            """
            result = HTTPSConnection(*args, **kwargs)
            if self.ca_certs:
                result.ca_certs = self.ca_certs
                result.check_domain = self.check_domain
            return result

        def https_open(self, req):
            try:
                return self.do_open(self._conn_maker, req)
            except URLError as e:
                if 'certificate verify failed' in str(e.reason):
                    raise CertificateError('Unable to verify server certificate '
                                           'for %s' % req.host)
                else:
                    raise

    #
    # To prevent against mixing HTTP traffic with HTTPS (examples: A Man-In-The-
    # Middle proxy using HTTP listens on port 443, or an index mistakenly serves
    # HTML containing a http://xyz link when it should be https://xyz),
    # you can use the following handler class, which does not allow HTTP traffic.
    #
    # It works by inheriting from HTTPHandler - so build_opener won't add a
    # handler for HTTP itself.
    #
    class HTTPSOnlyHandler(HTTPSHandler, HTTPHandler):
        def http_open(self, req):
            raise URLError('Unexpected HTTP request on what should be a secure '
                           'connection: %s' % req)

#
# XML-RPC with timeouts
#

_ver_info = sys.version_info[:2]

if _ver_info == (2, 6):
    class HTTP(httplib.HTTP):
        def __init__(self, host='', port=None, **kwargs):
            if port == 0:   # 0 means use port 0, not the default port
                port = None
            self._setup(self._connection_class(host, port, **kwargs))


    if ssl:
        class HTTPS(httplib.HTTPS):
            def __init__(self, host='', port=None, **kwargs):
                if port == 0:   # 0 means use port 0, not the default port
                    port = None
                self._setup(self._connection_class(host, port, **kwargs))


class Transport(xmlrpclib.Transport):
    def __init__(self, timeout, use_datetime=0):
        self.timeout = timeout
        xmlrpclib.Transport.__init__(self, use_datetime)

    def make_connection(self, host):
        h, eh, x509 = self.get_host_info(host)
        if _ver_info == (2, 6):
            result = HTTP(h, timeout=self.timeout)
        else:
            if not self._connection or host != self._connection[0]:
                self._extra_headers = eh
                self._connection = host, httplib.HTTPConnection(h)
            result = self._connection[1]
        return result

if ssl:
    class SafeTransport(xmlrpclib.SafeTransport):
        def __init__(self, timeout, use_datetime=0):
            self.timeout = timeout
            xmlrpclib.SafeTransport.__init__(self, use_datetime)

        def make_connection(self, host):
            h, eh, kwargs = self.get_host_info(host)
            if not kwargs:
                kwargs = {}
            kwargs['timeout'] = self.timeout
            if _ver_info == (2, 6):
                result = HTTPS(host, None, **kwargs)
            else:
                if not self._connection or host != self._connection[0]:
                    self._extra_headers = eh
                    self._connection = host, httplib.HTTPSConnection(h, None,
                                                                     **kwargs)
                result = self._connection[1]
            return result


class ServerProxy(xmlrpclib.ServerProxy):
    def __init__(self, uri, **kwargs):
        self.timeout = timeout = kwargs.pop('timeout', None)
        # The above classes only come into play if a timeout
        # is specified
        if timeout is not None:
            scheme, _ = splittype(uri)
            use_datetime = kwargs.get('use_datetime', 0)
            if scheme == 'https':
                tcls = SafeTransport
            else:
                tcls = Transport
            kwargs['transport'] = t = tcls(timeout, use_datetime=use_datetime)
            self.transport = t
        xmlrpclib.ServerProxy.__init__(self, uri, **kwargs)

#
# CSV functionality. This is provided because on 2.x, the csv module can't
# handle Unicode. However, we need to deal with Unicode in e.g. RECORD files.
#

def _csv_open(fn, mode, **kwargs):
    if sys.version_info[0] < 3:
        mode += 'b'
    else:
        kwargs['newline'] = ''
        # Python 3 determines encoding from locale. Force 'utf-8'
        # file encoding to match other forced utf-8 encoding
        kwargs['encoding'] = 'utf-8'
    return open(fn, mode, **kwargs)


class CSVBase(object):
    defaults = {
        'delimiter': str(','),      # The strs are used because we need native
        'quotechar': str('"'),      # str in the csv API (2.x won't take
        'lineterminator': str('\n') # Unicode)
    }

    def __enter__(self):
        return self

    def __exit__(self, *exc_info):
        self.stream.close()


class CSVReader(CSVBase):
    def __init__(self, **kwargs):
        if 'stream' in kwargs:
            stream = kwargs['stream']
            if sys.version_info[0] >= 3:
                # needs to be a text stream
                stream = codecs.getreader('utf-8')(stream)
            self.stream = stream
        else:
            self.stream = _csv_open(kwargs['path'], 'r')
        self.reader = csv.reader(self.stream, **self.defaults)

    def __iter__(self):
        return self

    def next(self):
        result = next(self.reader)
        if sys.version_info[0] < 3:
            for i, item in enumerate(result):
                if not isinstance(item, text_type):
                    result[i] = item.decode('utf-8')
        return result

    __next__ = next

class CSVWriter(CSVBase):
    def __init__(self, fn, **kwargs):
        self.stream = _csv_open(fn, 'w')
        self.writer = csv.writer(self.stream, **self.defaults)

    def writerow(self, row):
        if sys.version_info[0] < 3:
            r = []
            for item in row:
                if isinstance(item, text_type):
                    item = item.encode('utf-8')
                r.append(item)
            row = r
        self.writer.writerow(row)

#
#   Configurator functionality
#

class Configurator(BaseConfigurator):

    value_converters = dict(BaseConfigurator.value_converters)
    value_converters['inc'] = 'inc_convert'

    def __init__(self, config, base=None):
        super(Configurator, self).__init__(config)
        self.base = base or os.getcwd()

    def configure_custom(self, config):
        def convert(o):
            if isinstance(o, (list, tuple)):
                result = type(o)([convert(i) for i in o])
            elif isinstance(o, dict):
                if '()' in o:
                    result = self.configure_custom(o)
                else:
                    result = {}
                    for k in o:
                        result[k] = convert(o[k])
            else:
                result = self.convert(o)
            return result

        c = config.pop('()')
        if not callable(c):
            c = self.resolve(c)
        props = config.pop('.', None)
        # Check for valid identifiers
        args = config.pop('[]', ())
        if args:
            args = tuple([convert(o) for o in args])
        items = [(k, convert(config[k])) for k in config if valid_ident(k)]
        kwargs = dict(items)
        result = c(*args, **kwargs)
        if props:
            for n, v in props.items():
                setattr(result, n, convert(v))
        return result

    def __getitem__(self, key):
        result = self.config[key]
        if isinstance(result, dict) and '()' in result:
            self.config[key] = result = self.configure_custom(result)
        return result

    def inc_convert(self, value):
        """Default converter for the inc:// protocol."""
        if not os.path.isabs(value):
            value = os.path.join(self.base, value)
        with codecs.open(value, 'r', encoding='utf-8') as f:
            result = json.load(f)
        return result


class SubprocessMixin(object):
    """
    Mixin for running subprocesses and capturing their output
    """
    def __init__(self, verbose=False, progress=None):
        self.verbose = verbose
        self.progress = progress

    def reader(self, stream, context):
        """
        Read lines from a subprocess' output stream and either pass to a progress
        callable (if specified) or write progress information to sys.stderr.
        """
        progress = self.progress
        verbose = self.verbose
        while True:
            s = stream.readline()
            if not s:
                break
            if progress is not None:
                progress(s, context)
            else:
                if not verbose:
                    sys.stderr.write('.')
                else:
                    sys.stderr.write(s.decode('utf-8'))
                sys.stderr.flush()
        stream.close()

    def run_command(self, cmd, **kwargs):
        p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE, **kwargs)
        t1 = threading.Thread(target=self.reader, args=(p.stdout, 'stdout'))
        t1.start()
        t2 = threading.Thread(target=self.reader, args=(p.stderr, 'stderr'))
        t2.start()
        p.wait()
        t1.join()
        t2.join()
        if self.progress is not None:
            self.progress('done.', 'main')
        elif self.verbose:
            sys.stderr.write('done.\n')
        return p


def normalize_name(name):
    """Normalize a python package name a la PEP 503"""
    # https://www.python.org/dev/peps/pep-0503/#normalized-names
    return re.sub('[-_.]+', '-', name).lower()
PKÔ¶N]Ó
_Ê_Ê-site-packages/pip/_vendor/distlib/locators.pynu„[µü¤# -*- coding: utf-8 -*-
#
# Copyright (C) 2012-2015 Vinay Sajip.
# Licensed to the Python Software Foundation under a contributor agreement.
# See LICENSE.txt and CONTRIBUTORS.txt.
#

import gzip
from io import BytesIO
import json
import logging
import os
import posixpath
import re
try:
    import threading
except ImportError:  # pragma: no cover
    import dummy_threading as threading
import zlib

from . import DistlibException
from .compat import (urljoin, urlparse, urlunparse, url2pathname, pathname2url,
                     queue, quote, unescape, string_types, build_opener,
                     HTTPRedirectHandler as BaseRedirectHandler, text_type,
                     Request, HTTPError, URLError)
from .database import Distribution, DistributionPath, make_dist
from .metadata import Metadata, MetadataInvalidError
from .util import (cached_property, parse_credentials, ensure_slash,
                   split_filename, get_project_data, parse_requirement,
                   parse_name_and_version, ServerProxy, normalize_name)
from .version import get_scheme, UnsupportedVersionError
from .wheel import Wheel, is_compatible

logger = logging.getLogger(__name__)

HASHER_HASH = re.compile(r'^(\w+)=([a-f0-9]+)')
CHARSET = re.compile(r';\s*charset\s*=\s*(.*)\s*$', re.I)
HTML_CONTENT_TYPE = re.compile('text/html|application/x(ht)?ml')
DEFAULT_INDEX = 'https://pypi.org/pypi'

def get_all_distribution_names(url=None):
    """
    Return all distribution names known by an index.
    :param url: The URL of the index.
    :return: A list of all known distribution names.
    """
    if url is None:
        url = DEFAULT_INDEX
    client = ServerProxy(url, timeout=3.0)
    try:
        return client.list_packages()
    finally:
        client('close')()

class RedirectHandler(BaseRedirectHandler):
    """
    A class to work around a bug in some Python 3.2.x releases.
    """
    # There's a bug in the base version for some 3.2.x
    # (e.g. 3.2.2 on Ubuntu Oneiric). If a Location header
    # returns e.g. /abc, it bails because it says the scheme ''
    # is bogus, when actually it should use the request's
    # URL for the scheme. See Python issue #13696.
    def http_error_302(self, req, fp, code, msg, headers):
        # Some servers (incorrectly) return multiple Location headers
        # (so probably same goes for URI).  Use first header.
        newurl = None
        for key in ('location', 'uri'):
            if key in headers:
                newurl = headers[key]
                break
        if newurl is None:  # pragma: no cover
            return
        urlparts = urlparse(newurl)
        if urlparts.scheme == '':
            newurl = urljoin(req.get_full_url(), newurl)
            if hasattr(headers, 'replace_header'):
                headers.replace_header(key, newurl)
            else:
                headers[key] = newurl
        return BaseRedirectHandler.http_error_302(self, req, fp, code, msg,
                                                  headers)

    http_error_301 = http_error_303 = http_error_307 = http_error_302

class Locator(object):
    """
    A base class for locators - things that locate distributions.
    """
    source_extensions = ('.tar.gz', '.tar.bz2', '.tar', '.zip', '.tgz', '.tbz')
    binary_extensions = ('.egg', '.exe', '.whl')
    excluded_extensions = ('.pdf',)

    # A list of tags indicating which wheels you want to match. The default
    # value of None matches against the tags compatible with the running
    # Python. If you want to match other values, set wheel_tags on a locator
    # instance to a list of tuples (pyver, abi, arch) which you want to match.
    wheel_tags = None

    downloadable_extensions = source_extensions + ('.whl',)

    def __init__(self, scheme='default'):
        """
        Initialise an instance.
        :param scheme: Because locators look for most recent versions, they
                       need to know the version scheme to use. This specifies
                       the current PEP-recommended scheme - use ``'legacy'``
                       if you need to support existing distributions on PyPI.
        """
        self._cache = {}
        self.scheme = scheme
        # Because of bugs in some of the handlers on some of the platforms,
        # we use our own opener rather than just using urlopen.
        self.opener = build_opener(RedirectHandler())
        # If get_project() is called from locate(), the matcher instance
        # is set from the requirement passed to locate(). See issue #18 for
        # why this can be useful to know.
        self.matcher = None
        self.errors = queue.Queue()

    def get_errors(self):
        """
        Return any errors which have occurred.
        """
        result = []
        while not self.errors.empty():  # pragma: no cover
            try:
                e = self.errors.get(False)
                result.append(e)
            except self.errors.Empty:
                continue
            self.errors.task_done()
        return result

    def clear_errors(self):
        """
        Clear any errors which may have been logged.
        """
        # Just get the errors and throw them away
        self.get_errors()

    def clear_cache(self):
        self._cache.clear()

    def _get_scheme(self):
        return self._scheme

    def _set_scheme(self, value):
        self._scheme = value

    scheme = property(_get_scheme, _set_scheme)

    def _get_project(self, name):
        """
        For a given project, get a dictionary mapping available versions to Distribution
        instances.

        This should be implemented in subclasses.

        If called from a locate() request, self.matcher will be set to a
        matcher for the requirement to satisfy, otherwise it will be None.
        """
        raise NotImplementedError('Please implement in the subclass')

    def get_distribution_names(self):
        """
        Return all the distribution names known to this locator.
        """
        raise NotImplementedError('Please implement in the subclass')

    def get_project(self, name):
        """
        For a given project, get a dictionary mapping available versions to Distribution
        instances.

        This calls _get_project to do all the work, and just implements a caching layer on top.
        """
        if self._cache is None:  # pragma: no cover
            result = self._get_project(name)
        elif name in self._cache:
            result = self._cache[name]
        else:
            self.clear_errors()
            result = self._get_project(name)
            self._cache[name] = result
        return result

    def score_url(self, url):
        """
        Give an url a score which can be used to choose preferred URLs
        for a given project release.
        """
        t = urlparse(url)
        basename = posixpath.basename(t.path)
        compatible = True
        is_wheel = basename.endswith('.whl')
        is_downloadable = basename.endswith(self.downloadable_extensions)
        if is_wheel:
            compatible = is_compatible(Wheel(basename), self.wheel_tags)
        return (t.scheme == 'https', 'pypi.org' in t.netloc,
                is_downloadable, is_wheel, compatible, basename)

    def prefer_url(self, url1, url2):
        """
        Choose one of two URLs where both are candidates for distribution
        archives for the same version of a distribution (for example,
        .tar.gz vs. zip).

        The current implementation favours https:// URLs over http://, archives
        from PyPI over those from other locations, wheel compatibility (if a
        wheel) and then the archive name.
        """
        result = url2
        if url1:
            s1 = self.score_url(url1)
            s2 = self.score_url(url2)
            if s1 > s2:
                result = url1
            if result != url2:
                logger.debug('Not replacing %r with %r', url1, url2)
            else:
                logger.debug('Replacing %r with %r', url1, url2)
        return result

    def split_filename(self, filename, project_name):
        """
        Attempt to split a filename in project name, version and Python version.
        """
        return split_filename(filename, project_name)

    def convert_url_to_download_info(self, url, project_name):
        """
        See if a URL is a candidate for a download URL for a project (the URL
        has typically been scraped from an HTML page).

        If it is, a dictionary is returned with keys "name", "version",
        "filename" and "url"; otherwise, None is returned.
        """
        def same_project(name1, name2):
            return normalize_name(name1) == normalize_name(name2)

        result = None
        scheme, netloc, path, params, query, frag = urlparse(url)
        if frag.lower().startswith('egg='):  # pragma: no cover
            logger.debug('%s: version hint in fragment: %r',
                         project_name, frag)
        m = HASHER_HASH.match(frag)
        if m:
            algo, digest = m.groups()
        else:
            algo, digest = None, None
        origpath = path
        if path and path[-1] == '/':  # pragma: no cover
            path = path[:-1]
        if path.endswith('.whl'):
            try:
                wheel = Wheel(path)
                if not is_compatible(wheel, self.wheel_tags):
                    logger.debug('Wheel not compatible: %s', path)
                else:
                    if project_name is None:
                        include = True
                    else:
                        include = same_project(wheel.name, project_name)
                    if include:
                        result = {
                            'name': wheel.name,
                            'version': wheel.version,
                            'filename': wheel.filename,
                            'url': urlunparse((scheme, netloc, origpath,
                                               params, query, '')),
                            'python-version': ', '.join(
                                ['.'.join(list(v[2:])) for v in wheel.pyver]),
                        }
            except Exception as e:  # pragma: no cover
                logger.warning('invalid path for wheel: %s', path)
        elif not path.endswith(self.downloadable_extensions):  # pragma: no cover
            logger.debug('Not downloadable: %s', path)
        else:  # downloadable extension
            path = filename = posixpath.basename(path)
            for ext in self.downloadable_extensions:
                if path.endswith(ext):
                    path = path[:-len(ext)]
                    t = self.split_filename(path, project_name)
                    if not t:  # pragma: no cover
                        logger.debug('No match for project/version: %s', path)
                    else:
                        name, version, pyver = t
                        if not project_name or same_project(project_name, name):
                            result = {
                                'name': name,
                                'version': version,
                                'filename': filename,
                                'url': urlunparse((scheme, netloc, origpath,
                                                   params, query, '')),
                                #'packagetype': 'sdist',
                            }
                            if pyver:  # pragma: no cover
                                result['python-version'] = pyver
                    break
        if result and algo:
            result['%s_digest' % algo] = digest
        return result

    def _get_digest(self, info):
        """
        Get a digest from a dictionary by looking at keys of the form
        'algo_digest'.

        Returns a 2-tuple (algo, digest) if found, else None. Currently
        looks only for SHA256, then MD5.
        """
        result = None
        for algo in ('sha256', 'md5'):
            key = '%s_digest' % algo
            if key in info:
                result = (algo, info[key])
                break
        return result

    def _update_version_data(self, result, info):
        """
        Update a result dictionary (the final result from _get_project) with a
        dictionary for a specific version, which typically holds information
        gleaned from a filename or URL for an archive for the distribution.
        """
        name = info.pop('name')
        version = info.pop('version')
        if version in result:
            dist = result[version]
            md = dist.metadata
        else:
            dist = make_dist(name, version, scheme=self.scheme)
            md = dist.metadata
        dist.digest = digest = self._get_digest(info)
        url = info['url']
        result['digests'][url] = digest
        if md.source_url != info['url']:
            md.source_url = self.prefer_url(md.source_url, url)
            result['urls'].setdefault(version, set()).add(url)
        dist.locator = self
        result[version] = dist

    def locate(self, requirement, prereleases=False):
        """
        Find the most recent distribution which matches the given
        requirement.

        :param requirement: A requirement of the form 'foo (1.0)' or perhaps
                            'foo (>= 1.0, < 2.0, != 1.3)'
        :param prereleases: If ``True``, allow pre-release versions
                            to be located. Otherwise, pre-release versions
                            are not returned.
        :return: A :class:`Distribution` instance, or ``None`` if no such
                 distribution could be located.
        """
        result = None
        r = parse_requirement(requirement)
        if r is None:  # pragma: no cover
            raise DistlibException('Not a valid requirement: %r' % requirement)
        scheme = get_scheme(self.scheme)
        self.matcher = matcher = scheme.matcher(r.requirement)
        logger.debug('matcher: %s (%s)', matcher, type(matcher).__name__)
        versions = self.get_project(r.name)
        if len(versions) > 2:   # urls and digests keys are present
            # sometimes, versions are invalid
            slist = []
            vcls = matcher.version_class
            for k in versions:
                if k in ('urls', 'digests'):
                    continue
                try:
                    if not matcher.match(k):
                        logger.debug('%s did not match %r', matcher, k)
                    else:
                        if prereleases or not vcls(k).is_prerelease:
                            slist.append(k)
                        else:
                            logger.debug('skipping pre-release '
                                         'version %s of %s', k, matcher.name)
                except Exception:  # pragma: no cover
                    logger.warning('error matching %s with %r', matcher, k)
                    pass # slist.append(k)
            if len(slist) > 1:
                slist = sorted(slist, key=scheme.key)
            if slist:
                logger.debug('sorted list: %s', slist)
                version = slist[-1]
                result = versions[version]
        if result:
            if r.extras:
                result.extras = r.extras
            result.download_urls = versions.get('urls', {}).get(version, set())
            d = {}
            sd = versions.get('digests', {})
            for url in result.download_urls:
                if url in sd:  # pragma: no cover
                    d[url] = sd[url]
            result.digests = d
        self.matcher = None
        return result


class PyPIRPCLocator(Locator):
    """
    This locator uses XML-RPC to locate distributions. It therefore
    cannot be used with simple mirrors (that only mirror file content).
    """
    def __init__(self, url, **kwargs):
        """
        Initialise an instance.

        :param url: The URL to use for XML-RPC.
        :param kwargs: Passed to the superclass constructor.
        """
        super(PyPIRPCLocator, self).__init__(**kwargs)
        self.base_url = url
        self.client = ServerProxy(url, timeout=3.0)

    def get_distribution_names(self):
        """
        Return all the distribution names known to this locator.
        """
        return set(self.client.list_packages())

    def _get_project(self, name):
        result = {'urls': {}, 'digests': {}}
        versions = self.client.package_releases(name, True)
        for v in versions:
            urls = self.client.release_urls(name, v)
            data = self.client.release_data(name, v)
            metadata = Metadata(scheme=self.scheme)
            metadata.name = data['name']
            metadata.version = data['version']
            metadata.license = data.get('license')
            metadata.keywords = data.get('keywords', [])
            metadata.summary = data.get('summary')
            dist = Distribution(metadata)
            if urls:
                info = urls[0]
                metadata.source_url = info['url']
                dist.digest = self._get_digest(info)
                dist.locator = self
                result[v] = dist
                for info in urls:
                    url = info['url']
                    digest = self._get_digest(info)
                    result['urls'].setdefault(v, set()).add(url)
                    result['digests'][url] = digest
        return result

class PyPIJSONLocator(Locator):
    """
    This locator uses PyPI's JSON interface. It's very limited in functionality
    and probably not worth using.
    """
    def __init__(self, url, **kwargs):
        super(PyPIJSONLocator, self).__init__(**kwargs)
        self.base_url = ensure_slash(url)

    def get_distribution_names(self):
        """
        Return all the distribution names known to this locator.
        """
        raise NotImplementedError('Not available from this locator')

    def _get_project(self, name):
        result = {'urls': {}, 'digests': {}}
        url = urljoin(self.base_url, '%s/json' % quote(name))
        try:
            resp = self.opener.open(url)
            data = resp.read().decode() # for now
            d = json.loads(data)
            md = Metadata(scheme=self.scheme)
            data = d['info']
            md.name = data['name']
            md.version = data['version']
            md.license = data.get('license')
            md.keywords = data.get('keywords', [])
            md.summary = data.get('summary')
            dist = Distribution(md)
            dist.locator = self
            urls = d['urls']
            result[md.version] = dist
            for info in d['urls']:
                url = info['url']
                dist.download_urls.add(url)
                dist.digests[url] = self._get_digest(info)
                result['urls'].setdefault(md.version, set()).add(url)
                result['digests'][url] = self._get_digest(info)
            # Now get other releases
            for version, infos in d['releases'].items():
                if version == md.version:
                    continue    # already done
                omd = Metadata(scheme=self.scheme)
                omd.name = md.name
                omd.version = version
                odist = Distribution(omd)
                odist.locator = self
                result[version] = odist
                for info in infos:
                    url = info['url']
                    odist.download_urls.add(url)
                    odist.digests[url] = self._get_digest(info)
                    result['urls'].setdefault(version, set()).add(url)
                    result['digests'][url] = self._get_digest(info)
#            for info in urls:
#                md.source_url = info['url']
#                dist.digest = self._get_digest(info)
#                dist.locator = self
#                for info in urls:
#                    url = info['url']
#                    result['urls'].setdefault(md.version, set()).add(url)
#                    result['digests'][url] = self._get_digest(info)
        except Exception as e:
            self.errors.put(text_type(e))
            logger.exception('JSON fetch failed: %s', e)
        return result


class Page(object):
    """
    This class represents a scraped HTML page.
    """
    # The following slightly hairy-looking regex just looks for the contents of
    # an anchor link, which has an attribute "href" either immediately preceded
    # or immediately followed by a "rel" attribute. The attribute values can be
    # declared with double quotes, single quotes or no quotes - which leads to
    # the length of the expression.
    _href = re.compile("""
(rel\\s*=\\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\\s\n]*))\\s+)?
href\\s*=\\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\\s\n]*))
(\\s+rel\\s*=\\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\\s\n]*)))?
""", re.I | re.S | re.X)
    _base = re.compile(r"""]+)""", re.I | re.S)

    def __init__(self, data, url):
        """
        Initialise an instance with the Unicode page contents and the URL they
        came from.
        """
        self.data = data
        self.base_url = self.url = url
        m = self._base.search(self.data)
        if m:
            self.base_url = m.group(1)

    _clean_re = re.compile(r'[^a-z0-9$&+,/:;=?@.#%_\\|-]', re.I)

    @cached_property
    def links(self):
        """
        Return the URLs of all the links on a page together with information
        about their "rel" attribute, for determining which ones to treat as
        downloads and which ones to queue for further scraping.
        """
        def clean(url):
            "Tidy up an URL."
            scheme, netloc, path, params, query, frag = urlparse(url)
            return urlunparse((scheme, netloc, quote(path),
                               params, query, frag))

        result = set()
        for match in self._href.finditer(self.data):
            d = match.groupdict('')
            rel = (d['rel1'] or d['rel2'] or d['rel3'] or
                   d['rel4'] or d['rel5'] or d['rel6'])
            url = d['url1'] or d['url2'] or d['url3']
            url = urljoin(self.base_url, url)
            url = unescape(url)
            url = self._clean_re.sub(lambda m: '%%%2x' % ord(m.group(0)), url)
            result.add((url, rel))
        # We sort the result, hoping to bring the most recent versions
        # to the front
        result = sorted(result, key=lambda t: t[0], reverse=True)
        return result


class SimpleScrapingLocator(Locator):
    """
    A locator which scrapes HTML pages to locate downloads for a distribution.
    This runs multiple threads to do the I/O; performance is at least as good
    as pip's PackageFinder, which works in an analogous fashion.
    """

    # These are used to deal with various Content-Encoding schemes.
    decoders = {
        'deflate': zlib.decompress,
        'gzip': lambda b: gzip.GzipFile(fileobj=BytesIO(d)).read(),
        'none': lambda b: b,
    }

    def __init__(self, url, timeout=None, num_workers=10, **kwargs):
        """
        Initialise an instance.
        :param url: The root URL to use for scraping.
        :param timeout: The timeout, in seconds, to be applied to requests.
                        This defaults to ``None`` (no timeout specified).
        :param num_workers: The number of worker threads you want to do I/O,
                            This defaults to 10.
        :param kwargs: Passed to the superclass.
        """
        super(SimpleScrapingLocator, self).__init__(**kwargs)
        self.base_url = ensure_slash(url)
        self.timeout = timeout
        self._page_cache = {}
        self._seen = set()
        self._to_fetch = queue.Queue()
        self._bad_hosts = set()
        self.skip_externals = False
        self.num_workers = num_workers
        self._lock = threading.RLock()
        # See issue #45: we need to be resilient when the locator is used
        # in a thread, e.g. with concurrent.futures. We can't use self._lock
        # as it is for coordinating our internal threads - the ones created
        # in _prepare_threads.
        self._gplock = threading.RLock()
        self.platform_check = False  # See issue #112

    def _prepare_threads(self):
        """
        Threads are created only when get_project is called, and terminate
        before it returns. They are there primarily to parallelise I/O (i.e.
        fetching web pages).
        """
        self._threads = []
        for i in range(self.num_workers):
            t = threading.Thread(target=self._fetch)
            t.setDaemon(True)
            t.start()
            self._threads.append(t)

    def _wait_threads(self):
        """
        Tell all the threads to terminate (by sending a sentinel value) and
        wait for them to do so.
        """
        # Note that you need two loops, since you can't say which
        # thread will get each sentinel
        for t in self._threads:
            self._to_fetch.put(None)    # sentinel
        for t in self._threads:
            t.join()
        self._threads = []

    def _get_project(self, name):
        result = {'urls': {}, 'digests': {}}
        with self._gplock:
            self.result = result
            self.project_name = name
            url = urljoin(self.base_url, '%s/' % quote(name))
            self._seen.clear()
            self._page_cache.clear()
            self._prepare_threads()
            try:
                logger.debug('Queueing %s', url)
                self._to_fetch.put(url)
                self._to_fetch.join()
            finally:
                self._wait_threads()
            del self.result
        return result

    platform_dependent = re.compile(r'\b(linux_(i\d86|x86_64|arm\w+)|'
                                    r'win(32|_amd64)|macosx_?\d+)\b', re.I)

    def _is_platform_dependent(self, url):
        """
        Does an URL refer to a platform-specific download?
        """
        return self.platform_dependent.search(url)

    def _process_download(self, url):
        """
        See if an URL is a suitable download for a project.

        If it is, register information in the result dictionary (for
        _get_project) about the specific version it's for.

        Note that the return value isn't actually used other than as a boolean
        value.
        """
        if self.platform_check and self._is_platform_dependent(url):
            info = None
        else:
            info = self.convert_url_to_download_info(url, self.project_name)
        logger.debug('process_download: %s -> %s', url, info)
        if info:
            with self._lock:    # needed because self.result is shared
                self._update_version_data(self.result, info)
        return info

    def _should_queue(self, link, referrer, rel):
        """
        Determine whether a link URL from a referring page and with a
        particular "rel" attribute should be queued for scraping.
        """
        scheme, netloc, path, _, _, _ = urlparse(link)
        if path.endswith(self.source_extensions + self.binary_extensions +
                         self.excluded_extensions):
            result = False
        elif self.skip_externals and not link.startswith(self.base_url):
            result = False
        elif not referrer.startswith(self.base_url):
            result = False
        elif rel not in ('homepage', 'download'):
            result = False
        elif scheme not in ('http', 'https', 'ftp'):
            result = False
        elif self._is_platform_dependent(link):
            result = False
        else:
            host = netloc.split(':', 1)[0]
            if host.lower() == 'localhost':
                result = False
            else:
                result = True
        logger.debug('should_queue: %s (%s) from %s -> %s', link, rel,
                     referrer, result)
        return result

    def _fetch(self):
        """
        Get a URL to fetch from the work queue, get the HTML page, examine its
        links for download candidates and candidates for further scraping.

        This is a handy method to run in a thread.
        """
        while True:
            url = self._to_fetch.get()
            try:
                if url:
                    page = self.get_page(url)
                    if page is None:    # e.g. after an error
                        continue
                    for link, rel in page.links:
                        if link not in self._seen:
                            try:
                                self._seen.add(link)
                                if (not self._process_download(link) and
                                    self._should_queue(link, url, rel)):
                                    logger.debug('Queueing %s from %s', link, url)
                                    self._to_fetch.put(link)
                            except MetadataInvalidError:  # e.g. invalid versions
                                pass
            except Exception as e:  # pragma: no cover
                self.errors.put(text_type(e))
            finally:
                # always do this, to avoid hangs :-)
                self._to_fetch.task_done()
            if not url:
                #logger.debug('Sentinel seen, quitting.')
                break

    def get_page(self, url):
        """
        Get the HTML for an URL, possibly from an in-memory cache.

        XXX TODO Note: this cache is never actually cleared. It's assumed that
        the data won't get stale over the lifetime of a locator instance (not
        necessarily true for the default_locator).
        """
        # http://peak.telecommunity.com/DevCenter/EasyInstall#package-index-api
        scheme, netloc, path, _, _, _ = urlparse(url)
        if scheme == 'file' and os.path.isdir(url2pathname(path)):
            url = urljoin(ensure_slash(url), 'index.html')

        if url in self._page_cache:
            result = self._page_cache[url]
            logger.debug('Returning %s from cache: %s', url, result)
        else:
            host = netloc.split(':', 1)[0]
            result = None
            if host in self._bad_hosts:
                logger.debug('Skipping %s due to bad host %s', url, host)
            else:
                req = Request(url, headers={'Accept-encoding': 'identity'})
                try:
                    logger.debug('Fetching %s', url)
                    resp = self.opener.open(req, timeout=self.timeout)
                    logger.debug('Fetched %s', url)
                    headers = resp.info()
                    content_type = headers.get('Content-Type', '')
                    if HTML_CONTENT_TYPE.match(content_type):
                        final_url = resp.geturl()
                        data = resp.read()
                        encoding = headers.get('Content-Encoding')
                        if encoding:
                            decoder = self.decoders[encoding]   # fail if not found
                            data = decoder(data)
                        encoding = 'utf-8'
                        m = CHARSET.search(content_type)
                        if m:
                            encoding = m.group(1)
                        try:
                            data = data.decode(encoding)
                        except UnicodeError:  # pragma: no cover
                            data = data.decode('latin-1')    # fallback
                        result = Page(data, final_url)
                        self._page_cache[final_url] = result
                except HTTPError as e:
                    if e.code != 404:
                        logger.exception('Fetch failed: %s: %s', url, e)
                except URLError as e:  # pragma: no cover
                    logger.exception('Fetch failed: %s: %s', url, e)
                    with self._lock:
                        self._bad_hosts.add(host)
                except Exception as e:  # pragma: no cover
                    logger.exception('Fetch failed: %s: %s', url, e)
                finally:
                    self._page_cache[url] = result   # even if None (failure)
        return result

    _distname_re = re.compile(']*>([^<]+)<')

    def get_distribution_names(self):
        """
        Return all the distribution names known to this locator.
        """
        result = set()
        page = self.get_page(self.base_url)
        if not page:
            raise DistlibException('Unable to get %s' % self.base_url)
        for match in self._distname_re.finditer(page.data):
            result.add(match.group(1))
        return result

class DirectoryLocator(Locator):
    """
    This class locates distributions in a directory tree.
    """

    def __init__(self, path, **kwargs):
        """
        Initialise an instance.
        :param path: The root of the directory tree to search.
        :param kwargs: Passed to the superclass constructor,
                       except for:
                       * recursive - if True (the default), subdirectories are
                         recursed into. If False, only the top-level directory
                         is searched,
        """
        self.recursive = kwargs.pop('recursive', True)
        super(DirectoryLocator, self).__init__(**kwargs)
        path = os.path.abspath(path)
        if not os.path.isdir(path):  # pragma: no cover
            raise DistlibException('Not a directory: %r' % path)
        self.base_dir = path

    def should_include(self, filename, parent):
        """
        Should a filename be considered as a candidate for a distribution
        archive? As well as the filename, the directory which contains it
        is provided, though not used by the current implementation.
        """
        return filename.endswith(self.downloadable_extensions)

    def _get_project(self, name):
        result = {'urls': {}, 'digests': {}}
        for root, dirs, files in os.walk(self.base_dir):
            for fn in files:
                if self.should_include(fn, root):
                    fn = os.path.join(root, fn)
                    url = urlunparse(('file', '',
                                      pathname2url(os.path.abspath(fn)),
                                      '', '', ''))
                    info = self.convert_url_to_download_info(url, name)
                    if info:
                        self._update_version_data(result, info)
            if not self.recursive:
                break
        return result

    def get_distribution_names(self):
        """
        Return all the distribution names known to this locator.
        """
        result = set()
        for root, dirs, files in os.walk(self.base_dir):
            for fn in files:
                if self.should_include(fn, root):
                    fn = os.path.join(root, fn)
                    url = urlunparse(('file', '',
                                      pathname2url(os.path.abspath(fn)),
                                      '', '', ''))
                    info = self.convert_url_to_download_info(url, None)
                    if info:
                        result.add(info['name'])
            if not self.recursive:
                break
        return result

class JSONLocator(Locator):
    """
    This locator uses special extended metadata (not available on PyPI) and is
    the basis of performant dependency resolution in distlib. Other locators
    require archive downloads before dependencies can be determined! As you
    might imagine, that can be slow.
    """
    def get_distribution_names(self):
        """
        Return all the distribution names known to this locator.
        """
        raise NotImplementedError('Not available from this locator')

    def _get_project(self, name):
        result = {'urls': {}, 'digests': {}}
        data = get_project_data(name)
        if data:
            for info in data.get('files', []):
                if info['ptype'] != 'sdist' or info['pyversion'] != 'source':
                    continue
                # We don't store summary in project metadata as it makes
                # the data bigger for no benefit during dependency
                # resolution
                dist = make_dist(data['name'], info['version'],
                                 summary=data.get('summary',
                                                  'Placeholder for summary'),
                                 scheme=self.scheme)
                md = dist.metadata
                md.source_url = info['url']
                # TODO SHA256 digest
                if 'digest' in info and info['digest']:
                    dist.digest = ('md5', info['digest'])
                md.dependencies = info.get('requirements', {})
                dist.exports = info.get('exports', {})
                result[dist.version] = dist
                result['urls'].setdefault(dist.version, set()).add(info['url'])
        return result

class DistPathLocator(Locator):
    """
    This locator finds installed distributions in a path. It can be useful for
    adding to an :class:`AggregatingLocator`.
    """
    def __init__(self, distpath, **kwargs):
        """
        Initialise an instance.

        :param distpath: A :class:`DistributionPath` instance to search.
        """
        super(DistPathLocator, self).__init__(**kwargs)
        assert isinstance(distpath, DistributionPath)
        self.distpath = distpath

    def _get_project(self, name):
        dist = self.distpath.get_distribution(name)
        if dist is None:
            result = {'urls': {}, 'digests': {}}
        else:
            result = {
                dist.version: dist,
                'urls': {dist.version: set([dist.source_url])},
                'digests': {dist.version: set([None])}
            }
        return result


class AggregatingLocator(Locator):
    """
    This class allows you to chain and/or merge a list of locators.
    """
    def __init__(self, *locators, **kwargs):
        """
        Initialise an instance.

        :param locators: The list of locators to search.
        :param kwargs: Passed to the superclass constructor,
                       except for:
                       * merge - if False (the default), the first successful
                         search from any of the locators is returned. If True,
                         the results from all locators are merged (this can be
                         slow).
        """
        self.merge = kwargs.pop('merge', False)
        self.locators = locators
        super(AggregatingLocator, self).__init__(**kwargs)

    def clear_cache(self):
        super(AggregatingLocator, self).clear_cache()
        for locator in self.locators:
            locator.clear_cache()

    def _set_scheme(self, value):
        self._scheme = value
        for locator in self.locators:
            locator.scheme = value

    scheme = property(Locator.scheme.fget, _set_scheme)

    def _get_project(self, name):
        result = {}
        for locator in self.locators:
            d = locator.get_project(name)
            if d:
                if self.merge:
                    files = result.get('urls', {})
                    digests = result.get('digests', {})
                    # next line could overwrite result['urls'], result['digests']
                    result.update(d)
                    df = result.get('urls')
                    if files and df:
                        for k, v in files.items():
                            if k in df:
                                df[k] |= v
                            else:
                                df[k] = v
                    dd = result.get('digests')
                    if digests and dd:
                        dd.update(digests)
                else:
                    # See issue #18. If any dists are found and we're looking
                    # for specific constraints, we only return something if
                    # a match is found. For example, if a DirectoryLocator
                    # returns just foo (1.0) while we're looking for
                    # foo (>= 2.0), we'll pretend there was nothing there so
                    # that subsequent locators can be queried. Otherwise we
                    # would just return foo (1.0) which would then lead to a
                    # failure to find foo (>= 2.0), because other locators
                    # weren't searched. Note that this only matters when
                    # merge=False.
                    if self.matcher is None:
                        found = True
                    else:
                        found = False
                        for k in d:
                            if self.matcher.match(k):
                                found = True
                                break
                    if found:
                        result = d
                        break
        return result

    def get_distribution_names(self):
        """
        Return all the distribution names known to this locator.
        """
        result = set()
        for locator in self.locators:
            try:
                result |= locator.get_distribution_names()
            except NotImplementedError:
                pass
        return result


# We use a legacy scheme simply because most of the dists on PyPI use legacy
# versions which don't conform to PEP 426 / PEP 440.
default_locator = AggregatingLocator(
                    JSONLocator(),
                    SimpleScrapingLocator('https://pypi.org/simple/',
                                          timeout=3.0),
                    scheme='legacy')

locate = default_locator.locate

NAME_VERSION_RE = re.compile(r'(?P[\w-]+)\s*'
                             r'\(\s*(==\s*)?(?P[^)]+)\)$')

class DependencyFinder(object):
    """
    Locate dependencies for distributions.
    """

    def __init__(self, locator=None):
        """
        Initialise an instance, using the specified locator
        to locate distributions.
        """
        self.locator = locator or default_locator
        self.scheme = get_scheme(self.locator.scheme)

    def add_distribution(self, dist):
        """
        Add a distribution to the finder. This will update internal information
        about who provides what.
        :param dist: The distribution to add.
        """
        logger.debug('adding distribution %s', dist)
        name = dist.key
        self.dists_by_name[name] = dist
        self.dists[(name, dist.version)] = dist
        for p in dist.provides:
            name, version = parse_name_and_version(p)
            logger.debug('Add to provided: %s, %s, %s', name, version, dist)
            self.provided.setdefault(name, set()).add((version, dist))

    def remove_distribution(self, dist):
        """
        Remove a distribution from the finder. This will update internal
        information about who provides what.
        :param dist: The distribution to remove.
        """
        logger.debug('removing distribution %s', dist)
        name = dist.key
        del self.dists_by_name[name]
        del self.dists[(name, dist.version)]
        for p in dist.provides:
            name, version = parse_name_and_version(p)
            logger.debug('Remove from provided: %s, %s, %s', name, version, dist)
            s = self.provided[name]
            s.remove((version, dist))
            if not s:
                del self.provided[name]

    def get_matcher(self, reqt):
        """
        Get a version matcher for a requirement.
        :param reqt: The requirement
        :type reqt: str
        :return: A version matcher (an instance of
                 :class:`distlib.version.Matcher`).
        """
        try:
            matcher = self.scheme.matcher(reqt)
        except UnsupportedVersionError:  # pragma: no cover
            # XXX compat-mode if cannot read the version
            name = reqt.split()[0]
            matcher = self.scheme.matcher(name)
        return matcher

    def find_providers(self, reqt):
        """
        Find the distributions which can fulfill a requirement.

        :param reqt: The requirement.
         :type reqt: str
        :return: A set of distribution which can fulfill the requirement.
        """
        matcher = self.get_matcher(reqt)
        name = matcher.key   # case-insensitive
        result = set()
        provided = self.provided
        if name in provided:
            for version, provider in provided[name]:
                try:
                    match = matcher.match(version)
                except UnsupportedVersionError:
                    match = False

                if match:
                    result.add(provider)
                    break
        return result

    def try_to_replace(self, provider, other, problems):
        """
        Attempt to replace one provider with another. This is typically used
        when resolving dependencies from multiple sources, e.g. A requires
        (B >= 1.0) while C requires (B >= 1.1).

        For successful replacement, ``provider`` must meet all the requirements
        which ``other`` fulfills.

        :param provider: The provider we are trying to replace with.
        :param other: The provider we're trying to replace.
        :param problems: If False is returned, this will contain what
                         problems prevented replacement. This is currently
                         a tuple of the literal string 'cantreplace',
                         ``provider``, ``other``  and the set of requirements
                         that ``provider`` couldn't fulfill.
        :return: True if we can replace ``other`` with ``provider``, else
                 False.
        """
        rlist = self.reqts[other]
        unmatched = set()
        for s in rlist:
            matcher = self.get_matcher(s)
            if not matcher.match(provider.version):
                unmatched.add(s)
        if unmatched:
            # can't replace other with provider
            problems.add(('cantreplace', provider, other,
                          frozenset(unmatched)))
            result = False
        else:
            # can replace other with provider
            self.remove_distribution(other)
            del self.reqts[other]
            for s in rlist:
                self.reqts.setdefault(provider, set()).add(s)
            self.add_distribution(provider)
            result = True
        return result

    def find(self, requirement, meta_extras=None, prereleases=False):
        """
        Find a distribution and all distributions it depends on.

        :param requirement: The requirement specifying the distribution to
                            find, or a Distribution instance.
        :param meta_extras: A list of meta extras such as :test:, :build: and
                            so on.
        :param prereleases: If ``True``, allow pre-release versions to be
                            returned - otherwise, don't return prereleases
                            unless they're all that's available.

        Return a set of :class:`Distribution` instances and a set of
        problems.

        The distributions returned should be such that they have the
        :attr:`required` attribute set to ``True`` if they were
        from the ``requirement`` passed to ``find()``, and they have the
        :attr:`build_time_dependency` attribute set to ``True`` unless they
        are post-installation dependencies of the ``requirement``.

        The problems should be a tuple consisting of the string
        ``'unsatisfied'`` and the requirement which couldn't be satisfied
        by any distribution known to the locator.
        """

        self.provided = {}
        self.dists = {}
        self.dists_by_name = {}
        self.reqts = {}

        meta_extras = set(meta_extras or [])
        if ':*:' in meta_extras:
            meta_extras.remove(':*:')
            # :meta: and :run: are implicitly included
            meta_extras |= set([':test:', ':build:', ':dev:'])

        if isinstance(requirement, Distribution):
            dist = odist = requirement
            logger.debug('passed %s as requirement', odist)
        else:
            dist = odist = self.locator.locate(requirement,
                                               prereleases=prereleases)
            if dist is None:
                raise DistlibException('Unable to locate %r' % requirement)
            logger.debug('located %s', odist)
        dist.requested = True
        problems = set()
        todo = set([dist])
        install_dists = set([odist])
        while todo:
            dist = todo.pop()
            name = dist.key     # case-insensitive
            if name not in self.dists_by_name:
                self.add_distribution(dist)
            else:
                #import pdb; pdb.set_trace()
                other = self.dists_by_name[name]
                if other != dist:
                    self.try_to_replace(dist, other, problems)

            ireqts = dist.run_requires | dist.meta_requires
            sreqts = dist.build_requires
            ereqts = set()
            if meta_extras and dist in install_dists:
                for key in ('test', 'build', 'dev'):
                    e = ':%s:' % key
                    if e in meta_extras:
                        ereqts |= getattr(dist, '%s_requires' % key)
            all_reqts = ireqts | sreqts | ereqts
            for r in all_reqts:
                providers = self.find_providers(r)
                if not providers:
                    logger.debug('No providers found for %r', r)
                    provider = self.locator.locate(r, prereleases=prereleases)
                    # If no provider is found and we didn't consider
                    # prereleases, consider them now.
                    if provider is None and not prereleases:
                        provider = self.locator.locate(r, prereleases=True)
                    if provider is None:
                        logger.debug('Cannot satisfy %r', r)
                        problems.add(('unsatisfied', r))
                    else:
                        n, v = provider.key, provider.version
                        if (n, v) not in self.dists:
                            todo.add(provider)
                        providers.add(provider)
                        if r in ireqts and dist in install_dists:
                            install_dists.add(provider)
                            logger.debug('Adding %s to install_dists',
                                         provider.name_and_version)
                for p in providers:
                    name = p.key
                    if name not in self.dists_by_name:
                        self.reqts.setdefault(p, set()).add(r)
                    else:
                        other = self.dists_by_name[name]
                        if other != p:
                            # see if other can be replaced by p
                            self.try_to_replace(p, other, problems)

        dists = set(self.dists.values())
        for dist in dists:
            dist.build_time_dependency = dist not in install_dists
            if dist.build_time_dependency:
                logger.debug('%s is a build-time dependency only.',
                             dist.name_and_version)
        logger.debug('find done for %s', odist)
        return dists, problems
PKÔ¶N]%Øsaõ�õ�*site-packages/pip/_vendor/distlib/wheel.pynu„[µü¤# -*- coding: utf-8 -*-
#
# Copyright (C) 2013-2017 Vinay Sajip.
# Licensed to the Python Software Foundation under a contributor agreement.
# See LICENSE.txt and CONTRIBUTORS.txt.
#
from __future__ import unicode_literals

import base64
import codecs
import datetime
import distutils.util
from email import message_from_file
import hashlib
import imp
import json
import logging
import os
import posixpath
import re
import shutil
import sys
import tempfile
import zipfile

from . import __version__, DistlibException
from .compat import sysconfig, ZipFile, fsdecode, text_type, filter
from .database import InstalledDistribution
from .metadata import Metadata, METADATA_FILENAME, WHEEL_METADATA_FILENAME
from .util import (FileOperator, convert_path, CSVReader, CSVWriter, Cache,
                   cached_property, get_cache_base, read_exports, tempdir)
from .version import NormalizedVersion, UnsupportedVersionError

logger = logging.getLogger(__name__)

cache = None    # created when needed

if hasattr(sys, 'pypy_version_info'):  # pragma: no cover
    IMP_PREFIX = 'pp'
elif sys.platform.startswith('java'):  # pragma: no cover
    IMP_PREFIX = 'jy'
elif sys.platform == 'cli':  # pragma: no cover
    IMP_PREFIX = 'ip'
else:
    IMP_PREFIX = 'cp'

VER_SUFFIX = sysconfig.get_config_var('py_version_nodot')
if not VER_SUFFIX:   # pragma: no cover
    VER_SUFFIX = '%s%s' % sys.version_info[:2]
PYVER = 'py' + VER_SUFFIX
IMPVER = IMP_PREFIX + VER_SUFFIX

ARCH = distutils.util.get_platform().replace('-', '_').replace('.', '_')

ABI = sysconfig.get_config_var('SOABI')
if ABI and ABI.startswith('cpython-'):
    ABI = ABI.replace('cpython-', 'cp')
else:
    def _derive_abi():
        parts = ['cp', VER_SUFFIX]
        if sysconfig.get_config_var('Py_DEBUG'):
            parts.append('d')
        if sysconfig.get_config_var('WITH_PYMALLOC'):
            parts.append('m')
        if sysconfig.get_config_var('Py_UNICODE_SIZE') == 4:
            parts.append('u')
        return ''.join(parts)
    ABI = _derive_abi()
    del _derive_abi

FILENAME_RE = re.compile(r'''
(?P[^-]+)
-(?P\d+[^-]*)
(-(?P\d+[^-]*))?
-(?P\w+\d+(\.\w+\d+)*)
-(?P\w+)
-(?P\w+(\.\w+)*)
\.whl$
''', re.IGNORECASE | re.VERBOSE)

NAME_VERSION_RE = re.compile(r'''
(?P[^-]+)
-(?P\d+[^-]*)
(-(?P\d+[^-]*))?$
''', re.IGNORECASE | re.VERBOSE)

SHEBANG_RE = re.compile(br'\s*#![^\r\n]*')
SHEBANG_DETAIL_RE = re.compile(br'^(\s*#!("[^"]+"|\S+))\s+(.*)$')
SHEBANG_PYTHON = b'#!python'
SHEBANG_PYTHONW = b'#!pythonw'

if os.sep == '/':
    to_posix = lambda o: o
else:
    to_posix = lambda o: o.replace(os.sep, '/')


class Mounter(object):
    def __init__(self):
        self.impure_wheels = {}
        self.libs = {}

    def add(self, pathname, extensions):
        self.impure_wheels[pathname] = extensions
        self.libs.update(extensions)

    def remove(self, pathname):
        extensions = self.impure_wheels.pop(pathname)
        for k, v in extensions:
            if k in self.libs:
                del self.libs[k]

    def find_module(self, fullname, path=None):
        if fullname in self.libs:
            result = self
        else:
            result = None
        return result

    def load_module(self, fullname):
        if fullname in sys.modules:
            result = sys.modules[fullname]
        else:
            if fullname not in self.libs:
                raise ImportError('unable to find extension for %s' % fullname)
            result = imp.load_dynamic(fullname, self.libs[fullname])
            result.__loader__ = self
            parts = fullname.rsplit('.', 1)
            if len(parts) > 1:
                result.__package__ = parts[0]
        return result

_hook = Mounter()


class Wheel(object):
    """
    Class to build and install from Wheel files (PEP 427).
    """

    wheel_version = (1, 1)
    hash_kind = 'sha256'

    def __init__(self, filename=None, sign=False, verify=False):
        """
        Initialise an instance using a (valid) filename.
        """
        self.sign = sign
        self.should_verify = verify
        self.buildver = ''
        self.pyver = [PYVER]
        self.abi = ['none']
        self.arch = ['any']
        self.dirname = os.getcwd()
        if filename is None:
            self.name = 'dummy'
            self.version = '0.1'
            self._filename = self.filename
        else:
            m = NAME_VERSION_RE.match(filename)
            if m:
                info = m.groupdict('')
                self.name = info['nm']
                # Reinstate the local version separator
                self.version = info['vn'].replace('_', '-')
                self.buildver = info['bn']
                self._filename = self.filename
            else:
                dirname, filename = os.path.split(filename)
                m = FILENAME_RE.match(filename)
                if not m:
                    raise DistlibException('Invalid name or '
                                           'filename: %r' % filename)
                if dirname:
                    self.dirname = os.path.abspath(dirname)
                self._filename = filename
                info = m.groupdict('')
                self.name = info['nm']
                self.version = info['vn']
                self.buildver = info['bn']
                self.pyver = info['py'].split('.')
                self.abi = info['bi'].split('.')
                self.arch = info['ar'].split('.')

    @property
    def filename(self):
        """
        Build and return a filename from the various components.
        """
        if self.buildver:
            buildver = '-' + self.buildver
        else:
            buildver = ''
        pyver = '.'.join(self.pyver)
        abi = '.'.join(self.abi)
        arch = '.'.join(self.arch)
        # replace - with _ as a local version separator
        version = self.version.replace('-', '_')
        return '%s-%s%s-%s-%s-%s.whl' % (self.name, version, buildver,
                                         pyver, abi, arch)

    @property
    def exists(self):
        path = os.path.join(self.dirname, self.filename)
        return os.path.isfile(path)

    @property
    def tags(self):
        for pyver in self.pyver:
            for abi in self.abi:
                for arch in self.arch:
                    yield pyver, abi, arch

    @cached_property
    def metadata(self):
        pathname = os.path.join(self.dirname, self.filename)
        name_ver = '%s-%s' % (self.name, self.version)
        info_dir = '%s.dist-info' % name_ver
        wrapper = codecs.getreader('utf-8')
        with ZipFile(pathname, 'r') as zf:
            wheel_metadata = self.get_wheel_metadata(zf)
            wv = wheel_metadata['Wheel-Version'].split('.', 1)
            file_version = tuple([int(i) for i in wv])
            if file_version < (1, 1):
                fns = [WHEEL_METADATA_FILENAME, METADATA_FILENAME, 'METADATA']
            else:
                fns = [WHEEL_METADATA_FILENAME, METADATA_FILENAME]
            result = None
            for fn in fns:
                try:
                    metadata_filename = posixpath.join(info_dir, fn)
                    with zf.open(metadata_filename) as bf:
                        wf = wrapper(bf)
                        result = Metadata(fileobj=wf)
                        if result:
                            break
                except KeyError:
                    pass
            if not result:
                raise ValueError('Invalid wheel, because metadata is '
                                 'missing: looked in %s' % ', '.join(fns))
        return result

    def get_wheel_metadata(self, zf):
        name_ver = '%s-%s' % (self.name, self.version)
        info_dir = '%s.dist-info' % name_ver
        metadata_filename = posixpath.join(info_dir, 'WHEEL')
        with zf.open(metadata_filename) as bf:
            wf = codecs.getreader('utf-8')(bf)
            message = message_from_file(wf)
        return dict(message)

    @cached_property
    def info(self):
        pathname = os.path.join(self.dirname, self.filename)
        with ZipFile(pathname, 'r') as zf:
            result = self.get_wheel_metadata(zf)
        return result

    def process_shebang(self, data):
        m = SHEBANG_RE.match(data)
        if m:
            end = m.end()
            shebang, data_after_shebang = data[:end], data[end:]
            # Preserve any arguments after the interpreter
            if b'pythonw' in shebang.lower():
                shebang_python = SHEBANG_PYTHONW
            else:
                shebang_python = SHEBANG_PYTHON
            m = SHEBANG_DETAIL_RE.match(shebang)
            if m:
                args = b' ' + m.groups()[-1]
            else:
                args = b''
            shebang = shebang_python + args
            data = shebang + data_after_shebang
        else:
            cr = data.find(b'\r')
            lf = data.find(b'\n')
            if cr < 0 or cr > lf:
                term = b'\n'
            else:
                if data[cr:cr + 2] == b'\r\n':
                    term = b'\r\n'
                else:
                    term = b'\r'
            data = SHEBANG_PYTHON + term + data
        return data

    def get_hash(self, data, hash_kind=None):
        if hash_kind is None:
            hash_kind = self.hash_kind
        try:
            hasher = getattr(hashlib, hash_kind)
        except AttributeError:
            raise DistlibException('Unsupported hash algorithm: %r' % hash_kind)
        result = hasher(data).digest()
        result = base64.urlsafe_b64encode(result).rstrip(b'=').decode('ascii')
        return hash_kind, result

    def write_record(self, records, record_path, base):
        records = list(records) # make a copy for sorting
        p = to_posix(os.path.relpath(record_path, base))
        records.append((p, '', ''))
        records.sort()
        with CSVWriter(record_path) as writer:
            for row in records:
                writer.writerow(row)

    def write_records(self, info, libdir, archive_paths):
        records = []
        distinfo, info_dir = info
        hasher = getattr(hashlib, self.hash_kind)
        for ap, p in archive_paths:
            with open(p, 'rb') as f:
                data = f.read()
            digest = '%s=%s' % self.get_hash(data)
            size = os.path.getsize(p)
            records.append((ap, digest, size))

        p = os.path.join(distinfo, 'RECORD')
        self.write_record(records, p, libdir)
        ap = to_posix(os.path.join(info_dir, 'RECORD'))
        archive_paths.append((ap, p))

    def build_zip(self, pathname, archive_paths):
        with ZipFile(pathname, 'w', zipfile.ZIP_DEFLATED) as zf:
            for ap, p in archive_paths:
                logger.debug('Wrote %s to %s in wheel', p, ap)
                zf.write(p, ap)

    def build(self, paths, tags=None, wheel_version=None):
        """
        Build a wheel from files in specified paths, and use any specified tags
        when determining the name of the wheel.
        """
        if tags is None:
            tags = {}

        libkey = list(filter(lambda o: o in paths, ('purelib', 'platlib')))[0]
        if libkey == 'platlib':
            is_pure = 'false'
            default_pyver = [IMPVER]
            default_abi = [ABI]
            default_arch = [ARCH]
        else:
            is_pure = 'true'
            default_pyver = [PYVER]
            default_abi = ['none']
            default_arch = ['any']

        self.pyver = tags.get('pyver', default_pyver)
        self.abi = tags.get('abi', default_abi)
        self.arch = tags.get('arch', default_arch)

        libdir = paths[libkey]

        name_ver = '%s-%s' % (self.name, self.version)
        data_dir = '%s.data' % name_ver
        info_dir = '%s.dist-info' % name_ver

        archive_paths = []

        # First, stuff which is not in site-packages
        for key in ('data', 'headers', 'scripts'):
            if key not in paths:
                continue
            path = paths[key]
            if os.path.isdir(path):
                for root, dirs, files in os.walk(path):
                    for fn in files:
                        p = fsdecode(os.path.join(root, fn))
                        rp = os.path.relpath(p, path)
                        ap = to_posix(os.path.join(data_dir, key, rp))
                        archive_paths.append((ap, p))
                        if key == 'scripts' and not p.endswith('.exe'):
                            with open(p, 'rb') as f:
                                data = f.read()
                            data = self.process_shebang(data)
                            with open(p, 'wb') as f:
                                f.write(data)

        # Now, stuff which is in site-packages, other than the
        # distinfo stuff.
        path = libdir
        distinfo = None
        for root, dirs, files in os.walk(path):
            if root == path:
                # At the top level only, save distinfo for later
                # and skip it for now
                for i, dn in enumerate(dirs):
                    dn = fsdecode(dn)
                    if dn.endswith('.dist-info'):
                        distinfo = os.path.join(root, dn)
                        del dirs[i]
                        break
                assert distinfo, '.dist-info directory expected, not found'

            for fn in files:
                # comment out next suite to leave .pyc files in
                if fsdecode(fn).endswith(('.pyc', '.pyo')):
                    continue
                p = os.path.join(root, fn)
                rp = to_posix(os.path.relpath(p, path))
                archive_paths.append((rp, p))

        # Now distinfo. Assumed to be flat, i.e. os.listdir is enough.
        files = os.listdir(distinfo)
        for fn in files:
            if fn not in ('RECORD', 'INSTALLER', 'SHARED', 'WHEEL'):
                p = fsdecode(os.path.join(distinfo, fn))
                ap = to_posix(os.path.join(info_dir, fn))
                archive_paths.append((ap, p))

        wheel_metadata = [
            'Wheel-Version: %d.%d' % (wheel_version or self.wheel_version),
            'Generator: distlib %s' % __version__,
            'Root-Is-Purelib: %s' % is_pure,
        ]
        for pyver, abi, arch in self.tags:
            wheel_metadata.append('Tag: %s-%s-%s' % (pyver, abi, arch))
        p = os.path.join(distinfo, 'WHEEL')
        with open(p, 'w') as f:
            f.write('\n'.join(wheel_metadata))
        ap = to_posix(os.path.join(info_dir, 'WHEEL'))
        archive_paths.append((ap, p))

        # Now, at last, RECORD.
        # Paths in here are archive paths - nothing else makes sense.
        self.write_records((distinfo, info_dir), libdir, archive_paths)
        # Now, ready to build the zip file
        pathname = os.path.join(self.dirname, self.filename)
        self.build_zip(pathname, archive_paths)
        return pathname

    def skip_entry(self, arcname):
        """
        Determine whether an archive entry should be skipped when verifying
        or installing.
        """
        # The signature file won't be in RECORD,
        # and we  don't currently don't do anything with it
        # We also skip directories, as they won't be in RECORD
        # either. See:
        #
        # https://github.com/pypa/wheel/issues/294
        # https://github.com/pypa/wheel/issues/287
        # https://github.com/pypa/wheel/pull/289
        #
        return arcname.endswith(('/', '/RECORD.jws'))

    def install(self, paths, maker, **kwargs):
        """
        Install a wheel to the specified paths. If kwarg ``warner`` is
        specified, it should be a callable, which will be called with two
        tuples indicating the wheel version of this software and the wheel
        version in the file, if there is a discrepancy in the versions.
        This can be used to issue any warnings to raise any exceptions.
        If kwarg ``lib_only`` is True, only the purelib/platlib files are
        installed, and the headers, scripts, data and dist-info metadata are
        not written. If kwarg ``bytecode_hashed_invalidation`` is True, written
        bytecode will try to use file-hash based invalidation (PEP-552) on
        supported interpreter versions (CPython 2.7+).

        The return value is a :class:`InstalledDistribution` instance unless
        ``options.lib_only`` is True, in which case the return value is ``None``.
        """

        dry_run = maker.dry_run
        warner = kwargs.get('warner')
        lib_only = kwargs.get('lib_only', False)
        bc_hashed_invalidation = kwargs.get('bytecode_hashed_invalidation', False)

        pathname = os.path.join(self.dirname, self.filename)
        name_ver = '%s-%s' % (self.name, self.version)
        data_dir = '%s.data' % name_ver
        info_dir = '%s.dist-info' % name_ver

        metadata_name = posixpath.join(info_dir, METADATA_FILENAME)
        wheel_metadata_name = posixpath.join(info_dir, 'WHEEL')
        record_name = posixpath.join(info_dir, 'RECORD')

        wrapper = codecs.getreader('utf-8')

        with ZipFile(pathname, 'r') as zf:
            with zf.open(wheel_metadata_name) as bwf:
                wf = wrapper(bwf)
                message = message_from_file(wf)
            wv = message['Wheel-Version'].split('.', 1)
            file_version = tuple([int(i) for i in wv])
            if (file_version != self.wheel_version) and warner:
                warner(self.wheel_version, file_version)

            if message['Root-Is-Purelib'] == 'true':
                libdir = paths['purelib']
            else:
                libdir = paths['platlib']

            records = {}
            with zf.open(record_name) as bf:
                with CSVReader(stream=bf) as reader:
                    for row in reader:
                        p = row[0]
                        records[p] = row

            data_pfx = posixpath.join(data_dir, '')
            info_pfx = posixpath.join(info_dir, '')
            script_pfx = posixpath.join(data_dir, 'scripts', '')

            # make a new instance rather than a copy of maker's,
            # as we mutate it
            fileop = FileOperator(dry_run=dry_run)
            fileop.record = True    # so we can rollback if needed

            bc = not sys.dont_write_bytecode    # Double negatives. Lovely!

            outfiles = []   # for RECORD writing

            # for script copying/shebang processing
            workdir = tempfile.mkdtemp()
            # set target dir later
            # we default add_launchers to False, as the
            # Python Launcher should be used instead
            maker.source_dir = workdir
            maker.target_dir = None
            try:
                for zinfo in zf.infolist():
                    arcname = zinfo.filename
                    if isinstance(arcname, text_type):
                        u_arcname = arcname
                    else:
                        u_arcname = arcname.decode('utf-8')
                    if self.skip_entry(u_arcname):
                        continue
                    row = records[u_arcname]
                    if row[2] and str(zinfo.file_size) != row[2]:
                        raise DistlibException('size mismatch for '
                                               '%s' % u_arcname)
                    if row[1]:
                        kind, value = row[1].split('=', 1)
                        with zf.open(arcname) as bf:
                            data = bf.read()
                        _, digest = self.get_hash(data, kind)
                        if digest != value:
                            raise DistlibException('digest mismatch for '
                                                   '%s' % arcname)

                    if lib_only and u_arcname.startswith((info_pfx, data_pfx)):
                        logger.debug('lib_only: skipping %s', u_arcname)
                        continue
                    is_script = (u_arcname.startswith(script_pfx)
                                 and not u_arcname.endswith('.exe'))

                    if u_arcname.startswith(data_pfx):
                        _, where, rp = u_arcname.split('/', 2)
                        outfile = os.path.join(paths[where], convert_path(rp))
                    else:
                        # meant for site-packages.
                        if u_arcname in (wheel_metadata_name, record_name):
                            continue
                        outfile = os.path.join(libdir, convert_path(u_arcname))
                    if not is_script:
                        with zf.open(arcname) as bf:
                            fileop.copy_stream(bf, outfile)
                        outfiles.append(outfile)
                        # Double check the digest of the written file
                        if not dry_run and row[1]:
                            with open(outfile, 'rb') as bf:
                                data = bf.read()
                                _, newdigest = self.get_hash(data, kind)
                                if newdigest != digest:
                                    raise DistlibException('digest mismatch '
                                                           'on write for '
                                                           '%s' % outfile)
                        if bc and outfile.endswith('.py'):
                            try:
                                pyc = fileop.byte_compile(outfile,
                                                          hashed_invalidation=bc_hashed_invalidation)
                                outfiles.append(pyc)
                            except Exception:
                                # Don't give up if byte-compilation fails,
                                # but log it and perhaps warn the user
                                logger.warning('Byte-compilation failed',
                                               exc_info=True)
                    else:
                        fn = os.path.basename(convert_path(arcname))
                        workname = os.path.join(workdir, fn)
                        with zf.open(arcname) as bf:
                            fileop.copy_stream(bf, workname)

                        dn, fn = os.path.split(outfile)
                        maker.target_dir = dn
                        filenames = maker.make(fn)
                        fileop.set_executable_mode(filenames)
                        outfiles.extend(filenames)

                if lib_only:
                    logger.debug('lib_only: returning None')
                    dist = None
                else:
                    # Generate scripts

                    # Try to get pydist.json so we can see if there are
                    # any commands to generate. If this fails (e.g. because
                    # of a legacy wheel), log a warning but don't give up.
                    commands = None
                    file_version = self.info['Wheel-Version']
                    if file_version == '1.0':
                        # Use legacy info
                        ep = posixpath.join(info_dir, 'entry_points.txt')
                        try:
                            with zf.open(ep) as bwf:
                                epdata = read_exports(bwf)
                            commands = {}
                            for key in ('console', 'gui'):
                                k = '%s_scripts' % key
                                if k in epdata:
                                    commands['wrap_%s' % key] = d = {}
                                    for v in epdata[k].values():
                                        s = '%s:%s' % (v.prefix, v.suffix)
                                        if v.flags:
                                            s += ' %s' % v.flags
                                        d[v.name] = s
                        except Exception:
                            logger.warning('Unable to read legacy script '
                                           'metadata, so cannot generate '
                                           'scripts')
                    else:
                        try:
                            with zf.open(metadata_name) as bwf:
                                wf = wrapper(bwf)
                                commands = json.load(wf).get('extensions')
                                if commands:
                                    commands = commands.get('python.commands')
                        except Exception:
                            logger.warning('Unable to read JSON metadata, so '
                                           'cannot generate scripts')
                    if commands:
                        console_scripts = commands.get('wrap_console', {})
                        gui_scripts = commands.get('wrap_gui', {})
                        if console_scripts or gui_scripts:
                            script_dir = paths.get('scripts', '')
                            if not os.path.isdir(script_dir):
                                raise ValueError('Valid script path not '
                                                 'specified')
                            maker.target_dir = script_dir
                            for k, v in console_scripts.items():
                                script = '%s = %s' % (k, v)
                                filenames = maker.make(script)
                                fileop.set_executable_mode(filenames)

                            if gui_scripts:
                                options = {'gui': True }
                                for k, v in gui_scripts.items():
                                    script = '%s = %s' % (k, v)
                                    filenames = maker.make(script, options)
                                    fileop.set_executable_mode(filenames)

                    p = os.path.join(libdir, info_dir)
                    dist = InstalledDistribution(p)

                    # Write SHARED
                    paths = dict(paths)     # don't change passed in dict
                    del paths['purelib']
                    del paths['platlib']
                    paths['lib'] = libdir
                    p = dist.write_shared_locations(paths, dry_run)
                    if p:
                        outfiles.append(p)

                    # Write RECORD
                    dist.write_installed_files(outfiles, paths['prefix'],
                                               dry_run)
                return dist
            except Exception:  # pragma: no cover
                logger.exception('installation failed.')
                fileop.rollback()
                raise
            finally:
                shutil.rmtree(workdir)

    def _get_dylib_cache(self):
        global cache
        if cache is None:
            # Use native string to avoid issues on 2.x: see Python #20140.
            base = os.path.join(get_cache_base(), str('dylib-cache'),
                                sys.version[:3])
            cache = Cache(base)
        return cache

    def _get_extensions(self):
        pathname = os.path.join(self.dirname, self.filename)
        name_ver = '%s-%s' % (self.name, self.version)
        info_dir = '%s.dist-info' % name_ver
        arcname = posixpath.join(info_dir, 'EXTENSIONS')
        wrapper = codecs.getreader('utf-8')
        result = []
        with ZipFile(pathname, 'r') as zf:
            try:
                with zf.open(arcname) as bf:
                    wf = wrapper(bf)
                    extensions = json.load(wf)
                    cache = self._get_dylib_cache()
                    prefix = cache.prefix_to_dir(pathname)
                    cache_base = os.path.join(cache.base, prefix)
                    if not os.path.isdir(cache_base):
                        os.makedirs(cache_base)
                    for name, relpath in extensions.items():
                        dest = os.path.join(cache_base, convert_path(relpath))
                        if not os.path.exists(dest):
                            extract = True
                        else:
                            file_time = os.stat(dest).st_mtime
                            file_time = datetime.datetime.fromtimestamp(file_time)
                            info = zf.getinfo(relpath)
                            wheel_time = datetime.datetime(*info.date_time)
                            extract = wheel_time > file_time
                        if extract:
                            zf.extract(relpath, cache_base)
                        result.append((name, dest))
            except KeyError:
                pass
        return result

    def is_compatible(self):
        """
        Determine if a wheel is compatible with the running system.
        """
        return is_compatible(self)

    def is_mountable(self):
        """
        Determine if a wheel is asserted as mountable by its metadata.
        """
        return True # for now - metadata details TBD

    def mount(self, append=False):
        pathname = os.path.abspath(os.path.join(self.dirname, self.filename))
        if not self.is_compatible():
            msg = 'Wheel %s not compatible with this Python.' % pathname
            raise DistlibException(msg)
        if not self.is_mountable():
            msg = 'Wheel %s is marked as not mountable.' % pathname
            raise DistlibException(msg)
        if pathname in sys.path:
            logger.debug('%s already in path', pathname)
        else:
            if append:
                sys.path.append(pathname)
            else:
                sys.path.insert(0, pathname)
            extensions = self._get_extensions()
            if extensions:
                if _hook not in sys.meta_path:
                    sys.meta_path.append(_hook)
                _hook.add(pathname, extensions)

    def unmount(self):
        pathname = os.path.abspath(os.path.join(self.dirname, self.filename))
        if pathname not in sys.path:
            logger.debug('%s not in path', pathname)
        else:
            sys.path.remove(pathname)
            if pathname in _hook.impure_wheels:
                _hook.remove(pathname)
            if not _hook.impure_wheels:
                if _hook in sys.meta_path:
                    sys.meta_path.remove(_hook)

    def verify(self):
        pathname = os.path.join(self.dirname, self.filename)
        name_ver = '%s-%s' % (self.name, self.version)
        data_dir = '%s.data' % name_ver
        info_dir = '%s.dist-info' % name_ver

        metadata_name = posixpath.join(info_dir, METADATA_FILENAME)
        wheel_metadata_name = posixpath.join(info_dir, 'WHEEL')
        record_name = posixpath.join(info_dir, 'RECORD')

        wrapper = codecs.getreader('utf-8')

        with ZipFile(pathname, 'r') as zf:
            with zf.open(wheel_metadata_name) as bwf:
                wf = wrapper(bwf)
                message = message_from_file(wf)
            wv = message['Wheel-Version'].split('.', 1)
            file_version = tuple([int(i) for i in wv])
            # TODO version verification

            records = {}
            with zf.open(record_name) as bf:
                with CSVReader(stream=bf) as reader:
                    for row in reader:
                        p = row[0]
                        records[p] = row

            for zinfo in zf.infolist():
                arcname = zinfo.filename
                if isinstance(arcname, text_type):
                    u_arcname = arcname
                else:
                    u_arcname = arcname.decode('utf-8')
                # See issue #115: some wheels have .. in their entries, but
                # in the filename ... e.g. __main__..py ! So the check is
                # updated to look for .. in the directory portions
                p = u_arcname.split('/')
                if '..' in p:
                    raise DistlibException('invalid entry in '
                                           'wheel: %r' % u_arcname)

                if self.skip_entry(u_arcname):
                    continue
                row = records[u_arcname]
                if row[2] and str(zinfo.file_size) != row[2]:
                    raise DistlibException('size mismatch for '
                                           '%s' % u_arcname)
                if row[1]:
                    kind, value = row[1].split('=', 1)
                    with zf.open(arcname) as bf:
                        data = bf.read()
                    _, digest = self.get_hash(data, kind)
                    if digest != value:
                        raise DistlibException('digest mismatch for '
                                               '%s' % arcname)

    def update(self, modifier, dest_dir=None, **kwargs):
        """
        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.
        """

        def get_version(path_map, info_dir):
            version = path = None
            key = '%s/%s' % (info_dir, METADATA_FILENAME)
            if key not in path_map:
                key = '%s/PKG-INFO' % info_dir
            if key in path_map:
                path = path_map[key]
                version = Metadata(path=path).version
            return version, path

        def update_version(version, path):
            updated = None
            try:
                v = NormalizedVersion(version)
                i = version.find('-')
                if i < 0:
                    updated = '%s+1' % version
                else:
                    parts = [int(s) for s in version[i + 1:].split('.')]
                    parts[-1] += 1
                    updated = '%s+%s' % (version[:i],
                                         '.'.join(str(i) for i in parts))
            except UnsupportedVersionError:
                logger.debug('Cannot update non-compliant (PEP-440) '
                             'version %r', version)
            if updated:
                md = Metadata(path=path)
                md.version = updated
                legacy = not path.endswith(METADATA_FILENAME)
                md.write(path=path, legacy=legacy)
                logger.debug('Version updated from %r to %r', version,
                             updated)

        pathname = os.path.join(self.dirname, self.filename)
        name_ver = '%s-%s' % (self.name, self.version)
        info_dir = '%s.dist-info' % name_ver
        record_name = posixpath.join(info_dir, 'RECORD')
        with tempdir() as workdir:
            with ZipFile(pathname, 'r') as zf:
                path_map = {}
                for zinfo in zf.infolist():
                    arcname = zinfo.filename
                    if isinstance(arcname, text_type):
                        u_arcname = arcname
                    else:
                        u_arcname = arcname.decode('utf-8')
                    if u_arcname == record_name:
                        continue
                    if '..' in u_arcname:
                        raise DistlibException('invalid entry in '
                                               'wheel: %r' % u_arcname)
                    zf.extract(zinfo, workdir)
                    path = os.path.join(workdir, convert_path(u_arcname))
                    path_map[u_arcname] = path

            # Remember the version.
            original_version, _ = get_version(path_map, info_dir)
            # Files extracted. Call the modifier.
            modified = modifier(path_map, **kwargs)
            if modified:
                # Something changed - need to build a new wheel.
                current_version, path = get_version(path_map, info_dir)
                if current_version and (current_version == original_version):
                    # Add or update local version to signify changes.
                    update_version(current_version, path)
                # Decide where the new wheel goes.
                if dest_dir is None:
                    fd, newpath = tempfile.mkstemp(suffix='.whl',
                                                   prefix='wheel-update-',
                                                   dir=workdir)
                    os.close(fd)
                else:
                    if not os.path.isdir(dest_dir):
                        raise DistlibException('Not a directory: %r' % dest_dir)
                    newpath = os.path.join(dest_dir, self.filename)
                archive_paths = list(path_map.items())
                distinfo = os.path.join(workdir, info_dir)
                info = distinfo, info_dir
                self.write_records(info, workdir, archive_paths)
                self.build_zip(newpath, archive_paths)
                if dest_dir is None:
                    shutil.copyfile(newpath, pathname)
        return modified

def compatible_tags():
    """
    Return (pyver, abi, arch) tuples compatible with this Python.
    """
    versions = [VER_SUFFIX]
    major = VER_SUFFIX[0]
    for minor in range(sys.version_info[1] - 1, - 1, -1):
        versions.append(''.join([major, str(minor)]))

    abis = []
    for suffix, _, _ in imp.get_suffixes():
        if suffix.startswith('.abi'):
            abis.append(suffix.split('.', 2)[1])
    abis.sort()
    if ABI != 'none':
        abis.insert(0, ABI)
    abis.append('none')
    result = []

    arches = [ARCH]
    if sys.platform == 'darwin':
        m = re.match(r'(\w+)_(\d+)_(\d+)_(\w+)$', ARCH)
        if m:
            name, major, minor, arch = m.groups()
            minor = int(minor)
            matches = [arch]
            if arch in ('i386', 'ppc'):
                matches.append('fat')
            if arch in ('i386', 'ppc', 'x86_64'):
                matches.append('fat3')
            if arch in ('ppc64', 'x86_64'):
                matches.append('fat64')
            if arch in ('i386', 'x86_64'):
                matches.append('intel')
            if arch in ('i386', 'x86_64', 'intel', 'ppc', 'ppc64'):
                matches.append('universal')
            while minor >= 0:
                for match in matches:
                    s = '%s_%s_%s_%s' % (name, major, minor, match)
                    if s != ARCH:   # already there
                        arches.append(s)
                minor -= 1

    # Most specific - our Python version, ABI and arch
    for abi in abis:
        for arch in arches:
            result.append((''.join((IMP_PREFIX, versions[0])), abi, arch))

    # where no ABI / arch dependency, but IMP_PREFIX dependency
    for i, version in enumerate(versions):
        result.append((''.join((IMP_PREFIX, version)), 'none', 'any'))
        if i == 0:
            result.append((''.join((IMP_PREFIX, version[0])), 'none', 'any'))

    # no IMP_PREFIX, ABI or arch dependency
    for i, version in enumerate(versions):
        result.append((''.join(('py', version)), 'none', 'any'))
        if i == 0:
            result.append((''.join(('py', version[0])), 'none', 'any'))
    return set(result)


COMPATIBLE_TAGS = compatible_tags()

del compatible_tags


def is_compatible(wheel, tags=None):
    if not isinstance(wheel, Wheel):
        wheel = Wheel(wheel)    # assume it's a filename
    result = False
    if tags is None:
        tags = COMPATIBLE_TAGS
    for ver, abi, arch in tags:
        if ver in wheel.pyver and abi in wheel.abi and arch in wheel.arch:
            result = True
            break
    return result
PKÔ¶N]8ù^0KK-site-packages/pip/_vendor/distlib/__init__.pynu„[µü¤# -*- coding: utf-8 -*-
#
# Copyright (C) 2012-2019 Vinay Sajip.
# Licensed to the Python Software Foundation under a contributor agreement.
# See LICENSE.txt and CONTRIBUTORS.txt.
#
import logging

__version__ = '0.2.9.post0'

class DistlibException(Exception):
    pass

try:
    from logging import NullHandler
except ImportError: # pragma: no cover
    class NullHandler(logging.Handler):
        def handle(self, record): pass
        def emit(self, record): pass
        def createLock(self): self.lock = None

logger = logging.getLogger(__name__)
logger.addHandler(NullHandler())
PKÔ¶N]+‰üZ­g­gKsite-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.e*�ã@sdZddlmZddlZddlmZddlZddlZddlZddl	m
Z
mZddlm
Z
mZmZddlmZdd	lmZmZdd
lmZmZe e¡ZGdd„de
ƒZGd
d„de
ƒZGdd„de
ƒZGdd„de
ƒZdddgZdZ dZ!e "d¡Z#e "d¡Z$dZ%dZ&dZ'dZ(dZ)dZ*d Z+e*d!Z,d"Z-e.ƒZ/e/ 0e%¡e/ 0e&¡e/ 0e(¡e/ 0e*¡e/ 0e,¡e "d#¡Z1d$d%„Z2d&d'„Z3d(d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7d8d9d:d;dd?d@dAdBdCdDdEdFœZ4dGZ5dHZ6dIZ7dJZ8dKZ9dLZ:dMZ;e<ƒZ=e "dN¡Z>dXdPdQ„Z?GdRdS„dSe<ƒZ@dTZAdUZBdVZCGdWd„de<ƒZDdS)YzImplementation of the Metadata for Python packages PEPs.

Supports all metadata formats (1.0, 1.1, 1.2, and 2.0 experimental).
é)Úunicode_literalsN)Úmessage_from_fileé)ÚDistlibExceptionÚ__version__)ÚStringIOÚstring_typesÚ	text_type)Ú	interpret)Úextract_by_keyÚ
get_extras)Ú
get_schemeÚPEP440_VERSION_REc@seZdZdZdS)ÚMetadataMissingErrorzA required metadata is missingN©Ú__name__Ú
__module__Ú__qualname__Ú__doc__©rrú@/usr/lib/python3.8/site-packages/pip/_vendor/distlib/metadata.pyrsrc@seZdZdZdS)ÚMetadataConflictErrorz>Attempt to read or write metadata fields that are conflictual.Nrrrrrr src@seZdZdZdS)Ú MetadataUnrecognizedVersionErrorz Unknown metadata version number.Nrrrrrr$src@seZdZdZdS)ÚMetadataInvalidErrorzA metadata value is invalidNrrrrrr(srÚMetadataÚPKG_INFO_ENCODINGÚPKG_INFO_PREFERRED_VERSIONúutf-8ú1.1z

       \|ú	
        )úMetadata-VersionÚNameÚVersionÚPlatformÚSummaryÚDescriptionÚKeywordsú	Home-pageÚAuthorúAuthor-emailÚLicense)r r!r"r#úSupported-Platformr$r%r&r'r(r)r*Ú
ClassifierúDownload-URLÚ	ObsoletesÚProvidesÚRequires)r.r/r0r,r-)r r!r"r#r+r$r%r&r'r(r)Ú
MaintainerúMaintainer-emailr*r,r-úObsoletes-DistúProject-URLú
Provides-Distú
Requires-DistúRequires-PythonúRequires-External)r5r6r7r3r8r1r2r4)r r!r"r#r+r$r%r&r'r(r)r1r2r*r,r-r3r4r5r6r7r8úPrivate-VersionúObsoleted-ByúSetup-Requires-DistÚ	ExtensionúProvides-Extra)r9r=r:r;r<)úDescription-Content-Typer0r/)r>z"extra\s*==\s*("([^"]+)"|'([^']+)')cCsL|dkrtS|dkrtS|dkr$tS|dkr4ttS|dkr@tSt|ƒ‚dS)Nú1.0rú1.2)ú1.3ú2.1ú2.0)Ú_241_FIELDSÚ_314_FIELDSÚ_345_FIELDSÚ_566_FIELDSÚ_426_FIELDSr)ÚversionrrrÚ_version2fieldlistpsrJc
CsBdd„}g}| ¡D]"\}}|gddfkr,q| |¡qddddd	d
g}|D]ö}|tkrvd|krv| d¡t d|¡|tkrœd|krœ| d¡t d|¡|tkrÂd|krÂ| d¡t d
|¡|tkrèd|krè| d¡t d|¡|tk�rd
|k�r|dk�r| d
¡t d|¡|t	krLd	|krL| d	¡t d|¡qLt
|ƒdk�rZ|dSt
|ƒdk�r|t d|¡tdƒ‚d|k�oŽ||tƒ}d|k�o¢||t
ƒ}d
|k�o¶||tƒ}d	|k�oÊ||tƒ}	t|ƒt|ƒt|ƒt|	ƒdk�rútdƒ‚|�s |�s |�s |	�s t|k�r tS|�r*dS|�r4dS|�r>d
Sd	S)z5Detect the best version depending on the fields used.cSs|D]}||krdSqdS)NTFr)ÚkeysÚmarkersÚmarkerrrrÚ_has_marker€sz"_best_version.._has_markerÚUNKNOWNNr?rr@rArCrBzRemoved 1.0 due to %szRemoved 1.1 due to %szRemoved 1.2 due to %szRemoved 1.3 due to %sr%zRemoved 2.1 due to %szRemoved 2.0 due to %srrz)Out of options - unknown metadata set: %szUnknown metadata setz,You used incompatible 1.1/1.2/2.0/2.1 fields)ÚitemsÚappendrDÚremoveÚloggerÚdebugrErFrGrHÚlenrÚ_314_MARKERSÚ_345_MARKERSÚ_566_MARKERSÚ_426_MARKERSÚintr)
ÚfieldsrNrKÚkeyÚvalueZpossible_versionsZis_1_1Zis_1_2Zis_2_1Zis_2_0rrrÚ
_best_version~s`






&
r^r r!r"r#r+r$r%r&r'r(r)r1r2r*r,r-r3r5r6r;r7r8r0r/r.r4r9r:r<r=)Úmetadata_versionÚnamerIÚplatformZsupported_platformÚsummaryÚdescriptionÚkeywordsÚ	home_pageÚauthorÚauthor_emailÚ
maintainerÚmaintainer_emailÚlicenseÚ
classifierÚdownload_urlÚobsoletes_distÚ
provides_distÚ
requires_distÚsetup_requires_distÚrequires_pythonÚrequires_externalÚrequiresÚprovidesÚ	obsoletesÚproject_urlZprivate_versionZobsoleted_byÚ	extensionZprovides_extra)r6r3r5)r7)r")r#r,r.r0r/r3r5r6r8r4r+r;r=r<)r4)r&)r(r1r$r%z[^A-Za-z0-9.]+FcCs0|r$t d|¡}t d| dd¡¡}d||fS)zhReturn the distribution name with version.

    If for_filename is true, return a filename-escaped form.ú-ú Ú.z%s-%s)Ú	_FILESAFEÚsubÚreplace)r`rIZfor_filenamerrrÚ_get_name_and_versionùsr~c@s
eZdZdZd?dd„Zdd„Zdd	„Zd
d„Zdd
„Zdd„Z	dd„Z
dd„Zdd„Zdd„Z
dd„Zd@dd„Zdd„Zdd „Zd!d"„Zd#d$„ZdAd%d&„ZdBd'd(„ZdCd)d*„Zd+d,„Zefd-d.„ZdDd/d0„ZdEd1d2„Zd3d4„Zd5d6„Zd7d8„Zd9d:„Zd;d<„Z d=d>„Z!dS)FÚLegacyMetadataaaThe legacy metadata of a release.

    Supports versions 1.0, 1.1 and 1.2 (auto-detected). You can
    instantiate the class with one of these arguments (or none):
    - *path*, the path to a metadata file
    - *fileobj* give a file-like object with metadata as content
    - *mapping* is a dict-like object
    - *scheme* is a version scheme name
    NÚdefaultcCsz|||g d¡dkrtdƒ‚i|_g|_d|_||_|dk	rH| |¡n.|dk	r\| |¡n|dk	rv| |¡| 	¡dS)Néú'path, fileobj and mapping are exclusive)
ÚcountÚ	TypeErrorÚ_fieldsZrequires_filesZ
_dependenciesÚschemeÚreadÚ	read_fileÚupdateÚset_metadata_version)ÚselfÚpathÚfileobjÚmappingr†rrrÚ__init__s
zLegacyMetadata.__init__cCst|jƒ|jd<dS©Nr )r^r…©r‹rrrrŠ"sz#LegacyMetadata.set_metadata_versioncCs| d||f¡dS)Nz%s: %s
)Úwrite)r‹r�r`r]rrrÚ_write_field%szLegacyMetadata._write_fieldcCs
| |¡S©N)Úget©r‹r`rrrÚ__getitem__(szLegacyMetadata.__getitem__cCs| ||¡Sr”)Úset)r‹r`r]rrrÚ__setitem__+szLegacyMetadata.__setitem__cCs8| |¡}z|j|=Wntk
r2t|ƒ‚YnXdSr”)Ú
_convert_namer…ÚKeyError)r‹r`Ú
field_namerrrÚ__delitem__.s

zLegacyMetadata.__delitem__cCs||jkp| |¡|jkSr”)r…ršr–rrrÚ__contains__5s
ÿzLegacyMetadata.__contains__cCs(|tkr|S| dd¡ ¡}t ||¡S)NrxÚ_)Ú_ALL_FIELDSr}ÚlowerÚ_ATTR2FIELDr•r–rrrrš9szLegacyMetadata._convert_namecCs|tks|tkrgSdS)NrO)Ú_LISTFIELDSÚ_ELEMENTSFIELDr–rrrÚ_default_value?szLegacyMetadata._default_valuecCs&|jdkrt d|¡St d|¡SdS)N©r?rÚ
)r_Ú_LINE_PREFIX_PRE_1_2r|Ú_LINE_PREFIX_1_2©r‹r]rrrÚ_remove_line_prefixDs
z"LegacyMetadata._remove_line_prefixcCs|tkr||St|ƒ‚dSr”)r¢ÚAttributeErrorr–rrrÚ__getattr__JszLegacyMetadata.__getattr__FcCst|d|d|ƒS)zhReturn the distribution name with version.

        If filesafe is true, return a filename-escaped form.r!r")r~)r‹ZfilesaferrrÚget_fullnameUszLegacyMetadata.get_fullnamecCs| |¡}|tkS)z+return True if name is a valid metadata key)ršr r–rrrÚis_field[s
zLegacyMetadata.is_fieldcCs| |¡}|tkSr”)ršr£r–rrrÚis_multi_field`s
zLegacyMetadata.is_multi_fieldcCs.tj|ddd�}z| |¡W5| ¡XdS)z*Read the metadata values from a file path.Úrr©ÚencodingN)ÚcodecsÚopenÚcloserˆ)r‹ÚfilepathÚfprrrr‡dszLegacyMetadata.readcCs�t|ƒ}|d|jd<tD]p}||kr(q|tkrf| |¡}|tkrX|dk	rXdd„|Dƒ}| ||¡q||}|dk	r|dkr| ||¡qdS)z,Read the metadata values from a file object.zmetadata-versionr NcSsg|]}t| d¡ƒ‘qS©ú,)ÚtupleÚsplit©Ú.0r]rrrÚ
ysz,LegacyMetadata.read_file..rO)rr…r r£Zget_allÚ_LISTTUPLEFIELDSr˜)r‹ZfileobÚmsgÚfieldÚvaluesr]rrrrˆls
zLegacyMetadata.read_filecCs0tj|ddd�}z| ||¡W5| ¡XdS)z&Write the metadata fields to filepath.Úwrr²N)r´rµr¶Ú
write_file)r‹r·Úskip_unknownr¸rrrr’ƒszLegacyMetadata.writecCsÄ| ¡t|dƒD]ª}| |¡}|r8|dgdgfkr8q|tkrV| ||d |¡¡q|tkr�|dkrŠ|jdkr~| dd¡}n| dd¡}|g}|t	kr¦d	d
„|Dƒ}|D]}| |||¡qªqdS)z0Write the PKG-INFO format data to a file object.r rOrºr%r¦r§rz	
       |cSsg|]}d |¡‘qSr¹©Újoinr½rrrr¿Ÿsz-LegacyMetadata.write_file..N)
rŠrJr•r¤r“rÈr£r_r}rÀ)r‹Z
fileobjectrÆrÂrÃr]rrrrÅ‹s$

zLegacyMetadata.write_filecsv‡fdd„}|sn@t|dƒr:| ¡D]}||||ƒq$n|D]\}}|||ƒq>|rr| ¡D]\}}|||ƒq^dS)a…Set metadata values from the given iterable `other` and kwargs.

        Behavior is like `dict.update`: If `other` has a ``keys`` method,
        they are looped over and ``self[key]`` is assigned ``other[key]``.
        Else, ``other`` is an iterable of ``(key, value)`` iterables.

        Keys that don't match a metadata field or that have an empty value are
        dropped.
        cs"|tkr|rˆ ˆ |¡|¡dSr”)r¢r˜rš)r\r]r‘rrÚ_set®sz#LegacyMetadata.update.._setrKN)ÚhasattrrKrP)r‹ÚotherÚkwargsrÉÚkÚvrr‘rr‰¤s

zLegacyMetadata.updatecCsh| |¡}|tks|dkrNt|ttfƒsNt|tƒrHdd„| d¡Dƒ}qzg}n,|tkrzt|ttfƒszt|tƒrv|g}ng}t 	t
j¡�r<|d}t|j
ƒ}|tkrÚ|dk	rÚ|D](}| | d¡d¡s®t d	|||¡q®nb|tk�r|dk	�r| |¡�s.rºr!Nú;rz$'%s': '%s' is not valid (field '%s')z.'%s': '%s' is not a valid version (field '%s')r%)ršr¤Ú
isinstanceÚlistr»rr¼r£rSZisEnabledForÚloggingZWARNINGr
r†Ú_PREDICATE_FIELDSÚis_valid_matcherÚwarningÚ_VERSIONS_FIELDSÚis_valid_constraint_listÚ_VERSION_FIELDSÚis_valid_versionÚ_UNICODEFIELDSr«r…)r‹r`r]Zproject_namer†rÎrrrr˜ÀsV
ÿ
ÿ

þÿÿ


zLegacyMetadata.setcCsÊ| |¡}||jkr*|tkr&| |¡}|S|tkr@|j|}|S|tkrš|j|}|dkr^gSg}|D].}|tkr~| |¡qf| |d|df¡qf|S|tkrÀ|j|}t	|t
ƒrÀ| d¡S|j|S)zGet a metadata field.Nrrrº)ršr…Ú_MISSINGr¥rÛr£rÀrQr¤rÑrr¼)r‹r`r€r]ÚresÚvalrrrr•ìs.







zLegacyMetadata.getcsú| ¡gg}}dD]}||kr| |¡q|rP|gkrPdd |¡}t|ƒ‚dD]}||krT| |¡qT|ddkr€||fSt|jƒ‰‡fdd„}t|ftˆjft	ˆj
ffD]@\}}|D]2}	| |	d	¡}
|
d	k	r¼||
ƒs¼| d
|	|
f¡q¼q°||fS)zkCheck if the metadata is compliant. If strict is True then raise if
        no Name or Version are provided)r!r"zmissing required metadata: %sú, )r'r(r r@cs(|D]}ˆ | d¡d¡sdSqdS)NrÐrFT)rÕr¼)r]rΩr†rrÚare_valid_constraints#sz3LegacyMetadata.check..are_valid_constraintsNzWrong value for '%s': %s)rŠrQrÈrr
r†rÔr×rØrÙrÚr•)r‹ÚstrictÚmissingÚwarningsÚattrrÁrár[Z
controllerrÂr]rràrÚcheck	s8

ÿÿýzLegacyMetadata.checkcCsÎ| ¡d}i}|D]"\}}|r*||jkr||||<q|ddkr’d}|D]B\}}|rb||jkrL|dkrx||||<qLdd„||Dƒ||<qLn8|ddkrÊd	}|D]"\}}|r¼||jkr¦||||<q¦|S)
zºReturn fields as a dict.

        Field names will be converted to use the underscore-lowercase style
        instead of hyphen-mixed case (i.e. home_page instead of Home-page).
        )
)r_r )r`r!)rIr")rbr$)rer')rfr()rgr))rjr*)rcr%)rdr&)rar#)Úclassifiersr,)rlr-r r@))ror6)rqr7)rrr8)rnr5)rmr3)rvr4)rhr1)rir2rvcSsg|]}d |¡‘qSr¹rÇ)r¾Úurrrr¿bsz)LegacyMetadata.todict..r))rtr/)rsr0)rur.)rŠr…)r‹Zskip_missingZmapping_1_0Údatar\rœZmapping_1_2Zmapping_1_1rrrÚtodict5s&
zLegacyMetadata.todictcCs8|ddkr$dD]}||kr||=q|d|7<dS)Nr r)r.r0r/r6r)r‹ÚrequirementsrÂrrrÚadd_requirementsps
zLegacyMetadata.add_requirementscCstt|dƒƒSr�)rÒrJr‘rrrrK{szLegacyMetadata.keysccs| ¡D]
}|VqdSr”©rK)r‹r\rrrÚ__iter__~szLegacyMetadata.__iter__cs‡fdd„ˆ ¡DƒS)Ncsg|]}ˆ|‘qSrr©r¾r\r‘rrr¿ƒsz)LegacyMetadata.values..rír‘rr‘rrÂszLegacyMetadata.valuescs‡fdd„ˆ ¡DƒS)Ncsg|]}|ˆ|f‘qSrrrïr‘rrr¿†sz(LegacyMetadata.items..rír‘rr‘rrP…szLegacyMetadata.itemscCsd|jj|j|jfS)Nz
<%s %s %s>)Ú	__class__rr`rIr‘rrrÚ__repr__ˆsÿzLegacyMetadata.__repr__)NNNr€)F)F)F)N)F)F)"rrrrr�rŠr“r—r™r�ržršr¥r«r­r®r¯r°r‡rˆr’rÅr‰r˜rÜr•rærêrìrKrîrÃrPrñrrrrrs@ÿ




,
,
;rzpydist.jsonz
metadata.jsonZMETADATAc@s’eZdZdZe d¡Ze dej¡Ze	Z
e d¡ZdZde
Zdddd	œZd
ZdZedfedfe
dfedfdœZd
ZdDdd„ZedƒZdefZdefZdefdefeeedefeeeedefdddœ
Z[[dd„ZdEdd„Zdd„Zed d!„ƒZ ed"d#„ƒZ!e!j"d$d#„ƒZ!dFd%d&„Z#ed'd(„ƒZ$ed)d*„ƒZ%e%j"d+d*„ƒZ%d,d-„Z&d.d/„Z'd0d1„Z(d2d3„Z)d4d5d6d7d8dd9œZ*d:d;„Z+dGd>d?„Z,d@dA„Z-dBdC„Z.dS)HrzÊ
    The metadata of a release. This implementation uses 2.0 (JSON)
    metadata where possible. If not possible, it wraps a LegacyMetadata
    instance which handles the key-value metadata format.
    z
^\d+(\.\d+)*$z!^[0-9A-Z]([0-9A-Z_.-]*[0-9A-Z])?$z	.{1,2047}rCzdistlib (%s)r)Úlegacy)r`rIrbzqname version license summary description author author_email keywords platform home_page classifiers download_urlzwextras run_requires test_requires build_requires dev_requires provides meta_requires obsoleted_by supports_environments)r_r`rIrb)Ú_legacyÚ_datar†Nr€c	Cs0|||g d¡dkrtdƒ‚d|_d|_||_|dk	rzz| ||¡||_Wn*tk
rvt||d�|_| ¡YnXn²d}|r¢t	|dƒ�}| 
¡}W5QRXn|r®| 
¡}|dkrÈ|j|jdœ|_ndt
|tƒsÜ| d¡}zt |¡|_| |j|¡Wn0tk
�r*tt|ƒ|d�|_| ¡YnXdS)Nr�r‚)rŽr†Úrb©r_Ú	generatorr)r�r†)rƒr„rórôr†Ú_validate_mappingrrÚvalidaterµr‡ÚMETADATA_VERSIONÚ	GENERATORrÑr	ÚdecodeÚjsonÚloadsÚ
ValueErrorr)r‹rŒr�rŽr†réÚfrrrr�¼s@
þ


ÿzMetadata.__init__)r`rIrjrdrbr6r;r=r,)r-N)r N)
Úrun_requiresÚbuild_requiresÚdev_requiresZ
test_requiresÚ
meta_requiresÚextrasÚmodulesÚ
namespacesÚexportsÚcommandsrçZ
source_urlr_c
CsXt |d¡}t |d¡}||k�r||\}}|jr^|dkrP|dkrHdn|ƒ}n|j |¡}nº|dkrjdn|ƒ}|dkrˆ|j ||¡}n�tƒ}|}|j d¡}	|	�r
|dkrº|	 d|¡}nP|dkrÞ|	 d¡}	|	rÜ|	 ||¡}n,|	 d	¡}	|	sø|j d	¡}	|	�r
|	 ||¡}||k�rT|}n:||k�r2t ||¡}n"|j�rH|j |¡}n|j |¡}|S)
NÚcommon_keysÚmapped_keys©r	rrrrçÚ
extensionsr	úpython.commandsrçúpython.detailsúpython.exports)ÚobjectÚ__getattribute__rór•rô)
r‹r\ÚcommonÚmappedÚlkZmakerÚresultr]ÚsentinelÚdrrrrsD




zMetadata.__getattribute__cCsH||jkrD|j|\}}|p |j|krD| |¡}|sDtd||fƒ‚dS)Nz.'%s' is an invalid value for the '%s' property)ÚSYNTAX_VALIDATORSr†Úmatchr)r‹r\r]r†ÚpatternÚ
exclusionsÚmrrrÚ_validate_value+s

ÿÿzMetadata._validate_valuecCs*| ||¡t |d¡}t |d¡}||kr¾||\}}|jrV|dkrJt‚||j|<nf|dkrj||j|<nR|j di¡}|dkrŠ||d<n2|dkr¨| di¡}|||<n| d	i¡}|||<nh||krÖt |||¡nP|d
k�rt|t	ƒ�r| 
¡}|�r| ¡}ng}|j�r||j|<n
||j|<dS)Nr
rrr
r	rrçrrrd)rrrróÚNotImplementedErrorrôÚ
setdefaultÚ__setattr__rÑrrÏr¼)r‹r\r]rrrrŸrrrrr!5s<




zMetadata.__setattr__cCst|j|jdƒS©NT)r~r`rIr‘rrrÚname_and_version\szMetadata.name_and_versioncCsF|jr|jd}n|j dg¡}d|j|jf}||krB| |¡|S)Nr5rtz%s (%s))rórôr r`rIrQ)r‹rÚsrrrrt`s
zMetadata.providescCs |jr||jd<n
||jd<dS)Nr5rt)rórôrªrrrrtksc
CsÚ|jr|}nÊg}t|pg|jƒ}|D]d}d|kr>d|kr>d}n8d|krLd}n| d¡|k}|rv| d¡}|rvt||ƒ}|r$| |d¡q$dD]F}d|}	|	|krŽ| |	¡|j d|g¡}| |j|||d�¡qŽ|S)	a‹
        Base method to get dependencies, given a set of extras
        to satisfy and an optional environment context.
        :param reqts: A list of sometimes-wanted dependencies,
                      perhaps dependent on extras and environment.
        :param extras: A list of optional components being requested.
        :param env: An optional environment for marker evaluation.
        ÚextraÚenvironmentTrs)ZbuildZdevZtestz:%s:z%s_requires)rÚenv)	rórrr•r
ÚextendrRrôÚget_requirements)
r‹Úreqtsrr'rrZincluderMr\Úerrrr)rs2	


ÿ
zMetadata.get_requirementscCs|jr| ¡S|jSr”)róÚ_from_legacyrôr‘rrrÚ
dictionaryœszMetadata.dictionarycCs|jrt‚nt|j|jƒSdSr”)rórrrôÚDEPENDENCY_KEYSr‘rrrÚdependencies¢szMetadata.dependenciescCs|jrt‚n|j |¡dSr”)rórrôr‰rªrrrr/©sc	Cs†| d¡|jkrtƒ‚g}|j ¡D]"\}}||kr$||kr$| |¡q$|rbdd |¡}t|ƒ‚| ¡D]\}}| |||¡qjdS)Nr_zMissing metadata items: %srß)	r•rúrÚMANDATORY_KEYSrPrQrÈrr)	r‹rŽr†rãr\rrÁrÍrÎrrrrø°szMetadata._validate_mappingcCsB|jr.|j d¡\}}|s|r>t d||¡n| |j|j¡dS)NTz#Metadata: missing: %s, warnings: %s)rórærSrÖrørôr†)r‹rãrärrrrù¾sÿzMetadata.validatecCs(|jr|j d¡St|j|jƒ}|SdSr")rórêrrôÚ
INDEX_KEYS)r‹rrrrrêÇszMetadata.todictc
Cs¶|j|jdœ}|j d¡}dD]*}||kr|dkr8d}n|}||||<q| dg¡}|dgkrdg}||d<d	}|D]*\}}||krt||rtd
||ig||<qt|j|d<i}i}	|S)NröT)r`rIrjrbrcrkrkrçr&Úrd))ror)rprrsrt)rúrûrórêr•rt)
r‹rZlmdrÍÚnkÚkwrKÚokrfrhrrrr,Îs,þ

zMetadata._from_legacyr!r"r*r$r%)r`rIrjrbrcrçcCsŒdd„}tƒ}|j}|j ¡D]\}}||kr||||<q||j|jƒ}||j|jƒ}|jrpt	|jƒ|d<t	|ƒ|d<t	|ƒ|d<|S)NcSsŒtƒ}|D]|}| d¡}| d¡}|d}|D]V}|sF|sF| |¡q.d}|rVd|}|rp|rld||f}n|}| d ||f¡¡q.q
|S)Nr%r&rsr2z
extra == "%s"z(%s) and %srÐ)r˜r•ÚaddrÈ)Úentriesr*r+r%r'Zrlistr±rMrrrÚprocess_entriesõs"

z,Metadata._to_legacy..process_entriesr=r6r;)
rrôÚLEGACY_MAPPINGrPrrrrrÚsorted)r‹r8rZnmdr3r5Zr1Zr2rrrÚ
_to_legacyôszMetadata._to_legacyFTc	CsÂ||g d¡dkrtdƒ‚| ¡|r`|jr4|j}n| ¡}|rP|j||d�q¾|j||d�n^|jrp| ¡}n|j}|r�t	j
||dddd�n.t |dd¡�}t	j
||dddd�W5QRXdS)	Nrz)Exactly one of path and fileobj is needed)rÆTr�)Zensure_asciiÚindentZ	sort_keysrÄr)
rƒrÿrùrór;r’rÅr,rôrýÚdumpr´rµ)r‹rŒr�ròrÆZ	legacy_mdrrrrrr’s*
ÿÿzMetadata.writecCsŠ|jr|j |¡nr|j dg¡}d}|D]}d|kr*d|kr*|}qHq*|dkrfd|i}| d|¡n t|dƒt|ƒB}t|ƒ|d<dS)Nrr&r%rsr)rórìrôr Úinsertr˜r:)r‹rërÚalwaysÚentryZrsetrrrrì3szMetadata.add_requirementscCs*|jpd}|jpd}d|jj|j||fS)Nz	(no name)z
no versionz<%s %s %s (%s)>)r`rIrðrr_)r‹r`rIrrrrñDs

ÿzMetadata.__repr__)NNNr€)N)NN)NNFT)/rrrrÚreÚcompileZMETADATA_VERSION_MATCHERÚIZNAME_MATCHERrZVERSION_MATCHERZSUMMARY_MATCHERrúrrûr0r1r.rÚ	__slots__r�r˜r
rÒZ	none_listÚdictZ	none_dictrrrr!Úpropertyr#rtÚsetterr)r-r/rørùrêr,r9r;r’rìrñrrrrr’sŽ

ýüÿ
-ó+

'




*


	ú	%
)F)ErZ
__future__rr´ZemailrrýrÓrAr2rrÚcompatrrr	rLr
ÚutilrrrIr
rZ	getLoggerrrSrrrrÚ__all__rrrBr©r¨rDrErVrFrWrHrYrGrXr˜r r‰ZEXTRA_RErJr^r¢rÔr×rÙr£rÀr¤rÛrrÜr{r~rZMETADATA_FILENAMEZWHEEL_METADATA_FILENAMEZLEGACY_METADATA_FILENAMErrrrrÚs°










Hâ!



PKÔ¶N]w£dðgðgEsite-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-38.pycnu„[µü¤U

ÀÒ.e*�ã@sdZddlmZddlZddlmZddlZddlZddlZddl	m
Z
mZddlm
Z
mZmZddlmZdd	lmZmZdd
lmZmZe e¡ZGdd„de
ƒZGd
d„de
ƒZGdd„de
ƒZGdd„de
ƒZdddgZdZ dZ!e "d¡Z#e "d¡Z$dZ%dZ&dZ'dZ(dZ)dZ*d Z+e*d!Z,d"Z-e.ƒZ/e/ 0e%¡e/ 0e&¡e/ 0e(¡e/ 0e*¡e/ 0e,¡e "d#¡Z1d$d%„Z2d&d'„Z3d(d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7d8d9d:d;dd?d@dAdBdCdDdEdFœZ4dGZ5dHZ6dIZ7dJZ8dKZ9dLZ:dMZ;e<ƒZ=e "dN¡Z>dXdPdQ„Z?GdRdS„dSe<ƒZ@dTZAdUZBdVZCGdWd„de<ƒZDdS)YzImplementation of the Metadata for Python packages PEPs.

Supports all metadata formats (1.0, 1.1, 1.2, and 2.0 experimental).
é)Úunicode_literalsN)Úmessage_from_fileé)ÚDistlibExceptionÚ__version__)ÚStringIOÚstring_typesÚ	text_type)Ú	interpret)Úextract_by_keyÚ
get_extras)Ú
get_schemeÚPEP440_VERSION_REc@seZdZdZdS)ÚMetadataMissingErrorzA required metadata is missingN©Ú__name__Ú
__module__Ú__qualname__Ú__doc__©rrú@/usr/lib/python3.8/site-packages/pip/_vendor/distlib/metadata.pyrsrc@seZdZdZdS)ÚMetadataConflictErrorz>Attempt to read or write metadata fields that are conflictual.Nrrrrrr src@seZdZdZdS)Ú MetadataUnrecognizedVersionErrorz Unknown metadata version number.Nrrrrrr$src@seZdZdZdS)ÚMetadataInvalidErrorzA metadata value is invalidNrrrrrr(srÚMetadataÚPKG_INFO_ENCODINGÚPKG_INFO_PREFERRED_VERSIONúutf-8ú1.1z

       \|ú	
        )úMetadata-VersionÚNameÚVersionÚPlatformÚSummaryÚDescriptionÚKeywordsú	Home-pageÚAuthorúAuthor-emailÚLicense)r r!r"r#úSupported-Platformr$r%r&r'r(r)r*Ú
ClassifierúDownload-URLÚ	ObsoletesÚProvidesÚRequires)r.r/r0r,r-)r r!r"r#r+r$r%r&r'r(r)Ú
MaintainerúMaintainer-emailr*r,r-úObsoletes-DistúProject-URLú
Provides-Distú
Requires-DistúRequires-PythonúRequires-External)r5r6r7r3r8r1r2r4)r r!r"r#r+r$r%r&r'r(r)r1r2r*r,r-r3r4r5r6r7r8úPrivate-VersionúObsoleted-ByúSetup-Requires-DistÚ	ExtensionúProvides-Extra)r9r=r:r;r<)úDescription-Content-Typer0r/)r>z"extra\s*==\s*("([^"]+)"|'([^']+)')cCsL|dkrtS|dkrtS|dkr$tS|dkr4ttS|dkr@tSt|ƒ‚dS)Nú1.0rú1.2)ú1.3ú2.1ú2.0)Ú_241_FIELDSÚ_314_FIELDSÚ_345_FIELDSÚ_566_FIELDSÚ_426_FIELDSr)ÚversionrrrÚ_version2fieldlistpsrJc
CsBdd„}g}| ¡D]"\}}|gddfkr,q| |¡qddddd	d
g}|D]ö}|tkrvd|krv| d¡t d|¡|tkrœd|krœ| d¡t d|¡|tkrÂd|krÂ| d¡t d
|¡|tkrèd|krè| d¡t d|¡|tk�rd
|k�r|dk�r| d
¡t d|¡|t	krLd	|krL| d	¡t d|¡qLt
|ƒdk�rZ|dSt
|ƒdk�r|t d|¡tdƒ‚d|k�oŽ||tƒ}d|k�o¢||t
ƒ}d
|k�o¶||tƒ}d	|k�oÊ||tƒ}	t|ƒt|ƒt|ƒt|	ƒdk�rútdƒ‚|�s |�s |�s |	�s t|k�r tS|�r*dS|�r4dS|�r>d
Sd	S)z5Detect the best version depending on the fields used.cSs|D]}||krdSqdS)NTFr)ÚkeysÚmarkersÚmarkerrrrÚ_has_marker€sz"_best_version.._has_markerÚUNKNOWNNr?rr@rArCrBzRemoved 1.0 due to %szRemoved 1.1 due to %szRemoved 1.2 due to %szRemoved 1.3 due to %sr%zRemoved 2.1 due to %szRemoved 2.0 due to %srrz)Out of options - unknown metadata set: %szUnknown metadata setz,You used incompatible 1.1/1.2/2.0/2.1 fields)ÚitemsÚappendrDÚremoveÚloggerÚdebugrErFrGrHÚlenrÚ_314_MARKERSÚ_345_MARKERSÚ_566_MARKERSÚ_426_MARKERSÚintr)
ÚfieldsrNrKÚkeyÚvalueZpossible_versionsZis_1_1Zis_1_2Zis_2_1Zis_2_0rrrÚ
_best_version~s`






&
r^r r!r"r#r+r$r%r&r'r(r)r1r2r*r,r-r3r5r6r;r7r8r0r/r.r4r9r:r<r=)Úmetadata_versionÚnamerIÚplatformZsupported_platformÚsummaryÚdescriptionÚkeywordsÚ	home_pageÚauthorÚauthor_emailÚ
maintainerÚmaintainer_emailÚlicenseÚ
classifierÚdownload_urlÚobsoletes_distÚ
provides_distÚ
requires_distÚsetup_requires_distÚrequires_pythonÚrequires_externalÚrequiresÚprovidesÚ	obsoletesÚproject_urlZprivate_versionZobsoleted_byÚ	extensionZprovides_extra)r6r3r5)r7)r")r#r,r.r0r/r3r5r6r8r4r+r;r=r<)r4)r&)r(r1r$r%z[^A-Za-z0-9.]+FcCs0|r$t d|¡}t d| dd¡¡}d||fS)zhReturn the distribution name with version.

    If for_filename is true, return a filename-escaped form.ú-ú Ú.z%s-%s)Ú	_FILESAFEÚsubÚreplace)r`rIZfor_filenamerrrÚ_get_name_and_versionùsr~c@s
eZdZdZd?dd„Zdd„Zdd	„Zd
d„Zdd
„Zdd„Z	dd„Z
dd„Zdd„Zdd„Z
dd„Zd@dd„Zdd„Zdd „Zd!d"„Zd#d$„ZdAd%d&„ZdBd'd(„ZdCd)d*„Zd+d,„Zefd-d.„ZdDd/d0„ZdEd1d2„Zd3d4„Zd5d6„Zd7d8„Zd9d:„Zd;d<„Z d=d>„Z!dS)FÚLegacyMetadataaaThe legacy metadata of a release.

    Supports versions 1.0, 1.1 and 1.2 (auto-detected). You can
    instantiate the class with one of these arguments (or none):
    - *path*, the path to a metadata file
    - *fileobj* give a file-like object with metadata as content
    - *mapping* is a dict-like object
    - *scheme* is a version scheme name
    NÚdefaultcCsz|||g d¡dkrtdƒ‚i|_g|_d|_||_|dk	rH| |¡n.|dk	r\| |¡n|dk	rv| |¡| 	¡dS)Néú'path, fileobj and mapping are exclusive)
ÚcountÚ	TypeErrorÚ_fieldsZrequires_filesZ
_dependenciesÚschemeÚreadÚ	read_fileÚupdateÚset_metadata_version)ÚselfÚpathÚfileobjÚmappingr†rrrÚ__init__s
zLegacyMetadata.__init__cCst|jƒ|jd<dS©Nr )r^r…©r‹rrrrŠ"sz#LegacyMetadata.set_metadata_versioncCs| d||f¡dS)Nz%s: %s
)Úwrite)r‹r�r`r]rrrÚ_write_field%szLegacyMetadata._write_fieldcCs
| |¡S©N)Úget©r‹r`rrrÚ__getitem__(szLegacyMetadata.__getitem__cCs| ||¡Sr”)Úset)r‹r`r]rrrÚ__setitem__+szLegacyMetadata.__setitem__cCs8| |¡}z|j|=Wntk
r2t|ƒ‚YnXdSr”)Ú
_convert_namer…ÚKeyError)r‹r`Ú
field_namerrrÚ__delitem__.s

zLegacyMetadata.__delitem__cCs||jkp| |¡|jkSr”)r…ršr–rrrÚ__contains__5s
ÿzLegacyMetadata.__contains__cCs(|tkr|S| dd¡ ¡}t ||¡S)NrxÚ_)Ú_ALL_FIELDSr}ÚlowerÚ_ATTR2FIELDr•r–rrrrš9szLegacyMetadata._convert_namecCs|tks|tkrgSdS)NrO)Ú_LISTFIELDSÚ_ELEMENTSFIELDr–rrrÚ_default_value?szLegacyMetadata._default_valuecCs&|jdkrt d|¡St d|¡SdS)N©r?rÚ
)r_Ú_LINE_PREFIX_PRE_1_2r|Ú_LINE_PREFIX_1_2©r‹r]rrrÚ_remove_line_prefixDs
z"LegacyMetadata._remove_line_prefixcCs|tkr||St|ƒ‚dSr”)r¢ÚAttributeErrorr–rrrÚ__getattr__JszLegacyMetadata.__getattr__FcCst|d|d|ƒS)zhReturn the distribution name with version.

        If filesafe is true, return a filename-escaped form.r!r")r~)r‹ZfilesaferrrÚget_fullnameUszLegacyMetadata.get_fullnamecCs| |¡}|tkS)z+return True if name is a valid metadata key)ršr r–rrrÚis_field[s
zLegacyMetadata.is_fieldcCs| |¡}|tkSr”)ršr£r–rrrÚis_multi_field`s
zLegacyMetadata.is_multi_fieldcCs.tj|ddd�}z| |¡W5| ¡XdS)z*Read the metadata values from a file path.Úrr©ÚencodingN)ÚcodecsÚopenÚcloserˆ)r‹ÚfilepathÚfprrrr‡dszLegacyMetadata.readcCs�t|ƒ}|d|jd<tD]p}||kr(q|tkrf| |¡}|tkrX|dk	rXdd„|Dƒ}| ||¡q||}|dk	r|dkr| ||¡qdS)z,Read the metadata values from a file object.zmetadata-versionr NcSsg|]}t| d¡ƒ‘qS©ú,)ÚtupleÚsplit©Ú.0r]rrrÚ
ysz,LegacyMetadata.read_file..rO)rr…r r£Zget_allÚ_LISTTUPLEFIELDSr˜)r‹ZfileobÚmsgÚfieldÚvaluesr]rrrrˆls
zLegacyMetadata.read_filecCs0tj|ddd�}z| ||¡W5| ¡XdS)z&Write the metadata fields to filepath.Úwrr²N)r´rµr¶Ú
write_file)r‹r·Úskip_unknownr¸rrrr’ƒszLegacyMetadata.writecCsÄ| ¡t|dƒD]ª}| |¡}|r8|dgdgfkr8q|tkrV| ||d |¡¡q|tkr�|dkrŠ|jdkr~| dd¡}n| dd¡}|g}|t	kr¦d	d
„|Dƒ}|D]}| |||¡qªqdS)z0Write the PKG-INFO format data to a file object.r rOrºr%r¦r§rz	
       |cSsg|]}d |¡‘qSr¹©Újoinr½rrrr¿Ÿsz-LegacyMetadata.write_file..N)
rŠrJr•r¤r“rÈr£r_r}rÀ)r‹Z
fileobjectrÆrÂrÃr]rrrrÅ‹s$

zLegacyMetadata.write_filecsv‡fdd„}|sn@t|dƒr:| ¡D]}||||ƒq$n|D]\}}|||ƒq>|rr| ¡D]\}}|||ƒq^dS)a…Set metadata values from the given iterable `other` and kwargs.

        Behavior is like `dict.update`: If `other` has a ``keys`` method,
        they are looped over and ``self[key]`` is assigned ``other[key]``.
        Else, ``other`` is an iterable of ``(key, value)`` iterables.

        Keys that don't match a metadata field or that have an empty value are
        dropped.
        cs"|tkr|rˆ ˆ |¡|¡dSr”)r¢r˜rš)r\r]r‘rrÚ_set®sz#LegacyMetadata.update.._setrKN)ÚhasattrrKrP)r‹ÚotherÚkwargsrÉÚkÚvrr‘rr‰¤s

zLegacyMetadata.updatecCsh| |¡}|tks|dkrNt|ttfƒsNt|tƒrHdd„| d¡Dƒ}qzg}n,|tkrzt|ttfƒszt|tƒrv|g}ng}t 	t
j¡�r<|d}t|j
ƒ}|tkrÚ|dk	rÚ|D](}| | d¡d¡s®t d	|||¡q®nb|tk�r|dk	�r| |¡�s.rºr!Nú;rz$'%s': '%s' is not valid (field '%s')z.'%s': '%s' is not a valid version (field '%s')r%)ršr¤Ú
isinstanceÚlistr»rr¼r£rSZisEnabledForÚloggingZWARNINGr
r†Ú_PREDICATE_FIELDSÚis_valid_matcherÚwarningÚ_VERSIONS_FIELDSÚis_valid_constraint_listÚ_VERSION_FIELDSÚis_valid_versionÚ_UNICODEFIELDSr«r…)r‹r`r]Zproject_namer†rÎrrrr˜ÀsV
ÿ
ÿ

þÿÿ


zLegacyMetadata.setcCsÊ| |¡}||jkr*|tkr&| |¡}|S|tkr@|j|}|S|tkrš|j|}|dkr^gSg}|D].}|tkr~| |¡qf| |d|df¡qf|S|tkrÀ|j|}t	|t
ƒrÀ| d¡S|j|S)zGet a metadata field.Nrrrº)ršr…Ú_MISSINGr¥rÛr£rÀrQr¤rÑrr¼)r‹r`r€r]ÚresÚvalrrrr•ìs.







zLegacyMetadata.getcsú| ¡gg}}dD]}||kr| |¡q|rP|gkrPdd |¡}t|ƒ‚dD]}||krT| |¡qT|ddkr€||fSt|jƒ‰‡fdd„}t|ftˆjft	ˆj
ffD]@\}}|D]2}	| |	d	¡}
|
d	k	r¼||
ƒs¼| d
|	|
f¡q¼q°||fS)zkCheck if the metadata is compliant. If strict is True then raise if
        no Name or Version are provided)r!r"zmissing required metadata: %sú, )r'r(r r@cs(|D]}ˆ | d¡d¡sdSqdS)NrÐrFT)rÕr¼)r]rΩr†rrÚare_valid_constraints#sz3LegacyMetadata.check..are_valid_constraintsNzWrong value for '%s': %s)rŠrQrÈrr
r†rÔr×rØrÙrÚr•)r‹ÚstrictÚmissingÚwarningsÚattrrÁrár[Z
controllerrÂr]rràrÚcheck	s8

ÿÿýzLegacyMetadata.checkcCsÎ| ¡d}i}|D]"\}}|r*||jkr||||<q|ddkr’d}|D]B\}}|rb||jkrL|dkrx||||<qLdd„||Dƒ||<qLn8|ddkrÊd	}|D]"\}}|r¼||jkr¦||||<q¦|S)
zºReturn fields as a dict.

        Field names will be converted to use the underscore-lowercase style
        instead of hyphen-mixed case (i.e. home_page instead of Home-page).
        )
)r_r )r`r!)rIr")rbr$)rer')rfr()rgr))rjr*)rcr%)rdr&)rar#)Úclassifiersr,)rlr-r r@))ror6)rqr7)rrr8)rnr5)rmr3)rvr4)rhr1)rir2rvcSsg|]}d |¡‘qSr¹rÇ)r¾Úurrrr¿bsz)LegacyMetadata.todict..r))rtr/)rsr0)rur.)rŠr…)r‹Zskip_missingZmapping_1_0Údatar\rœZmapping_1_2Zmapping_1_1rrrÚtodict5s&
zLegacyMetadata.todictcCs8|ddkr$dD]}||kr||=q|d|7<dS)Nr r)r.r0r/r6r)r‹ÚrequirementsrÂrrrÚadd_requirementsps
zLegacyMetadata.add_requirementscCstt|dƒƒSr�)rÒrJr‘rrrrK{szLegacyMetadata.keysccs| ¡D]
}|VqdSr”©rK)r‹r\rrrÚ__iter__~szLegacyMetadata.__iter__cs‡fdd„ˆ ¡DƒS)Ncsg|]}ˆ|‘qSrr©r¾r\r‘rrr¿ƒsz)LegacyMetadata.values..rír‘rr‘rrÂszLegacyMetadata.valuescs‡fdd„ˆ ¡DƒS)Ncsg|]}|ˆ|f‘qSrrrïr‘rrr¿†sz(LegacyMetadata.items..rír‘rr‘rrP…szLegacyMetadata.itemscCsd|jj|j|jfS)Nz
<%s %s %s>)Ú	__class__rr`rIr‘rrrÚ__repr__ˆsÿzLegacyMetadata.__repr__)NNNr€)F)F)F)N)F)F)"rrrrr�rŠr“r—r™r�ržršr¥r«r­r®r¯r°r‡rˆr’rÅr‰r˜rÜr•rærêrìrKrîrÃrPrñrrrrrs@ÿ




,
,
;rzpydist.jsonz
metadata.jsonZMETADATAc@s’eZdZdZe d¡Ze dej¡Ze	Z
e d¡ZdZde
Zdddd	œZd
ZdZedfedfe
dfedfdœZd
ZdDdd„ZedƒZdefZdefZdefdefeeedefeeeedefdddœ
Z[[dd„ZdEdd„Zdd„Zed d!„ƒZ ed"d#„ƒZ!e!j"d$d#„ƒZ!dFd%d&„Z#ed'd(„ƒZ$ed)d*„ƒZ%e%j"d+d*„ƒZ%d,d-„Z&d.d/„Z'd0d1„Z(d2d3„Z)d4d5d6d7d8dd9œZ*d:d;„Z+dGd>d?„Z,d@dA„Z-dBdC„Z.dS)HrzÊ
    The metadata of a release. This implementation uses 2.0 (JSON)
    metadata where possible. If not possible, it wraps a LegacyMetadata
    instance which handles the key-value metadata format.
    z
^\d+(\.\d+)*$z!^[0-9A-Z]([0-9A-Z_.-]*[0-9A-Z])?$z	.{1,2047}rCzdistlib (%s)r)Úlegacy)r`rIrbzqname version license summary description author author_email keywords platform home_page classifiers download_urlzwextras run_requires test_requires build_requires dev_requires provides meta_requires obsoleted_by supports_environments)r_r`rIrb)Ú_legacyÚ_datar†Nr€c	Cs0|||g d¡dkrtdƒ‚d|_d|_||_|dk	rzz| ||¡||_Wn*tk
rvt||d�|_| ¡YnXn²d}|r¢t	|dƒ�}| 
¡}W5QRXn|r®| 
¡}|dkrÈ|j|jdœ|_ndt
|tƒsÜ| d¡}zt |¡|_| |j|¡Wn0tk
�r*tt|ƒ|d�|_| ¡YnXdS)Nr�r‚)rŽr†Úrb©r_Ú	generatorr)r�r†)rƒr„rórôr†Ú_validate_mappingrrÚvalidaterµr‡ÚMETADATA_VERSIONÚ	GENERATORrÑr	ÚdecodeÚjsonÚloadsÚ
ValueErrorr)r‹rŒr�rŽr†réÚfrrrr�¼s@
þ


ÿzMetadata.__init__)r`rIrjrdrbr6r;r=r,)r-N)r N)
Úrun_requiresÚbuild_requiresÚdev_requiresZ
test_requiresÚ
meta_requiresÚextrasÚmodulesÚ
namespacesÚexportsÚcommandsrçZ
source_urlr_c
CsXt |d¡}t |d¡}||k�r||\}}|jr^|dkrP|dkrHdn|ƒ}n|j |¡}nº|dkrjdn|ƒ}|dkrˆ|j ||¡}n�tƒ}|}|j d¡}	|	�r
|dkrº|	 d|¡}nP|dkrÞ|	 d¡}	|	rÜ|	 ||¡}n,|	 d	¡}	|	sø|j d	¡}	|	�r
|	 ||¡}||k�rT|}n:||k�r2t ||¡}n"|j�rH|j |¡}n|j |¡}|S)
NÚcommon_keysÚmapped_keys©r	rrrrçÚ
extensionsr	úpython.commandsrçúpython.detailsúpython.exports)ÚobjectÚ__getattribute__rór•rô)
r‹r\ÚcommonÚmappedÚlkZmakerÚresultr]ÚsentinelÚdrrrrsD




zMetadata.__getattribute__cCsH||jkrD|j|\}}|p |j|krD| |¡}|sDtd||fƒ‚dS)Nz.'%s' is an invalid value for the '%s' property)ÚSYNTAX_VALIDATORSr†Úmatchr)r‹r\r]r†ÚpatternÚ
exclusionsÚmrrrÚ_validate_value+s

ÿÿzMetadata._validate_valuecCs*| ||¡t |d¡}t |d¡}||kr¾||\}}|jrV|dkrJt‚||j|<nf|dkrj||j|<nR|j di¡}|dkrŠ||d<n2|dkr¨| di¡}|||<n| d	i¡}|||<nh||krÖt |||¡nP|d
k�rt|t	ƒ�r| 
¡}|�r| ¡}ng}|j�r||j|<n
||j|<dS)Nr
rrr
r	rrçrrrd)rrrróÚNotImplementedErrorrôÚ
setdefaultÚ__setattr__rÑrrÏr¼)r‹r\r]rrrrŸrrrrr!5s<




zMetadata.__setattr__cCst|j|jdƒS©NT)r~r`rIr‘rrrÚname_and_version\szMetadata.name_and_versioncCsF|jr|jd}n|j dg¡}d|j|jf}||krB| |¡|S)Nr5rtz%s (%s))rórôr r`rIrQ)r‹rÚsrrrrt`s
zMetadata.providescCs |jr||jd<n
||jd<dS)Nr5rt)rórôrªrrrrtksc
CsÚ|jr|}nÊg}t|pg|jƒ}|D]d}d|kr>d|kr>d}n8d|krLd}n| d¡|k}|rv| d¡}|rvt||ƒ}|r$| |d¡q$dD]F}d|}	|	|krŽ| |	¡|j d|g¡}| |j|||d�¡qŽ|S)	a‹
        Base method to get dependencies, given a set of extras
        to satisfy and an optional environment context.
        :param reqts: A list of sometimes-wanted dependencies,
                      perhaps dependent on extras and environment.
        :param extras: A list of optional components being requested.
        :param env: An optional environment for marker evaluation.
        ÚextraÚenvironmentTrs)ZbuildZdevZtestz:%s:z%s_requires)rÚenv)	rórrr•r
ÚextendrRrôÚget_requirements)
r‹Úreqtsrr'rrZincluderMr\Úerrrr)rs2	


ÿ
zMetadata.get_requirementscCs|jr| ¡S|jSr”)róÚ_from_legacyrôr‘rrrÚ
dictionaryœszMetadata.dictionarycCs|jrt‚nt|j|jƒSdSr”)rórrrôÚDEPENDENCY_KEYSr‘rrrÚdependencies¢szMetadata.dependenciescCs|jrt‚n|j |¡dSr”)rórrôr‰rªrrrr/©sc	Cs†| d¡|jkrtƒ‚g}|j ¡D]"\}}||kr$||kr$| |¡q$|rbdd |¡}t|ƒ‚| ¡D]\}}| |||¡qjdS)Nr_zMissing metadata items: %srß)	r•rúrÚMANDATORY_KEYSrPrQrÈrr)	r‹rŽr†rãr\rrÁrÍrÎrrrrø°szMetadata._validate_mappingcCsB|jr.|j d¡\}}|s|r>t d||¡n| |j|j¡dS)NTz#Metadata: missing: %s, warnings: %s)rórærSrÖrørôr†)r‹rãrärrrrù¾sÿzMetadata.validatecCs(|jr|j d¡St|j|jƒ}|SdSr")rórêrrôÚ
INDEX_KEYS)r‹rrrrrêÇszMetadata.todictc
CsÆ|jr|jrt‚|j|jdœ}|j d¡}dD]*}||kr.|dkrHd}n|}||||<q.| dg¡}|dgkrtg}||d<d	}|D]*\}}||kr„||r„d
||ig||<q„|j|d<i}i}	|S)NröT)r`rIrjrbrcrkrkrçr&Úrd))ror)rprrsrt)rórôÚAssertionErrorrúrûrêr•rt)
r‹rZlmdrÍÚnkÚkwrKÚokrfrhrrrr,Îs.þ

zMetadata._from_legacyr!r"r*r$r%)r`rIrjrbrcrçcCsœdd„}|jr|jrt‚tƒ}|j}|j ¡D]\}}||kr.||||<q.||j|jƒ}||j|j	ƒ}|j
r€t|j
ƒ|d<t|ƒ|d<t|ƒ|d<|S)NcSsŒtƒ}|D]|}| d¡}| d¡}|d}|D]V}|sF|sF| |¡q.d}|rVd|}|rp|rld||f}n|}| d ||f¡¡q.q
|S)Nr%r&rsr2z
extra == "%s"z(%s) and %srÐ)r˜r•ÚaddrÈ)Úentriesr*r+r%r'Zrlistr±rMrrrÚprocess_entriesõs"

z,Metadata._to_legacy..process_entriesr=r6r;)rôrór3rÚLEGACY_MAPPINGrPrrrrrÚsorted)r‹r9rZnmdr4r6Zr1Zr2rrrÚ
_to_legacyôszMetadata._to_legacyFTc	CsÂ||g d¡dkrtdƒ‚| ¡|r`|jr4|j}n| ¡}|rP|j||d�q¾|j||d�n^|jrp| ¡}n|j}|r�t	j
||dddd�n.t |dd¡�}t	j
||dddd�W5QRXdS)	Nrz)Exactly one of path and fileobj is needed)rÆTr�)Zensure_asciiÚindentZ	sort_keysrÄr)
rƒrÿrùrór<r’rÅr,rôrýÚdumpr´rµ)r‹rŒr�ròrÆZ	legacy_mdrrrrrr’s*
ÿÿzMetadata.writecCsŠ|jr|j |¡nr|j dg¡}d}|D]}d|kr*d|kr*|}qHq*|dkrfd|i}| d|¡n t|dƒt|ƒB}t|ƒ|d<dS)Nrr&r%rsr)rórìrôr Úinsertr˜r;)r‹rërÚalwaysÚentryZrsetrrrrì3szMetadata.add_requirementscCs*|jpd}|jpd}d|jj|j||fS)Nz	(no name)z
no versionz<%s %s %s (%s)>)r`rIrðrr_)r‹r`rIrrrrñDs

ÿzMetadata.__repr__)NNNr€)N)NN)NNFT)/rrrrÚreÚcompileZMETADATA_VERSION_MATCHERÚIZNAME_MATCHERrZVERSION_MATCHERZSUMMARY_MATCHERrúrrûr0r1r.rÚ	__slots__r�r˜r
rÒZ	none_listÚdictZ	none_dictrrrr!Úpropertyr#rtÚsetterr)r-r/rørùrêr,r:r<r’rìrñrrrrr’sŽ

ýüÿ
-ó+

'




*


	ú	%
)F)ErZ
__future__rr´ZemailrrýrÓrBr2rrÚcompatrrr	rLr
ÚutilrrrIr
rZ	getLoggerrrSrrrrÚ__all__rrrCr©r¨rDrErVrFrWrHrYrGrXr˜r r‰ZEXTRA_RErJr^r¢rÔr×rÙr£rÀr¤rÛrrÜr{r~rZMETADATA_FILENAMEZWHEEL_METADATA_FILENAMEZLEGACY_METADATA_FILENAMErrrrrÚs°










Hâ!



PKÔ¶N]±4BÌ�•�•Esite-packages/pip/_vendor/distlib/__pycache__/locators.cpython-38.pycnu„[µü¤U

ÀÒ.e_Êã@sDddlZddlmZddlZddlZddlZddlZddlZzddlZWne	k
rdddl
ZYnXddlZddlm
Z
ddlmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZddlm Z m!Z!m"Z"ddl#m$Z$m%Z%ddl&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/dd	l0m1Z1m2Z2dd
l3m4Z4m5Z5e 6e7¡Z8e 9d¡Z:e 9dej;¡Zd-dd„Z?Gdd„deƒZ@Gdd„deAƒZBGdd„deBƒZCGdd„deBƒZDGdd„deAƒZEGdd„deBƒZFGdd„deBƒZGGdd „d eBƒZHGd!d"„d"eBƒZIGd#d$„d$eBƒZJeJeHƒeFd%d&d'�d(d)�ZKeKjLZLe 9d*¡ZMGd+d,„d,eAƒZNdS).éN)ÚBytesIOé)ÚDistlibException)ÚurljoinÚurlparseÚ
urlunparseÚurl2pathnameÚpathname2urlÚqueueÚquoteÚunescapeÚstring_typesÚbuild_openerÚHTTPRedirectHandlerÚ	text_typeÚRequestÚ	HTTPErrorÚURLError)ÚDistributionÚDistributionPathÚ	make_dist)ÚMetadataÚMetadataInvalidError)	Úcached_propertyÚparse_credentialsÚensure_slashÚsplit_filenameÚget_project_dataÚparse_requirementÚparse_name_and_versionÚServerProxyÚnormalize_name)Ú
get_schemeÚUnsupportedVersionError)ÚWheelÚ
is_compatiblez^(\w+)=([a-f0-9]+)z;\s*charset\s*=\s*(.*)\s*$ztext/html|application/x(ht)?mlzhttps://pypi.org/pypicCs6|dkrt}t|dd�}z| ¡W¢S|dƒƒXdS)z•
    Return all distribution names known by an index.
    :param url: The URL of the index.
    :return: A list of all known distribution names.
    Nç@©ÚtimeoutÚclose)Ú
DEFAULT_INDEXr Ú
list_packages)ÚurlÚclient©r.ú@/usr/lib/python3.8/site-packages/pip/_vendor/distlib/locators.pyÚget_all_distribution_names)sr0c@s$eZdZdZdd„ZeZZZdS)ÚRedirectHandlerzE
    A class to work around a bug in some Python 3.2.x releases.
    c	Cs‚d}dD]}||kr||}q"q|dkr.dSt|ƒ}|jdkrnt| ¡|ƒ}t|dƒrf| ||¡n|||<t ||||||¡S)N)ÚlocationZuriÚÚreplace_header)rÚschemerZget_full_urlÚhasattrr4ÚBaseRedirectHandlerÚhttp_error_302)	ÚselfÚreqÚfpÚcodeÚmsgÚheadersZnewurlÚkeyZurlpartsr.r.r/r8@s 

ÿzRedirectHandler.http_error_302N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r8Zhttp_error_301Zhttp_error_303Zhttp_error_307r.r.r.r/r17sr1c@s¶eZdZdZdZdZdZdZedZd)dd	„Z	d
d„Z
dd
„Zdd„Zdd„Z
dd„Zee
eƒZdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zd d!„Zd"d#„Zd$d%„Zd*d'd(„ZdS)+ÚLocatorzG
    A base class for locators - things that locate distributions.
    )z.tar.gzz.tar.bz2z.tarz.zipz.tgzz.tbz)z.eggz.exeú.whl)z.pdfN)rEÚdefaultcCs,i|_||_ttƒƒ|_d|_t ¡|_dS)a^
        Initialise an instance.
        :param scheme: Because locators look for most recent versions, they
                       need to know the version scheme to use. This specifies
                       the current PEP-recommended scheme - use ``'legacy'``
                       if you need to support existing distributions on PyPI.
        N)	Ú_cacher5rr1ÚopenerÚmatcherr
ÚQueueÚerrors)r9r5r.r.r/Ú__init__fs
zLocator.__init__cCsVg}|j ¡sRz|j d¡}| |¡Wn|jjk
rDYqYnX|j ¡q|S)z8
        Return any errors which have occurred.
        F)rKÚemptyÚgetÚappendZEmptyÚ	task_done)r9ÚresultÚer.r.r/Ú
get_errorsys

zLocator.get_errorscCs| ¡dS)z>
        Clear any errors which may have been logged.
        N)rS©r9r.r.r/Úclear_errors‡szLocator.clear_errorscCs|j ¡dS©N)rGÚclearrTr.r.r/Úclear_cacheŽszLocator.clear_cachecCs|jSrV©Ú_schemerTr.r.r/Ú_get_scheme‘szLocator._get_schemecCs
||_dSrVrY)r9Úvaluer.r.r/Ú_set_scheme”szLocator._set_schemecCstdƒ‚dS)a=
        For a given project, get a dictionary mapping available versions to Distribution
        instances.

        This should be implemented in subclasses.

        If called from a locate() request, self.matcher will be set to a
        matcher for the requirement to satisfy, otherwise it will be None.
        ú Please implement in the subclassN©ÚNotImplementedError)r9Únamer.r.r/Ú_get_project™s
zLocator._get_projectcCstdƒ‚dS)úJ
        Return all the distribution names known to this locator.
        r^Nr_rTr.r.r/Úget_distribution_names¥szLocator.get_distribution_namescCsL|jdkr| |¡}n2||jkr,|j|}n| ¡| |¡}||j|<|S)zÖ
        For a given project, get a dictionary mapping available versions to Distribution
        instances.

        This calls _get_project to do all the work, and just implements a caching layer on top.
        N)rGrbrU)r9rarQr.r.r/Úget_project«s



zLocator.get_projectcCs^t|ƒ}t |j¡}d}| d¡}| |j¡}|rBtt|ƒ|jƒ}|j	dkd|j
k||||fS)zu
        Give an url a score which can be used to choose preferred URLs
        for a given project release.
        TrEÚhttpszpypi.org)rÚ	posixpathÚbasenameÚpathÚendswithÚdownloadable_extensionsr%r$Ú
wheel_tagsr5Únetloc)r9r,ÚtrhZ
compatibleZis_wheelZis_downloadabler.r.r/Ú	score_url¼s
ÿzLocator.score_urlcCsR|}|rN| |¡}| |¡}||kr(|}||kr@t d||¡nt d||¡|S)a{
        Choose one of two URLs where both are candidates for distribution
        archives for the same version of a distribution (for example,
        .tar.gz vs. zip).

        The current implementation favours https:// URLs over http://, archives
        from PyPI over those from other locations, wheel compatibility (if a
        wheel) and then the archive name.
        zNot replacing %r with %rzReplacing %r with %r)roÚloggerÚdebug)r9Úurl1Úurl2rQÚs1Ús2r.r.r/Ú
prefer_urlËs


zLocator.prefer_urlcCs
t||ƒS)zZ
        Attempt to split a filename in project name, version and Python version.
        )r)r9ÚfilenameÚproject_namer.r.r/rászLocator.split_filenamecCsdd„}d}t|ƒ\}}}}}	}
|
 ¡ d¡rz~t	|ƒ}t
||jƒs°t d
|¡nX|dkr¾d}n||j|ƒ}|�r|j|j
|jt|||||	dfƒd
 dd„|jDƒ¡dœ}Wn0tk
�r:}zt d|¡W5d}~XYnXnÄ| |j¡�sZt d|¡n¨t |¡}}|jD]’}| |¡�rn|dt|ƒ…}| ||¡}|�s°t d|¡nH|\}}}|�rÌ|||ƒ�rø|||t|||||	dfƒdœ}|�rø||d<�q�qn|�r|�r|
|d|<|S)a
        See if a URL is a candidate for a download URL for a project (the URL
        has typically been scraped from an HTML page).

        If it is, a dictionary is returned with keys "name", "version",
        "filename" and "url"; otherwise, None is returned.
        cSst|ƒt|ƒkSrV)r!)Zname1Zname2r.r.r/Úsame_projectïsz:Locator.convert_url_to_download_info..same_projectNzegg=z %s: version hint in fragment: %r)NNéÿÿÿÿú/rEzWheel not compatible: %sTr3z, cSs"g|]}d t|dd…ƒ¡‘qS)Ú.éN)ÚjoinÚlist)Ú.0Úvr.r.r/Ú
sz8Locator.convert_url_to_download_info..)raÚversionrwr,úpython-versionzinvalid path for wheel: %szNot downloadable: %sz No match for project/version: %s)rarƒrwr,r„ú	%s_digest)rÚlowerÚ
startswithrprqÚHASHER_HASHÚmatchÚgroupsrjr$r%rlrarƒrwrr~ÚpyverÚ	ExceptionÚwarningrkrgrhÚlenr)r9r,rxryrQr5rmriÚparamsÚqueryÚfragÚmÚalgoÚdigestZorigpathÚwheelZincluderRrwZextrnrarƒr‹r.r.r/Úconvert_url_to_download_infoçs€ÿ
ÿÿú
	 

ÿü
z$Locator.convert_url_to_download_infocCs2d}dD]$}d|}||kr|||f}q.q|S)zØ
        Get a digest from a dictionary by looking at keys of the form
        'algo_digest'.

        Returns a 2-tuple (algo, digest) if found, else None. Currently
        looks only for SHA256, then MD5.
        N)Zsha256Úmd5r…r.)r9ÚinforQr“r?r.r.r/Ú_get_digest1szLocator._get_digestc	Cs®| d¡}| d¡}||kr,||}|j}nt|||jd�}|j}| |¡|_}|d}||d|<|j|dkrœ| |j|¡|_|d |t	ƒ¡ 
|¡||_|||<dS)zñ
        Update a result dictionary (the final result from _get_project) with a
        dictionary for a specific version, which typically holds information
        gleaned from a filename or URL for an archive for the distribution.
        rarƒ©r5r,ÚdigestsÚurlsN)ÚpopÚmetadatarr5r™r”Ú
source_urlrvÚ
setdefaultÚsetÚaddÚlocator)	r9rQr˜rarƒÚdistÚmdr”r,r.r.r/Ú_update_version_dataAs

zLocator._update_version_dataFc	Cs¤d}t|ƒ}|dkr td|ƒ‚t|jƒ}| |j¡|_}t d|t|ƒj	¡| 
|j¡}t|ƒdk�r2g}|j
}	|D]z}
|
dkr†qxzH| |
¡s¢t d||
¡n*|s°|	|
ƒjs¼| |
¡nt d|
|j¡Wqxtk
rðt d||
¡YqxXqxt|ƒd	k�rt||jd
�}|�r2t d|¡|d}||}|�rš|j�rH|j|_| d
i¡ |tƒ¡|_i}| di¡}
|jD]}||
k�rv|
|||<�qv||_d|_|S)a
        Find the most recent distribution which matches the given
        requirement.

        :param requirement: A requirement of the form 'foo (1.0)' or perhaps
                            'foo (>= 1.0, < 2.0, != 1.3)'
        :param prereleases: If ``True``, allow pre-release versions
                            to be located. Otherwise, pre-release versions
                            are not returned.
        :return: A :class:`Distribution` instance, or ``None`` if no such
                 distribution could be located.
        NzNot a valid requirement: %rzmatcher: %s (%s)r}©rœr›z%s did not match %rz%skipping pre-release version %s of %szerror matching %s with %rr)r?zsorted list: %srzrœr›)rrr"r5rIÚrequirementrprqÚtyper@rerarŽZ
version_classr‰Z
is_prereleaserOrŒr�Úsortedr?ZextrasrNr¡Ú
download_urlsr›)r9r¨ÚprereleasesrQÚrr5rIÚversionsZslistZvclsÚkrƒÚdZsdr,r.r.r/ÚlocateXsX


ÿ

zLocator.locate)rF)F)r@rArBrCÚsource_extensionsÚbinary_extensionsÚexcluded_extensionsrlrkrLrSrUrXr[r]Úpropertyr5rbrdrerorvrr–r™r¦r±r.r.r.r/rDVs.

JrDcs0eZdZdZ‡fdd„Zdd„Zdd„Z‡ZS)ÚPyPIRPCLocatorz‘
    This locator uses XML-RPC to locate distributions. It therefore
    cannot be used with simple mirrors (that only mirror file content).
    cs*tt|ƒjf|Ž||_t|dd�|_dS)z—
        Initialise an instance.

        :param url: The URL to use for XML-RPC.
        :param kwargs: Passed to the superclass constructor.
        r&r'N)Úsuperr¶rLÚbase_urlr r-©r9r,Úkwargs©Ú	__class__r.r/rL™szPyPIRPCLocator.__init__cCst|j ¡ƒS©rc)r¡r-r+rTr.r.r/rd¤sz%PyPIRPCLocator.get_distribution_namescCsiidœ}|j |d¡}|D]Þ}|j ||¡}|j ||¡}t|jd�}|d|_|d|_| d¡|_	| dg¡|_
| d¡|_t|ƒ}|r|d	}	|	d
|_
| |	¡|_||_|||<|D]:}	|	d
}
| |	¡}|d |tƒ¡ |
¡||d|
<q¾q|S)
Nr§TršrarƒÚlicenseÚkeywordsÚsummaryrr,rœr›)r-Zpackage_releasesZrelease_urlsZrelease_datarr5rarƒrNr¾r¿rÀrrŸr™r”r£r r¡r¢)r9rarQr®r�rœÚdataržr¤r˜r,r”r.r.r/rbªs0




zPyPIRPCLocator._get_project©r@rArBrCrLrdrbÚ
__classcell__r.r.r»r/r¶”sr¶cs0eZdZdZ‡fdd„Zdd„Zdd„Z‡ZS)ÚPyPIJSONLocatorzw
    This locator uses PyPI's JSON interface. It's very limited in functionality
    and probably not worth using.
    cs tt|ƒjf|Žt|ƒ|_dSrV)r·rÄrLrr¸r¹r»r.r/rLÉszPyPIJSONLocator.__init__cCstdƒ‚dS©rczNot available from this locatorNr_rTr.r.r/rdÍsz&PyPIJSONLocator.get_distribution_namesc
Cs
iidœ}t|jdt|ƒƒ}�z¤|j |¡}| ¡ ¡}t |¡}t	|j
d�}|d}|d|_|d|_| 
d¡|_| 
dg¡|_| 
d	¡|_t|ƒ}||_|d
}	|||j<|d
D]T}
|
d}|j |¡| |
¡|j|<|d
 |jtƒ¡ |¡| |
¡|d|<qº|d
 ¡D]¤\}}||jk�r4�qt	|j
d�}
|j|
_||
_t|
ƒ}||_|||<|D]T}
|
d}|j |¡| |
¡|j|<|d
 |tƒ¡ |¡| |
¡|d|<�qh�qWn@tk
�r}z |j t|ƒ¡t d|¡W5d}~XYnX|S)Nr§z%s/jsonršr˜rarƒr¾r¿rÀrœr,r›ZreleaseszJSON fetch failed: %s) rr¸rrHÚopenÚreadÚdecodeÚjsonÚloadsrr5rarƒrNr¾r¿rÀrr£r«r¢r™r›r r¡ÚitemsrŒrKÚputrrpÚ	exception)r9rarQr,ÚresprÁr°r¥r¤rœr˜rƒZinfosZomdÚodistrRr.r.r/rbÓsT




	zPyPIJSONLocator._get_projectrÂr.r.r»r/rÄÄsrÄc@s`eZdZdZe dejejBejB¡Z	e dejejB¡Z
dd„Ze dej¡Ze
dd„ƒZd	S)
ÚPagez4
    This class represents a scraped HTML page.
    zÝ
(rel\s*=\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\s
]*))\s+)?
href\s*=\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\s
]*))
(\s+rel\s*=\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\s
]*)))?
z!]+)cCs4||_||_|_|j |j¡}|r0| d¡|_dS)zk
        Initialise an instance with the Unicode page contents and the URL they
        came from.
        rN)rÁr¸r,Ú_baseÚsearchÚgroup)r9rÁr,r’r.r.r/rLs
z
Page.__init__z[^a-z0-9$&+,/:;=?@.#%_\\|-]cCs¾dd„}tƒ}|j |j¡D]Š}| d¡}|dpX|dpX|dpX|dpX|dpX|d	}|d
pp|dpp|d}t|j|ƒ}t|ƒ}|j 	d
d„|¡}| 
||f¡qt|dd„dd�}|S)zâ
        Return the URLs of all the links on a page together with information
        about their "rel" attribute, for determining which ones to treat as
        downloads and which ones to queue for further scraping.
        cSs,t|ƒ\}}}}}}t||t|ƒ|||fƒS)zTidy up an URL.)rrr)r,r5rmrir�r�r‘r.r.r/Úclean-sÿzPage.links..cleanr3Zrel1Zrel2Zrel3Zrel4Zrel5Zrel6rrrsZurl3cSsdt| d¡ƒS)Nz%%%2xr)ÚordrÓ)r’r.r.r/Ú;ózPage.links..cSs|dS)Nrr.)rnr.r.r/rÖ?r×T)r?Úreverse)r¡Ú_hrefÚfinditerrÁÚ	groupdictrr¸rÚ	_clean_reÚsubr¢rª)r9rÔrQr‰r°Úrelr,r.r.r/Úlinks&s$
ÿÿÿz
Page.linksN)r@rArBrCÚreÚcompileÚIÚSÚXrÙrÑrLrÜrrßr.r.r.r/rÐ	sürÐcs˜eZdZdZejdd„dd„dœZd‡fdd	„	Zd
d„Zdd
„Z	dd„Z
e dej
¡Zdd„Zdd„Zdd„Zdd„Zdd„Ze d¡Zdd„Z‡ZS)ÚSimpleScrapingLocatorzã
    A locator which scrapes HTML pages to locate downloads for a distribution.
    This runs multiple threads to do the I/O; performance is at least as good
    as pip's PackageFinder, which works in an analogous fashion.
    cCstjttƒd� ¡S)N)Zfileobj)ÚgzipZGzipFilerr°rÇ©Úbr.r.r/rÖMr×zSimpleScrapingLocator.cCs|SrVr.rçr.r.r/rÖNr×)ZdeflateræZnoneNé
csltt|ƒjf|Žt|ƒ|_||_i|_tƒ|_t	 
¡|_tƒ|_d|_
||_t ¡|_t ¡|_d|_dS)a¤
        Initialise an instance.
        :param url: The root URL to use for scraping.
        :param timeout: The timeout, in seconds, to be applied to requests.
                        This defaults to ``None`` (no timeout specified).
        :param num_workers: The number of worker threads you want to do I/O,
                            This defaults to 10.
        :param kwargs: Passed to the superclass.
        FN)r·rårLrr¸r(Ú_page_cacher¡Ú_seenr
rJÚ	_to_fetchÚ
_bad_hostsÚskip_externalsÚnum_workersÚ	threadingÚRLockÚ_lockÚ_gplockÚplatform_check)r9r,r(rïrºr»r.r/rLQs




zSimpleScrapingLocator.__init__cCsFg|_t|jƒD]0}tj|jd�}| d¡| ¡|j |¡qdS)z¾
        Threads are created only when get_project is called, and terminate
        before it returns. They are there primarily to parallelise I/O (i.e.
        fetching web pages).
        )ÚtargetTN)	Ú_threadsÚrangerïrðZThreadÚ_fetchZ	setDaemonÚstartrO)r9Úirnr.r.r/Ú_prepare_threadsls
z&SimpleScrapingLocator._prepare_threadscCs6|jD]}|j d¡q|jD]}| ¡qg|_dS)zu
        Tell all the threads to terminate (by sending a sentinel value) and
        wait for them to do so.
        N)rörìrÌr~)r9rnr.r.r/Ú
_wait_threadsys



z#SimpleScrapingLocator._wait_threadsc	Cs’iidœ}|j�x||_||_t|jdt|ƒƒ}|j ¡|j ¡| 	¡z&t d|¡|j
 |¡|j
 ¡W5| 
¡X|`W5QRX|S)Nr§z%s/zQueueing %s)rórQrxrr¸rrërWrêrûrürprqrìrÌr~)r9rarQr,r.r.r/rb†s



z"SimpleScrapingLocator._get_projectz<\b(linux_(i\d86|x86_64|arm\w+)|win(32|_amd64)|macosx_?\d+)\bcCs|j |¡S)zD
        Does an URL refer to a platform-specific download?
        )Úplatform_dependentrÒ)r9r,r.r.r/Ú_is_platform_dependent›sz,SimpleScrapingLocator._is_platform_dependentc	CsZ|jr| |¡rd}n| ||j¡}t d||¡|rV|j�| |j|¡W5QRX|S)a%
        See if an URL is a suitable download for a project.

        If it is, register information in the result dictionary (for
        _get_project) about the specific version it's for.

        Note that the return value isn't actually used other than as a boolean
        value.
        Nzprocess_download: %s -> %s)	rôrþr–rxrprqròr¦rQ)r9r,r˜r.r.r/Ú_process_download¡s
z'SimpleScrapingLocator._process_downloadc
CsÄt|ƒ\}}}}}}| |j|j|j¡r2d}n||jrJ| |j¡sJd}nd| |j¡s\d}nR|dkrjd}nD|dkrxd}n6| |¡rˆd}n&| 	dd¡d}	|	 
¡dkrªd}nd}t d	||||¡|S)
z‘
        Determine whether a link URL from a referring page and with a
        particular "rel" attribute should be queued for scraping.
        F)ZhomepageZdownload)ZhttprfZftpú:rrZ	localhostTz#should_queue: %s (%s) from %s -> %s)
rrjr²r³r´rîr‡r¸rþÚsplitr†rprq)
r9ÚlinkZreferrerrÞr5rmriÚ_rQÚhostr.r.r/Ú
_should_queueµs0ÿ

ÿz#SimpleScrapingLocator._should_queuec
Csð|j ¡}zÌz”|rž| |¡}|dkr,WW¢®q|jD]j\}}||jkr2zB|j |¡| |¡s„| |||¡r„t	 
d||¡|j |¡Wq2tk
ršYq2Xq2Wn2t
k
rÒ}z|j t|ƒ¡W5d}~XYnXW5|j ¡X|sqìqdS)z×
        Get a URL to fetch from the work queue, get the HTML page, examine its
        links for download candidates and candidates for further scraping.

        This is a handy method to run in a thread.
        NzQueueing %s from %s)rìrNrPÚget_pagerßrër¢rÿrrprqrÌrrŒrKr)r9r,ÚpagerrÞrRr.r.r/røÒs,



ÿ&zSimpleScrapingLocator._fetchcCsXt|ƒ\}}}}}}|dkr:tj t|ƒ¡r:tt|ƒdƒ}||jkr`|j|}t 	d||¡�nô| 
dd¡d}d}||jkr�t 	d||¡�nÄt|d	d
id�}�z¤zât 	d|¡|j
j||jd
�}	t 	d|¡|	 ¡}
|
 dd¡}t |¡�r„|	 ¡}|	 ¡}
|
 d¡}|�r"|j|}||
ƒ}
d}t |¡}|�r@| d¡}z|
 |¡}
Wn tk
�rn|
 d¡}
YnXt|
|ƒ}||j|<Wn¼tk
�rÄ}z|jdk�r´t d||¡W5d}~XYn€t k
�r}z0t d||¡|j!�|j "|¡W5QRXW5d}~XYn2t#k
�rB}zt d||¡W5d}~XYnXW5||j|<X|S)a
        Get the HTML for an URL, possibly from an in-memory cache.

        XXX TODO Note: this cache is never actually cleared. It's assumed that
        the data won't get stale over the lifetime of a locator instance (not
        necessarily true for the default_locator).
        Úfilez
index.htmlzReturning %s from cache: %srrrNzSkipping %s due to bad host %szAccept-encodingZidentity)r>zFetching %sr'z
Fetched %szContent-Typer3zContent-Encodingzutf-8zlatin-1i”zFetch failed: %s: %s)$rÚosriÚisdirrrrrêrprqrrírrHrÆr(r˜rNÚHTML_CONTENT_TYPEr‰ZgeturlrÇÚdecodersÚCHARSETrÒrÓrÈÚUnicodeErrorrÐrr<rÍrròr¢rŒ)r9r,r5rmrirrQrr:rÎr>Zcontent_typeZ	final_urlrÁÚencodingÚdecoderr’rRr.r.r/rósZ	







&$zSimpleScrapingLocator.get_pagez]*>([^<]+)[\w-]+)\s*\(\s*(==\s*)?(?P[^)]+)\)$c@sLeZdZdZddd„Zdd„Zdd„Zd	d
„Zdd„Zd
d„Z	ddd„Z
dS)ÚDependencyFinderz0
    Locate dependencies for distributions.
    NcCs|pt|_t|jjƒ|_dS)zf
        Initialise an instance, using the specified locator
        to locate distributions.
        N)Údefault_locatorr£r"r5r)r.r.r/rL*s
zDependencyFinder.__init__cCsrt d|¡|j}||j|<||j||jf<|jD]:}t|ƒ\}}t d|||¡|j 	|t
ƒ¡ ||f¡q2dS)z¨
        Add a distribution to the finder. This will update internal information
        about who provides what.
        :param dist: The distribution to add.
        zadding distribution %szAdd to provided: %s, %s, %sN)rprqr?Ú
dists_by_nameÚdistsrƒÚprovidesrÚprovidedr r¡r¢)r9r¤raÚprƒr.r.r/Úadd_distribution2s

z!DependencyFinder.add_distributioncCsxt d|¡|j}|j|=|j||jf=|jD]D}t|ƒ\}}t d|||¡|j|}| 	||f¡|s.|j|=q.dS)z°
        Remove a distribution from the finder. This will update internal
        information about who provides what.
        :param dist: The distribution to remove.
        zremoving distribution %sz Remove from provided: %s, %s, %sN)
rprqr?r0r1rƒr2rr3Úremove)r9r¤rar4rƒÚsr.r.r/Úremove_distributionAs

z$DependencyFinder.remove_distributioncCsBz|j |¡}Wn,tk
r<| ¡d}|j |¡}YnX|S)zÞ
        Get a version matcher for a requirement.
        :param reqt: The requirement
        :type reqt: str
        :return: A version matcher (an instance of
                 :class:`distlib.version.Matcher`).
        r)r5rIr#r)r9ÚreqtrIrar.r.r/Úget_matcherSszDependencyFinder.get_matcherc		Cst| |¡}|j}tƒ}|j}||krp||D]B\}}z| |¡}Wntk
rZd}YnX|r,| |¡qpq,|S)zÓ
        Find the distributions which can fulfill a requirement.

        :param reqt: The requirement.
         :type reqt: str
        :return: A set of distribution which can fulfill the requirement.
        F)r:r?r¡r3r‰r#r¢)	r9r9rIrarQr3rƒÚproviderr‰r.r.r/Úfind_providerscs


zDependencyFinder.find_providersc	Csž|j|}tƒ}|D]$}| |¡}| |j¡s| |¡q|rZ| d||t|ƒf¡d}n@| |¡|j|=|D]}|j |tƒ¡ |¡qp| 	|¡d}|S)aŠ
        Attempt to replace one provider with another. This is typically used
        when resolving dependencies from multiple sources, e.g. A requires
        (B >= 1.0) while C requires (B >= 1.1).

        For successful replacement, ``provider`` must meet all the requirements
        which ``other`` fulfills.

        :param provider: The provider we are trying to replace with.
        :param other: The provider we're trying to replace.
        :param problems: If False is returned, this will contain what
                         problems prevented replacement. This is currently
                         a tuple of the literal string 'cantreplace',
                         ``provider``, ``other``  and the set of requirements
                         that ``provider`` couldn't fulfill.
        :return: True if we can replace ``other`` with ``provider``, else
                 False.
        ZcantreplaceFT)
Úreqtsr¡r:r‰rƒr¢Ú	frozensetr8r r5)	r9r;ÚotherÚproblemsZrlistZ	unmatchedr7rIrQr.r.r/Útry_to_replace{s$


ÿ

zDependencyFinder.try_to_replaceFcCsòi|_i|_i|_i|_t|p gƒ}d|krH| d¡|tdddgƒO}t|tƒrh|}}t 	d|¡n4|j
j||d�}}|dkr�td|ƒ‚t 	d	|¡d
|_
tƒ}t|gƒ}t|gƒ}|�r¤| ¡}|j}	|	|jkræ| |¡n"|j|	}
|
|k�r| ||
|¡|j|jB}|j}tƒ}
|�r`||k�r`dD]*}d|}||k�r4|
t|d
|ƒO}
�q4||B|
B}|D�].}| |¡}|�sFt 	d|¡|j
j||d�}|dk�rÂ|�sÂ|j
j|d
d�}|dk�rèt 	d|¡| d|f¡n^|j|j}}||f|jk�r| |¡| |¡||k�rF||k�rF| |¡t 	d|j¡|D]R}|j}	|	|jk�rx|j |tƒ¡ |¡n"|j|	}
|
|k�rJ| ||
|¡�qJ�qpq¼t|j ¡ƒ}|D]&}||k|_|j�r¶t 	d|j¡�q¶t 	d|¡||fS)aŽ
        Find a distribution and all distributions it depends on.

        :param requirement: The requirement specifying the distribution to
                            find, or a Distribution instance.
        :param meta_extras: A list of meta extras such as :test:, :build: and
                            so on.
        :param prereleases: If ``True``, allow pre-release versions to be
                            returned - otherwise, don't return prereleases
                            unless they're all that's available.

        Return a set of :class:`Distribution` instances and a set of
        problems.

        The distributions returned should be such that they have the
        :attr:`required` attribute set to ``True`` if they were
        from the ``requirement`` passed to ``find()``, and they have the
        :attr:`build_time_dependency` attribute set to ``True`` unless they
        are post-installation dependencies of the ``requirement``.

        The problems should be a tuple consisting of the string
        ``'unsatisfied'`` and the requirement which couldn't be satisfied
        by any distribution known to the locator.
        z:*:z:test:z:build:z:dev:zpassed %s as requirement)r¬NzUnable to locate %rz
located %sT)ZtestZbuildZdevz:%s:z%s_requireszNo providers found for %rzCannot satisfy %rZunsatisfiedzAdding %s to install_distsz#%s is a build-time dependency only.zfind done for %s)r3r1r0r=r¡r6r#rrprqr£r±rZ	requestedr�r?r5rAZrun_requiresZ
meta_requiresZbuild_requiresÚgetattrr<r¢rƒZname_and_versionr ÚvaluesZbuild_time_dependency)r9r¨Zmeta_extrasr¬r¤rÏr@ZtodoZ
install_distsrar?ZireqtsZsreqtsZereqtsr?rRZ	all_reqtsr­Z	providersr;Únr�r4r1r.r.r/Úfind£s’

ÿ












ÿ


ÿzDependencyFinder.find)N)NF)r@rArBrCrLr5r8r:r<rArEr.r.r.r/r.%s
(r.)N)OræÚiorrÉZloggingr	rgràrðÚImportErrorZdummy_threadingrr3rÚcompatrrrrr	r
rrr
rrr7rrrrZdatabaserrrržrrÚutilrrrrrrrr r!rƒr"r#r•r$r%Z	getLoggerr@rprárˆrâr
rr*r0r1ÚobjectrDr¶rÄrÐrårrr"r&r/r±ZNAME_VERSION_REr.r.r.r.r/Ús^D,



@0E:zA&[ÿü
PKÔ¶N]±#ã×Ksite-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eKã@snddlZdZGdd„deƒZzddlmZWn&ek
rRGdd„dejƒZYnXe e¡Z	e	 
eƒ¡dS)éNz0.2.9.post0c@seZdZdS)ÚDistlibExceptionN)Ú__name__Ú
__module__Ú__qualname__©rrú@/usr/lib/python3.8/site-packages/pip/_vendor/distlib/__init__.pyrsr)ÚNullHandlerc@s$eZdZdd„Zdd„Zdd„ZdS)rcCsdS©Nr©ÚselfÚrecordrrrÚhandleózNullHandler.handlecCsdSr	rr
rrrÚemitrzNullHandler.emitcCs
d|_dSr	)Úlock)rrrrÚ
createLockrzNullHandler.createLockN)rrrr
rrrrrrrsr)ZloggingÚ__version__Ú	ExceptionrrÚImportErrorZHandlerZ	getLoggerrZloggerZ
addHandlerrrrrÚs
PKÔ¶N]ºéºÜ*Ü*Fsite-packages/pip/_vendor/distlib/__pycache__/resources.cpython-38.pycnu„[µü¤U

ÀÒ.e*ã	@sˆddlmZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlmZddl
mZmZmZmZe e¡ZdaGdd„deƒZGdd	„d	eƒZGd
d„deƒZGdd
„d
eƒZGdd„deƒZGdd„deƒZedƒee
jeiZzFzddl Z!Wne"k
�r$ddl#Z!YnXeee!j$<eee!j%<[!Wne"e&fk
�rXYnXdd„Z'iZ(dd„Z)e	 *e+dƒ¡Z,dd„Z-dS)é)Úunicode_literalsNé)ÚDistlibException)Úcached_propertyÚget_cache_baseÚpath_to_cache_dirÚCachecs.eZdZd‡fdd„	Zdd„Zdd„Z‡ZS)	Ú
ResourceCacheNcs0|dkrtj tƒtdƒ¡}tt|ƒ |¡dS)Nzresource-cache)ÚosÚpathÚjoinrÚstrÚsuperr	Ú__init__)ÚselfÚbase©Ú	__class__©úA/usr/lib/python3.8/site-packages/pip/_vendor/distlib/resources.pyrszResourceCache.__init__cCsdS)zã
        Is the cache stale for the given resource?

        :param resource: The :class:`Resource` being cached.
        :param path: The path of the resource in the cache.
        :return: True if the cache is stale.
        Tr©rÚresourcerrrrÚis_stale#s	zResourceCache.is_stalec	Cs |j |¡\}}|dkr|}n~tj |j| |¡|¡}tj |¡}tj |¡sXt 	|¡tj 
|¡sjd}n| ||¡}|rœt|dƒ�}| 
|j¡W5QRX|S)z¤
        Get a resource into the cache,

        :param resource: A :class:`Resource` instance.
        :return: The pathname of the resource in the cache.
        NTÚwb)ÚfinderÚget_cache_infor
rrrZ
prefix_to_dirÚdirnameÚisdirÚmakedirsÚexistsrÚopenÚwriteÚbytes)rrÚprefixrÚresultrZstaleÚfrrrÚget.s
zResourceCache.get)N)Ú__name__Ú
__module__Ú__qualname__rrr&Ú
__classcell__rrrrr	sr	c@seZdZdd„ZdS)ÚResourceBasecCs||_||_dS©N)rÚname)rrr-rrrrIszResourceBase.__init__N)r'r(r)rrrrrr+Hsr+c@s@eZdZdZdZdd„Zedd„ƒZedd„ƒZed	d
„ƒZ	dS)ÚResourcezÇ
    A class representing an in-package resource, such as a data file. This is
    not normally instantiated by user code, but rather by a
    :class:`ResourceFinder` which manages the resource.
    FcCs|j |¡S)z’
        Get the resource as a stream.

        This is not a property to make it obvious that it returns a new stream
        each time.
        )rÚ
get_stream©rrrrÚ	as_streamVszResource.as_streamcCstdkrtƒat |¡Sr,)Úcacher	r&r0rrrÚ	file_path_szResource.file_pathcCs|j |¡Sr,)rÚ	get_bytesr0rrrr"fszResource.bytescCs|j |¡Sr,)rÚget_sizer0rrrÚsizejsz
Resource.sizeN)
r'r(r)Ú__doc__Úis_containerr1rr3r"r6rrrrr.Ns	

r.c@seZdZdZedd„ƒZdS)ÚResourceContainerTcCs|j |¡Sr,)rÚ
get_resourcesr0rrrÚ	resourcesrszResourceContainer.resourcesN)r'r(r)r8rr;rrrrr9osr9c@s’eZdZdZej d¡rdZndZdd„Zdd„Z	d	d
„Z
dd„Zd
d„Zdd„Z
dd„Zdd„Zdd„Zdd„Zdd„ZeejjƒZdd„ZdS)ÚResourceFinderz4
    Resource finder for file system resources.
    Újava)ú.pycú.pyoz.class)r>r?cCs.||_t|ddƒ|_tj t|ddƒ¡|_dS)NÚ
__loader__Ú__file__Ú)ÚmoduleÚgetattrÚloaderr
rrr)rrCrrrr�szResourceFinder.__init__cCstj |¡Sr,)r
rÚrealpath©rrrrrÚ_adjust_path†szResourceFinder._adjust_pathcCsBt|tƒrd}nd}| |¡}| d|j¡tjj|Ž}| |¡S)Nó/ú/r)	Ú
isinstancer"ÚsplitÚinsertrr
rrrH)rÚ
resource_nameÚsepÚpartsr$rrrÚ
_make_path‰s

zResourceFinder._make_pathcCstj |¡Sr,)r
rrrGrrrÚ_find•szResourceFinder._findcCs
d|jfSr,)r©rrrrrr˜szResourceFinder.get_cache_infocCsD| |¡}| |¡sd}n&| |¡r0t||ƒ}n
t||ƒ}||_|Sr,)rQrRÚ
_is_directoryr9r.r)rrNrr$rrrÚfind›s



zResourceFinder.findcCst|jdƒS©NÚrb)r rrSrrrr/§szResourceFinder.get_streamc
Cs,t|jdƒ�}| ¡W5QR£SQRXdSrV)r rÚread)rrr%rrrr4ªszResourceFinder.get_bytescCstj |j¡Sr,)r
rÚgetsizerSrrrr5®szResourceFinder.get_sizecs*‡fdd„‰t‡fdd„t |j¡DƒƒS)Ncs|dko| ˆj¡S)NÚ__pycache__)ÚendswithÚskipped_extensions)r%r0rrÚallowed²s
ÿz-ResourceFinder.get_resources..allowedcsg|]}ˆ|ƒr|‘qSrr)Ú.0r%)r]rrÚ
µsz0ResourceFinder.get_resources..)Úsetr
ÚlistdirrrSr)r]rrr:±szResourceFinder.get_resourcescCs| |j¡Sr,)rTrrSrrrr8·szResourceFinder.is_containerccs„| |¡}|dk	r€|g}|r€| d¡}|V|jr|j}|jD]>}|sL|}nd ||g¡}| |¡}|jrv| |¡q>|Vq>qdS)NrrJ)rUÚpopr8r-r;rÚappend)rrNrZtodoZrnamer-Únew_nameZchildrrrÚiterator¼s 



zResourceFinder.iteratorN)r'r(r)r7ÚsysÚplatformÚ
startswithr\rrHrQrRrrUr/r4r5r:r8Ústaticmethodr
rrrTrerrrrr<ws"r<cs`eZdZdZ‡fdd„Zdd„Zdd„Zdd	„Zd
d„Zdd
„Z	dd„Z
dd„Zdd„Z‡Z
S)ÚZipResourceFinderz6
    Resource finder for resources in .zip files.
    csZtt|ƒ |¡|jj}dt|ƒ|_t|jdƒr>|jj|_nt	j
||_t|jƒ|_dS)NrÚ_files)
rrjrrEÚarchiveÚlenÚ
prefix_lenÚhasattrrkÚ	zipimportÚ_zip_directory_cacheÚsortedÚindex)rrCrlrrrrÕszZipResourceFinder.__init__cCs|Sr,rrGrrrrHàszZipResourceFinder._adjust_pathcCs¤||jd…}||jkrd}nX|r:|dtjkr:|tj}t |j|¡}z|j| |¡}Wntk
rtd}YnX|sŽt 	d||j
j¡nt 	d||j
j¡|S)NTéÿÿÿÿFz_find failed: %r %rz_find worked: %r %r)rnrkr
rOÚbisectrsrhÚ
IndexErrorÚloggerÚdebugrEr#)rrr$ÚirrrrRãs


zZipResourceFinder._findcCs&|jj}|jdt|ƒd…}||fS)Nr)rErlrrm)rrr#rrrrrõsz ZipResourceFinder.get_cache_infocCs|j |j¡Sr,)rEÚget_datarrSrrrr4úszZipResourceFinder.get_bytescCst | |¡¡Sr,)ÚioÚBytesIOr4rSrrrr/ýszZipResourceFinder.get_streamcCs|j|jd…}|j|dS)Né)rrnrkrrrrr5szZipResourceFinder.get_sizecCs |j|jd…}|r,|dtjkr,|tj7}t|ƒ}tƒ}t |j|¡}|t|jƒkrœ|j| |¡shqœ|j||d…}| 	| 
tjd¡d¡|d7}qH|S)Nrtrr)rrnr
rOrmr`rursrhÚaddrL)rrrZplenr$ryÚsrrrr:s

zZipResourceFinder.get_resourcescCsj||jd…}|r*|dtjkr*|tj7}t |j|¡}z|j| |¡}Wntk
rdd}YnX|S)NrtF)rnr
rOrursrhrv)rrryr$rrrrTs

zZipResourceFinder._is_directory)r'r(r)r7rrHrRrr4r/r5r:rTr*rrrrrjÑsrjcCs|tt|ƒ<dSr,)Ú_finder_registryÚtype)rEÚfinder_makerrrrÚregister_finder0srƒcCsŒ|tkrt|}nv|tjkr$t|ƒtj|}t|ddƒ}|dkrJtdƒ‚t|ddƒ}t t|ƒ¡}|dkrxtd|ƒ‚||ƒ}|t|<|S)zŸ
    Return a resource finder for a package.
    :param package: The name of the package.
    :return: A :class:`ResourceFinder` instance for the package.
    Ú__path__Nz8You cannot get a finder for a module, only for a packager@zUnable to locate finder for %r)	Ú
_finder_cacherfÚmodulesÚ
__import__rDrr€r&r�)Úpackager$rCrrEr‚rrrr6s


rZ	__dummy__cCsRd}t |¡tj |¡}t t|ƒ¡}|rNt}tj	 
|d¡|_||_||ƒ}|S)z¬
    Return a resource finder for a path, which should represent a container.

    :param path: The path.
    :return: A :class:`ResourceFinder` instance for the path.
    NrB)
ÚpkgutilZget_importerrfÚpath_importer_cacher&r€r�Ú
_dummy_moduler
rrrAr@)rr$rErrCrrrÚfinder_for_pathRs
rŒ).Z
__future__rrur{Zloggingr
r‰ZshutilrfÚtypesrprBrÚutilrrrrZ	getLoggerr'rwr2r	Úobjectr+r.r9r<rjr�Úzipimporterr€Ú_frozen_importlib_externalZ_fiÚImportErrorÚ_frozen_importlibÚSourceFileLoaderÚ
FileFinderÚAttributeErrorrƒr…rÚ
ModuleTyper
r‹rŒrrrrÚsN
,!ZNþ

PKÔ¶N]ÊáÞàmmDsite-packages/pip/_vendor/distlib/__pycache__/markers.cpython-38.pycnu„[µü¤U

ÀÒ.e#ã@sŠdZddlZddlZddlZddlZddlmZmZmZddl	m
Z
mZdgZdd„Z
Gd	d
„d
eƒZdd„ZeƒZ[eƒZdd
d„ZdS)zG
Parser for the environment markers micro-language defined in PEP 508.
éNé)Úpython_implementationÚurlparseÚstring_types)Úin_venvÚparse_markerÚ	interpretcCst|tƒr|sdS|ddkS)NFrú'")Ú
isinstancer)Úo©rú?/usr/lib/python3.8/site-packages/pip/_vendor/distlib/markers.pyÚ_is_literalsrc
@sfeZdZdZdd„dd„dd„dd„dd„dd„d	d„d
d„dd„dd„d
d„dd„dœZdd„ZdS)Ú	Evaluatorz;
    This class is used to evaluate marker expessions.
    cCs||kS©Nr©ÚxÚyrrr
Ú$ózEvaluator.cCs||kSrrrrrr
r%rcCs||kp||kSrrrrrr
r&rcCs||kSrrrrrr
r'rcCs||kSrrrrrr
r(rcCs||kp||kSrrrrrr
r)rcCs||kSrrrrrr
r*rcCs||kp||kSrrrrrr
r+rcCs|o|Srrrrrr
r,rcCs|p|Srrrrrr
r-rcCs||kSrrrrrr
r.rcCs||kSrrrrrr
r/r)z==z===z~=z!=úz>=ÚandÚorÚinznot inc	CsÔt|tƒrB|ddkr$|dd…}qÐ||kr8td|ƒ‚||}nŽt|tƒsPt‚|d}||jkrntd|ƒ‚|d}|d	}t|dƒr¨t|d	ƒr¨td
|||fƒ‚| ||¡}| ||¡}|j|||ƒ}|S)zƒ
        Evaluate a marker expression returned by the :func:`parse_requirement`
        function in the specified context.
        rr	réÿÿÿÿzunknown variable: %sÚopzop not implemented: %sÚlhsÚrhszinvalid comparison: %s %s %s)	r
rÚSyntaxErrorÚdictÚAssertionErrorÚ
operationsÚNotImplementedErrorrÚevaluate)	ÚselfÚexprÚcontextÚresultrZelhsZerhsrrrrr
r$2s$


zEvaluator.evaluateN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r"r$rrrr
rsôrc
Cs€dd„}ttdƒr(|tjjƒ}tjj}nd}d}||tjt ¡t ¡t 	¡t 
¡t ¡ttƒƒt 
¡t 
¡dd…tjdœ}|S)NcSs<d|j|j|jf}|j}|dkr8||dt|jƒ7}|S)Nz%s.%s.%sÚfinalr)ÚmajorÚminorÚmicroÚreleaselevelÚstrÚserial)ÚinfoÚversionZkindrrr
Úformat_full_versionNs
z,default_context..format_full_versionÚimplementationÚ0Úé)Úimplementation_nameÚimplementation_versionZos_nameZplatform_machineZplatform_python_implementationZplatform_releaseZplatform_systemZplatform_versionZplatform_in_venvZpython_full_versionÚpython_versionZsys_platform)ÚhasattrÚsysr7r5ÚnameÚosÚplatformÚmachinerÚreleaseÚsystemr2rr=)r6r<r;r(rrr
Údefault_contextMs(

ôrFc
Cs†zt|ƒ\}}Wn2tk
rB}ztd||fƒ‚W5d}~XYnX|rd|ddkrdtd||fƒ‚ttƒ}|rz| |¡t ||¡S)zò
    Interpret a marker and return a result depending on environment.

    :param marker: The marker to interpret.
    :type marker: str
    :param execution_context: The context used for name lookup.
    :type execution_context: mapping
    z)Unable to interpret marker syntax: %s: %sNrú#z*unexpected trailing data in marker: %s: %s)rÚ	Exceptionrr ÚDEFAULT_CONTEXTÚupdateÚ	evaluatorr$)ZmarkerZexecution_contextr&ÚrestÚer'rrr
rqs	"
)N)r,rAr?rBÚreÚcompatrrrÚutilrrÚ__all__rÚobjectrrFrIrKrrrrr
Ús/PKÔ¶N]q~�~e'e'Ksite-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eÛ9ã@s¤dZddlZddlZddlZddlZddlZddlmZddlm	Z	ddl
mZdgZe 
e¡Ze dej¡Ze d	ejejB¡Zejdd
…ZGdd„deƒZdS)zu
Class representing the list of files in a distribution.

Equivalent to distutils.filelist, but fixes some problems.
éNé)ÚDistlibException)Úfsdecode©Úconvert_pathÚManifestz\\w*
z#.*?(?=
)|
(?=$)éc@szeZdZdZddd„Zdd„Zdd„Zd	d
„Zddd
„Zdd„Z	dd„Z
dd„Zddd„Zd dd„Z
d!dd„Zdd„ZdS)"rz~A list of files built by on exploring the filesystem and filtered by
    applying various patterns to what we find there.
    NcCs>tj tj |pt ¡¡¡|_|jtj|_d|_t	ƒ|_
dS)zd
        Initialise an instance.

        :param base: The base directory to explore under.
        N)ÚosÚpathÚabspathÚnormpathÚgetcwdÚbaseÚsepÚprefixÚallfilesÚsetÚfiles)Úselfr©rú@/usr/lib/python3.8/site-packages/pip/_vendor/distlib/manifest.pyÚ__init__*szManifest.__init__cCs¨ddlm}m}m}g|_}|j}|g}|j}|j}|r¤|ƒ}t 	|¡}	|	D]R}
tj
 ||
¡}t |¡}|j}
||
ƒrˆ| t
|ƒ¡qN||
ƒrN||
ƒsN||ƒqNq6dS)zmFind all files under the base and set ``allfiles`` to the absolute
        pathnames of files found.
        r)ÚS_ISREGÚS_ISDIRÚS_ISLNKN)ÚstatrrrrrÚpopÚappendr	Úlistdirr
ÚjoinÚst_moder)rrrrrÚrootÚstackrÚpushÚnamesÚnameÚfullnamerÚmoderrrÚfindall9s"


zManifest.findallcCs4| |j¡stj |j|¡}|j tj |¡¡dS)zz
        Add a file to the manifest.

        :param item: The pathname to add. This can be relative to the base.
        N)	Ú
startswithrr	r
rrrÚaddr)rÚitemrrrr*TszManifest.addcCs|D]}| |¡qdS)z†
        Add a list of files to the manifest.

        :param items: The pathnames to add. These can be relative to the base.
        N)r*)rÚitemsr+rrrÚadd_many^szManifest.add_manyFcsb‡‡fdd„‰tˆjƒ}|rFtƒ}|D]}ˆ|tj |¡ƒq&||O}dd„tdd„|DƒƒDƒS)z8
        Return sorted files in directory order
        cs>| |¡t d|¡|ˆjkr:tj |¡\}}ˆ||ƒdS)Nzadd_dir added %s)r*ÚloggerÚdebugrr	r
Úsplit)ÚdirsÚdÚparentÚ_©Úadd_dirrrrr6ls


z Manifest.sorted..add_dircSsg|]}tjj|ޑqSr)r	r
r)Ú.0Z
path_tuplerrrÚ
zsz#Manifest.sorted..css|]}tj |¡VqdS)N)r	r
r0)r7r
rrrÚ	{sz"Manifest.sorted..)rrr	r
ÚdirnameÚsorted)rZwantdirsÚresultr1Úfrr5rr;gs
ÿzManifest.sortedcCstƒ|_g|_dS)zClear all collected files.N)rrr)rrrrÚclear}szManifest.clearcCsj| |¡\}}}}|dkrB|D]}|j|dd�st d|¡q�n$|dkrf|D]}|j|dd�}qN�n|dkr”|D]}|j|dd�srt d|¡qrnÒ|d	kr¶|D]}|j|dd�}q n°|d
kræ|D] }|j||d�sÂt d||¡qÂn€|d
k�r
|D]}|j||d�}qôn\|dk�r2|jd|d��sft d|¡n4|dk�rZ|jd|d��sft d|¡ntd|ƒ‚dS)av
        Process a directive which either adds some files from ``allfiles`` to
        ``files``, or removes some files from ``files``.

        :param directive: The directive to process. This should be in a format
                     compatible with distutils ``MANIFEST.in`` files:

                     http://docs.python.org/distutils/sourcedist.html#commands
        ÚincludeT)Úanchorzno files found matching %rÚexcludeúglobal-includeFz3no files found matching %r anywhere in distributionúglobal-excludeúrecursive-include)rz-no files found matching %r under directory %rúrecursive-excludeÚgraftNz no directories found matching %rÚprunez4no previously-included directories found matching %rzinvalid action %r)Ú_parse_directiveÚ_include_patternr.ZwarningÚ_exclude_patternr)rÚ	directiveÚactionÚpatternsÚthedirZ
dirpatternÚpatternÚfoundrrrÚprocess_directive‚sPÿÿ

ÿ
ÿÿzManifest.process_directivecCs| ¡}t|ƒdkr,|ddkr,| dd¡|d}d}}}|dkrxt|ƒdkr`td|ƒ‚d	d
„|dd…Dƒ}n~|dkr¼t|ƒdkr˜td
|ƒ‚t|dƒ}dd
„|dd…Dƒ}n:|dkrêt|ƒdkrÜtd|ƒ‚t|dƒ}ntd|ƒ‚||||fS)zŸ
        Validate a directive.
        :param directive: The directive to validate.
        :return: A tuple of action, patterns, thedir, dir_patterns
        rr)r?rArBrCrDrErFrGr?N)r?rArBrCrz$%r expects   ...cSsg|]}t|ƒ‘qSrr©r7Zwordrrrr8êsz-Manifest._parse_directive..)rDrEéz*%r expects    ...cSsg|]}t|ƒ‘qSrrrRrrrr8òs)rFrGz!%r expects a single zunknown action %r)r0ÚlenÚinsertrr)rrKZwordsrLrMrNZdir_patternrrrrHÑs4ÿÿÿzManifest._parse_directiveTcCsPd}| ||||¡}|jdkr&| ¡|jD]}| |¡r,|j |¡d}q,|S)a…Select strings (presumably filenames) from 'self.files' that
        match 'pattern', a Unix-style wildcard (glob) pattern.

        Patterns are not quite the same as implemented by the 'fnmatch'
        module: '*' and '?'  match non-special characters, where "special"
        is platform-dependent: slash on Unix; colon, slash, and backslash on
        DOS/Windows; and colon on Mac OS.

        If 'anchor' is true (the default), then the pattern match is more
        stringent: "*.py" will match "foo.py" but not "foo/bar.py".  If
        'anchor' is false, both of these will match.

        If 'prefix' is supplied, then only filenames starting with 'prefix'
        (itself a pattern) and ending with 'pattern', with anything in between
        them, will match.  'anchor' is ignored in this case.

        If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and
        'pattern' is assumed to be either a string containing a regex or a
        regex object -- no translation is done, the regex is just compiled
        and used as-is.

        Selected strings will be added to self.files.

        Return True if files are found.
        FNT)Ú_translate_patternrr(Úsearchrr*)rrOr@rÚis_regexrPÚ
pattern_rer%rrrrIs


zManifest._include_patterncCsBd}| ||||¡}t|jƒD]}| |¡r|j |¡d}q|S)atRemove strings (presumably filenames) from 'files' that match
        'pattern'.

        Other parameters are the same as for 'include_pattern()', above.
        The list 'self.files' is modified in place. Return True if files are
        found.

        This API is public to allow e.g. exclusion of SCM subdirs, e.g. when
        packaging source distributions
        FT)rVÚlistrrWÚremove)rrOr@rrXrPrYr=rrrrJ)s
zManifest._exclude_patternc
Csv|rt|tƒrt |¡S|Stdkr:| d¡ d¡\}}}|rR| |¡}tdkrVnd}t tj	 
|jd¡¡}	|dk	�r4tdkr¢| d¡}
| |¡dt|
ƒ…}n&| |¡}|t|ƒt|ƒt|ƒ…}tj
}tj
dkrÜd}tdk�rd|	| 
|d|f¡}n0|t|ƒt|ƒt|ƒ…}d	||	||||f}n8|�rltdk�rRd|	|}nd
||	|t|ƒd…f}t |¡S)aTranslate a shell-like wildcard pattern to a compiled regular
        expression.

        Return the compiled regex.  If 'is_regex' true,
        then 'pattern' is directly compiled to a regex (if it's a string)
        or just returned as-is (assumes it's a regex object).
        )rSrr4ÚNú\z\\ú^z.*z%s%s%s%s.*%s%sz%s%s%s)Ú
isinstanceÚstrÚreÚcompileÚ_PYTHON_VERSIONÚ_glob_to_reÚ	partitionÚescaper	r
rrrTr)
rrOr@rrXÚstartr4ÚendrYrZ
empty_patternZ	prefix_rerrrrrV=sF	







ÿ

ÿ
zManifest._translate_patterncCs8t |¡}tj}tjdkrd}d|}t d||¡}|S)z÷Translate a shell-like glob pattern to a regular expression.

        Return a string containing the regex.  Differs from
        'fnmatch.translate()' in that '*' does not match "special characters"
        (which are platform-specific).
        r]z\\\\z\1[^%s]z((?rQrHrIrJrVrdrrrrr%s&

	
O/ÿ
)ÿ
ÿ
7)roriZloggingr	raÚsysr\rÚcompatrÚutilrÚ__all__Z	getLoggerrlr.rbÚMZ_COLLAPSE_PATTERNÚSZ_COMMENTED_LINEÚversion_inforcÚobjectrrrrrÚs
PKÔ¶N]"îxßCßCHsite-packages/pip/_vendor/distlib/__pycache__/index.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eJRã@sÈddlZddlZddlZddlZddlZddlZzddlmZWn ek
r`ddl	mZYnXddl
mZddlm
Z
mZmZmZmZmZddlmZmZmZe e¡ZdZdZGd	d
„d
eƒZdS)éN)ÚThreadé)ÚDistlibException)ÚHTTPBasicAuthHandlerÚRequestÚHTTPPasswordMgrÚurlparseÚbuild_openerÚstring_types)Úcached_propertyÚzip_dirÚServerProxyzhttps://pypi.org/pypiÚpypic@s¶eZdZdZdZd*dd„Zdd„Zdd	„Zd
d„Zdd
„Z	dd„Z
dd„Zd+dd„Zd,dd„Z
d-dd„Zd.dd„Zdd„Zd/dd„Zd0d d!„Zd1d"d#„Zd$d%„Zd&d'„Zd2d(d)„ZdS)3ÚPackageIndexzc
    This class represents a package index compatible with PyPI, the Python
    Package Index.
    s.----------ThIs_Is_tHe_distlib_index_bouNdaRY_$Nc
CsÊ|pt|_| ¡t|jƒ\}}}}}}|s<|s<|s<|dkrJtd|jƒ‚d|_d|_d|_d|_t	t
jdƒ�R}dD]F}	z,tj
|	dg||d�}
|
dkr¢|	|_Wq¼Wqttk
r¸YqtXqtW5QRXdS)	z”
        Initialise an instance.

        :param url: The URL of the index. If not specified, the URL for PyPI is
                    used.
        )ZhttpZhttpszinvalid repository: %sNÚw)ÚgpgZgpg2z	--version©ÚstdoutÚstderrr)Ú
DEFAULT_INDEXÚurlÚread_configurationrrÚpassword_handlerÚssl_verifierrÚgpg_homeÚopenÚosÚdevnullÚ
subprocessZ
check_callÚOSError)ÚselfrZschemeÚnetlocÚpathZparamsZqueryZfragZsinkÚsÚrc©r%ú=/usr/lib/python3.8/site-packages/pip/_vendor/distlib/index.pyÚ__init__$s(
ÿ
zPackageIndex.__init__cCs&ddlm}ddlm}|ƒ}||ƒS)zs
        Get the distutils command for interacting with PyPI configurations.
        :return: the command.
        r)ÚDistribution)Ú
PyPIRCCommand)Zdistutils.corer(Zdistutils.configr))r r(r)Údr%r%r&Ú_get_pypirc_commandAsz PackageIndex._get_pypirc_commandcCsR| ¡}|j|_| ¡}| d¡|_| d¡|_| dd¡|_| d|j¡|_dS)zç
        Read the PyPI access configuration as supported by distutils, getting
        PyPI to do the actual work. This populates ``username``, ``password``,
        ``realm`` and ``url`` attributes from the configuration.
        ÚusernameÚpasswordÚrealmrÚ
repositoryN)r+rr/Z_read_pypircÚgetr,r-r.)r ÚcZcfgr%r%r&rKszPackageIndex.read_configurationcCs$| ¡| ¡}| |j|j¡dS)zÍ
        Save the PyPI access configuration. You must have set ``username`` and
        ``password`` attributes before calling this method.

        Again, distutils is used to do the actual work.
        N)Úcheck_credentialsr+Z
_store_pypircr,r-)r r1r%r%r&Úsave_configurationZszPackageIndex.save_configurationcCs\|jdks|jdkrtdƒ‚tƒ}t|jƒ\}}}}}}| |j||j|j¡t|ƒ|_	dS)zp
        Check that ``username`` and ``password`` have been set, and raise an
        exception if not.
        Nz!username and password must be set)
r,r-rrrrZadd_passwordr.rr)r ZpmÚ_r!r%r%r&r2fszPackageIndex.check_credentialscCs\| ¡| ¡| ¡}d|d<| | ¡g¡}| |¡}d|d<| | ¡g¡}| |¡S)aq
        Register a distribution on PyPI, using the provided metadata.

        :param metadata: A :class:`Metadata` instance defining at least a name
                         and version number for the distribution to be
                         registered.
        :return: The HTTP response received from PyPI upon submission of the
                request.
        Zverifyú:actionZsubmit)r2ÚvalidateÚtodictÚencode_requestÚitemsÚsend_request)r Úmetadatar*ÚrequestZresponser%r%r&Úregisterrs

zPackageIndex.registercCsF| ¡}|sq:| d¡ ¡}| |¡t d||f¡q| ¡dS)ar
        Thread runner for reading lines of from a subprocess into a buffer.

        :param name: The logical name of the stream (used for logging only).
        :param stream: The stream to read from. This will typically a pipe
                       connected to the output stream of a subprocess.
        :param outbuf: The list to append the read lines to.
        úutf-8z%s: %sN)ÚreadlineÚdecodeÚrstripÚappendÚloggerÚdebugÚclose)r ÚnameÚstreamZoutbufr#r%r%r&Ú_reader†s

zPackageIndex._readerc	Csš|jdddg}|dkr|j}|r.| d|g¡|dk	rF| dddg¡t ¡}tj |tj |¡d	¡}| d
dd|d
||g¡t	 
dd |¡¡||fS)a‰
        Return a suitable command for signing a file.

        :param filename: The pathname to the file to be signed.
        :param signer: The identifier of the signer of the file.
        :param sign_password: The passphrase for the signer's
                              private key used for signing.
        :param keystore: The path to a directory which contains the keys
                         used in verification. If not specified, the
                         instance's ``gpg_home`` attribute is used instead.
        :return: The signing command as a list suitable to be
                 passed to :class:`subprocess.Popen`.
        ú--status-fdÚ2ú--no-ttyNú	--homedirz--batchz--passphrase-fdÚ0z.ascz
--detach-signz--armorz--local-userz--outputúinvoking: %sú )rrÚextendÚtempfileZmkdtemprr"ÚjoinÚbasenamerCrD)r ÚfilenameÚsignerÚ
sign_passwordÚkeystoreÚcmdZtdZsfr%r%r&Úget_sign_command˜s"
ÿzPackageIndex.get_sign_commandc	Cs´tjtjdœ}|dk	r tj|d<g}g}tj|f|Ž}t|jd|j|fd�}| ¡t|jd|j|fd�}| ¡|dk	r�|j 	|¡|j 
¡| ¡| ¡| ¡|j
||fS)aæ
        Run a command in a child process , passing it any input data specified.

        :param cmd: The command to run.
        :param input_data: If specified, this must be a byte string containing
                           data to be sent to the child process.
        :return: A tuple consisting of the subprocess' exit code, a list of
                 lines read from the subprocess' ``stdout``, and a list of
                 lines read from the subprocess' ``stderr``.
        rNÚstdinr)ÚtargetÚargsr)rÚPIPEÚPopenrrHrÚstartrrZÚwriterEÚwaitrRÚ
returncode)	r rXZ
input_dataÚkwargsrrÚpÚt1Út2r%r%r&Úrun_commandµs&þ

zPackageIndex.run_commandc
CsD| ||||¡\}}| || d¡¡\}}}	|dkr@td|ƒ‚|S)aR
        Sign a file.

        :param filename: The pathname to the file to be signed.
        :param signer: The identifier of the signer of the file.
        :param sign_password: The passphrase for the signer's
                              private key used for signing.
        :param keystore: The path to a directory which contains the keys
                         used in signing. If not specified, the instance's
                         ``gpg_home`` attribute is used instead.
        :return: The absolute pathname of the file where the signature is
                 stored.
        r>rz&sign command failed with error code %s)rYrgÚencoder)
r rTrUrVrWrXÚsig_filer$rrr%r%r&Ú	sign_fileØs
ÿÿ
ÿzPackageIndex.sign_fileÚsdistÚsourcec	Cs(| ¡tj |¡s td|ƒ‚| ¡| ¡}d}	|rZ|jsJt 	d¡n| 
||||¡}	t|dƒ�}
|
 ¡}W5QRXt
 |¡ ¡}t
 |¡ ¡}
| dd||||
dœ¡dtj |¡|fg}|	�rt|	dƒ�}
|
 ¡}W5QRX| d	tj |	¡|f¡t tj |	¡¡| | ¡|¡}| |¡S)
a´
        Upload a release file to the index.

        :param metadata: A :class:`Metadata` instance defining at least a name
                         and version number for the file to be uploaded.
        :param filename: The pathname of the file to be uploaded.
        :param signer: The identifier of the signer of the file.
        :param sign_password: The passphrase for the signer's
                              private key used for signing.
        :param filetype: The type of the file being uploaded. This is the
                        distutils command which produced that file, e.g.
                        ``sdist`` or ``bdist_wheel``.
        :param pyversion: The version of Python which the release relates
                          to. For code compatible with any Python, this would
                          be ``source``, otherwise it would be e.g. ``3.2``.
        :param keystore: The path to a directory which contains the keys
                         used in signing. If not specified, the instance's
                         ``gpg_home`` attribute is used instead.
        :return: The HTTP response received from PyPI upon submission of the
                request.
        z
not found: %sNz)no signing program available - not signedÚrbZfile_uploadÚ1)r5Zprotocol_versionÚfiletypeÚ	pyversionÚ
md5_digestÚ
sha256_digestÚcontentZ
gpg_signature)r2rr"Úexistsrr6r7rrCZwarningrjrÚreadÚhashlibÚmd5Ú	hexdigestZsha256ÚupdaterSrBÚshutilZrmtreeÚdirnamer8r9r:)r r;rTrUrVrorprWr*riÚfZ	file_datarqrrÚfilesZsig_datar<r%r%r&Úupload_fileïsD
ÿúÿzPackageIndex.upload_filec
Csœ| ¡tj |¡s td|ƒ‚tj |d¡}tj |¡sFtd|ƒ‚| ¡|j|j	}}t
|ƒ ¡}dd|fd|fg}d||fg}| ||¡}	| 
|	¡S)a2
        Upload documentation to the index.

        :param metadata: A :class:`Metadata` instance defining at least a name
                         and version number for the documentation to be
                         uploaded.
        :param doc_dir: The pathname of the directory which contains the
                        documentation. This should be the directory that
                        contains the ``index.html`` for the documentation.
        :return: The HTTP response received from PyPI upon submission of the
                request.
        znot a directory: %rz
index.htmlz
not found: %r)r5Z
doc_uploadrFÚversionrs)r2rr"ÚisdirrrRrtr6rFrrÚgetvaluer8r:)
r r;Zdoc_dirÚfnrFrZzip_dataÚfieldsr}r<r%r%r&Úupload_documentation(s 
ÿz!PackageIndex.upload_documentationcCsT|jdddg}|dkr|j}|r.| d|g¡| d||g¡t dd |¡¡|S)	a|
        Return a suitable command for verifying a file.

        :param signature_filename: The pathname to the file containing the
                                   signature.
        :param data_filename: The pathname to the file containing the
                              signed data.
        :param keystore: The path to a directory which contains the keys
                         used in verification. If not specified, the
                         instance's ``gpg_home`` attribute is used instead.
        :return: The verifying command as a list suitable to be
                 passed to :class:`subprocess.Popen`.
        rIrJrKNrLz--verifyrNrO)rrrPrCrDrR)r Úsignature_filenameÚ
data_filenamerWrXr%r%r&Úget_verify_commandDszPackageIndex.get_verify_commandcCsH|jstdƒ‚| |||¡}| |¡\}}}|dkr@td|ƒ‚|dkS)a6
        Verify a signature for a file.

        :param signature_filename: The pathname to the file containing the
                                   signature.
        :param data_filename: The pathname to the file containing the
                              signed data.
        :param keystore: The path to a directory which contains the keys
                         used in verification. If not specified, the
                         instance's ``gpg_home`` attribute is used instead.
        :return: True if the signature was verified, else False.
        z0verification unavailable because gpg unavailable)rrz(verify command failed with error code %sr)rrr‡rg)r r…r†rWrXr$rrr%r%r&Úverify_signature\sÿÿzPackageIndex.verify_signaturec	Csl|dkrd}t d¡n6t|ttfƒr0|\}}nd}tt|ƒƒ}t d|¡t|dƒ�®}| t	|ƒ¡}zŽ| ¡}	d}
d}d}d}
d	|	kr–t|	d
ƒ}|r¦||
|
|ƒ| 
|
¡}|s¶qô|t|ƒ7}| |¡|rÚ| |¡|
d7}
|r¦||
|
|ƒq¦W5| 
¡XW5QRX|dk�r0||k�r0td||fƒ‚|�rh| ¡}||k�r\td
||||fƒ‚t d|¡dS)a
        This is a convenience method for downloading a file from an URL.
        Normally, this will be a file from the index, though currently
        no check is made for this (i.e. a file can be downloaded from
        anywhere).

        The method is just like the :func:`urlretrieve` function in the
        standard library, except that it allows digest computation to be
        done during download and checking that the downloaded data
        matched any expected value.

        :param url: The URL of the file to be downloaded (assumed to be
                    available via an HTTP GET request).
        :param destfile: The pathname where the downloaded file is to be
                         saved.
        :param digest: If specified, this must be a (hasher, value)
                       tuple, where hasher is the algorithm used (e.g.
                       ``'md5'``) and ``value`` is the expected value.
        :param reporthook: The same as for :func:`urlretrieve` in the
                           standard library.
        NzNo digest specifiedrwzDigest specified: %sÚwbi éÿÿÿÿrzcontent-lengthzContent-Lengthrz1retrieval incomplete: got only %d out of %d bytesz.%s digest mismatch for %s: expected %s, got %szDigest verified: %s)rCrDÚ
isinstanceÚlistÚtupleÚgetattrrvrr:rrEÚinfoÚintruÚlenr`ryrrx)r rZdestfileZdigestZ
reporthookZdigesterZhasherZdfpZsfpÚheadersZ	blocksizeÚsizeruZblocknumÚblockÚactualr%r%r&Ú
download_fileus^



ÿÿ
ÿÿzPackageIndex.download_filecCs:g}|jr| |j¡|jr(| |j¡t|Ž}| |¡S)zÝ
        Send a standard library :class:`Request` to PyPI and return its
        response.

        :param req: The request to send.
        :return: The HTTP response from PyPI (a standard library HTTPResponse).
        )rrBrr	r)r ZreqZhandlersZopenerr%r%r&r:ÂszPackageIndex.send_requestc
CsØg}|j}|D]L\}}t|ttfƒs*|g}|D]*}| d|d| d¡d| d¡f¡q.q|D].\}}	}
| d|d||	f d¡d|
f¡q`| d|ddf¡d |¡}d|}|tt|ƒƒdœ}
t	|j
||
ƒS)	a&
        Encode fields and files for posting to an HTTP server.

        :param fields: The fields to send as a list of (fieldname, value)
                       tuples.
        :param files: The files to send as a list of (fieldname, filename,
                      file_bytes) tuple.
        s--z)Content-Disposition: form-data; name="%s"r>óz8Content-Disposition: form-data; name="%s"; filename="%s"s
smultipart/form-data; boundary=)zContent-typezContent-length)Úboundaryr‹rŒr�rPrhrRÚstrr‘rr)r rƒr}Úpartsr˜ÚkÚvaluesÚvÚkeyrTÚvalueZbodyZctr’r%r%r&r8ÒsDÿÿû
ÿÿû

þzPackageIndex.encode_requestcCsFt|tƒrd|i}t|jdd�}z| ||p.d¡W¢S|dƒƒXdS)NrFg@)ZtimeoutrEÚand)r‹r
r
rÚsearch)r ZtermsÚoperatorZ	rpc_proxyr%r%r&r¡ýs
zPackageIndex.search)N)N)N)N)NNrkrlN)N)N)NN)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r˜r'r+rr3r2r=rHrYrgrjr~r„r‡rˆr–r:r8r¡r%r%r%r&rs6

ÿ

#
ÿ
9ÿ
ÿ

M+r)rvZloggingrrzrrQZ	threadingrÚImportErrorZdummy_threadingÚrÚcompatrrrrr	r
Úutilrrr
Z	getLoggerr£rCrZ
DEFAULT_REALMÚobjectrr%r%r%r&Ús  
PKÔ¶N]E]
ØW•W•Ksite-packages/pip/_vendor/distlib/__pycache__/locators.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.e_Êã@sDddlZddlmZddlZddlZddlZddlZddlZzddlZWne	k
rdddl
ZYnXddlZddlm
Z
ddlmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZddlm Z m!Z!m"Z"ddl#m$Z$m%Z%ddl&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/dd	l0m1Z1m2Z2dd
l3m4Z4m5Z5e 6e7¡Z8e 9d¡Z:e 9dej;¡Zd-dd„Z?Gdd„deƒZ@Gdd„deAƒZBGdd„deBƒZCGdd„deBƒZDGdd„deAƒZEGdd„deBƒZFGdd„deBƒZGGdd „d eBƒZHGd!d"„d"eBƒZIGd#d$„d$eBƒZJeJeHƒeFd%d&d'�d(d)�ZKeKjLZLe 9d*¡ZMGd+d,„d,eAƒZNdS).éN)ÚBytesIOé)ÚDistlibException)ÚurljoinÚurlparseÚ
urlunparseÚurl2pathnameÚpathname2urlÚqueueÚquoteÚunescapeÚstring_typesÚbuild_openerÚHTTPRedirectHandlerÚ	text_typeÚRequestÚ	HTTPErrorÚURLError)ÚDistributionÚDistributionPathÚ	make_dist)ÚMetadataÚMetadataInvalidError)	Úcached_propertyÚparse_credentialsÚensure_slashÚsplit_filenameÚget_project_dataÚparse_requirementÚparse_name_and_versionÚServerProxyÚnormalize_name)Ú
get_schemeÚUnsupportedVersionError)ÚWheelÚ
is_compatiblez^(\w+)=([a-f0-9]+)z;\s*charset\s*=\s*(.*)\s*$ztext/html|application/x(ht)?mlzhttps://pypi.org/pypicCs6|dkrt}t|dd�}z| ¡W¢S|dƒƒXdS)z•
    Return all distribution names known by an index.
    :param url: The URL of the index.
    :return: A list of all known distribution names.
    Nç@©ÚtimeoutÚclose)Ú
DEFAULT_INDEXr Ú
list_packages)ÚurlÚclient©r.ú@/usr/lib/python3.8/site-packages/pip/_vendor/distlib/locators.pyÚget_all_distribution_names)sr0c@s$eZdZdZdd„ZeZZZdS)ÚRedirectHandlerzE
    A class to work around a bug in some Python 3.2.x releases.
    c	Cs‚d}dD]}||kr||}q"q|dkr.dSt|ƒ}|jdkrnt| ¡|ƒ}t|dƒrf| ||¡n|||<t ||||||¡S)N)ÚlocationZuriÚÚreplace_header)rÚschemerZget_full_urlÚhasattrr4ÚBaseRedirectHandlerÚhttp_error_302)	ÚselfÚreqÚfpÚcodeÚmsgÚheadersZnewurlÚkeyZurlpartsr.r.r/r8@s 

ÿzRedirectHandler.http_error_302N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r8Zhttp_error_301Zhttp_error_303Zhttp_error_307r.r.r.r/r17sr1c@s¶eZdZdZdZdZdZdZedZd)dd	„Z	d
d„Z
dd
„Zdd„Zdd„Z
dd„Zee
eƒZdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zd d!„Zd"d#„Zd$d%„Zd*d'd(„ZdS)+ÚLocatorzG
    A base class for locators - things that locate distributions.
    )z.tar.gzz.tar.bz2z.tarz.zipz.tgzz.tbz)z.eggz.exeú.whl)z.pdfN)rEÚdefaultcCs,i|_||_ttƒƒ|_d|_t ¡|_dS)a^
        Initialise an instance.
        :param scheme: Because locators look for most recent versions, they
                       need to know the version scheme to use. This specifies
                       the current PEP-recommended scheme - use ``'legacy'``
                       if you need to support existing distributions on PyPI.
        N)	Ú_cacher5rr1ÚopenerÚmatcherr
ÚQueueÚerrors)r9r5r.r.r/Ú__init__fs
zLocator.__init__cCsVg}|j ¡sRz|j d¡}| |¡Wn|jjk
rDYqYnX|j ¡q|S)z8
        Return any errors which have occurred.
        F)rKÚemptyÚgetÚappendZEmptyÚ	task_done)r9ÚresultÚer.r.r/Ú
get_errorsys

zLocator.get_errorscCs| ¡dS)z>
        Clear any errors which may have been logged.
        N)rS©r9r.r.r/Úclear_errors‡szLocator.clear_errorscCs|j ¡dS©N)rGÚclearrTr.r.r/Úclear_cacheŽszLocator.clear_cachecCs|jSrV©Ú_schemerTr.r.r/Ú_get_scheme‘szLocator._get_schemecCs
||_dSrVrY)r9Úvaluer.r.r/Ú_set_scheme”szLocator._set_schemecCstdƒ‚dS)a=
        For a given project, get a dictionary mapping available versions to Distribution
        instances.

        This should be implemented in subclasses.

        If called from a locate() request, self.matcher will be set to a
        matcher for the requirement to satisfy, otherwise it will be None.
        ú Please implement in the subclassN©ÚNotImplementedError)r9Únamer.r.r/Ú_get_project™s
zLocator._get_projectcCstdƒ‚dS)úJ
        Return all the distribution names known to this locator.
        r^Nr_rTr.r.r/Úget_distribution_names¥szLocator.get_distribution_namescCsL|jdkr| |¡}n2||jkr,|j|}n| ¡| |¡}||j|<|S)zÖ
        For a given project, get a dictionary mapping available versions to Distribution
        instances.

        This calls _get_project to do all the work, and just implements a caching layer on top.
        N)rGrbrU)r9rarQr.r.r/Úget_project«s



zLocator.get_projectcCs^t|ƒ}t |j¡}d}| d¡}| |j¡}|rBtt|ƒ|jƒ}|j	dkd|j
k||||fS)zu
        Give an url a score which can be used to choose preferred URLs
        for a given project release.
        TrEÚhttpszpypi.org)rÚ	posixpathÚbasenameÚpathÚendswithÚdownloadable_extensionsr%r$Ú
wheel_tagsr5Únetloc)r9r,ÚtrhZ
compatibleZis_wheelZis_downloadabler.r.r/Ú	score_url¼s
ÿzLocator.score_urlcCsR|}|rN| |¡}| |¡}||kr(|}||kr@t d||¡nt d||¡|S)a{
        Choose one of two URLs where both are candidates for distribution
        archives for the same version of a distribution (for example,
        .tar.gz vs. zip).

        The current implementation favours https:// URLs over http://, archives
        from PyPI over those from other locations, wheel compatibility (if a
        wheel) and then the archive name.
        zNot replacing %r with %rzReplacing %r with %r)roÚloggerÚdebug)r9Úurl1Úurl2rQÚs1Ús2r.r.r/Ú
prefer_urlËs


zLocator.prefer_urlcCs
t||ƒS)zZ
        Attempt to split a filename in project name, version and Python version.
        )r)r9ÚfilenameÚproject_namer.r.r/rászLocator.split_filenamecCsdd„}d}t|ƒ\}}}}}	}
|
 ¡ d¡rz~t	|ƒ}t
||jƒs°t d
|¡nX|dkr¾d}n||j|ƒ}|�r|j|j
|jt|||||	dfƒd
 dd„|jDƒ¡dœ}Wn0tk
�r:}zt d|¡W5d}~XYnXnÄ| |j¡�sZt d|¡n¨t |¡}}|jD]’}| |¡�rn|dt|ƒ…}| ||¡}|�s°t d|¡nH|\}}}|�rÌ|||ƒ�rø|||t|||||	dfƒdœ}|�rø||d<�q�qn|�r|�r|
|d|<|S)a
        See if a URL is a candidate for a download URL for a project (the URL
        has typically been scraped from an HTML page).

        If it is, a dictionary is returned with keys "name", "version",
        "filename" and "url"; otherwise, None is returned.
        cSst|ƒt|ƒkSrV)r!)Zname1Zname2r.r.r/Úsame_projectïsz:Locator.convert_url_to_download_info..same_projectNzegg=z %s: version hint in fragment: %r)NNéÿÿÿÿú/rEzWheel not compatible: %sTr3z, cSs"g|]}d t|dd…ƒ¡‘qS)Ú.éN)ÚjoinÚlist)Ú.0Úvr.r.r/Ú
sz8Locator.convert_url_to_download_info..)raÚversionrwr,úpython-versionzinvalid path for wheel: %szNot downloadable: %sz No match for project/version: %s)rarƒrwr,r„ú	%s_digest)rÚlowerÚ
startswithrprqÚHASHER_HASHÚmatchÚgroupsrjr$r%rlrarƒrwrr~ÚpyverÚ	ExceptionÚwarningrkrgrhÚlenr)r9r,rxryrQr5rmriÚparamsÚqueryÚfragÚmÚalgoÚdigestZorigpathÚwheelZincluderRrwZextrnrarƒr‹r.r.r/Úconvert_url_to_download_infoçs€ÿ
ÿÿú
	 

ÿü
z$Locator.convert_url_to_download_infocCs2d}dD]$}d|}||kr|||f}q.q|S)zØ
        Get a digest from a dictionary by looking at keys of the form
        'algo_digest'.

        Returns a 2-tuple (algo, digest) if found, else None. Currently
        looks only for SHA256, then MD5.
        N)Zsha256Úmd5r…r.)r9ÚinforQr“r?r.r.r/Ú_get_digest1szLocator._get_digestc	Cs®| d¡}| d¡}||kr,||}|j}nt|||jd�}|j}| |¡|_}|d}||d|<|j|dkrœ| |j|¡|_|d |t	ƒ¡ 
|¡||_|||<dS)zñ
        Update a result dictionary (the final result from _get_project) with a
        dictionary for a specific version, which typically holds information
        gleaned from a filename or URL for an archive for the distribution.
        rarƒ©r5r,ÚdigestsÚurlsN)ÚpopÚmetadatarr5r™r”Ú
source_urlrvÚ
setdefaultÚsetÚaddÚlocator)	r9rQr˜rarƒÚdistÚmdr”r,r.r.r/Ú_update_version_dataAs

zLocator._update_version_dataFc	Cs¤d}t|ƒ}|dkr td|ƒ‚t|jƒ}| |j¡|_}t d|t|ƒj	¡| 
|j¡}t|ƒdk�r2g}|j
}	|D]z}
|
dkr†qxzH| |
¡s¢t d||
¡n*|s°|	|
ƒjs¼| |
¡nt d|
|j¡Wqxtk
rðt d||
¡YqxXqxt|ƒd	k�rt||jd
�}|�r2t d|¡|d}||}|�rš|j�rH|j|_| d
i¡ |tƒ¡|_i}| di¡}
|jD]}||
k�rv|
|||<�qv||_d|_|S)a
        Find the most recent distribution which matches the given
        requirement.

        :param requirement: A requirement of the form 'foo (1.0)' or perhaps
                            'foo (>= 1.0, < 2.0, != 1.3)'
        :param prereleases: If ``True``, allow pre-release versions
                            to be located. Otherwise, pre-release versions
                            are not returned.
        :return: A :class:`Distribution` instance, or ``None`` if no such
                 distribution could be located.
        NzNot a valid requirement: %rzmatcher: %s (%s)r}©rœr›z%s did not match %rz%skipping pre-release version %s of %szerror matching %s with %rr)r?zsorted list: %srzrœr›)rrr"r5rIÚrequirementrprqÚtyper@rerarŽZ
version_classr‰Z
is_prereleaserOrŒr�Úsortedr?ZextrasrNr¡Ú
download_urlsr›)r9r¨ÚprereleasesrQÚrr5rIÚversionsZslistZvclsÚkrƒÚdZsdr,r.r.r/ÚlocateXsX


ÿ

zLocator.locate)rF)F)r@rArBrCÚsource_extensionsÚbinary_extensionsÚexcluded_extensionsrlrkrLrSrUrXr[r]Úpropertyr5rbrdrerorvrr–r™r¦r±r.r.r.r/rDVs.

JrDcs0eZdZdZ‡fdd„Zdd„Zdd„Z‡ZS)ÚPyPIRPCLocatorz‘
    This locator uses XML-RPC to locate distributions. It therefore
    cannot be used with simple mirrors (that only mirror file content).
    cs*tt|ƒjf|Ž||_t|dd�|_dS)z—
        Initialise an instance.

        :param url: The URL to use for XML-RPC.
        :param kwargs: Passed to the superclass constructor.
        r&r'N)Úsuperr¶rLÚbase_urlr r-©r9r,Úkwargs©Ú	__class__r.r/rL™szPyPIRPCLocator.__init__cCst|j ¡ƒS©rc)r¡r-r+rTr.r.r/rd¤sz%PyPIRPCLocator.get_distribution_namescCsiidœ}|j |d¡}|D]Þ}|j ||¡}|j ||¡}t|jd�}|d|_|d|_| d¡|_	| dg¡|_
| d¡|_t|ƒ}|r|d	}	|	d
|_
| |	¡|_||_|||<|D]:}	|	d
}
| |	¡}|d |tƒ¡ |
¡||d|
<q¾q|S)
Nr§TršrarƒÚlicenseÚkeywordsÚsummaryrr,rœr›)r-Zpackage_releasesZrelease_urlsZrelease_datarr5rarƒrNr¾r¿rÀrrŸr™r”r£r r¡r¢)r9rarQr®r�rœÚdataržr¤r˜r,r”r.r.r/rbªs0




zPyPIRPCLocator._get_project©r@rArBrCrLrdrbÚ
__classcell__r.r.r»r/r¶”sr¶cs0eZdZdZ‡fdd„Zdd„Zdd„Z‡ZS)ÚPyPIJSONLocatorzw
    This locator uses PyPI's JSON interface. It's very limited in functionality
    and probably not worth using.
    cs tt|ƒjf|Žt|ƒ|_dSrV)r·rÄrLrr¸r¹r»r.r/rLÉszPyPIJSONLocator.__init__cCstdƒ‚dS©rczNot available from this locatorNr_rTr.r.r/rdÍsz&PyPIJSONLocator.get_distribution_namesc
Cs
iidœ}t|jdt|ƒƒ}�z¤|j |¡}| ¡ ¡}t |¡}t	|j
d�}|d}|d|_|d|_| 
d¡|_| 
dg¡|_| 
d	¡|_t|ƒ}||_|d
}	|||j<|d
D]T}
|
d}|j |¡| |
¡|j|<|d
 |jtƒ¡ |¡| |
¡|d|<qº|d
 ¡D]¤\}}||jk�r4�qt	|j
d�}
|j|
_||
_t|
ƒ}||_|||<|D]T}
|
d}|j |¡| |
¡|j|<|d
 |tƒ¡ |¡| |
¡|d|<�qh�qWn@tk
�r}z |j t|ƒ¡t d|¡W5d}~XYnX|S)Nr§z%s/jsonršr˜rarƒr¾r¿rÀrœr,r›ZreleaseszJSON fetch failed: %s) rr¸rrHÚopenÚreadÚdecodeÚjsonÚloadsrr5rarƒrNr¾r¿rÀrr£r«r¢r™r›r r¡ÚitemsrŒrKÚputrrpÚ	exception)r9rarQr,ÚresprÁr°r¥r¤rœr˜rƒZinfosZomdÚodistrRr.r.r/rbÓsT




	zPyPIJSONLocator._get_projectrÂr.r.r»r/rÄÄsrÄc@s`eZdZdZe dejejBejB¡Z	e dejejB¡Z
dd„Ze dej¡Ze
dd„ƒZd	S)
ÚPagez4
    This class represents a scraped HTML page.
    zÝ
(rel\s*=\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\s
]*))\s+)?
href\s*=\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\s
]*))
(\s+rel\s*=\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\s
]*)))?
z!]+)cCs4||_||_|_|j |j¡}|r0| d¡|_dS)zk
        Initialise an instance with the Unicode page contents and the URL they
        came from.
        rN)rÁr¸r,Ú_baseÚsearchÚgroup)r9rÁr,r’r.r.r/rLs
z
Page.__init__z[^a-z0-9$&+,/:;=?@.#%_\\|-]cCs¾dd„}tƒ}|j |j¡D]Š}| d¡}|dpX|dpX|dpX|dpX|dpX|d	}|d
pp|dpp|d}t|j|ƒ}t|ƒ}|j 	d
d„|¡}| 
||f¡qt|dd„dd�}|S)zâ
        Return the URLs of all the links on a page together with information
        about their "rel" attribute, for determining which ones to treat as
        downloads and which ones to queue for further scraping.
        cSs,t|ƒ\}}}}}}t||t|ƒ|||fƒS)zTidy up an URL.)rrr)r,r5rmrir�r�r‘r.r.r/Úclean-sÿzPage.links..cleanr3Zrel1Zrel2Zrel3Zrel4Zrel5Zrel6rrrsZurl3cSsdt| d¡ƒS)Nz%%%2xr)ÚordrÓ)r’r.r.r/Ú;ózPage.links..cSs|dS)Nrr.)rnr.r.r/rÖ?r×T)r?Úreverse)r¡Ú_hrefÚfinditerrÁÚ	groupdictrr¸rÚ	_clean_reÚsubr¢rª)r9rÔrQr‰r°Úrelr,r.r.r/Úlinks&s$
ÿÿÿz
Page.linksN)r@rArBrCÚreÚcompileÚIÚSÚXrÙrÑrLrÜrrßr.r.r.r/rÐ	sürÐcs˜eZdZdZejdd„dd„dœZd‡fdd	„	Zd
d„Zdd
„Z	dd„Z
e dej
¡Zdd„Zdd„Zdd„Zdd„Zdd„Ze d¡Zdd„Z‡ZS)ÚSimpleScrapingLocatorzã
    A locator which scrapes HTML pages to locate downloads for a distribution.
    This runs multiple threads to do the I/O; performance is at least as good
    as pip's PackageFinder, which works in an analogous fashion.
    cCstjttƒd� ¡S)N)Zfileobj)ÚgzipZGzipFilerr°rÇ©Úbr.r.r/rÖMr×zSimpleScrapingLocator.cCs|SrVr.rçr.r.r/rÖNr×)ZdeflateræZnoneNé
csltt|ƒjf|Žt|ƒ|_||_i|_tƒ|_t	 
¡|_tƒ|_d|_
||_t ¡|_t ¡|_d|_dS)a¤
        Initialise an instance.
        :param url: The root URL to use for scraping.
        :param timeout: The timeout, in seconds, to be applied to requests.
                        This defaults to ``None`` (no timeout specified).
        :param num_workers: The number of worker threads you want to do I/O,
                            This defaults to 10.
        :param kwargs: Passed to the superclass.
        FN)r·rårLrr¸r(Ú_page_cacher¡Ú_seenr
rJÚ	_to_fetchÚ
_bad_hostsÚskip_externalsÚnum_workersÚ	threadingÚRLockÚ_lockÚ_gplockÚplatform_check)r9r,r(rïrºr»r.r/rLQs




zSimpleScrapingLocator.__init__cCsFg|_t|jƒD]0}tj|jd�}| d¡| ¡|j |¡qdS)z¾
        Threads are created only when get_project is called, and terminate
        before it returns. They are there primarily to parallelise I/O (i.e.
        fetching web pages).
        )ÚtargetTN)	Ú_threadsÚrangerïrðZThreadÚ_fetchZ	setDaemonÚstartrO)r9Úirnr.r.r/Ú_prepare_threadsls
z&SimpleScrapingLocator._prepare_threadscCs6|jD]}|j d¡q|jD]}| ¡qg|_dS)zu
        Tell all the threads to terminate (by sending a sentinel value) and
        wait for them to do so.
        N)rörìrÌr~)r9rnr.r.r/Ú
_wait_threadsys



z#SimpleScrapingLocator._wait_threadsc	Cs’iidœ}|j�x||_||_t|jdt|ƒƒ}|j ¡|j ¡| 	¡z&t d|¡|j
 |¡|j
 ¡W5| 
¡X|`W5QRX|S)Nr§z%s/zQueueing %s)rórQrxrr¸rrërWrêrûrürprqrìrÌr~)r9rarQr,r.r.r/rb†s



z"SimpleScrapingLocator._get_projectz<\b(linux_(i\d86|x86_64|arm\w+)|win(32|_amd64)|macosx_?\d+)\bcCs|j |¡S)zD
        Does an URL refer to a platform-specific download?
        )Úplatform_dependentrÒ)r9r,r.r.r/Ú_is_platform_dependent›sz,SimpleScrapingLocator._is_platform_dependentc	CsZ|jr| |¡rd}n| ||j¡}t d||¡|rV|j�| |j|¡W5QRX|S)a%
        See if an URL is a suitable download for a project.

        If it is, register information in the result dictionary (for
        _get_project) about the specific version it's for.

        Note that the return value isn't actually used other than as a boolean
        value.
        Nzprocess_download: %s -> %s)	rôrþr–rxrprqròr¦rQ)r9r,r˜r.r.r/Ú_process_download¡s
z'SimpleScrapingLocator._process_downloadc
CsÄt|ƒ\}}}}}}| |j|j|j¡r2d}n||jrJ| |j¡sJd}nd| |j¡s\d}nR|dkrjd}nD|dkrxd}n6| |¡rˆd}n&| 	dd¡d}	|	 
¡dkrªd}nd}t d	||||¡|S)
z‘
        Determine whether a link URL from a referring page and with a
        particular "rel" attribute should be queued for scraping.
        F)ZhomepageZdownload)ZhttprfZftpú:rrZ	localhostTz#should_queue: %s (%s) from %s -> %s)
rrjr²r³r´rîr‡r¸rþÚsplitr†rprq)
r9ÚlinkZreferrerrÞr5rmriÚ_rQÚhostr.r.r/Ú
_should_queueµs0ÿ

ÿz#SimpleScrapingLocator._should_queuec
Csð|j ¡}zÌz”|rž| |¡}|dkr,WW¢®q|jD]j\}}||jkr2zB|j |¡| |¡s„| |||¡r„t	 
d||¡|j |¡Wq2tk
ršYq2Xq2Wn2t
k
rÒ}z|j t|ƒ¡W5d}~XYnXW5|j ¡X|sqìqdS)z×
        Get a URL to fetch from the work queue, get the HTML page, examine its
        links for download candidates and candidates for further scraping.

        This is a handy method to run in a thread.
        NzQueueing %s from %s)rìrNrPÚget_pagerßrër¢rÿrrprqrÌrrŒrKr)r9r,ÚpagerrÞrRr.r.r/røÒs,



ÿ&zSimpleScrapingLocator._fetchcCsXt|ƒ\}}}}}}|dkr:tj t|ƒ¡r:tt|ƒdƒ}||jkr`|j|}t 	d||¡�nô| 
dd¡d}d}||jkr�t 	d||¡�nÄt|d	d
id�}�z¤zât 	d|¡|j
j||jd
�}	t 	d|¡|	 ¡}
|
 dd¡}t |¡�r„|	 ¡}|	 ¡}
|
 d¡}|�r"|j|}||
ƒ}
d}t |¡}|�r@| d¡}z|
 |¡}
Wn tk
�rn|
 d¡}
YnXt|
|ƒ}||j|<Wn¼tk
�rÄ}z|jdk�r´t d||¡W5d}~XYn€t k
�r}z0t d||¡|j!�|j "|¡W5QRXW5d}~XYn2t#k
�rB}zt d||¡W5d}~XYnXW5||j|<X|S)a
        Get the HTML for an URL, possibly from an in-memory cache.

        XXX TODO Note: this cache is never actually cleared. It's assumed that
        the data won't get stale over the lifetime of a locator instance (not
        necessarily true for the default_locator).
        Úfilez
index.htmlzReturning %s from cache: %srrrNzSkipping %s due to bad host %szAccept-encodingZidentity)r>zFetching %sr'z
Fetched %szContent-Typer3zContent-Encodingzutf-8zlatin-1i”zFetch failed: %s: %s)$rÚosriÚisdirrrrrêrprqrrírrHrÆr(r˜rNÚHTML_CONTENT_TYPEr‰ZgeturlrÇÚdecodersÚCHARSETrÒrÓrÈÚUnicodeErrorrÐrr<rÍrròr¢rŒ)r9r,r5rmrirrQrr:rÎr>Zcontent_typeZ	final_urlrÁÚencodingÚdecoderr’rRr.r.r/rósZ	







&$zSimpleScrapingLocator.get_pagez]*>([^<]+)[\w-]+)\s*\(\s*(==\s*)?(?P[^)]+)\)$c@sLeZdZdZddd„Zdd„Zdd„Zd	d
„Zdd„Zd
d„Z	ddd„Z
dS)ÚDependencyFinderz0
    Locate dependencies for distributions.
    NcCs|pt|_t|jjƒ|_dS)zf
        Initialise an instance, using the specified locator
        to locate distributions.
        N)Údefault_locatorr£r"r5r'r.r.r/rL*s
zDependencyFinder.__init__cCsrt d|¡|j}||j|<||j||jf<|jD]:}t|ƒ\}}t d|||¡|j 	|t
ƒ¡ ||f¡q2dS)z¨
        Add a distribution to the finder. This will update internal information
        about who provides what.
        :param dist: The distribution to add.
        zadding distribution %szAdd to provided: %s, %s, %sN)rprqr?Ú
dists_by_nameÚdistsrƒÚprovidesrÚprovidedr r¡r¢)r9r¤raÚprƒr.r.r/Úadd_distribution2s

z!DependencyFinder.add_distributioncCsxt d|¡|j}|j|=|j||jf=|jD]D}t|ƒ\}}t d|||¡|j|}| 	||f¡|s.|j|=q.dS)z°
        Remove a distribution from the finder. This will update internal
        information about who provides what.
        :param dist: The distribution to remove.
        zremoving distribution %sz Remove from provided: %s, %s, %sN)
rprqr?r.r/rƒr0rr1Úremove)r9r¤rar2rƒÚsr.r.r/Úremove_distributionAs

z$DependencyFinder.remove_distributioncCsBz|j |¡}Wn,tk
r<| ¡d}|j |¡}YnX|S)zÞ
        Get a version matcher for a requirement.
        :param reqt: The requirement
        :type reqt: str
        :return: A version matcher (an instance of
                 :class:`distlib.version.Matcher`).
        r)r5rIr#r)r9ÚreqtrIrar.r.r/Úget_matcherSszDependencyFinder.get_matcherc		Cst| |¡}|j}tƒ}|j}||krp||D]B\}}z| |¡}Wntk
rZd}YnX|r,| |¡qpq,|S)zÓ
        Find the distributions which can fulfill a requirement.

        :param reqt: The requirement.
         :type reqt: str
        :return: A set of distribution which can fulfill the requirement.
        F)r8r?r¡r1r‰r#r¢)	r9r7rIrarQr1rƒÚproviderr‰r.r.r/Úfind_providerscs


zDependencyFinder.find_providersc	Csž|j|}tƒ}|D]$}| |¡}| |j¡s| |¡q|rZ| d||t|ƒf¡d}n@| |¡|j|=|D]}|j |tƒ¡ |¡qp| 	|¡d}|S)aŠ
        Attempt to replace one provider with another. This is typically used
        when resolving dependencies from multiple sources, e.g. A requires
        (B >= 1.0) while C requires (B >= 1.1).

        For successful replacement, ``provider`` must meet all the requirements
        which ``other`` fulfills.

        :param provider: The provider we are trying to replace with.
        :param other: The provider we're trying to replace.
        :param problems: If False is returned, this will contain what
                         problems prevented replacement. This is currently
                         a tuple of the literal string 'cantreplace',
                         ``provider``, ``other``  and the set of requirements
                         that ``provider`` couldn't fulfill.
        :return: True if we can replace ``other`` with ``provider``, else
                 False.
        ZcantreplaceFT)
Úreqtsr¡r8r‰rƒr¢Ú	frozensetr6r r3)	r9r9ÚotherÚproblemsZrlistZ	unmatchedr5rIrQr.r.r/Útry_to_replace{s$


ÿ

zDependencyFinder.try_to_replaceFcCsòi|_i|_i|_i|_t|p gƒ}d|krH| d¡|tdddgƒO}t|tƒrh|}}t 	d|¡n4|j
j||d�}}|dkr�td|ƒ‚t 	d	|¡d
|_
tƒ}t|gƒ}t|gƒ}|�r¤| ¡}|j}	|	|jkræ| |¡n"|j|	}
|
|k�r| ||
|¡|j|jB}|j}tƒ}
|�r`||k�r`dD]*}d|}||k�r4|
t|d
|ƒO}
�q4||B|
B}|D�].}| |¡}|�sFt 	d|¡|j
j||d�}|dk�rÂ|�sÂ|j
j|d
d�}|dk�rèt 	d|¡| d|f¡n^|j|j}}||f|jk�r| |¡| |¡||k�rF||k�rF| |¡t 	d|j¡|D]R}|j}	|	|jk�rx|j |tƒ¡ |¡n"|j|	}
|
|k�rJ| ||
|¡�qJ�qpq¼t|j ¡ƒ}|D]&}||k|_|j�r¶t 	d|j¡�q¶t 	d|¡||fS)aŽ
        Find a distribution and all distributions it depends on.

        :param requirement: The requirement specifying the distribution to
                            find, or a Distribution instance.
        :param meta_extras: A list of meta extras such as :test:, :build: and
                            so on.
        :param prereleases: If ``True``, allow pre-release versions to be
                            returned - otherwise, don't return prereleases
                            unless they're all that's available.

        Return a set of :class:`Distribution` instances and a set of
        problems.

        The distributions returned should be such that they have the
        :attr:`required` attribute set to ``True`` if they were
        from the ``requirement`` passed to ``find()``, and they have the
        :attr:`build_time_dependency` attribute set to ``True`` unless they
        are post-installation dependencies of the ``requirement``.

        The problems should be a tuple consisting of the string
        ``'unsatisfied'`` and the requirement which couldn't be satisfied
        by any distribution known to the locator.
        z:*:z:test:z:build:z:dev:zpassed %s as requirement)r¬NzUnable to locate %rz
located %sT)ZtestZbuildZdevz:%s:z%s_requireszNo providers found for %rzCannot satisfy %rZunsatisfiedzAdding %s to install_distsz#%s is a build-time dependency only.zfind done for %s)r1r/r.r;r¡r4Ú
isinstancerrprqr£r±rZ	requestedr�r?r3r?Zrun_requiresZ
meta_requiresZbuild_requiresÚgetattrr:r¢rƒZname_and_versionr ÚvaluesZbuild_time_dependency)r9r¨Zmeta_extrasr¬r¤rÏr>ZtodoZ
install_distsrar=ZireqtsZsreqtsZereqtsr?rRZ	all_reqtsr­Z	providersr9Únr�r2r/r.r.r/Úfind£s’

ÿ












ÿ


ÿzDependencyFinder.find)N)NF)r@rArBrCrLr3r6r8r:r?rDr.r.r.r/r,%s
(r,)N)OræÚiorrÉZloggingr	rgràrðÚImportErrorZdummy_threadingrr3rÚcompatrrrrr	r
rrr
rrr7rrrrZdatabaserrrržrrÚutilrrrrrrrr r!rƒr"r#r•r$r%Z	getLoggerr@rprárˆrâr
rr*r0r1ÚobjectrDr¶rÄrÐrårrr"r$r-r±ZNAME_VERSION_REr,r.r.r.r/Ús^D,



@0E:zA&[ÿü
PKÔ¶N]›xˆô«}«}Csite-packages/pip/_vendor/distlib/__pycache__/compat.cpython-38.pycnu„[µü¤U

ÀÒ.e¼¡ã@sBddlmZddlZddlZddlZzddlZWnek
rHdZYnXejddk�r~ddlmZe	fZ
eZddl
mZddlZddlZddlmZddlmZmZmZmZmZdd	lmZmZmZm Z m!Z!m"Z"m#Z#d
d„Zddl$Z$ddl$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-e�r&dd
l$m.Z.ddl/Z/ddl0Z0ddl1Z2ddl3m3Z3ddl4Z4e5Z5ddl6m7Z8ddl6m9Z:da;dd„Z<�nddl=mZe>fZ
e>Zddl=m?ZddlZddlZddlZddl@mZmZmZmd?„Zod@dA„ZiYnXzddBlpmqZqWn"ek
�rddBlrmqZqYnXejddC…dDk�r:e3ƒjsZsnddElpmsZszddFl`mtZtWndek
�rºddGl`muZuzddHlvmwZxWn ek
�r¤dedJdK„ZxYnXGdLdM„dMeuƒZtYnXzddNlymzZzWnHek
�rzddNl{mzZzWn ek
�rdfdOdP„ZzYnXYnXzddQl`m|Z|WnŠek
�r°zddRl}m~ZWn"ek
�rjddRl€m~ZYnXzddSl�m‚Z‚mƒZƒm„Z„Wnek
�ršYnXGdTdU„dUe…ƒZ|YnXzddVl†m‡Z‡mˆZˆWnvek
�r<e mdWej‰¡ZŠdXdY„ZˆGdZd[„d[e…ƒZ‹dgd\d]„ZŒGd^d_„d_e�ƒZŽGd`da„dae�ƒZ�Gdbdc„dceQƒZ‡YnXdS)hé)Úabsolute_importNé)ÚStringIO)ÚFileTypeé)Úshutil)ÚurlparseÚ
urlunparseÚurljoinÚurlsplitÚ
urlunsplit)ÚurlretrieveÚquoteÚunquoteÚurl2pathnameÚpathname2urlÚContentTooShortErrorÚ	splittypecCst|tƒr| d¡}t|ƒS)Núutf-8)Ú
isinstanceÚunicodeÚencodeÚ_quote)Ús©rú>/usr/lib/python3.8/site-packages/pip/_vendor/distlib/compat.pyrs

r)	ÚRequestÚurlopenÚURLErrorÚ	HTTPErrorÚHTTPBasicAuthHandlerÚHTTPPasswordMgrÚHTTPHandlerÚHTTPRedirectHandlerÚbuild_opener)ÚHTTPSHandler)Ú
HTMLParser)Úifilter)ÚifilterfalsecCs<tdkrddl}| d¡at |¡}|r4| dd¡Sd|fS)zJsplituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'.Nrz^(.*)@(.*)$ré)Ú	_userprogÚreÚcompileÚmatchÚgroup)Zhostr+r-rrrÚ	splituser4s

r/)Ú
TextIOWrapper)	rr	r
r/rrrrr)
rr
rrrr r!r"r#r$)rrr)Úfilterfalse)Úmatch_hostnameÚCertificateErrorc@seZdZdS)r3N)Ú__name__Ú
__module__Ú__qualname__rrrrr3^sr3c
Csôg}|sdS| d¡}|d|dd…}}| d¡}||krNtdt|ƒƒ‚|sb| ¡| ¡kS|dkrv| d¡n>| d	¡sŠ| d	¡rœ| t |¡¡n| t |¡ 	d
d¡¡|D]}| t |¡¡q¸t 
dd
 |¡dtj¡}	|	 
|¡S)zpMatching according to RFC 6125, section 6.4.3

        http://tools.ietf.org/html/rfc6125#section-6.4.3
        FÚ.rrNÚ*z,too many wildcards in certificate DNS name: z[^.]+zxn--z\*z[^.]*z\Az\.z\Z)ÚsplitÚcountr3ÚreprÚlowerÚappendÚ
startswithr+ÚescapeÚreplacer,ÚjoinÚ
IGNORECASEr-)
ZdnÚhostnameZ
max_wildcardsZpatsÚpartsZleftmostZ	remainderZ	wildcardsÚfragZpatrrrÚ_dnsname_matchbs*


ÿrFcCsì|stdƒ‚g}| dd¡}|D]*\}}|dkr t||ƒr@dS| |¡q |s”| dd¡D]6}|D],\}}|dkrdt||ƒr†dS| |¡qdq\t|ƒdkr¾td	|d
 tt|ƒ¡fƒ‚n*t|ƒdkràtd||dfƒ‚ntd
ƒ‚dS)a=Verify that *cert* (in decoded format as returned by
        SSLSocket.getpeercert()) matches the *hostname*.  RFC 2818 and RFC 6125
        rules are followed, but IP addresses are not accepted for *hostname*.

        CertificateError is raised on failure. On success, the function
        returns nothing.
        ztempty or no certificate, match_hostname needs a SSL socket or SSL context with either CERT_OPTIONAL or CERT_REQUIREDZsubjectAltNamerZDNSNZsubjectZ
commonNamerz&hostname %r doesn't match either of %sú, zhostname %r doesn't match %rrz=no appropriate commonName or subjectAltName fields were found)	Ú
ValueErrorÚgetrFr=Úlenr3rAÚmapr;)ZcertrCZdnsnamesZsanÚkeyÚvalueÚsubrrrr2”s2

þ
þr2)ÚSimpleNamespacec@seZdZdZdd„ZdS)Ú	ContainerzR
        A generic container for when multiple values need to be returned
        cKs|j |¡dS©N©Ú__dict__Úupdate)ÚselfÚkwargsrrrÚ__init__ÆszContainer.__init__N)r4r5r6Ú__doc__rWrrrrrPÂsrP)Úwhichcs"dd„}tj ˆ¡r&|ˆ|ƒr"ˆSdS|dkr>tj dtj¡}|sFdS| tj¡}tj	dkr¼tj
|krt| dtj
¡tj dd¡ tj¡}t‡fd	d
„|Dƒƒr¨ˆg}q‡fdd„|Dƒ}nˆg}t
ƒ}|D]P}tj |¡}||krÌ| |¡|D](}	tj ||	¡}
||
|ƒrò|
SqòqÌdS)
aKGiven a command, mode, and a PATH string, return the path which
        conforms to the given mode on the PATH, or None if there is no such
        file.

        `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
        of os.environ.get("PATH"), or can be overridden with a custom search
        path.

        cSs&tj |¡o$t ||¡o$tj |¡SrQ)ÚosÚpathÚexistsÚaccessÚisdir)ÚfnÚmoderrrÚ
_access_checkÛsÿzwhich.._access_checkNÚPATHZwin32rZPATHEXTÚc3s |]}ˆ ¡ | ¡¡VqdSrQ)r<Úendswith©Ú.0Úext©ÚcmdrrÚ	øszwhich..csg|]}ˆ|‘qSrrrerhrrÚ
ûszwhich..)rZr[ÚdirnameÚenvironrIÚdefpathr9ÚpathsepÚsysÚplatformÚcurdirÚinsertÚanyÚsetÚnormcaseÚaddrA)rir`r[raZpathextÚfilesÚseenÚdirZnormdirZthefileÚnamerrhrrYÎs8





rY)ÚZipFileÚ	__enter__)Ú
ZipExtFilec@s$eZdZdd„Zdd„Zdd„ZdS)r~cCs|j |j¡dSrQrR)rUÚbaserrrrWszZipExtFile.__init__cCs|SrQr©rUrrrr}szZipExtFile.__enter__cGs| ¡dSrQ©Úclose©rUÚexc_inforrrÚ__exit__szZipExtFile.__exit__N)r4r5r6rWr}r…rrrrr~sr~c@s$eZdZdd„Zdd„Zdd„ZdS)r|cCs|SrQrr€rrrr}"szZipFile.__enter__cGs| ¡dSrQr�rƒrrrr…%szZipFile.__exit__cOstj|f|ž|Ž}t|ƒSrQ)ÚBaseZipFileÚopenr~)rUÚargsrVrrrrr‡)szZipFile.openN)r4r5r6r}r…r‡rrrrr|!sr|)Úpython_implementationcCs0dtjkrdStjdkrdStj d¡r,dSdS)z6Return a string identifying the Python implementation.ZPyPyÚjavaZJythonZ
IronPythonZCPython)rpÚversionrZr{r>rrrrr‰0s

r‰)Ú	sysconfig)ÚCallablecCs
t|tƒSrQ)rr�)ÚobjrrrÚcallableDsr�rÚmbcsÚstrictÚsurrogateescapecCs:t|tƒr|St|tƒr$| tt¡Stdt|ƒjƒ‚dS©Nzexpect bytes or str, not %s)	rÚbytesÚ	text_typerÚ_fsencodingÚ	_fserrorsÚ	TypeErrorÚtyper4©ÚfilenamerrrÚfsencodeXs

ÿrœcCs:t|tƒr|St|tƒr$| tt¡Stdt|ƒjƒ‚dSr“)	rr•r”Údecoder–r—r˜r™r4ršrrrÚfsdecodeas

ÿrž)Údetect_encoding)ÚBOM_UTF8Úlookupzcoding[:=]\s*([-\w.]+)cCsH|dd… ¡ dd¡}|dks*| d¡r.dS|dks@| d¡rDd	S|S)
z(Imitates get_normal_name in tokenizer.c.NéÚ_ú-rzutf-8-)zlatin-1ú
iso-8859-1ziso-latin-1)zlatin-1-ziso-8859-1-ziso-latin-1-r¥)r<r@r>)Úorig_encÚencrrrÚ_get_normal_namersÿr¨csÊzˆjj‰Wntk
r$d‰YnXd‰d}d}‡fdd„}‡‡fdd„}|ƒ}| t¡rpd‰|d	d…}d
}|s||gfS||ƒ}|r’||gfS|ƒ}|s¦||gfS||ƒ}|r¾|||gfS|||gfS)a?
        The detect_encoding() function is used to detect the encoding that should
        be used to decode a Python source file.  It requires one argument, readline,
        in the same way as the tokenize() generator.

        It will call readline a maximum of twice, and return the encoding used
        (as a string) and a list of any lines (left as bytes) it has read in.

        It detects the encoding from the presence of a utf-8 bom or an encoding
        cookie as specified in pep-0263.  If both a bom and a cookie are present,
        but disagree, a SyntaxError will be raised.  If the encoding cookie is an
        invalid charset, raise a SyntaxError.  Note that if a utf-8 bom is found,
        'utf-8-sig' is returned.

        If no encoding is specified, then the default of 'utf-8' will be returned.
        NFrcs$zˆƒWStk
rYdSXdS)Nó)Ú
StopIterationr)ÚreadlinerrÚread_or_stop•sz%detect_encoding..read_or_stopcsäz| d¡}Wn4tk
rBd}ˆdk	r6d |ˆ¡}t|ƒ‚YnXt |¡}|sVdSt|dƒ}zt|ƒ}Wn:tk
r¨ˆdkr�d|}nd ˆ|¡}t|ƒ‚YnXˆrà|j	dkr؈dkrÆd}n
d ˆ¡}t|ƒ‚|d	7}|S)
Nrz'invalid or missing encoding declarationz{} for {!r}rzunknown encoding: zunknown encoding for {!r}: {}zencoding problem: utf-8z encoding problem for {!r}: utf-8z-sig)
r�ÚUnicodeDecodeErrorÚformatÚSyntaxErrorÚ	cookie_reÚfindallr¨r¡ÚLookupErrorr{)ÚlineÚline_stringÚmsgZmatchesÚencodingÚcodec)Ú	bom_foundr›rrÚfind_cookie›s8

ÿ

z$detect_encoding..find_cookieTrz	utf-8-sig)Ú__self__r{ÚAttributeErrorr>r )r«r¶Údefaultr¬r¹ÚfirstÚsecondr)r¸r›r«rrŸ}s4
&


rŸ)r?r))ré)Úunescape)ÚChainMap)ÚMutableMapping)Úrecursive_reprú...cs‡fdd„}|S)zm
            Decorator to make a repr function return fillvalue for a recursive
            call
            csLtƒ‰‡‡‡fdd„}tˆdƒ|_tˆdƒ|_tˆdƒ|_tˆdiƒ|_|S)Nc	sBt|ƒtƒf}|ˆkrˆSˆ |¡zˆ|ƒ}W5ˆ |¡X|SrQ)ÚidÚ	get_identrwÚdiscard)rUrLÚresult)Ú	fillvalueÚrepr_runningÚ
user_functionrrÚwrapperòs
z=_recursive_repr..decorating_function..wrapperr5rXr4Ú__annotations__)ruÚgetattrr5rXr4rÍ)rËrÌ©rÉ)rÊrËrÚdecorating_functionïsz,_recursive_repr..decorating_functionr)rÉrÐrrÏrÚ_recursive_représrÑc@s´eZdZdZdd„Zdd„Zdd„Zd'd	d
„Zdd„Zd
d„Z	dd„Z
dd„Zeƒdd„ƒZ
edd„ƒZdd„ZeZdd„Zedd„ƒZdd„Zdd „Zd!d"„Zd#d$„Zd%d&„ZdS)(rÁaÍ A ChainMap groups multiple dicts (or other mappings) together
        to create a single, updateable view.

        The underlying mappings are stored in a list.  That list is public and can
        accessed or updated using the *maps* attribute.  There is no other state.

        Lookups search the underlying mappings successively until a key is found.
        In contrast, writes, updates, and deletions only operate on the first
        mapping.

        cGst|ƒpig|_dS)z˜Initialize a ChainMap by setting *maps* to the given mappings.
            If no mappings are provided, a single empty dictionary is used.

            N)ÚlistÚmaps)rUrÓrrrrWszChainMap.__init__cCst|ƒ‚dSrQ)ÚKeyError©rUrLrrrÚ__missing__szChainMap.__missing__c	Cs:|jD](}z||WStk
r,YqXq| |¡SrQ)rÓrÔrÖ)rUrLÚmappingrrrÚ__getitem__s
zChainMap.__getitem__NcCs||kr||S|SrQr©rUrLr¼rrrrI%szChainMap.getcCsttƒj|jŽƒSrQ)rJruÚunionrÓr€rrrÚ__len__(szChainMap.__len__cCsttƒj|jŽƒSrQ)ÚiterrurÚrÓr€rrrÚ__iter__+szChainMap.__iter__cst‡fdd„|jDƒƒS)Nc3s|]}ˆ|kVqdSrQr)rfÚm©rLrrrj/sz(ChainMap.__contains__..©rtrÓrÕrrßrÚ__contains__.szChainMap.__contains__cCs
t|jƒSrQràr€rrrÚ__bool__1szChainMap.__bool__cCsd |d tt|jƒ¡¡S)Nz{0.__class__.__name__}({1})rG)r®rArKr;rÓr€rrrÚ__repr__4sÿzChainMap.__repr__cGs|tj|f|žŽƒS)z?Create a ChainMap with a single dict created from the iterable.)ÚdictÚfromkeys)ÚclsÚiterablerˆrrrrå9szChainMap.fromkeyscCs$|j|jd ¡f|jdd…žŽS)zHNew ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]rrN)Ú	__class__rÓÚcopyr€rrrré>sz
ChainMap.copycCs|jif|jžŽS)z;New ChainMap with a new dict followed by all previous maps.©rèrÓr€rrrÚ	new_childDszChainMap.new_childcCs|j|jdd…ŽS)zNew ChainMap from maps[1:].rNrêr€rrrÚparentsHszChainMap.parentscCs||jd|<dS)Nr)rÓ)rUrLrMrrrÚ__setitem__MszChainMap.__setitem__cCs8z|jd|=Wn"tk
r2td |¡ƒ‚YnXdS)Nrú(Key not found in the first mapping: {!r})rÓrÔr®rÕrrrÚ__delitem__PszChainMap.__delitem__cCs2z|jd ¡WStk
r,tdƒ‚YnXdS)zPRemove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.rz#No keys found in the first mapping.N)rÓÚpopitemrÔr€rrrrðVszChainMap.popitemcGs@z|jdj|f|žŽWStk
r:td |¡ƒ‚YnXdS)zWRemove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].rrîN)rÓÚpoprÔr®)rUrLrˆrrrrñ]szChainMap.popcCs|jd ¡dS)z'Clear maps[0], leaving maps[1:] intact.rN)rÓÚclearr€rrrròdszChainMap.clear)N)r4r5r6rXrWrÖrØrIrÛrÝrárârÑrãÚclassmethodråréÚ__copy__rëÚpropertyrìrírïrðrñròrrrrrÁs.



rÁ)Úcache_from_sourcecCs0| d¡st‚|dkrd}|r$d}nd}||S)Nz.pyTÚcÚo)rdÚAssertionError)r[Údebug_overrideÚsuffixrrrrönsrö)ÚOrderedDict)rÆ)ÚKeysViewÚ
ValuesViewÚ	ItemsViewc@sþeZdZdZdd„Zejfdd„Zejfdd„Zdd	„Zd
d„Z	dd
„Z
d6dd„Zdd„Zdd„Z
dd„Zdd„Zdd„Zdd„Zdd„ZeZeƒZefdd „Zd7d"d#„Zd8d$d%„Zd&d'„Zd(d)„Zed9d*d+„ƒZd,d-„Zd.d/„Zd0d1„Zd2d3„Z d4d5„Z!d!S):rüz)Dictionary that remembers insertion ordercOsnt|ƒdkrtdt|ƒƒ‚z
|jWn6tk
r\g|_}||dg|dd…<i|_YnX|j||ŽdS)zÑInitialize an ordered dictionary.  Signature is the same as for
            regular dictionaries, but keyword arguments are not recommended
            because their insertion order is arbitrary.

            rz$expected at most 1 arguments, got %dN)rJr˜Ú_OrderedDict__rootr»Ú_OrderedDict__mapÚ_OrderedDict__update)rUrˆÚkwdsÚrootrrrrW•s

zOrderedDict.__init__cCsF||kr6|j}|d}|||g|d<|d<|j|<||||ƒdS)z!od.__setitem__(i, y) <==> od[i]=yrrN)rr)rUrLrMZdict_setitemrÚlastrrrrí¥s
 zOrderedDict.__setitem__cCs0|||ƒ|j |¡\}}}||d<||d<dS)z od.__delitem__(y) <==> del od[y]rrN)rrñ)rUrLZdict_delitemÚ	link_prevÚ	link_nextrrrrï¯s
zOrderedDict.__delitem__ccs.|j}|d}||k	r*|dV|d}qdS)zod.__iter__() <==> iter(od)rr)N©r©rUrZcurrrrrrݸs

zOrderedDict.__iter__ccs.|j}|d}||k	r*|dV|d}qdS)z#od.__reversed__() <==> reversed(od)rr)Nrr	rrrÚ__reversed__Às

zOrderedDict.__reversed__cCsdz@|j ¡D]}|dd…=q|j}||dg|dd…<|j ¡Wntk
rTYnXt |¡dS)z.od.clear() -> None.  Remove all items from od.N)rÚ
itervaluesrròr»rä)rUZnoderrrrròÈszOrderedDict.clearTcCs||stdƒ‚|j}|r8|d}|d}||d<||d<n |d}|d}||d<||d<|d}|j|=t ||¡}||fS)z¡od.popitem() -> (k, v), return and remove a (key, value) pair.
            Pairs are returned in LIFO order if last is true or FIFO order if false.

            zdictionary is emptyrrr))rÔrrrärñ)rUrrÚlinkrrrLrMrrrrðÔs 
zOrderedDict.popitemcCst|ƒS)zod.keys() -> list of keys in od)rÒr€rrrÚkeysíszOrderedDict.keyscs‡fdd„ˆDƒS)z#od.values() -> list of values in odcsg|]}ˆ|‘qSrr©rfrLr€rrrkósz&OrderedDict.values..rr€rr€rÚvaluesñszOrderedDict.valuescs‡fdd„ˆDƒS)z.od.items() -> list of (key, value) pairs in odcsg|]}|ˆ|f‘qSrrrr€rrrk÷sz%OrderedDict.items..rr€rr€rÚitemsõszOrderedDict.itemscCst|ƒS)z0od.iterkeys() -> an iterator over the keys in od)rÜr€rrrÚiterkeysùszOrderedDict.iterkeysccs|D]}||VqdS)z2od.itervalues -> an iterator over the values in odNr©rUÚkrrrrýszOrderedDict.itervaluesccs|D]}|||fVqdS)z=od.iteritems -> an iterator over the (key, value) items in odNrrrrrÚ	iteritemsszOrderedDict.iteritemscOsÈt|ƒdkr tdt|ƒfƒ‚n|s,tdƒ‚|d}d}t|ƒdkrL|d}t|tƒrn|D]}||||<qZn None.  Update od from dict/iterable E and F.

            If E is a dict instance, does:           for k in E: od[k] = E[k]
            If E has a .keys() method, does:         for k in E.keys(): od[k] = E[k]
            Or if E is an iterable of items, does:   for k, v in E: od[k] = v
            In either case, this is followed by:     for k, v in F.items(): od[k] = v

            r)z8update() takes at most 2 positional arguments (%d given)z,update() takes at least 1 argument (0 given)rrrr
N)rJr˜rräÚhasattrr
r)rˆrrUÚotherrLrMrrrrTs(	ÿ


zOrderedDict.updatecCs0||kr||}||=|S||jkr,t|ƒ‚|S)z±od.pop(k[,d]) -> v, remove specified key and return the corresponding value.
            If key is not found, d is returned if given, otherwise KeyError is raised.

            )Ú_OrderedDict__markerrÔ)rUrLr¼rÈrrrrñ*s
zOrderedDict.popNcCs||kr||S|||<|S)zDod.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in odrrÙrrrÚ
setdefault7szOrderedDict.setdefaultcCsf|si}t|ƒtƒf}||kr"dSd||<z.|sBd|jjfW¢Sd|jj| ¡fW¢S||=XdS)zod.__repr__() <==> repr(od)rÄrz%s()z%s(%r)N)rÅÚ
_get_identrèr4r)rUZ
_repr_runningZcall_keyrrrrã>szOrderedDict.__repr__csX‡fdd„ˆDƒ}tˆƒ ¡}ttƒƒD]}| |d¡q(|rLˆj|f|fSˆj|ffS)z%Return state information for picklingcsg|]}|ˆ|g‘qSrr©rfrr€rrrkNsz*OrderedDict.__reduce__..N)Úvarsrérürñrè)rUrZ	inst_dictrrr€rÚ
__reduce__LszOrderedDict.__reduce__cCs
| |¡S)z!od.copy() -> a shallow copy of od)rèr€rrrréVszOrderedDict.copycCs|ƒ}|D]}|||<q
|S)zˆOD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
            and values equal to v (which defaults to None).

            r)rærçrMÚdrLrrrråZs
zOrderedDict.fromkeyscCs6t|tƒr*t|ƒt|ƒko(| ¡| ¡kSt ||¡S)z›od.__eq__(y) <==> od==y.  Comparison to another OD is order-sensitive
            while comparison to a regular mapping is order-insensitive.

            )rrürJrräÚ__eq__©rUrrrrres
 zOrderedDict.__eq__cCs
||kSrQrrrrrÚ__ne__nszOrderedDict.__ne__cCst|ƒS)z@od.viewkeys() -> a set-like object providing a view on od's keys)rýr€rrrÚviewkeyssszOrderedDict.viewkeyscCst|ƒS)z an object providing a view on od's values)rþr€rrrÚ
viewvalueswszOrderedDict.viewvaluescCst|ƒS)zBod.viewitems() -> a set-like object providing a view on od's items)rÿr€rrrÚ	viewitems{szOrderedDict.viewitems)T)N)N)N)"r4r5r6rXrWrärírïrÝr
ròrðr
rrrrrrTrÚobjectrrñrrãrrérórårr r!r"r#rrrrrü‰s:
	




	rü)ÚBaseConfiguratorÚvalid_identz^[a-z_][a-z0-9_]*$cCst |¡}|std|ƒ‚dS)Nz!Not a valid Python identifier: %rT)Ú
IDENTIFIERr-rH)rrÞrrrr&…s
r&c@s"eZdZdZdd„Zddd„ZdS)ÚConvertingDictz A converting dictionary wrapper.cCsJt ||¡}|j |¡}||k	rF|||<t|ƒtttfkrF||_||_	|SrQ)
rärØÚconfiguratorÚconvertr™r(ÚConvertingListÚConvertingTupleÚparentrL©rUrLrMrÈrrrrؘs
ÿzConvertingDict.__getitem__NcCsLt |||¡}|j |¡}||k	rH|||<t|ƒtttfkrH||_||_	|SrQ)
rärIr)r*r™r(r+r,r-rL©rUrLr¼rMrÈrrrrI¤s
ÿzConvertingDict.get)N)r4r5r6rXrØrIrrrrr(•sr(cCsDt |||¡}|j |¡}||k	r@t|ƒtttfkr@||_||_	|SrQ)
rärñr)r*r™r(r+r,r-rLr/rrrrñ°s
ÿrñc@s"eZdZdZdd„Zddd„ZdS)	r+zA converting list wrapper.cCsJt ||¡}|j |¡}||k	rF|||<t|ƒtttfkrF||_||_	|SrQ)
rÒrØr)r*r™r(r+r,r-rLr.rrrrؼs
ÿzConvertingList.__getitem__éÿÿÿÿcCs<t ||¡}|j |¡}||k	r8t|ƒtttfkr8||_|SrQ)	rÒrñr)r*r™r(r+r,r-)rUÚidxrMrÈrrrrñÈs
ÿzConvertingList.popN)r0)r4r5r6rXrØrñrrrrr+ºsr+c@seZdZdZdd„ZdS)r,zA converting tuple wrapper.cCsBt ||¡}|j |¡}||k	r>t|ƒtttfkr>||_||_	|SrQ)
ÚtuplerØr)r*r™r(r+r,r-rLr.rrrrØÓs
ÿzConvertingTuple.__getitem__N)r4r5r6rXrØrrrrr,Ñsr,c@sŒeZdZdZe d¡Ze d¡Ze d¡Ze d¡Z	e d¡Z
ddd	œZee
ƒZd
d„Zdd
„Zdd„Zdd„Zdd„Zdd„Zdd„ZdS)r%zQ
        The configurator base class which defines some useful defaults.
        z%^(?P[a-z]+)://(?P.*)$z^\s*(\w+)\s*z^\.\s*(\w+)\s*z^\[\s*(\w+)\s*\]\s*z^\d+$Úext_convertÚcfg_convert)rgZcfgcCst|ƒ|_||j_dSrQ)r(Úconfigr))rUr5rrrrWñs
zBaseConfigurator.__init__c		CsÂ| d¡}| d¡}z^| |¡}|D]H}|d|7}zt||ƒ}Wq$tk
rj| |¡t||ƒ}Yq$Xq$|WStk
r¼t ¡dd…\}}td||fƒ}|||_	|_
|‚YnXdS)zl
            Resolve strings to objects using standard import and attribute
            syntax.
            r7rrNzCannot resolve %r: %s)r9rñÚimporterrÎr»ÚImportErrorrpr„rHÚ	__cause__Ú
__traceback__)	rUrr{ZusedÚfoundrEÚeÚtbÚvrrrÚresolveõs"



zBaseConfigurator.resolvecCs
| |¡S)z*Default converter for the ext:// protocol.)r>©rUrMrrrr3szBaseConfigurator.ext_convertcCsþ|}|j |¡}|dkr&td|ƒ‚nÔ|| ¡d…}|j| ¡d}|rú|j |¡}|rn|| ¡d}nd|j |¡}|rÒ| ¡d}|j |¡s ||}n2zt	|ƒ}||}Wnt
k
rÐ||}YnX|rè|| ¡d…}qHtd||fƒ‚qH|S)z*Default converter for the cfg:// protocol.NzUnable to convert %rrzUnable to convert %r at %r)ÚWORD_PATTERNr-rHÚendr5ÚgroupsÚDOT_PATTERNÚ
INDEX_PATTERNÚ
DIGIT_PATTERNÚintr˜)rUrMÚrestrÞrr1Únrrrr4s4
ÿzBaseConfigurator.cfg_convertcCsÆt|tƒs$t|tƒr$t|ƒ}||_nžt|tƒsHt|tƒrHt|ƒ}||_nzt|tƒslt|tƒrlt|ƒ}||_nVt|tƒrÂ|j	 
|¡}|rÂ| ¡}|d}|j 
|d¡}|rÂ|d}t||ƒ}||ƒ}|S)zù
            Convert values to an appropriate type. dicts, lists and tuples are
            replaced by their converting alternatives. Strings are checked to
            see if they have a conversion format and are converted if they do.
            ÚprefixNrû)rr(rär)r+rÒr,r2Ústring_typesÚCONVERT_PATTERNr-Ú	groupdictÚvalue_convertersrIrÎ)rUrMrÞrrIZ	converterrûrrrr*2s,
ÿ

zBaseConfigurator.convertcsnˆ d¡}t|ƒs| |¡}ˆ dd¡}t‡fdd„ˆDƒƒ}|f|Ž}|rj| ¡D]\}}t|||ƒqT|S)z1Configure an object with a user-supplied factory.z()r7Ncs g|]}t|ƒr|ˆ|f‘qSr)r&r©r5rrrkUsz5BaseConfigurator.configure_custom..)rñr�r>rärÚsetattr)rUr5r÷ZpropsrVrÈr{rMrrNrÚconfigure_customNs


z!BaseConfigurator.configure_customcCst|tƒrt|ƒ}|S)z0Utility function which converts lists to tuples.)rrÒr2r?rrrÚas_tuple\s
zBaseConfigurator.as_tupleN)r4r5r6rXr+r,rKr@rCrDrErMÚstaticmethodÚ
__import__r6rWr>r3r4r*rPrQrrrrr%Ýs"




þ"r%)r)rÄ)N)N)‘Z
__future__rrZr+rpZsslr7Úversion_inforZ
basestringrJrr•ÚtypesrZ	file_typeZ__builtin__ÚbuiltinsZConfigParserZconfigparserZ	_backportrrr	r
rrZurllibr
rrrrrrrZurllib2rrrrr r!r"r#r$r%ZhttplibZ	xmlrpclibZQueueZqueuer&ZhtmlentitydefsZ	raw_inputÚ	itertoolsr'Úfilterr(r1r*r/ÚioÚstrr0Zurllib.parseZurllib.requestZurllib.errorZhttp.clientZclientZrequestZ
xmlrpc.clientZhtml.parserZ
html.entitiesZentitiesÚinputr2r3rHrFrOrPr$rYÚF_OKÚX_OKZzipfiler|r†rr~ZBaseZipExtFilerqr‰rŒr�Ú	NameErrorÚcollectionsr�rœržr»Úgetfilesystemencodingr–r—ÚtokenizerŸÚcodecsr r¡r,r°r¨Zhtmlr?ZcgirÀrÁrÂÚreprlibrÃrÑÚimportlib.utilröZimprüÚthreadrÆrZdummy_threadZ_abcollrýrþrÿräZlogging.configr%r&ÚIr'r(rñrÒr+r2r,rrrrÚs,
$,,0
2+A


		
[
b
w

PKÔ¶N]F�aX„}„}Isite-packages/pip/_vendor/distlib/__pycache__/compat.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.e¼¡ã@sBddlmZddlZddlZddlZzddlZWnek
rHdZYnXejddk�r~ddlmZe	fZ
eZddl
mZddlZddlZddlmZddlmZmZmZmZmZdd	lmZmZmZm Z m!Z!m"Z"m#Z#d
d„Zddl$Z$ddl$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-e�r&dd
l$m.Z.ddl/Z/ddl0Z0ddl1Z2ddl3m3Z3ddl4Z4e5Z5ddl6m7Z8ddl6m9Z:da;dd„Z<�nddl=mZe>fZ
e>Zddl=m?ZddlZddlZddlZddl@mZmZmZmd?„Zod@dA„ZiYnXzddBlpmqZqWn"ek
�rddBlrmqZqYnXejddC…dDk�r:e3ƒjsZsnddElpmsZszddFl`mtZtWndek
�rºddGl`muZuzddHlvmwZxWn ek
�r¤dedJdK„ZxYnXGdLdM„dMeuƒZtYnXzddNlymzZzWnHek
�rzddNl{mzZzWn ek
�rdfdOdP„ZzYnXYnXzddQl`m|Z|WnŠek
�r°zddRl}m~ZWn"ek
�rjddRl€m~ZYnXzddSl�m‚Z‚mƒZƒm„Z„Wnek
�ršYnXGdTdU„dUe…ƒZ|YnXzddVl†m‡Z‡mˆZˆWnvek
�r<e mdWej‰¡ZŠdXdY„ZˆGdZd[„d[e…ƒZ‹dgd\d]„ZŒGd^d_„d_e�ƒZŽGd`da„dae�ƒZ�Gdbdc„dceQƒZ‡YnXdS)hé)Úabsolute_importNé)ÚStringIO)ÚFileTypeé)Úshutil)ÚurlparseÚ
urlunparseÚurljoinÚurlsplitÚ
urlunsplit)ÚurlretrieveÚquoteÚunquoteÚurl2pathnameÚpathname2urlÚContentTooShortErrorÚ	splittypecCst|tƒr| d¡}t|ƒS)Núutf-8)Ú
isinstanceÚunicodeÚencodeÚ_quote)Ús©rú>/usr/lib/python3.8/site-packages/pip/_vendor/distlib/compat.pyrs

r)	ÚRequestÚurlopenÚURLErrorÚ	HTTPErrorÚHTTPBasicAuthHandlerÚHTTPPasswordMgrÚHTTPHandlerÚHTTPRedirectHandlerÚbuild_opener)ÚHTTPSHandler)Ú
HTMLParser)Úifilter)ÚifilterfalsecCs<tdkrddl}| d¡at |¡}|r4| dd¡Sd|fS)zJsplituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'.Nrz^(.*)@(.*)$ré)Ú	_userprogÚreÚcompileÚmatchÚgroup)Zhostr+r-rrrÚ	splituser4s

r/)Ú
TextIOWrapper)	rr	r
r/rrrrr)
rr
rrrr r!r"r#r$)rrr)Úfilterfalse)Úmatch_hostnameÚCertificateErrorc@seZdZdS)r3N)Ú__name__Ú
__module__Ú__qualname__rrrrr3^sr3c
Csôg}|sdS| d¡}|d|dd…}}| d¡}||krNtdt|ƒƒ‚|sb| ¡| ¡kS|dkrv| d¡n>| d	¡sŠ| d	¡rœ| t |¡¡n| t |¡ 	d
d¡¡|D]}| t |¡¡q¸t 
dd
 |¡dtj¡}	|	 
|¡S)zpMatching according to RFC 6125, section 6.4.3

        http://tools.ietf.org/html/rfc6125#section-6.4.3
        FÚ.rrNÚ*z,too many wildcards in certificate DNS name: z[^.]+zxn--z\*z[^.]*z\Az\.z\Z)ÚsplitÚcountr3ÚreprÚlowerÚappendÚ
startswithr+ÚescapeÚreplacer,ÚjoinÚ
IGNORECASEr-)
ZdnÚhostnameZ
max_wildcardsZpatsÚpartsZleftmostZ	remainderZ	wildcardsÚfragZpatrrrÚ_dnsname_matchbs*


ÿrFcCsì|stdƒ‚g}| dd¡}|D]*\}}|dkr t||ƒr@dS| |¡q |s”| dd¡D]6}|D],\}}|dkrdt||ƒr†dS| |¡qdq\t|ƒdkr¾td	|d
 tt|ƒ¡fƒ‚n*t|ƒdkràtd||dfƒ‚ntd
ƒ‚dS)a=Verify that *cert* (in decoded format as returned by
        SSLSocket.getpeercert()) matches the *hostname*.  RFC 2818 and RFC 6125
        rules are followed, but IP addresses are not accepted for *hostname*.

        CertificateError is raised on failure. On success, the function
        returns nothing.
        ztempty or no certificate, match_hostname needs a SSL socket or SSL context with either CERT_OPTIONAL or CERT_REQUIREDZsubjectAltNamerZDNSNZsubjectZ
commonNamerz&hostname %r doesn't match either of %sú, zhostname %r doesn't match %rrz=no appropriate commonName or subjectAltName fields were found)	Ú
ValueErrorÚgetrFr=Úlenr3rAÚmapr;)ZcertrCZdnsnamesZsanÚkeyÚvalueÚsubrrrr2”s2

þ
þr2)ÚSimpleNamespacec@seZdZdZdd„ZdS)Ú	ContainerzR
        A generic container for when multiple values need to be returned
        cKs|j |¡dS©N©Ú__dict__Úupdate)ÚselfÚkwargsrrrÚ__init__ÆszContainer.__init__N)r4r5r6Ú__doc__rWrrrrrPÂsrP)Úwhichcs"dd„}tj ˆ¡r&|ˆ|ƒr"ˆSdS|dkr>tj dtj¡}|sFdS| tj¡}tj	dkr¼tj
|krt| dtj
¡tj dd¡ tj¡}t‡fd	d
„|Dƒƒr¨ˆg}q‡fdd„|Dƒ}nˆg}t
ƒ}|D]P}tj |¡}||krÌ| |¡|D](}	tj ||	¡}
||
|ƒrò|
SqòqÌdS)
aKGiven a command, mode, and a PATH string, return the path which
        conforms to the given mode on the PATH, or None if there is no such
        file.

        `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
        of os.environ.get("PATH"), or can be overridden with a custom search
        path.

        cSs&tj |¡o$t ||¡o$tj |¡SrQ)ÚosÚpathÚexistsÚaccessÚisdir)ÚfnÚmoderrrÚ
_access_checkÛsÿzwhich.._access_checkNÚPATHZwin32rZPATHEXTÚc3s |]}ˆ ¡ | ¡¡VqdSrQ)r<Úendswith©Ú.0Úext©ÚcmdrrÚ	øszwhich..csg|]}ˆ|‘qSrrrerhrrÚ
ûszwhich..)rZr[ÚdirnameÚenvironrIÚdefpathr9ÚpathsepÚsysÚplatformÚcurdirÚinsertÚanyÚsetÚnormcaseÚaddrA)rir`r[raZpathextÚfilesÚseenÚdirZnormdirZthefileÚnamerrhrrYÎs8





rY)ÚZipFileÚ	__enter__)Ú
ZipExtFilec@s$eZdZdd„Zdd„Zdd„ZdS)r~cCs|j |j¡dSrQrR)rUÚbaserrrrWszZipExtFile.__init__cCs|SrQr©rUrrrr}szZipExtFile.__enter__cGs| ¡dSrQ©Úclose©rUÚexc_inforrrÚ__exit__szZipExtFile.__exit__N)r4r5r6rWr}r…rrrrr~sr~c@s$eZdZdd„Zdd„Zdd„ZdS)r|cCs|SrQrr€rrrr}"szZipFile.__enter__cGs| ¡dSrQr�rƒrrrr…%szZipFile.__exit__cOstj|f|ž|Ž}t|ƒSrQ)ÚBaseZipFileÚopenr~)rUÚargsrVrrrrr‡)szZipFile.openN)r4r5r6r}r…r‡rrrrr|!sr|)Úpython_implementationcCs0dtjkrdStjdkrdStj d¡r,dSdS)z6Return a string identifying the Python implementation.ZPyPyÚjavaZJythonZ
IronPythonZCPython)rpÚversionrZr{r>rrrrr‰0s

r‰)Ú	sysconfig)ÚCallablecCs
t|tƒSrQ)rr�)ÚobjrrrÚcallableDsr�rÚmbcsÚstrictÚsurrogateescapecCs:t|tƒr|St|tƒr$| tt¡Stdt|ƒjƒ‚dS©Nzexpect bytes or str, not %s)	rÚbytesÚ	text_typerÚ_fsencodingÚ	_fserrorsÚ	TypeErrorÚtyper4©ÚfilenamerrrÚfsencodeXs

ÿrœcCs:t|tƒr|St|tƒr$| tt¡Stdt|ƒjƒ‚dSr“)	rr•r”Údecoder–r—r˜r™r4ršrrrÚfsdecodeas

ÿrž)Údetect_encoding)ÚBOM_UTF8Úlookupzcoding[:=]\s*([-\w.]+)cCsH|dd… ¡ dd¡}|dks*| d¡r.dS|dks@| d¡rDd	S|S)
z(Imitates get_normal_name in tokenizer.c.NéÚ_ú-rzutf-8-)zlatin-1ú
iso-8859-1ziso-latin-1)zlatin-1-ziso-8859-1-ziso-latin-1-r¥)r<r@r>)Úorig_encÚencrrrÚ_get_normal_namersÿr¨csÊzˆjj‰Wntk
r$d‰YnXd‰d}d}‡fdd„}‡‡fdd„}|ƒ}| t¡rpd‰|d	d…}d
}|s||gfS||ƒ}|r’||gfS|ƒ}|s¦||gfS||ƒ}|r¾|||gfS|||gfS)a?
        The detect_encoding() function is used to detect the encoding that should
        be used to decode a Python source file.  It requires one argument, readline,
        in the same way as the tokenize() generator.

        It will call readline a maximum of twice, and return the encoding used
        (as a string) and a list of any lines (left as bytes) it has read in.

        It detects the encoding from the presence of a utf-8 bom or an encoding
        cookie as specified in pep-0263.  If both a bom and a cookie are present,
        but disagree, a SyntaxError will be raised.  If the encoding cookie is an
        invalid charset, raise a SyntaxError.  Note that if a utf-8 bom is found,
        'utf-8-sig' is returned.

        If no encoding is specified, then the default of 'utf-8' will be returned.
        NFrcs$zˆƒWStk
rYdSXdS)Nó)Ú
StopIterationr)ÚreadlinerrÚread_or_stop•sz%detect_encoding..read_or_stopcsäz| d¡}Wn4tk
rBd}ˆdk	r6d |ˆ¡}t|ƒ‚YnXt |¡}|sVdSt|dƒ}zt|ƒ}Wn:tk
r¨ˆdkr�d|}nd ˆ|¡}t|ƒ‚YnXˆrà|j	dkr؈dkrÆd}n
d ˆ¡}t|ƒ‚|d	7}|S)
Nrz'invalid or missing encoding declarationz{} for {!r}rzunknown encoding: zunknown encoding for {!r}: {}zencoding problem: utf-8z encoding problem for {!r}: utf-8z-sig)
r�ÚUnicodeDecodeErrorÚformatÚSyntaxErrorÚ	cookie_reÚfindallr¨r¡ÚLookupErrorr{)ÚlineÚline_stringÚmsgZmatchesÚencodingÚcodec)Ú	bom_foundr›rrÚfind_cookie›s8

ÿ

z$detect_encoding..find_cookieTrz	utf-8-sig)Ú__self__r{ÚAttributeErrorr>r )r«r¶Údefaultr¬r¹ÚfirstÚsecondr)r¸r›r«rrŸ}s4
&


rŸ)r?r))ré)Úunescape)ÚChainMap)ÚMutableMapping)Úrecursive_reprú...cs‡fdd„}|S)zm
            Decorator to make a repr function return fillvalue for a recursive
            call
            csLtƒ‰‡‡‡fdd„}tˆdƒ|_tˆdƒ|_tˆdƒ|_tˆdiƒ|_|S)Nc	sBt|ƒtƒf}|ˆkrˆSˆ |¡zˆ|ƒ}W5ˆ |¡X|SrQ)ÚidÚ	get_identrwÚdiscard)rUrLÚresult)Ú	fillvalueÚrepr_runningÚ
user_functionrrÚwrapperòs
z=_recursive_repr..decorating_function..wrapperr5rXr4Ú__annotations__)ruÚgetattrr5rXr4rÍ)rËrÌ©rÉ)rÊrËrÚdecorating_functionïsz,_recursive_repr..decorating_functionr)rÉrÐrrÏrÚ_recursive_représrÑc@s´eZdZdZdd„Zdd„Zdd„Zd'd	d
„Zdd„Zd
d„Z	dd„Z
dd„Zeƒdd„ƒZ
edd„ƒZdd„ZeZdd„Zedd„ƒZdd„Zdd „Zd!d"„Zd#d$„Zd%d&„ZdS)(rÁaÍ A ChainMap groups multiple dicts (or other mappings) together
        to create a single, updateable view.

        The underlying mappings are stored in a list.  That list is public and can
        accessed or updated using the *maps* attribute.  There is no other state.

        Lookups search the underlying mappings successively until a key is found.
        In contrast, writes, updates, and deletions only operate on the first
        mapping.

        cGst|ƒpig|_dS)z˜Initialize a ChainMap by setting *maps* to the given mappings.
            If no mappings are provided, a single empty dictionary is used.

            N)ÚlistÚmaps)rUrÓrrrrWszChainMap.__init__cCst|ƒ‚dSrQ)ÚKeyError©rUrLrrrÚ__missing__szChainMap.__missing__c	Cs:|jD](}z||WStk
r,YqXq| |¡SrQ)rÓrÔrÖ)rUrLÚmappingrrrÚ__getitem__s
zChainMap.__getitem__NcCs||kr||S|SrQr©rUrLr¼rrrrI%szChainMap.getcCsttƒj|jŽƒSrQ)rJruÚunionrÓr€rrrÚ__len__(szChainMap.__len__cCsttƒj|jŽƒSrQ)ÚiterrurÚrÓr€rrrÚ__iter__+szChainMap.__iter__cst‡fdd„|jDƒƒS)Nc3s|]}ˆ|kVqdSrQr)rfÚm©rLrrrj/sz(ChainMap.__contains__..©rtrÓrÕrrßrÚ__contains__.szChainMap.__contains__cCs
t|jƒSrQràr€rrrÚ__bool__1szChainMap.__bool__cCsd |d tt|jƒ¡¡S)Nz{0.__class__.__name__}({1})rG)r®rArKr;rÓr€rrrÚ__repr__4sÿzChainMap.__repr__cGs|tj|f|žŽƒS)z?Create a ChainMap with a single dict created from the iterable.)ÚdictÚfromkeys)ÚclsÚiterablerˆrrrrå9szChainMap.fromkeyscCs$|j|jd ¡f|jdd…žŽS)zHNew ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]rrN)Ú	__class__rÓÚcopyr€rrrré>sz
ChainMap.copycCs|jif|jžŽS)z;New ChainMap with a new dict followed by all previous maps.©rèrÓr€rrrÚ	new_childDszChainMap.new_childcCs|j|jdd…ŽS)zNew ChainMap from maps[1:].rNrêr€rrrÚparentsHszChainMap.parentscCs||jd|<dS)Nr)rÓ)rUrLrMrrrÚ__setitem__MszChainMap.__setitem__cCs8z|jd|=Wn"tk
r2td |¡ƒ‚YnXdS)Nrú(Key not found in the first mapping: {!r})rÓrÔr®rÕrrrÚ__delitem__PszChainMap.__delitem__cCs2z|jd ¡WStk
r,tdƒ‚YnXdS)zPRemove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.rz#No keys found in the first mapping.N)rÓÚpopitemrÔr€rrrrðVszChainMap.popitemcGs@z|jdj|f|žŽWStk
r:td |¡ƒ‚YnXdS)zWRemove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].rrîN)rÓÚpoprÔr®)rUrLrˆrrrrñ]szChainMap.popcCs|jd ¡dS)z'Clear maps[0], leaving maps[1:] intact.rN)rÓÚclearr€rrrròdszChainMap.clear)N)r4r5r6rXrWrÖrØrIrÛrÝrárârÑrãÚclassmethodråréÚ__copy__rëÚpropertyrìrírïrðrñròrrrrrÁs.



rÁ)Úcache_from_sourcecCs"|dkrd}|rd}nd}||S)NFÚcÚor)r[Údebug_overrideÚsuffixrrrrönsrö)ÚOrderedDict)rÆ)ÚKeysViewÚ
ValuesViewÚ	ItemsViewc@sþeZdZdZdd„Zejfdd„Zejfdd„Zdd	„Zd
d„Z	dd
„Z
d6dd„Zdd„Zdd„Z
dd„Zdd„Zdd„Zdd„Zdd„ZeZeƒZefdd „Zd7d"d#„Zd8d$d%„Zd&d'„Zd(d)„Zed9d*d+„ƒZd,d-„Zd.d/„Zd0d1„Zd2d3„Z d4d5„Z!d!S):rûz)Dictionary that remembers insertion ordercOsnt|ƒdkrtdt|ƒƒ‚z
|jWn6tk
r\g|_}||dg|dd…<i|_YnX|j||ŽdS)zÑInitialize an ordered dictionary.  Signature is the same as for
            regular dictionaries, but keyword arguments are not recommended
            because their insertion order is arbitrary.

            rz$expected at most 1 arguments, got %dN)rJr˜Ú_OrderedDict__rootr»Ú_OrderedDict__mapÚ_OrderedDict__update)rUrˆÚkwdsÚrootrrrrW•s

zOrderedDict.__init__cCsF||kr6|j}|d}|||g|d<|d<|j|<||||ƒdS)z!od.__setitem__(i, y) <==> od[i]=yrrN)rÿr)rUrLrMZdict_setitemrÚlastrrrrí¥s
 zOrderedDict.__setitem__cCs0|||ƒ|j |¡\}}}||d<||d<dS)z od.__delitem__(y) <==> del od[y]rrN)rrñ)rUrLZdict_delitemÚ	link_prevÚ	link_nextrrrrï¯s
zOrderedDict.__delitem__ccs.|j}|d}||k	r*|dV|d}qdS)zod.__iter__() <==> iter(od)rr)N©rÿ©rUrZcurrrrrrݸs

zOrderedDict.__iter__ccs.|j}|d}||k	r*|dV|d}qdS)z#od.__reversed__() <==> reversed(od)rr)NrrrrrÚ__reversed__Às

zOrderedDict.__reversed__cCsdz@|j ¡D]}|dd…=q|j}||dg|dd…<|j ¡Wntk
rTYnXt |¡dS)z.od.clear() -> None.  Remove all items from od.N)rÚ
itervaluesrÿròr»rä)rUZnoderrrrròÈszOrderedDict.clearTcCs||stdƒ‚|j}|r8|d}|d}||d<||d<n |d}|d}||d<||d<|d}|j|=t ||¡}||fS)z¡od.popitem() -> (k, v), return and remove a (key, value) pair.
            Pairs are returned in LIFO order if last is true or FIFO order if false.

            zdictionary is emptyrrr))rÔrÿrrärñ)rUrrÚlinkrrrLrMrrrrðÔs 
zOrderedDict.popitemcCst|ƒS)zod.keys() -> list of keys in od)rÒr€rrrÚkeysíszOrderedDict.keyscs‡fdd„ˆDƒS)z#od.values() -> list of values in odcsg|]}ˆ|‘qSrr©rfrLr€rrrkósz&OrderedDict.values..rr€rr€rÚvaluesñszOrderedDict.valuescs‡fdd„ˆDƒS)z.od.items() -> list of (key, value) pairs in odcsg|]}|ˆ|f‘qSrrr
r€rrrk÷sz%OrderedDict.items..rr€rr€rÚitemsõszOrderedDict.itemscCst|ƒS)z0od.iterkeys() -> an iterator over the keys in od)rÜr€rrrÚiterkeysùszOrderedDict.iterkeysccs|D]}||VqdS)z2od.itervalues -> an iterator over the values in odNr©rUÚkrrrr
ýszOrderedDict.itervaluesccs|D]}|||fVqdS)z=od.iteritems -> an iterator over the (key, value) items in odNrrrrrÚ	iteritemsszOrderedDict.iteritemscOsÈt|ƒdkr tdt|ƒfƒ‚n|s,tdƒ‚|d}d}t|ƒdkrL|d}t|tƒrn|D]}||||<qZn None.  Update od from dict/iterable E and F.

            If E is a dict instance, does:           for k in E: od[k] = E[k]
            If E has a .keys() method, does:         for k in E.keys(): od[k] = E[k]
            Or if E is an iterable of items, does:   for k, v in E: od[k] = v
            In either case, this is followed by:     for k, v in F.items(): od[k] = v

            r)z8update() takes at most 2 positional arguments (%d given)z,update() takes at least 1 argument (0 given)rrrrN)rJr˜rräÚhasattrrr)rˆrrUÚotherrLrMrrrrTs(	ÿ


zOrderedDict.updatecCs0||kr||}||=|S||jkr,t|ƒ‚|S)z±od.pop(k[,d]) -> v, remove specified key and return the corresponding value.
            If key is not found, d is returned if given, otherwise KeyError is raised.

            )Ú_OrderedDict__markerrÔ)rUrLr¼rÈrrrrñ*s
zOrderedDict.popNcCs||kr||S|||<|S)zDod.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in odrrÙrrrÚ
setdefault7szOrderedDict.setdefaultcCsf|si}t|ƒtƒf}||kr"dSd||<z.|sBd|jjfW¢Sd|jj| ¡fW¢S||=XdS)zod.__repr__() <==> repr(od)rÄrz%s()z%s(%r)N)rÅÚ
_get_identrèr4r)rUZ
_repr_runningZcall_keyrrrrã>szOrderedDict.__repr__csX‡fdd„ˆDƒ}tˆƒ ¡}ttƒƒD]}| |d¡q(|rLˆj|f|fSˆj|ffS)z%Return state information for picklingcsg|]}|ˆ|g‘qSrr©rfrr€rrrkNsz*OrderedDict.__reduce__..N)Úvarsrérûrñrè)rUrZ	inst_dictrrr€rÚ
__reduce__LszOrderedDict.__reduce__cCs
| |¡S)z!od.copy() -> a shallow copy of od)rèr€rrrréVszOrderedDict.copycCs|ƒ}|D]}|||<q
|S)zˆOD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
            and values equal to v (which defaults to None).

            r)rærçrMÚdrLrrrråZs
zOrderedDict.fromkeyscCs6t|tƒr*t|ƒt|ƒko(| ¡| ¡kSt ||¡S)z›od.__eq__(y) <==> od==y.  Comparison to another OD is order-sensitive
            while comparison to a regular mapping is order-insensitive.

            )rrûrJrräÚ__eq__©rUrrrrres
 zOrderedDict.__eq__cCs
||kSrQrrrrrÚ__ne__nszOrderedDict.__ne__cCst|ƒS)z@od.viewkeys() -> a set-like object providing a view on od's keys)rür€rrrÚviewkeyssszOrderedDict.viewkeyscCst|ƒS)z an object providing a view on od's values)rýr€rrrÚ
viewvalueswszOrderedDict.viewvaluescCst|ƒS)zBod.viewitems() -> a set-like object providing a view on od's items)rþr€rrrÚ	viewitems{szOrderedDict.viewitems)T)N)N)N)"r4r5r6rXrWrärírïrÝr	ròrðrrrrr
rrTrÚobjectrrñrrãrrérórårrr r!r"rrrrrû‰s:
	




	rû)ÚBaseConfiguratorÚvalid_identz^[a-z_][a-z0-9_]*$cCst |¡}|std|ƒ‚dS)Nz!Not a valid Python identifier: %rT)Ú
IDENTIFIERr-rH)rrÞrrrr%…s
r%c@s"eZdZdZdd„Zddd„ZdS)ÚConvertingDictz A converting dictionary wrapper.cCsJt ||¡}|j |¡}||k	rF|||<t|ƒtttfkrF||_||_	|SrQ)
rärØÚconfiguratorÚconvertr™r'ÚConvertingListÚConvertingTupleÚparentrL©rUrLrMrÈrrrrؘs
ÿzConvertingDict.__getitem__NcCsLt |||¡}|j |¡}||k	rH|||<t|ƒtttfkrH||_||_	|SrQ)
rärIr(r)r™r'r*r+r,rL©rUrLr¼rMrÈrrrrI¤s
ÿzConvertingDict.get)N)r4r5r6rXrØrIrrrrr'•sr'cCsDt |||¡}|j |¡}||k	r@t|ƒtttfkr@||_||_	|SrQ)
rärñr(r)r™r'r*r+r,rLr.rrrrñ°s
ÿrñc@s"eZdZdZdd„Zddd„ZdS)	r*zA converting list wrapper.cCsJt ||¡}|j |¡}||k	rF|||<t|ƒtttfkrF||_||_	|SrQ)
rÒrØr(r)r™r'r*r+r,rLr-rrrrؼs
ÿzConvertingList.__getitem__éÿÿÿÿcCs<t ||¡}|j |¡}||k	r8t|ƒtttfkr8||_|SrQ)	rÒrñr(r)r™r'r*r+r,)rUÚidxrMrÈrrrrñÈs
ÿzConvertingList.popN)r/)r4r5r6rXrØrñrrrrr*ºsr*c@seZdZdZdd„ZdS)r+zA converting tuple wrapper.cCsBt ||¡}|j |¡}||k	r>t|ƒtttfkr>||_||_	|SrQ)
ÚtuplerØr(r)r™r'r*r+r,rLr-rrrrØÓs
ÿzConvertingTuple.__getitem__N)r4r5r6rXrØrrrrr+Ñsr+c@sŒeZdZdZe d¡Ze d¡Ze d¡Ze d¡Z	e d¡Z
ddd	œZee
ƒZd
d„Zdd
„Zdd„Zdd„Zdd„Zdd„Zdd„ZdS)r$zQ
        The configurator base class which defines some useful defaults.
        z%^(?P[a-z]+)://(?P.*)$z^\s*(\w+)\s*z^\.\s*(\w+)\s*z^\[\s*(\w+)\s*\]\s*z^\d+$Úext_convertÚcfg_convert)rgZcfgcCst|ƒ|_||j_dSrQ)r'Úconfigr()rUr4rrrrWñs
zBaseConfigurator.__init__c		CsÂ| d¡}| d¡}z^| |¡}|D]H}|d|7}zt||ƒ}Wq$tk
rj| |¡t||ƒ}Yq$Xq$|WStk
r¼t ¡dd…\}}td||fƒ}|||_	|_
|‚YnXdS)zl
            Resolve strings to objects using standard import and attribute
            syntax.
            r7rrNzCannot resolve %r: %s)r9rñÚimporterrÎr»ÚImportErrorrpr„rHÚ	__cause__Ú
__traceback__)	rUrr{ZusedÚfoundrEÚeÚtbÚvrrrÚresolveõs"



zBaseConfigurator.resolvecCs
| |¡S)z*Default converter for the ext:// protocol.)r=©rUrMrrrr2szBaseConfigurator.ext_convertcCsþ|}|j |¡}|dkr&td|ƒ‚nÔ|| ¡d…}|j| ¡d}|rú|j |¡}|rn|| ¡d}nd|j |¡}|rÒ| ¡d}|j |¡s ||}n2zt	|ƒ}||}Wnt
k
rÐ||}YnX|rè|| ¡d…}qHtd||fƒ‚qH|S)z*Default converter for the cfg:// protocol.NzUnable to convert %rrzUnable to convert %r at %r)ÚWORD_PATTERNr-rHÚendr4ÚgroupsÚDOT_PATTERNÚ
INDEX_PATTERNÚ
DIGIT_PATTERNÚintr˜)rUrMÚrestrÞrr0Únrrrr3s4
ÿzBaseConfigurator.cfg_convertcCsÆt|tƒs$t|tƒr$t|ƒ}||_nžt|tƒsHt|tƒrHt|ƒ}||_nzt|tƒslt|tƒrlt|ƒ}||_nVt|tƒrÂ|j	 
|¡}|rÂ| ¡}|d}|j 
|d¡}|rÂ|d}t||ƒ}||ƒ}|S)zù
            Convert values to an appropriate type. dicts, lists and tuples are
            replaced by their converting alternatives. Strings are checked to
            see if they have a conversion format and are converted if they do.
            ÚprefixNrú)rr'rär(r*rÒr+r1Ústring_typesÚCONVERT_PATTERNr-Ú	groupdictÚvalue_convertersrIrÎ)rUrMrÞrrHZ	converterrúrrrr)2s,
ÿ

zBaseConfigurator.convertcsnˆ d¡}t|ƒs| |¡}ˆ dd¡}t‡fdd„ˆDƒƒ}|f|Ž}|rj| ¡D]\}}t|||ƒqT|S)z1Configure an object with a user-supplied factory.z()r7Ncs g|]}t|ƒr|ˆ|f‘qSr)r%r©r4rrrkUsz5BaseConfigurator.configure_custom..)rñr�r=rärÚsetattr)rUr4r÷ZpropsrVrÈr{rMrrMrÚconfigure_customNs


z!BaseConfigurator.configure_customcCst|tƒrt|ƒ}|S)z0Utility function which converts lists to tuples.)rrÒr1r>rrrÚas_tuple\s
zBaseConfigurator.as_tupleN)r4r5r6rXr+r,rJr?rBrCrDrLÚstaticmethodÚ
__import__r5rWr=r2r3r)rOrPrrrrr$Ýs"




þ"r$)r)rÄ)N)N)‘Z
__future__rrZr+rpZsslr6Úversion_inforZ
basestringrIrr•ÚtypesrZ	file_typeZ__builtin__ÚbuiltinsZConfigParserZconfigparserZ	_backportrrr	r
rrZurllibr
rrrrrrrZurllib2rrrrr r!r"r#r$r%ZhttplibZ	xmlrpclibZQueueZqueuer&ZhtmlentitydefsZ	raw_inputÚ	itertoolsr'Úfilterr(r1r*r/ÚioÚstrr0Zurllib.parseZurllib.requestZurllib.errorZhttp.clientZclientZrequestZ
xmlrpc.clientZhtml.parserZ
html.entitiesZentitiesÚinputr2r3rHrFrOrPr#rYÚF_OKÚX_OKZzipfiler|r†rr~ZBaseZipExtFilerqr‰rŒr�Ú	NameErrorÚcollectionsr�rœržr»Úgetfilesystemencodingr–r—ÚtokenizerŸÚcodecsr r¡r,r°r¨Zhtmlr?ZcgirÀrÁrÂÚreprlibrÃrÑÚimportlib.utilröZimprûÚthreadrÆrZdummy_threadZ_abcollrürýrþräZlogging.configr$r%ÚIr&r'rñrÒr*r1r+rrrrÚs,
$,,0
2+A


		
[
b
w

PKÔ¶N]ZÀÎ=½=½Asite-packages/pip/_vendor/distlib/__pycache__/util.cpython-38.pycnu„[µü¤U

ÀÒ.eøëã@s¸ddlZddlmZddlZddlZddlmZddlZddl	Z	ddl
Z
ddlZddlZddl
Z
ddlZzddlZWnek
rŒdZYnXddlZddlZddlZddlZddlZzddlZWnek
rÞddlZYnXddlZddlmZddlmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0e
 1e2¡Z3e
 4d¡Z5e
 4d¡Z6e
 4d	¡Z7e
 4d
¡Z8e
 4d¡Z9e
 4d¡Z:e
 4d
¡Z;e
 4d¡Zdd„Z?dd„Z@dd„ZAdˆdd„ZBdd„ZCdd„ZDdd „ZEejFd!d"„ƒZGejFd#d$„ƒZHejFd‰d&d'„ƒZIGd(d)„d)eJƒZKd*d+„ZLGd,d-„d-eJƒZMd.d/„ZNGd0d1„d1eJƒZOe
 4d2e
jP¡ZQd3d4„ZRdŠd5d6„ZSd7d8„ZTd9d:„ZUd;d<„ZVd=d>„ZWd?d@„ZXe
 4dAe
jY¡ZZe
 4dB¡Z[d‹dCdD„Z\e
 4dE¡Z]dFdG„Z^dHdI„Z_dJdK„Z`dLZadMdN„ZbdOdP„ZcGdQdR„dReJƒZdGdSdT„dTeJƒZeGdUdV„dVeJƒZfdWZgdŒdYdZ„Zhd[d\„Zid]ZjGd^d_„d_eJƒZke
 4d`¡Zle
 4da¡Zme
 4db¡Zndcdd„Zdedf„Zoe�rÖddglmpZqmrZrmsZsGdhdi„die$jtƒZtGdjdk„dkeqƒZpGdldm„dmepe'ƒZuejvddn…Zwewdok�rGdpdq„dqe$jxƒZxe�rGdrds„dse$jyƒZyGdtdu„due%jzƒZze�rBGdvdw„dwe%j{ƒZ{Gdxdy„dye%j|ƒZ|dzd{„Z}Gd|d}„d}eJƒZ~Gd~d„de~ƒZGd€d�„d�e~ƒZ€Gd‚dƒ„dƒe(ƒZ�Gd„d…„d…eJƒZ‚d†d‡„ZƒdS)�éN)Údeque)Úiglobé)ÚDistlibException)Ústring_typesÚ	text_typeÚshutilÚ	raw_inputÚStringIOÚcache_from_sourceÚurlopenÚurljoinÚhttplibÚ	xmlrpclibÚ	splittypeÚHTTPHandlerÚBaseConfiguratorÚvalid_identÚ	ContainerÚconfigparserÚURLErrorÚZipFileÚfsdecodeÚunquoteÚurlparsez^([\w\.-]+)\s*z^([\w\.*+-]+)\s*z^(<=?|>=?|={2,3}|[~!]=)\s*z*^((<=?)|(>=?)|={2,3}|[~!]=|in|not\s+in)\s*z^or\b\s*z	^and\b\s*z(\S+)\s*z(([\s\w\.{}()*+#:;,/?!~`@$%^&=|<>\[\]-]+)cs6dd„‰‡‡fdd„‰‡fdd„‰‡fdd„‰ˆ|ƒS)	ae
    Parse a marker string and return a dictionary containing a marker expression.

    The dictionary will contain keys "op", "lhs" and "rhs" for non-terminals in
    the expression grammar, or strings. A string contained in quotes is to be
    interpreted as a literal string, and a string not contained in quotes is a
    variable (such as os_name).
    cSs.t |¡}|r,| ¡d}|| ¡d…}nú|s:tdƒ‚nì|d}|dkrVtd|ƒ‚d |d¡}|dd…}|g}|rì|d|krŠ�qqt|d|kr®| |¡|dd…}qtt |¡}|sÈtd|ƒ‚| | ¡d¡|| ¡d…}qtd |¡}td|ƒ‚| |¡d |¡}|dd… 	¡}||fS)	Nrzunexpected end of inputz'"zinvalid expression: %sÚrzerror in string literal: %szunterminated string: %s)
Ú
IDENTIFIERÚmatchÚgroupsÚendÚSyntaxErrorÚreplaceÚappendÚSTRING_CHUNKÚjoinÚlstrip)Ú	remainingÚmÚresultÚqZoqÚpartsÚs©r,ú.marker_varcs´|rR|ddkrRˆ|dd… ¡ƒ\}}|ddkr@td|ƒ‚|dd… ¡}nZˆ|ƒ\}}|r¨t |¡}|srq¨| ¡d}|| ¡d…}ˆ|ƒ\}}|||dœ}q^|}||fS)Nrú(rú)úunterminated parenthesis: %s©ÚopÚlhsÚrhs)r%r Ú	MARKER_OPrrr)r&r(r4r'r3r5)Úmarkerr.r,r-Úmarker_expres 
z!parse_marker..marker_exprcsRˆ|ƒ\}}|rJt |¡}|s qJ|| ¡d…}ˆ|ƒ\}}d||dœ}q||fS)NÚandr2)ÚANDrr©r&r4r'r5)r8r,r-Ú
marker_andxs
z parse_marker..marker_andcsRˆ|ƒ\}}|rJt |¡}|s qJ|| ¡d…}ˆ|ƒ\}}d||dœ}q||fS)NÚorr2)ÚORrrr;)r<r,r-r7ƒs
zparse_marker..markerr,)Z
marker_stringr,)r7r<r8r.r-Úparse_marker8s
	$r?cCs0| ¡}|r| d¡rdSt |¡}|s4td|ƒ‚| ¡d}|| ¡d…}d}}}}|�r:|ddk�r:| dd¡}|dkr”td|ƒ‚|d|…}	||dd… ¡}g}|	�r0t |	¡}|sØtd	|	ƒ‚| 	| ¡d¡|	| ¡d…}	|	�s�q0|	dd
k�rtd|	ƒ‚|	dd… ¡}	q¸|�s:d}|�r˜|ddk�rÀ|dd… ¡}t
 |¡}|�sztd
|ƒ‚| ¡d}t|ƒ}
|
j�rž|
j
�sªtd|ƒ‚|| ¡d… ¡}nØdd„}|ddk�rä||ƒ\}}n´| dd¡}|dk�rtd|ƒ‚|d|…}	||dd… ¡}t |	¡�r@||	ƒ\}}nXt |	¡}|�s\td|	ƒ‚| ¡d}
|	| ¡d… ¡}	|	�rŽtd|	ƒ‚d|
fg}|�rÔ|ddk�r¸td|ƒ‚|dd… ¡}t|ƒ\}}|�rô|ddk�rôtd|ƒ‚|�s|}nd|d dd„|Dƒ¡f}t||||||d�S)zŠ
    Parse a requirement passed in as a string. Return a Container
    whose attributes contain the various parts of the requirement.
    ú#Nzname expected: %srú[ú]rzunterminated extra: %szmalformed extra: %sú,zcomma expected in extras: %sú@zinvalid URI: %szInvalid URL: %scSsÄt |¡}d}|r¼g}| ¡d}|| ¡d…}t |¡}|sLtd|ƒ‚| ¡d}| ||f¡|| ¡d…}|r´|ddkrˆq´|dd… ¡}t |¡}|std|ƒ‚q|s¼d}||fS)z|
                Return a list of operator, version tuples if any are
                specified, else None.
                Nrzinvalid version: %srCrúinvalid constraint: %s)Ú
COMPARE_OPrrrÚVERSION_IDENTIFIERr r"r%)Z
ver_remainingr'Úversionsr3Úvr,r,r-Úget_versionsÅs*


z'parse_requirement..get_versionsr/r0r1rEz~=ú;zinvalid requirement: %szunexpected trailing data: %sú%s %sú, cSsg|]}d|‘qS)rLr,)Ú.0Zconr,r,r-Ú
sz%parse_requirement..)ÚnameÚextrasZconstraintsr7ÚurlZrequirement)ÚstripÚ
startswithrrr rrÚfindr%r"Ú	NON_SPACErÚschemeÚnetlocrFrGr?r$r)Úreqr&r'ZdistnamerQZ	mark_exprrHÚuriÚir+ÚtrJÚ_rIZrsr,r,r-Úparse_requirement‘s’





ÿr^cCs¨dd„}i}|D]’\}}}tj ||¡}t|ƒD]p}tj ||¡}	t|	ƒD]T}
|||
ƒ}|dkrn| |d¡qJ|||
ƒ}| tjjd¡ d¡}
|
d|||<qJq0q|S)z%Find destinations for resources filescSsD| tjjd¡}| tjjd¡}| |¡s.t‚|t|ƒd… d¡S©Nú/)r!ÚosÚpathÚseprTÚAssertionErrorÚlenr%)Úrootrbr,r,r-Úget_rel_path
sz)get_resources_dests..get_rel_pathNr`)rarbr$rÚpopr!rcÚrstrip)Zresources_rootZrulesrgZdestinationsÚbaseÚsuffixÚdestÚprefixZabs_baseZabs_globZabs_pathZ
resource_fileZrel_pathZrel_destr,r,r-Úget_resources_dests
s

rncCs(ttdƒrd}ntjttdtjƒk}|S)NZreal_prefixTÚbase_prefix)ÚhasattrÚsysrmÚgetattr©r(r,r,r-Úin_venv$s
rtcCs$tj tj¡}t|tƒs t|ƒ}|S©N)rarbÚnormcaserqÚ
executableÚ
isinstancerrrsr,r,r-Úget_executable.s

rycCsN|}t|ƒ}|}|s|r|}|r|d ¡}||kr6qJ|rd|||f}q|S)Nrz	%c: %s
%s)r	Úlower)ÚpromptZ
allowed_charsZerror_promptÚdefaultÚpr+Úcr,r,r-Úproceed>srcCs8t|tƒr| ¡}i}|D]}||kr||||<q|Sru)rxrÚsplit)ÚdÚkeysr(Úkeyr,r,r-Úextract_by_keyNs
r„cCsztjddkrt d¡|ƒ}| ¡}t|ƒ}zlt |¡}|ddd}| ¡D]B\}}| ¡D]0\}}d||f}t	|ƒ}	|	dk	sˆt
‚|	||<q`qP|WStk
r¸| dd¡YnXdd	„}
t
 ¡}z|
||ƒWn<t
jk
�r| ¡t |¡}t|ƒ}|
||ƒYnXi}| ¡D]R}i||<}| |¡D]4\}
}d|
|f}t	|ƒ}	|	dk	�sft
‚|	||
<�q<�q"|S)
Nréúutf-8Ú
extensionszpython.exportsÚexportsz%s = %scSs$t|dƒr| |¡n
| |¡dS)NÚ	read_file)rpr‰Zreadfp)ÚcpÚstreamr,r,r-Úread_streamks
z!read_exports..read_stream)rqÚversion_infoÚcodecsÚ	getreaderÚreadr
ÚjsonÚloadÚitemsÚget_export_entryrdÚ	ExceptionÚseekrÚConfigParserZMissingSectionHeaderErrorÚcloseÚtextwrapÚdedentZsections)r‹ÚdataZjdatar(ÚgroupÚentriesÚkrIr+ÚentryrŒrŠrƒrPÚvaluer,r,r-Úread_exportsWsD

r¡cCs¨tjddkrt d¡|ƒ}t ¡}| ¡D]l\}}| |¡| ¡D]P}|j	dkr\|j
}nd|j
|j	f}|jr†d|d |j¡f}| 
||j|¡qFq,| |¡dS)Nrr…r†z%s:%sz%s [%s]rM)rqr�rŽÚ	getwriterrr—r“Zadd_sectionÚvaluesrkrmÚflagsr$ÚsetrPÚwrite)rˆr‹rŠržrIrŸr+r,r,r-Ú
write_exports†s

r§c	cs$t ¡}z
|VW5t |¡XdSru)ÚtempfileÚmkdtemprÚrmtree)Ztdr,r,r-Útempdir™s
r«c	cs.t ¡}zt |¡dVW5t |¡XdSru)raÚgetcwdÚchdir)r�Úcwdr,r,r-r­¡s


r­éc	cs.t ¡}zt |¡dVW5t |¡XdSru)ÚsocketZgetdefaulttimeoutZsetdefaulttimeout)ZsecondsZctor,r,r-Úsocket_timeout«s


r±c@seZdZdd„Zddd„ZdS)Úcached_propertycCs
||_dSru)Úfunc)Úselfr³r,r,r-Ú__init__¶szcached_property.__init__NcCs,|dkr|S| |¡}t ||jj|¡|Sru)r³ÚobjectÚ__setattr__Ú__name__)r´ÚobjÚclsr r,r,r-Ú__get__»s

zcached_property.__get__)N)r¸Ú
__module__Ú__qualname__rµr»r,r,r,r-r²µsr²cCs~tjdkr|S|s|S|ddkr.td|ƒ‚|ddkrFtd|ƒ‚| d¡}tj|krh| tj¡qP|srtjStjj|ŽS)aÐReturn 'pathname' as a name that will work on the native filesystem.

    The path is split on '/' and put back together again using the current
    directory separator.  Needed because filenames in the setup script are
    always supplied in Unix style, and have to be converted to the local
    convention before we can actually use them in the filesystem.  Raises
    ValueError on non-Unix-ish systems if 'pathname' either starts or
    ends with a slash.
    r`rzpath '%s' cannot be absoluteéÿÿÿÿzpath '%s' cannot end with '/')rarcÚ
ValueErrorr€ÚcurdirÚremoverbr$)ÚpathnameÚpathsr,r,r-Úconvert_pathÃs



rÄc@s”eZdZd$dd„Zdd„Zdd„Zdd	„Zd%dd„Zd&dd„Zdd„Z	dd„Z
dd„Zdd„Zdd„Z
d'dd„Zdd„Zdd„Zd d!„Zd"d#„Zd
S)(ÚFileOperatorFcCs||_tƒ|_| ¡dSru)Údry_runr¥ÚensuredÚ_init_record)r´rÆr,r,r-rµßszFileOperator.__init__cCsd|_tƒ|_tƒ|_dS©NF)Úrecordr¥Ú
files_writtenÚdirs_created©r´r,r,r-rÈäszFileOperator._init_recordcCs|jr|j |¡dSru)rÊrËÚadd)r´rbr,r,r-Úrecord_as_writtenészFileOperator.record_as_writtencCsHtj |¡s tdtj |¡ƒ‚tj |¡s0dSt |¡jt |¡jkS)aÎTell if the target is newer than the source.

        Returns true if 'source' exists and is more recently modified than
        'target', or if 'source' exists and 'target' doesn't.

        Returns false if both exist and 'target' is the same age or younger
        than 'source'. Raise PackagingFileError if 'source' does not exist.

        Note that this test is not very accurate: files created in the same
        second will have the same "age".
        zfile '%r' does not existT)rarbÚexistsrÚabspathÚstatÚst_mtime)r´ÚsourceÚtargetr,r,r-Únewerís
ÿzFileOperator.newerTcCsŽ| tj |¡¡t d||¡|js€d}|rdtj |¡rDd|}n tj |¡rdtj 	|¡sdd|}|rtt
|dƒ‚t ||¡| 
|¡dS)z8Copy a file respecting dry-run and force flags.
        zCopying %s to %sNz%s is a symlinkz%s is a non-regular filez which would be overwritten)Ú
ensure_dirrarbÚdirnameÚloggerÚinforÆÚislinkrÐÚisfiler¿rZcopyfilerÏ)r´ZinfileÚoutfileÚcheckÚmsgr,r,r-Ú	copy_files
zFileOperator.copy_fileNcCs„tj |¡rt‚| tj |¡¡t d||¡|jsv|dkrJt	|dƒ}nt
j	|d|d�}zt 
||¡W5| ¡X| |¡dS)NzCopying stream %s to %sÚwbÚw©Úencoding)rarbÚisdirrdr×rØrÙrÚrÆÚopenrŽr˜rZcopyfileobjrÏ)r´ZinstreamrÝräZ	outstreamr,r,r-Úcopy_streams
zFileOperator.copy_streamc	Cs\| tj |¡¡|jsNtj |¡r.t |¡t|dƒ�}| |¡W5QRX| 	|¡dS)Nrá)
r×rarbrØrÆrÐrÁrær¦rÏ)r´rbr›Úfr,r,r-Úwrite_binary_file!s
zFileOperator.write_binary_filecCs| || |¡¡dSru)réÚencode)r´rbr›rär,r,r-Úwrite_text_file*szFileOperator.write_text_filecCsntjdkstjdkrjtjdkrj|D]F}|jr:t d|¡q"t |¡j|B|@}t d||¡t ||¡q"dS)NÚposixÚjavazchanging mode of %szchanging mode of %s to %o)	rarPÚ_namerÆrÙrÚrÒÚst_modeÚchmod)r´ÚbitsÚmaskÚfilesrèÚmoder,r,r-Úset_mode-szFileOperator.set_modecCs| dd|¡S)Nimiÿ)rõ)r+rèr,r,r-Ú9ózFileOperator.cCs|tj |¡}||jkrxtj |¡sx|j |¡tj |¡\}}| |¡t 	d|¡|j
sft |¡|jrx|j
 |¡dS)NzCreating %s)rarbrÑrÇrÐrÎr€r×rÙrÚrÆÚmkdirrÊrÌ)r´rbr�rèr,r,r-r×;s

zFileOperator.ensure_dirc	Cs˜t||ƒ}t d||¡|jsŠ|s0| ||¡rX|s:d}n| |¡sHt‚|t|ƒd…}i}|rvtt	dƒrvt	j
j|d<t	j|||df|Ž| 
|¡|S)NzByte-compiling %s to %sÚPycInvalidationModeÚinvalidation_modeT)rrÙrÚrÆrÖrTrdrerpÚ
py_compilerùÚCHECKED_HASHÚcompilerÏ)	r´rbÚoptimizeÚforcermZhashed_invalidationZdpathZdiagpathZcompile_kwargsr,r,r-Úbyte_compileGs
zFileOperator.byte_compilecCs²tj |¡r®tj |¡r^tj |¡s^t d|¡|js@t 	|¡|j
r®||jkr®|j |¡nPtj |¡rpd}nd}t d||¡|js’t |¡|j
r®||j
kr®|j
 |¡dS)NzRemoving directory tree at %sÚlinkÚfilezRemoving %s %s)rarbrÐrårÛrÙÚdebugrÆrrªrÊrÌrÁrË)r´rbr+r,r,r-Úensure_removedXs"



zFileOperator.ensure_removedcCsDd}|s@tj |¡r$t |tj¡}q@tj |¡}||kr:q@|}q|SrÉ)rarbrÐÚaccessÚW_OKrØ)r´rbr(Úparentr,r,r-Úis_writablemszFileOperator.is_writablecCs"|js
t‚|j|jf}| ¡|S)zV
        Commit recorded changes, turn off recording, return
        changes.
        )rÊrdrËrÌrÈ)r´r(r,r,r-Úcommitys
zFileOperator.commitcCs’|js†t|jƒD]}tj |¡rt |¡qt|jdd�}|D]F}t 	|¡}|rz|dgks^t
‚tj ||d¡}t |¡t |¡q>| 
¡dS)NT)ÚreverseÚ__pycache__r)rÆÚlistrËrarbrÐrÁÚsortedrÌÚlistdirrdr$ÚrmdirrÈ)r´rèÚdirsr�ÚflistZsdr,r,r-Úrollbackƒs

zFileOperator.rollback)F)T)N)FFNF)r¸r¼r½rµrÈrÏrÖràrçrérërõZset_executable_moder×rrrr	rr,r,r,r-rÅÞs 


	

rÅcCs^|tjkrtj|}nt|ƒ}|dkr,|}n.| d¡}t|| d¡ƒ}|D]}t||ƒ}qJ|S)NÚ.r)rqÚmodulesÚ
__import__r€rrrh)Zmodule_nameZdotted_pathÚmodr(r*r}r,r,r-Úresolve•s

rc@s6eZdZdd„Zedd„ƒZdd„Zdd„Zej	Z	d	S)
ÚExportEntrycCs||_||_||_||_dSru©rPrmrkr¤)r´rPrmrkr¤r,r,r-rµ¥szExportEntry.__init__cCst|j|jƒSru)rrmrkrÍr,r,r-r «szExportEntry.valuecCsd|j|j|j|jfS)NzrrÍr,r,r-Ú__repr__¯s
ÿzExportEntry.__repr__cCsDt|tƒsd}n0|j|jko>|j|jko>|j|jko>|j|jk}|SrÉ)rxrrPrmrkr¤)r´Úotherr(r,r,r-Ú__eq__³s

ÿ
þ
ýzExportEntry.__eq__N)
r¸r¼r½rµr²r rrr¶Ú__hash__r,r,r,r-r¤s

rzµ(?P(\w|[-.+])+)
                      \s*=\s*(?P(\w+)([:\.]\w+)*)
                      \s*(\[\s*(?P\w+(=\w+)?(,\s*\w+(=\w+)?)*)\s*\])?
                      c
Csàt |¡}|s0d}d|ks"d|krÜtd|ƒ‚n¬| ¡}|d}|d}| d¡}|dkrf|d}}n"|dkrztd|ƒ‚| d¡\}}|d	}	|	dkrºd|ks¨d|kr´td|ƒ‚g}	nd
d„|	 d¡Dƒ}	t||||	ƒ}|S)
NrArBzInvalid specification '%s'rPÚcallableú:rrr¤cSsg|]}| ¡‘qSr,)rS)rNrèr,r,r-rOßsz$get_export_entry..rC)ÚENTRY_REÚsearchrÚ	groupdictÚcountr€r)
Z
specificationr'r(r�rPrbZcolonsrmrkr¤r,r,r-r”Ås8
ÿ
ÿÿr”cCsÈ|dkrd}tjdkr.dtjkr.tj d¡}ntj d¡}tj |¡rft |tj¡}|s¢t	 
d|¡n| dd¡\}}d|kr.|}n| dd¡\}}|rJt|ƒ}|rVt|ƒ}|||fS)NrDrr)Úrsplitr€r)rXZusernameZpasswordrmr,r,r-Úparse_credentials$sr3cCst d¡}t |¡|S)Né)raÚumaskrsr,r,r-Úget_process_umask3s

r6cCs<d}d}t|ƒD]\}}t|tƒsd}q,q|dk	s8t‚|S)NTF)Ú	enumeraterxrrd)Úseqr(r[r+r,r,r-Úis_string_sequence8s
r9z3([a-z0-9_]+([.-][a-z_][a-z0-9_]*)*)-([a-z0-9_.+-]+)z
-py(\d\.?\d?)cCsÈd}d}t|ƒ dd¡}t |¡}|r@| d¡}|d| ¡…}|r˜t|ƒt|ƒdkr˜t t 	|¡d|¡}|r˜| 
¡}|d|…||dd…|f}|dkrÄt |¡}|rÄ| d¡| d¡|f}|S)zw
    Extract name, version, python version from a filename (no extension)

    Return name, version, pyver or None
    Nú ú-rz\br…)rr!ÚPYTHON_VERSIONr!rœÚstartreÚrerÚescaperÚPROJECT_NAME_AND_VERSION)ÚfilenameZproject_namer(Zpyverr'Únr,r,r-Úsplit_filenameGs"


rCz-(?P[\w .-]+)\s*\(\s*(?P[^\s)]+)\)$cCs:t |¡}|std|ƒ‚| ¡}|d ¡ ¡|dfS)zÇ
    A utility method used to get name and version from a string.

    From e.g. a Provides-Dist value.

    :param p: A value in a form 'foo (1.0)'
    :return: The name and version as a tuple.
    z$Ill-formed name/version string: '%s'rPZver)ÚNAME_VERSION_RErrr"rSrz)r}r'r�r,r,r-Úparse_name_and_versioncs
	
rEcCsºtƒ}t|pgƒ}t|pgƒ}d|kr8| d¡||O}|D]x}|dkrT| |¡q<| d¡r”|dd…}||kr€t d|¡||kr´| |¡q<||krªt d|¡| |¡q<|S)NÚ*r;rzundeclared extra: %s)r¥rÁrÎrTrÙr*)Z	requestedZ	availabler(ÚrZunwantedr,r,r-Ú
get_extrasrs&

rHc
Csˆi}zNt|ƒ}| ¡}| d¡}| d¡s8t d|¡nt d¡|ƒ}t 	|¡}Wn0t
k
r‚}zt d||¡W5d}~XYnX|S)NzContent-Typezapplication/jsonz(Unexpected response for JSON request: %sr†z&Failed to get external data for %s: %s)rrÚÚgetrTrÙrrŽr�r‘r’r•Ú	exception)rRr(ZrespZheadersZctÚreaderÚer,r,r-Ú_get_external_data‹s

 rMz'https://www.red-dove.com/pypi/projects/cCs*d|d ¡|f}tt|ƒ}t|ƒ}|S)Nz%s/%s/project.jsonr©Úupperr
Ú_external_data_base_urlrM)rPrRr(r,r,r-Úget_project_data¡s
rQcCs(d|d ¡||f}tt|ƒ}t|ƒS)Nz%s/%s/package-%s.jsonrrN)rPÚversionrRr,r,r-Úget_package_data§s
rSc@s(eZdZdZdd„Zdd„Zdd„ZdS)	ÚCachezæ
    A class implementing a cache for resources that need to live in the file system
    e.g. shared libraries. This class was moved from resources to here because it
    could be used by other modules, e.g. the wheel module.
    cCsPtj |¡st |¡t |¡jd@dkr6t d|¡tj tj 	|¡¡|_
dS)zu
        Initialise an instance.

        :param base: The base directory where the cache should be located.
        é?rzDirectory '%s' is not privateN)rarbrår+rÒrïrÙr*rÑÚnormpathrj)r´rjr,r,r-rµ´s

zCache.__init__cCst|ƒS)zN
        Converts a resource prefix to a directory name in the cache.
        )r/)r´rmr,r,r-Ú
prefix_to_dirÂszCache.prefix_to_dirc	Csˆg}t |j¡D]r}tj |j|¡}z>tj |¡s>tj |¡rJt |¡ntj |¡r`t	 
|¡Wqtk
r€| |¡YqXq|S)z"
        Clear the cache.
        )
rarrjrbr$rÛrÜrÁrårrªr•r")r´Znot_removedÚfnr,r,r-ÚclearÈszCache.clearN)r¸r¼r½Ú__doc__rµrWrYr,r,r,r-rT­srTc@s:eZdZdZdd„Zddd„Zdd„Zd	d
„Zdd„Zd
S)Ú
EventMixinz1
    A very simple publish/subscribe system.
    cCs
i|_dSru)Ú_subscribersrÍr,r,r-rµÝszEventMixin.__init__TcCsD|j}||krt|gƒ||<n"||}|r6| |¡n
| |¡dS)a`
        Add a subscriber for an event.

        :param event: The name of an event.
        :param subscriber: The subscriber to be added (and called when the
                           event is published).
        :param append: Whether to append or prepend the subscriber to an
                       existing subscriber list for the event.
        N)r\rr"Ú
appendleft)r´ÚeventÚ
subscriberr"ÚsubsZsqr,r,r-rÎàs
zEventMixin.addcCs,|j}||krtd|ƒ‚|| |¡dS)z™
        Remove a subscriber for an event.

        :param event: The name of an event.
        :param subscriber: The subscriber to be removed.
        zNo subscribers: %rN)r\r¿rÁ)r´r^r_r`r,r,r-rÁôszEventMixin.removecCst|j |d¡ƒS)z�
        Return an iterator for the subscribers for an event.
        :param event: The event to return subscribers for.
        r,)Úiterr\rI)r´r^r,r,r-Úget_subscribersszEventMixin.get_subscribersc	Oslg}| |¡D]F}z||f|ž|Ž}Wn"tk
rHt d¡d}YnX| |¡qt d||||¡|S)a^
        Publish a event and return a list of values returned by its
        subscribers.

        :param event: The event to publish.
        :param args: The positional arguments to pass to the event's
                     subscribers.
        :param kwargs: The keyword arguments to pass to the event's
                       subscribers.
        z"Exception during event publicationNz/publish %s: args = %s, kwargs = %s, result = %s)rbr•rÙrJr"r)r´r^ÚargsÚkwargsr(r_r r,r,r-Úpublishs

ÿzEventMixin.publishN)T)	r¸r¼r½rZrµrÎrÁrbrer,r,r,r-r[Ùs
r[c@s^eZdZdd„Zdd„Zddd„Zdd	„Zd
d„Zdd
„Zdd„Z	e
dd„ƒZe
dd„ƒZdS)Ú	SequencercCsi|_i|_tƒ|_dSru)Ú_predsÚ_succsr¥Ú_nodesrÍr,r,r-rµ"szSequencer.__init__cCs|j |¡dSru)rirΩr´Únoder,r,r-Úadd_node'szSequencer.add_nodeFcCs®||jkr|j |¡|rªt|j |d¡ƒD]}| ||¡q,t|j |d¡ƒD]}| ||¡qPt|j ¡ƒD]\}}|sp|j|=qpt|j ¡ƒD]\}}|s”|j|=q”dS)Nr,)rirÁr¥rgrIrhrr“)r´rkZedgesr}r+ržrIr,r,r-Úremove_node*s

zSequencer.remove_nodecCs<||kst‚|j |tƒ¡ |¡|j |tƒ¡ |¡dSru)rdrgÚ
setdefaultr¥rÎrh)r´ÚpredÚsuccr,r,r-rÎ:sz
Sequencer.addcCsˆ||kst‚z|j|}|j|}Wn tk
rDtd|ƒ‚YnXz| |¡| |¡Wn$tk
r‚td||fƒ‚YnXdS)Nz%r not a successor of anythingz%r not a successor of %r)rdrgrhÚKeyErrorr¿rÁ)r´rorpÚpredsZsuccsr,r,r-rÁ?s

zSequencer.removecCs||jkp||jkp||jkSru)rgrhri)r´Ústepr,r,r-Úis_stepLsÿzSequencer.is_stepcCs˜| |¡std|ƒ‚g}g}tƒ}| |¡|r�| d¡}||krb||krŽ| |¡| |¡q.| |¡| |¡|j |d¡}| 	|¡q.t
|ƒS)NzUnknown: %rrr,)rtr¿r¥r"rhrÁrÎrgrIÚextendÚreversed)r´Úfinalr(ZtodoÚseenrsrrr,r,r-Ú	get_stepsPs"





zSequencer.get_stepscsRdg‰g‰i‰i‰g‰|j‰‡‡‡‡‡‡‡fdd„‰ˆD]}|ˆkr8ˆ|ƒq8ˆS)Nrcsðˆdˆ|<ˆdˆ|<ˆdd7<ˆ |¡zˆ|}Wntk
rVg}YnX|D]J}|ˆkrˆˆ|ƒtˆ|ˆ|ƒˆ|<q\|ˆkr\tˆ|ˆ|ƒˆ|<q\ˆ|ˆ|krìg}ˆ ¡}| |¡||kr¼qÚq¼t|ƒ}ˆ |¡dS)Nrr)r"r•ÚminrhÚtuple)rkZ
successorsZ	successorZconnected_componentZ	component©ZgraphÚindexZ
index_counterZlowlinksr(ÚstackÚ
strongconnectr,r-rts,


z3Sequencer.strong_connections..strongconnect)rhrjr,r|r-Ústrong_connectionsis"
zSequencer.strong_connectionscCsfdg}|jD]*}|j|}|D]}| d||f¡qq|jD]}| d|¡q>| d¡d |¡S)Nzdigraph G {z  %s -> %s;z  %s;Ú}Ú
)rgr"rir$)r´r(rprrrorkr,r,r-Údotœs



z
Sequencer.dotN)F)
r¸r¼r½rµrlrmrÎrÁrtryÚpropertyr€rƒr,r,r,r-rf!s


2rf)ú.tar.gzú.tar.bz2ú.tarú.zipú.tgzú.tbzú.whlTcsZ‡‡fdd„}tj ˆ¡‰tˆƒ‰d}|dkr†| d¡r>d}nH| d¡rRd}d}n4| d¡rfd	}d
}n | d¡rzd}d
}ntd|ƒ‚z¾|dkrºt|d
ƒ}|rä| ¡}|D]}||ƒqªn*t	 
||¡}|rä| ¡}|D]}||ƒqÖ|dk�r*tj
ddk�r*| ¡D]"}	t|	jtƒ�s|	j d¡|	_�qdd„}
|
|_| ˆ¡W5|�rT| ¡XdS)NcsRt|tƒs| d¡}tj tj ˆ|¡¡}| ˆ¡rB|ˆtjkrNt	d|ƒ‚dS)Nr†zpath outside destination: %r)
rxrÚdecoderarbrÑr$rTrcr¿)rbr}©Údest_dirZplenr,r-Ú
check_path±s


zunarchive..check_path)rˆr‹Úzip)r…r‰Ztgzzr:gz)r†rŠZtbzzr:bz2r‡ZtarrGzUnknown format for %rrr…r†c
SsDzt ||¡WStjk
r>}ztt|ƒƒ‚W5d}~XYnXdS)z:Run tarfile.tar_fillter, but raise the expected ValueErrorN)ÚtarfileZ
tar_filterZFilterErrorr¿Ústr)ÚmemberrbÚexcr,r,r-Úextraction_filterâsz$unarchive..extraction_filter)rarbrÑrer0r¿r˜rZnamelistr‘ræZgetnamesrqr�Z
getmembersrxrPrrŒr•Z
extractall)Zarchive_filenamerŽÚformatrÞr�ÚarchiverôÚnamesrPZtarinfor•r,r�r-Ú	unarchive¯sL





r™c	Cs~t ¡}t|ƒ}t|dƒ�Z}t |¡D]H\}}}|D]8}tj ||¡}||d…}	tj |	|¡}
| ||
¡q4q&W5QRX|S)z*zip a directory tree into a BytesIO objectrâN)	ÚioÚBytesIOrerraÚwalkrbr$r¦)Z	directoryr(ZdlenZzfrfrrórPZfullZrelrlr,r,r-Úzip_diròsr�)rÚKÚMÚGÚTÚPc@sreZdZdZddd„Zdd„Zdd	„Zd
d„Zdd
„Ze	dd„ƒZ
e	dd„ƒZdd„Ze	dd„ƒZ
e	dd„ƒZdS)ÚProgressZUNKNOWNrédcCs<|dks||kst‚||_|_||_d|_d|_d|_dS)NrF)rdrzÚcurÚmaxÚstartedÚelapsedÚdone)r´ZminvalZmaxvalr,r,r-rµ	szProgress.__init__cCsV|j|kst‚|jdks&||jks&t‚||_t ¡}|jdkrF||_n||j|_dSru)rzrdr¦r¥Útimer§r¨)r´ZcurvalZnowr,r,r-Úupdates
zProgress.updatecCs |dkst‚| |j|¡dS©Nr)rdr«r¥)r´Zincrr,r,r-Ú	incrementszProgress.incrementcCs| |j¡|Sru)r«rzrÍr,r,r-r=szProgress.startcCs |jdk	r| |j¡d|_dS)NT)r¦r«r©rÍr,r,r-Ústop#s
z
Progress.stopcCs|jdkr|jS|jSru)r¦ÚunknownrÍr,r,r-Úmaximum(szProgress.maximumcCsD|jrd}n4|jdkrd}n$d|j|j|j|j}d|}|S)Nz100 %z ?? %gY@z%3d %%)r©r¦r¥rz)r´r(rIr,r,r-Ú
percentage,s
zProgress.percentagecCs:|dkr|jdks|j|jkr$d}nt dt |¡¡}|S)Nrz??:??:??z%H:%M:%S)r¦r¥rzrªÚstrftimeÚgmtime)r´Zdurationr(r,r,r-Úformat_duration7szProgress.format_durationcCs‚|jrd}|j}n^d}|jdkr&d}nJ|jdks<|j|jkrBd}n.t|j|jƒ}||j|j}|d|j}d|| |¡fS)NZDonezETA r¾rrz%s: %s)r©r¨r¦r¥rzÚfloatr´)r´rmr\r,r,r-ÚETA@s
zProgress.ETAcCsL|jdkrd}n|j|j|j}tD]}|dkr6q@|d}q&d||fS)Nrgièg@�@z%d %sB/s)r¨r¥rzÚUNITS)r´r(Zunitr,r,r-ÚspeedSs

zProgress.speedN)rr¤)r¸r¼r½r¯rµr«r­r=r®r„r°r±r´r¶r¸r,r,r,r-r£s




	
r£z\{([^}]*)\}z[^/\\,{]\*\*|\*\*[^/\\,}]z^[^{]*\}|\{[^}]*$cCs<t |¡rd}t||ƒ‚t |¡r4d}t||ƒ‚t|ƒS)zAExtended globbing function that supports ** and {opt1,opt2,opt3}.z7invalid glob %r: recursive glob "**" must be used alonez2invalid glob %r: mismatching set marker '{' or '}')Ú_CHECK_RECURSIVE_GLOBr!r¿Ú_CHECK_MISMATCH_SETÚ_iglob)Ú	path_globrßr,r,r-rhs

rccst |d¡}t|ƒdkrht|ƒdks,t|ƒ‚|\}}}| d¡D]$}td |||f¡ƒD]
}|VqXq@nœd|kr†t|ƒD]
}|Vqxn~| dd¡\}}|dkr¢d}|dkr°d}n| d¡}| d	¡}t 	|¡D]4\}}}	tj
 |¡}ttj
 ||¡ƒD]
}
|
VqöqÎdS)
Nrr…rCrz**rrFr`ú\)Ú	RICH_GLOBr€rerdr»r$Ú	std_iglobr%rarœrbrV)r¼Zrich_path_globrmr¥rkÚitemrbZradicalÚdirrórXr,r,r-r»ss*



r»)ÚHTTPSHandlerÚmatch_hostnameÚCertificateErrorc@seZdZdZdZdd„ZdS)ÚHTTPSConnectionNTcCsRt |j|jf|j¡}t|ddƒr0||_| ¡tt	dƒsp|j
rHt	j}nt	j}t	j
||j|j|t	j|j
d�|_nxt	 t	j¡}|jt	jO_|jr¢| |j|j¡i}|j
rØt	j|_|j|j
d�tt	ddƒrØ|j|d<|j
|f|Ž|_|j
�rN|j�rNz$t|j ¡|jƒt d|j¡Wn0tk
�rL|j tj¡|j ¡‚YnXdS)	NZ_tunnel_hostFÚ
SSLContext)Ú	cert_reqsZssl_versionÚca_certs)ZcafileZHAS_SNIZserver_hostnamezHost verified: %s) r°Zcreate_connectionÚhostÚportÚtimeoutrrÚsockZ_tunnelrpÚsslrÈZ
CERT_REQUIREDZ	CERT_NONEZwrap_socketZkey_fileZ	cert_fileZPROTOCOL_SSLv23rÆZoptionsZOP_NO_SSLv2Zload_cert_chainZverify_modeZload_verify_locationsÚcheck_domainrÃZgetpeercertrÙrrÄZshutdownZ	SHUT_RDWRr˜)r´rÌrÇÚcontextrdr,r,r-Úconnectœs@
ý


zHTTPSConnection.connect)r¸r¼r½rÈrÎrÐr,r,r,r-rÅ—srÅc@s&eZdZd	dd„Zdd„Zdd„ZdS)
rÂTcCst |¡||_||_dSru)ÚBaseHTTPSHandlerrµrÈrÎ)r´rÈrÎr,r,r-rµÂs
zHTTPSHandler.__init__cOs$t||Ž}|jr |j|_|j|_|S)a
            This is called to create a connection instance. Normally you'd
            pass a connection class to do_open, but it doesn't actually check for
            a class, and just expects a callable. As long as we behave just as a
            constructor would have, we should be OK. If it ever changes so that
            we *must* pass a class, we'll create an UnsafeHTTPSConnection class
            which just sets check_domain to False in the class definition, and
            choose which one to pass to do_open.
            )rÅrÈrÎ)r´rcrdr(r,r,r-Ú_conn_makerÇs


zHTTPSHandler._conn_makerc
CsXz| |j|¡WStk
rR}z$dt|jƒkr@td|jƒ‚n‚W5d}~XYnXdS)Nzcertificate verify failedz*Unable to verify server certificate for %s)Zdo_openrÒrr’ÚreasonrÄrÉ)r´rYrLr,r,r-Ú
https_open×sÿzHTTPSHandler.https_openN)T)r¸r¼r½rµrÒrÔr,r,r,r-rÂÁs
rÂc@seZdZdd„ZdS)ÚHTTPSOnlyHandlercCstd|ƒ‚dS)NzAUnexpected HTTP request on what should be a secure connection: %s)r)r´rYr,r,r-Ú	http_openësÿzHTTPSOnlyHandler.http_openN)r¸r¼r½rÖr,r,r,r-rÕêsrÕé©r×éc@seZdZddd„ZdS)ÚHTTPrNcKs&|dkrd}| |j||f|Ž¡dSr¬©Ú_setupZ_connection_class©r´rÉrÊrdr,r,r-rµ÷sz
HTTP.__init__)rN©r¸r¼r½rµr,r,r,r-rÚösrÚc@seZdZddd„ZdS)ÚHTTPSrNcKs&|dkrd}| |j||f|Ž¡dSr¬rÛrÝr,r,r-rµÿszHTTPS.__init__)rNrÞr,r,r,r-rßþsrßc@seZdZddd„Zdd„ZdS)Ú	TransportrcCs||_tj ||¡dSru)rËrràrµ©r´rËÚuse_datetimer,r,r-rµszTransport.__init__cCs`| |¡\}}}tdkr(t||jd�}n4|jr<||jdkrR||_|t |¡f|_|jd}|S)NrØ)rËrr)Ú
get_host_infoÚ	_ver_inforÚrËÚ_connectionÚ_extra_headersrZHTTPConnection)r´rÉÚhÚehZx509r(r,r,r-Úmake_connection
s
zTransport.make_connectionN)r©r¸r¼r½rµrér,r,r,r-ràs
ràc@seZdZddd„Zdd„ZdS)Ú
SafeTransportrcCs||_tj ||¡dSru)rËrrërµrár,r,r-rµszSafeTransport.__init__cCsx| |¡\}}}|si}|j|d<tdkr:t|df|Ž}n:|jrN||jdkrj||_|tj|df|Žf|_|jd}|S)NrËrØrr)rãrËrärßrårærrÅ)r´rÉrçrèrdr(r,r,r-rés
ÿ
zSafeTransport.make_connectionN)rrêr,r,r,r-rës
rëc@seZdZdd„ZdS)ÚServerProxyc	Kst| dd¡|_}|dk	r^t|ƒ\}}| dd¡}|dkr@t}nt}|||d�|d<}||_tjj	||f|ŽdS)NrËrârZhttps)râÚ	transport)
rhrËrrIrëràrírrìrµ)	r´rZrdrËrWr]râZtclsr\r,r,r-rµ,szServerProxy.__init__NrÞr,r,r,r-rì+srìcKs6tjddkr|d7}nd|d<d|d<t||f|ŽS)Nrr…ÚbrÚnewliner†rä)rqr�ræ)rXrôrdr,r,r-Ú	_csv_open@s

rðc@s4eZdZedƒedƒedƒdœZdd„Zdd„Zd	S)
ÚCSVBaserCú"r‚)Z	delimiterZ	quotecharZlineterminatorcCs|Srur,rÍr,r,r-Ú	__enter__RszCSVBase.__enter__cGs|j ¡dSru)r‹r˜)r´r&r,r,r-Ú__exit__UszCSVBase.__exit__N)r¸r¼r½r’Údefaultsrórôr,r,r,r-rñKsýrñc@s(eZdZdd„Zdd„Zdd„ZeZdS)Ú	CSVReadercKs\d|kr4|d}tjddkr,t d¡|ƒ}||_nt|ddƒ|_tj|jf|jŽ|_dS)Nr‹rr…r†rbrG)	rqr�rŽr�r‹rðÚcsvrKrõ)r´rdr‹r,r,r-rµZszCSVReader.__init__cCs|Srur,rÍr,r,r-Ú__iter__eszCSVReader.__iter__cCsFt|jƒ}tjddkrBt|ƒD] \}}t|tƒs | d¡||<q |S©Nrr…r†)ÚnextrKrqr�r7rxrrŒ)r´r(r[rÀr,r,r-rúhs

zCSVReader.nextN)r¸r¼r½rµrørúÚ__next__r,r,r,r-röYsröc@seZdZdd„Zdd„ZdS)Ú	CSVWritercKs$t|dƒ|_tj|jf|jŽ|_dS)Nrâ)rðr‹r÷Úwriterrõ)r´rXrdr,r,r-rµsszCSVWriter.__init__cCsNtjddkr>g}|D]"}t|tƒr.| d¡}| |¡q|}|j |¡dSrù)rqr�rxrrêr"rýÚwriterow)r´ÚrowrGrÀr,r,r-rþws

zCSVWriter.writerowN)r¸r¼r½rµrþr,r,r,r-rürsrücsHeZdZeejƒZded<d‡fdd„	Zdd„Zdd	„Zd
d„Z	‡Z
S)
ÚConfiguratorÚinc_convertZincNcs"tt|ƒ |¡|pt ¡|_dSru)Úsuperrrµrar¬rj)r´Úconfigrj©Ú	__class__r,r-rµŠszConfigurator.__init__c
s¬‡‡fdd„‰ˆ d¡}t|ƒs*ˆ |¡}ˆ dd¡}ˆ dd¡}|r\t‡fdd„|Dƒƒ}‡‡fd	d„ˆDƒ}t|ƒ}|||Ž}|r¨| ¡D]\}}	t||ˆ|	ƒƒqŽ|S)
Ncsvt|ttfƒr*t|ƒ‡fdd„|Dƒƒ}nHt|tƒrhd|krHˆ |¡}qri}|D]}ˆ||ƒ||<qPn
ˆ |¡}|S)Ncsg|]}ˆ|ƒ‘qSr,r,)rNr[©Úconvertr,r-rO‘szBConfigurator.configure_custom..convert..ú())rxrr{ÚtypeÚdictÚconfigure_customr)Úor(rž)rr´r,r-r�s

z.Configurator.configure_custom..convertrrz[]r,csg|]}ˆ|ƒ‘qSr,r,)rNrrr,r-rO¤sz1Configurator.configure_custom..cs$g|]}t|ƒr|ˆˆ|ƒf‘qSr,)r)rNrž)rrr,r-rO¥s)rhrrr{r
r“Úsetattr)
r´rr~Zpropsrcr“rdr(rBrIr,)rrr´r-rŽs


zConfigurator.configure_customcCs4|j|}t|tƒr0d|kr0| |¡|j|<}|S)Nr)rrxr
r)r´rƒr(r,r,r-Ú__getitem__­s
zConfigurator.__getitem__c	CsFtj |¡stj |j|¡}tj|ddd��}t |¡}W5QRX|S)z*Default converter for the inc:// protocol.rGr†rã)	rarbÚisabsr$rjrŽrær‘r’)r´r rèr(r,r,r-r³s
zConfigurator.inc_convert)N)r¸r¼r½r
rZvalue_convertersrµrrrÚ
__classcell__r,r,rr-r…s
rc@s*eZdZdZd
dd„Zdd„Zdd	„ZdS)ÚSubprocessMixinzC
    Mixin for running subprocesses and capturing their output
    FNcCs||_||_dSru)ÚverboseÚprogress)r´rrr,r,r-rµÀszSubprocessMixin.__init__cCsj|j}|j}| ¡}|sq^|dk	r.|||ƒq|s@tj d¡ntj | d¡¡tj ¡q| ¡dS)z¨
        Read lines from a subprocess' output stream and either pass to a progress
        callable (if specified) or write progress information to sys.stderr.
        Nrr†)	rrÚreadlinerqÚstderrr¦rŒÚflushr˜)r´r‹rÏrrr+r,r,r-rKÄszSubprocessMixin.readercKsžtj|ftjtjdœ|—Ž}tj|j|jdfd�}| ¡tj|j|jdfd�}| ¡| 	¡| 
¡| 
¡|jdk	rˆ| dd¡n|jršt
j d¡|S)N)Ústdoutrr)rÕrcrzdone.Úmainzdone.
)Ú
subprocessÚPopenÚPIPEÚ	threadingZThreadrKrr=rÚwaitr$rrrqr¦)r´Úcmdrdr}Út1Út2r,r,r-Úrun_commandÙs"ÿÿ
zSubprocessMixin.run_command)FN)r¸r¼r½rZrµrKr!r,r,r,r-r¼s
rcCst dd|¡ ¡S)z,Normalize a python package name a la PEP 503z[-_.]+r;)r>Úsubrz)rPr,r,r-Únormalize_nameêsr#)NN)r¯)N)N)NT)„rŽÚcollectionsrÚ
contextlibr÷Zglobrr¿ršr‘Zloggingrarûr>r°rÍÚImportErrorrrqr‘r¨r™rZdummy_threadingrªrrÚcompatrrrr	r
rrr
rrrrrrrrrrrrrZ	getLoggerr¸rÙrýrrGrFr6r>r:rVr#r?r^rnrtryrr„r¡r§Úcontextmanagerr«r­r±r¶r²rÄrÅrrÚVERBOSEr r”r-r/r1r3r6r9ÚIr@r<rCrDrErHrMrPrQrSrTr[rfZARCHIVE_EXTENSIONSr™r�r·r£r¾r¹rºr»rÂrÑrÃrÄrÅrÕr�rärÚrßràrërìrðrñrörürrr#r,r,r,r-Úsä
\








Yy

	/

		8ý
)
ÿ


,H
C]


*)	
7.PKÔ¶N]±#ã×Esite-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-38.pycnu„[µü¤U

ÀÒ.eKã@snddlZdZGdd„deƒZzddlmZWn&ek
rRGdd„dejƒZYnXe e¡Z	e	 
eƒ¡dS)éNz0.2.9.post0c@seZdZdS)ÚDistlibExceptionN)Ú__name__Ú
__module__Ú__qualname__©rrú@/usr/lib/python3.8/site-packages/pip/_vendor/distlib/__init__.pyrsr)ÚNullHandlerc@s$eZdZdd„Zdd„Zdd„ZdS)rcCsdS©Nr©ÚselfÚrecordrrrÚhandleózNullHandler.handlecCsdSr	rr
rrrÚemitrzNullHandler.emitcCs
d|_dSr	)Úlock)rrrrÚ
createLockrzNullHandler.createLockN)rrrr
rrrrrrrsr)ZloggingÚ__version__Ú	ExceptionrrÚImportErrorZHandlerZ	getLoggerrZloggerZ
addHandlerrrrrÚs
PKÔ¶N]¯ASÈ)O)OJsite-packages/pip/_vendor/distlib/__pycache__/version.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.e_[ã@sfdZddlZddlZddlmZddlmZdddd	d
ddd
gZe e	¡Z
Gdd„deƒZGdd„de
ƒZGdd„de
ƒZe d¡Zdd„ZeZGdd„deƒZdd„ZGdd„deƒZe d¡dfe d¡dfe d¡dfe d¡d fe d!¡d"fe d#¡d"fe d$¡d%fe d&¡d'fe d(¡d)fe d*¡d+ff
Ze d,¡dfe d-¡dfe d.¡d%fe d$¡d%fe d/¡dffZe d0¡Zd1d2„Zd3d4„Ze d5ej¡Zd6d6d7d6d8ddd9œZd:d;„ZGdej¡Z"d?d@„Z#dAdB„Z$GdCd
„d
eƒZ%GdDd„deƒZ&GdEdF„dFe
ƒZ'e'eeeƒe'ee!dGdH„ƒe'e$e&eƒdIœZ(e(dJe(dK<dLd
„Z)dS)Mz~
Implementation of a flexible versioning scheme providing support for PEP-440,
setuptools-compatible and semantic versioning.
éNé)Ústring_types©Úparse_requirementÚNormalizedVersionÚNormalizedMatcherÚ
LegacyVersionÚ
LegacyMatcherÚSemanticVersionÚSemanticMatcherÚUnsupportedVersionErrorÚ
get_schemec@seZdZdZdS)rzThis is an unsupported version.N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__©rrú?/usr/lib/python3.8/site-packages/pip/_vendor/distlib/version.pyrsc@sxeZdZdd„Zdd„Zdd„Zdd„Zd	d
„Zdd„Zd
d„Z	dd„Z
dd„Zdd„Zdd„Z
dd„Zedd„ƒZdS)ÚVersioncCs"| ¡|_}| |¡|_}dS©N)ÚstripÚ_stringÚparseÚ_parts)ÚselfÚsÚpartsrrrÚ__init__szVersion.__init__cCstdƒ‚dS)Nzplease implement in a subclass©ÚNotImplementedError©rrrrrr%sz
Version.parsecCs$t|ƒt|ƒkr td||fƒ‚dS)Nzcannot compare %r and %r)ÚtypeÚ	TypeError©rÚotherrrrÚ_check_compatible(szVersion._check_compatiblecCs| |¡|j|jkSr©r%rr#rrrÚ__eq__,s
zVersion.__eq__cCs| |¡Sr©r'r#rrrÚ__ne__0szVersion.__ne__cCs| |¡|j|jkSrr&r#rrrÚ__lt__3s
zVersion.__lt__cCs| |¡p| |¡Sr©r*r'r#rrrÚ__gt__7szVersion.__gt__cCs| |¡p| |¡Srr+r#rrrÚ__le__:szVersion.__le__cCs| |¡p| |¡Sr)r,r'r#rrrÚ__ge__=szVersion.__ge__cCs
t|jƒSr)Úhashr©rrrrÚ__hash__AszVersion.__hash__cCsd|jj|jfS)Nz%s('%s')©Ú	__class__rrr0rrrÚ__repr__DszVersion.__repr__cCs|jSr©rr0rrrÚ__str__GszVersion.__str__cCstdƒ‚dS)NzPlease implement in subclasses.rr0rrrÚ
is_prereleaseJszVersion.is_prereleaseN)rrrrrr%r'r)r*r,r-r.r1r4r6Úpropertyr7rrrrrsrc	@sšeZdZdZdd„dd„dd„dd„dd„dd„d	d„d
d„dœZdd
„Zdd„Zdd„Zedd„ƒZ	dd„Z
dd„Zdd„Zdd„Z
dd„Zdd„ZdS) ÚMatcherNcCs||kSrr©ÚvÚcÚprrrÚTózMatcher.cCs||kSrrr:rrrr>Ur?cCs||kp||kSrrr:rrrr>Vr?cCs||kp||kSrrr:rrrr>Wr?cCs||kSrrr:rrrr>Xr?cCs||kSrrr:rrrr>Yr?cCs||kp||kSrrr:rrrr>[r?cCs||kSrrr:rrrr>\r?)ú<ú>ú<=ú>=ú==ú===ú~=ú!=cCst|ƒSrrr rrrraszMatcher.parse_requirementcCsÒ|jdkrtdƒ‚| ¡|_}| |¡}|s:td|ƒ‚|j|_|j ¡|_g}|jrÄ|jD]d\}}| 	d¡r¢|dkr„td|ƒ‚|dd…d}}| |¡n| |¡d}}| 
|||f¡q^t|ƒ|_dS)	NzPlease specify a version classz
Not valid: %rz.*)rDrGz#'.*' not allowed for %r constraintséþÿÿÿTF)
Ú
version_classÚ
ValueErrorrrrÚnameÚlowerÚkeyZconstraintsÚendswithÚappendÚtupler)rrÚrZclistÚopZvnÚprefixrrrrds*


ÿzMatcher.__init__cCsxt|tƒr| |¡}|jD]X\}}}|j |¡}t|tƒrDt||ƒ}|s`d||jjf}t	|ƒ‚||||ƒsdSqdS)zÉ
        Check if the provided version matches the constraints.

        :param version: The version to match against this instance.
        :type version: String or :class:`Version` instance.
        z%r not implemented for %sFT)
Ú
isinstancerrIrÚ
_operatorsÚgetÚgetattrr3rr)rÚversionÚoperatorÚ
constraintrSÚfÚmsgrrrÚmatch�s




ÿz
Matcher.matchcCs6d}t|jƒdkr2|jdddkr2|jdd}|S)Nrr)rDrE)Úlenr)rÚresultrrrÚ
exact_version–s zMatcher.exact_versioncCs0t|ƒt|ƒks|j|jkr,td||fƒ‚dS)Nzcannot compare %s and %s)r!rKr"r#rrrr%�szMatcher._check_compatiblecCs"| |¡|j|jko |j|jkSr)r%rMrr#rrrr'¡s
zMatcher.__eq__cCs| |¡Srr(r#rrrr)¥szMatcher.__ne__cCst|jƒt|jƒSr)r/rMrr0rrrr1©szMatcher.__hash__cCsd|jj|jfS)Nz%s(%r)r2r0rrrr4¬szMatcher.__repr__cCs|jSrr5r0rrrr6¯szMatcher.__str__)rrrrIrUrrr]r8r`r%r'r)r1r4r6rrrrr9Os*÷
r9zk^v?(\d+!)?(\d+(\.\d+)*)((a|b|c|rc)(\d+))?(\.(post)(\d+))?(\.(dev)(\d+))?(\+([a-zA-Z\d]+(\.[a-zA-Z\d]+)?))?$cCs²| ¡}t |¡}|s"td|ƒ‚| ¡}tdd„|d d¡Dƒƒ}t|ƒdkrl|ddkrl|dd…}qF|dszd}nt|dƒ}|dd	…}|d
d…}|dd
…}|d}|dkrÀd}n|dt|dƒf}|dkrâd}n|dt|dƒf}|dk�rd}n|dt|dƒf}|dk�r*d}nHg}	| d¡D]0}
|
 	¡�rTdt|
ƒf}
nd|
f}
|	 
|
¡�q8t|	ƒ}|�sŽ|�sŠ|�rŠd}nd}|�s˜d}|�s¢d}||||||fS)NzNot a valid version: %scss|]}t|ƒVqdSr©Úint©Ú.0r;rrrÚ	¾sz_pep_440_key..rÚ.éÿÿÿÿréééé	é
éé
)NNr)Úarg)Úz)Ú_)Úfinal)rÚPEP440_VERSION_REr]rÚgroupsrPÚsplitr^rbÚisdigitrO)rÚmrtZnumsZepochÚpreZpostÚdevZlocalrÚpartrrrÚ_pep_440_key¸sT



r{c@s6eZdZdZdd„ZedddddgƒZed	d
„ƒZdS)raIA rational version.

    Good:
        1.2         # equivalent to "1.2.0"
        1.2.0
        1.2a1
        1.2.3a2
        1.2.3b1
        1.2.3c1
        1.2.3.4
        TODO: fill this out

    Bad:
        1           # minimum two numbers
        1.2a        # release level must have a release serial
        1.2.3b
    cCs<t|ƒ}t |¡}| ¡}tdd„|d d¡Dƒƒ|_|S)Ncss|]}t|ƒVqdSrrarcrrrresz*NormalizedVersion.parse..rrf)Ú_normalized_keyrsr]rtrPruÚ_release_clause)rrr_rwrtrrrr
s

zNormalizedVersion.parseroÚbr<Úrcrycst‡fdd„ˆjDƒƒS)Nc3s |]}|r|dˆjkVqdS)rN)ÚPREREL_TAGS)rdÚtr0rrresz2NormalizedVersion.is_prerelease..)Úanyrr0rr0rr7szNormalizedVersion.is_prereleaseN)	rrrrrÚsetr€r8r7rrrrrøs
cCs>t|ƒ}t|ƒ}||krdS| |¡s*dSt|ƒ}||dkS)NTFrf)ÚstrÚ
startswithr^)ÚxÚyÚnrrrÚ
_match_prefixs
r‰c	@sneZdZeZddddddddd	œZd
d„Zdd
„Zdd„Zdd„Z	dd„Z
dd„Zdd„Zdd„Z
dd„ZdS)rÚ_match_compatibleÚ	_match_ltÚ	_match_gtÚ	_match_leÚ	_match_geÚ	_match_eqÚ_match_arbitraryÚ	_match_ne)rFr@rArBrCrDrErGcCsV|rd|ko|jd}n|jdo,|jd}|rN|j dd¡d}| |¡}||fS)Nú+rgrr)rrrurI)rrXrZrSZstrip_localrrrrÚ
_adjust_local6s
zNormalizedMatcher._adjust_localcCsD| |||¡\}}||krdS|j}d dd„|Dƒ¡}t||ƒS)NFrfcSsg|]}t|ƒ‘qSr©r„©rdÚirrrÚ
Isz/NormalizedMatcher._match_lt..©r“r}Újoinr‰©rrXrZrSZrelease_clauseZpfxrrrr‹DszNormalizedMatcher._match_ltcCsD| |||¡\}}||krdS|j}d dd„|Dƒ¡}t||ƒS)NFrfcSsg|]}t|ƒ‘qSrr”r•rrrr—Qsz/NormalizedMatcher._match_gt..r˜ršrrrrŒLszNormalizedMatcher._match_gtcCs| |||¡\}}||kSr©r“©rrXrZrSrrrr�TszNormalizedMatcher._match_lecCs| |||¡\}}||kSrr›rœrrrrŽXszNormalizedMatcher._match_gecCs.| |||¡\}}|s ||k}n
t||ƒ}|Sr©r“r‰©rrXrZrSr_rrrr�\s


zNormalizedMatcher._match_eqcCst|ƒt|ƒkSrr”rœrrrr�dsz"NormalizedMatcher._match_arbitrarycCs0| |||¡\}}|s ||k}nt||ƒ}|Srr�ržrrrr‘gs

zNormalizedMatcher._match_necCsf| |||¡\}}||krdS||kr*dS|j}t|ƒdkrH|dd…}d dd„|Dƒ¡}t||ƒS)NTFrrgrfcSsg|]}t|ƒ‘qSrr”r•rrrr—zsz7NormalizedMatcher._match_compatible..)r“r}r^r™r‰ršrrrrŠosz#NormalizedMatcher._match_compatibleN)rrrrrIrUr“r‹rŒr�rŽr�r�r‘rŠrrrrr's&øz[.+-]$Úz^[.](\d)z0.\1z^[.-]z
^\((.*)\)$ú\1z^v(ersion)?\s*(\d+)z\2z^r(ev)?\s*(\d+)z[.]{2,}rfz\b(alfa|apha)\bÚalphaz\b(pre-alpha|prealpha)\bz	pre.alphaz	\(beta\)$Úbetaz
^[:~._+-]+z
[,*")([\]]z[~:+_ -]z\.$z
(\d+(\.\d+)*)cCsL| ¡ ¡}tD]\}}| ||¡}q|s.d}t |¡}|sFd}|}nª| ¡d d¡}dd„|Dƒ}t|ƒdkr~| 	d¡qft|ƒdkrœ|| 
¡d…}n8d dd„|dd…Dƒ¡|| 
¡d…}|dd…}d d	d„|Dƒ¡}| ¡}|�rtD]\}}| ||¡}qú|�s|}nd
|k�r*dnd}|||}t
|ƒ�sHd}|S)
z€
    Try to suggest a semantic form for a version for which
    _suggest_normalized_version couldn't come up with anything.
    z0.0.0rrfcSsg|]}t|ƒ‘qSrrar•rrrr—ªsz-_suggest_semantic_version..éNcSsg|]}t|ƒ‘qSrr”r•rrrr—°scSsg|]}t|ƒ‘qSrr”r•rrrr—²sryú-r’)rrLÚ
_REPLACEMENTSÚsubÚ_NUMERIC_PREFIXr]rtrur^rOÚendr™Ú_SUFFIX_REPLACEMENTSÚ	is_semver)rr_ZpatÚreplrwrSÚsuffixÚseprrrÚ_suggest_semantic_version–s:
,
r®cCshzt|ƒ|WStk
r"YnX| ¡}dD]\}}| ||¡}q0t dd|¡}t dd|¡}t dd|¡}t dd	|¡}t d
d|¡}| d¡r¢|d
d…}t dd|¡}t dd|¡}t dd|¡}t dd|¡}t dd|¡}t dd|¡}t dd|¡}t dd|¡}t dd|¡}t dd|¡}t dd |¡}zt|ƒWntk
�rbd}YnX|S)!aèSuggest a normalized version close to the given version string.

    If you have a version string that isn't rational (i.e. NormalizedVersion
    doesn't like it) then you might be able to get an equivalent (or close)
    rational version from this function.

    This does a number of simple normalizations to the given string, based
    on observation of versions currently in use on PyPI. Given a dump of
    those version during PyCon 2009, 4287 of them:
    - 2312 (53.93%) match NormalizedVersion without change
      with the automatic suggestion
    - 3474 (81.04%) match when using this suggestion method

    @param s {str} An irrational version string.
    @returns A rational version string, or None, if couldn't determine one.
    ))z-alpharo)z-betar~)r¡ro)r¢r~)rr<)z-finalrŸ)z-prer<)z-releaserŸ)z.releaserŸ)z-stablerŸ)r’rf)rqrf)ú rŸ)z.finalrŸ)rrrŸzpre$Zpre0zdev$Zdev0z([abc]|rc)[\-\.](\d+)$z\1\2z[\-\.](dev)[\-\.]?r?(\d+)$z.\1\2z[.~]?([abc])\.?r r;rNz\b0+(\d+)(?!\d)z(\d+[abc])$z\g<1>0z\.?(dev-r|dev\.r)\.?(\d+)$z.dev\2z-(a|b|c)(\d+)$z[\.\-](dev|devel)$z.dev0z(?![\.\-])dev$z(final|stable)$rŸz\.?(r|-|-r)\.?(\d+)$z.post\2z\.?(dev|git|bzr)\.?(\d+)$z\.?(pre|preview|-c)(\d+)$zc\g<2>zp(\d+)$z.post\1)r|rrLÚreplaceÚrer¦r…)rZrsZorigr«rrrÚ_suggest_normalized_versionÄs>
	
r²z([a-z]+|\d+|[\.-])r<zfinal-ú@)rxZpreviewr¤rryrŸrfcCsrdd„}g}||ƒD]T}| d¡r^|dkrD|rD|ddkrD| ¡q*|r^|ddkr^| ¡qD| |¡qt|ƒS)NcSstg}t | ¡¡D]R}t ||¡}|rd|dd…krBdkrRnn| d¡}nd|}| |¡q| d¡|S)NÚ0rÚ9éÚ*ú*final)Ú
_VERSION_PARTrurLÚ_VERSION_REPLACErVÚzfillrO)rr_r=rrrÚ	get_partsCs 
z_legacy_key..get_partsr·r¸rgz*final-Z00000000)r…ÚpoprOrP)rr¼r_r=rrrÚ_legacy_keyBs



r¾c@s eZdZdd„Zedd„ƒZdS)rcCst|ƒSr)r¾r rrrr]szLegacyVersion.parsecCs8d}|jD](}t|tƒr
| d¡r
|dkr
d}q4q
|S)NFr·r¸T)rrTrr…)rr_r†rrrr7`s
ÿzLegacyVersion.is_prereleaseN©rrrrr8r7rrrrr\sc@s4eZdZeZeejƒZded<e 	d¡Z
dd„ZdS)r	rŠrFz^(\d+(\.\d+)*)cCs`||krdS|j t|ƒ¡}|s2t d||¡dS| ¡d}d|krV| dd¡d}t||ƒS)NFzACannot compute compatible match for version %s  and constraint %sTrrfr)Ú
numeric_rer]r„ÚloggerZwarningrtÚrsplitr‰)rrXrZrSrwrrrrrŠssÿzLegacyMatcher._match_compatibleN)rrrrrIÚdictr9rUr±ÚcompilerÀrŠrrrrr	ks


zN^(\d+)\.(\d+)\.(\d+)(-[a-z0-9]+(\.[a-z0-9-]+)*)?(\+[a-z0-9]+(\.[a-z0-9-]+)*)?$cCs
t |¡Sr)Ú
_SEMVER_REr])rrrrrª‰srªc	Csndd„}t|ƒ}|st|ƒ‚| ¡}dd„|dd…Dƒ\}}}||ddƒ||ddƒ}}|||f||fS)	NcSs8|dkr|f}n$|dd… d¡}tdd„|Dƒƒ}|S)NrrfcSs"g|]}| ¡r| d¡n|‘qS)r¶)rvr»)rdr=rrrr—•sz5_semantic_key..make_tuple..)rurP)rZabsentr_rrrrÚ
make_tupleŽs
z!_semantic_key..make_tuplecSsg|]}t|ƒ‘qSrrar•rrrr—œsz!_semantic_key..r£ú|ér·)rªrrt)	rrÆrwrtÚmajorÚminorZpatchrxZbuildrrrÚ
_semantic_key�s
rËc@s eZdZdd„Zedd„ƒZdS)r
cCst|ƒSr)rËr rrrr£szSemanticVersion.parsecCs|jdddkS)NrrrÇ)rr0rrrr7¦szSemanticVersion.is_prereleaseNr¿rrrrr
¢sc@seZdZeZdS)rN)rrrr
rIrrrrr«sc@s6eZdZddd„Zdd„Zdd„Zdd	„Zd
d„ZdS)
Ú
VersionSchemeNcCs||_||_||_dSr)rMÚmatcherÚ	suggester)rrMrÍrÎrrrr°szVersionScheme.__init__cCs2z|j |¡d}Wntk
r,d}YnX|S©NTF)rÍrIr©rrr_rrrÚis_valid_versionµs
zVersionScheme.is_valid_versioncCs0z| |¡d}Wntk
r*d}YnX|SrÏ)rÍrrÐrrrÚis_valid_matcher½s

zVersionScheme.is_valid_matchercCs| d|¡S)z:
        Used for processing some metadata fields
        zdummy_name (%s))rÒr rrrÚis_valid_constraint_listÅsz&VersionScheme.is_valid_constraint_listcCs|jdkrd}n
| |¡}|Sr)rÎrÐrrrÚsuggestËs

zVersionScheme.suggest)N)rrrrrÑrÒrÓrÔrrrrr̯s

rÌcCs|Srrr rrrr>Õr?r>)Ú
normalizedÚlegacyZsemanticrÕÚdefaultcCs|tkrtd|ƒ‚t|S)Nzunknown scheme name: %r)Ú_SCHEMESrJ)rKrrrr
Ýs)*rZloggingr±ÚcompatrÚutilrÚ__all__Z	getLoggerrrÁrJrÚobjectrr9rÄrsr{r|rr‰rr¥r©r§r®r²ÚIr¹rºr¾rr	rÅrªrËr
rrÌrØr
rrrrÚs”ý
1d
=$Wÿõû
.rùþ	$ÿÿüPKÕ¶N]"îxßCßCBsite-packages/pip/_vendor/distlib/__pycache__/index.cpython-38.pycnu„[µü¤U

ÀÒ.eJRã@sÈddlZddlZddlZddlZddlZddlZzddlmZWn ek
r`ddl	mZYnXddl
mZddlm
Z
mZmZmZmZmZddlmZmZmZe e¡ZdZdZGd	d
„d
eƒZdS)éN)ÚThreadé)ÚDistlibException)ÚHTTPBasicAuthHandlerÚRequestÚHTTPPasswordMgrÚurlparseÚbuild_openerÚstring_types)Úcached_propertyÚzip_dirÚServerProxyzhttps://pypi.org/pypiÚpypic@s¶eZdZdZdZd*dd„Zdd„Zdd	„Zd
d„Zdd
„Z	dd„Z
dd„Zd+dd„Zd,dd„Z
d-dd„Zd.dd„Zdd„Zd/dd„Zd0d d!„Zd1d"d#„Zd$d%„Zd&d'„Zd2d(d)„ZdS)3ÚPackageIndexzc
    This class represents a package index compatible with PyPI, the Python
    Package Index.
    s.----------ThIs_Is_tHe_distlib_index_bouNdaRY_$Nc
CsÊ|pt|_| ¡t|jƒ\}}}}}}|s<|s<|s<|dkrJtd|jƒ‚d|_d|_d|_d|_t	t
jdƒ�R}dD]F}	z,tj
|	dg||d�}
|
dkr¢|	|_Wq¼Wqttk
r¸YqtXqtW5QRXdS)	z”
        Initialise an instance.

        :param url: The URL of the index. If not specified, the URL for PyPI is
                    used.
        )ZhttpZhttpszinvalid repository: %sNÚw)ÚgpgZgpg2z	--version©ÚstdoutÚstderrr)Ú
DEFAULT_INDEXÚurlÚread_configurationrrÚpassword_handlerÚssl_verifierrÚgpg_homeÚopenÚosÚdevnullÚ
subprocessZ
check_callÚOSError)ÚselfrZschemeÚnetlocÚpathZparamsZqueryZfragZsinkÚsÚrc©r%ú=/usr/lib/python3.8/site-packages/pip/_vendor/distlib/index.pyÚ__init__$s(
ÿ
zPackageIndex.__init__cCs&ddlm}ddlm}|ƒ}||ƒS)zs
        Get the distutils command for interacting with PyPI configurations.
        :return: the command.
        r)ÚDistribution)Ú
PyPIRCCommand)Zdistutils.corer(Zdistutils.configr))r r(r)Údr%r%r&Ú_get_pypirc_commandAsz PackageIndex._get_pypirc_commandcCsR| ¡}|j|_| ¡}| d¡|_| d¡|_| dd¡|_| d|j¡|_dS)zç
        Read the PyPI access configuration as supported by distutils, getting
        PyPI to do the actual work. This populates ``username``, ``password``,
        ``realm`` and ``url`` attributes from the configuration.
        ÚusernameÚpasswordÚrealmrÚ
repositoryN)r+rr/Z_read_pypircÚgetr,r-r.)r ÚcZcfgr%r%r&rKszPackageIndex.read_configurationcCs$| ¡| ¡}| |j|j¡dS)zÍ
        Save the PyPI access configuration. You must have set ``username`` and
        ``password`` attributes before calling this method.

        Again, distutils is used to do the actual work.
        N)Úcheck_credentialsr+Z
_store_pypircr,r-)r r1r%r%r&Úsave_configurationZszPackageIndex.save_configurationcCs\|jdks|jdkrtdƒ‚tƒ}t|jƒ\}}}}}}| |j||j|j¡t|ƒ|_	dS)zp
        Check that ``username`` and ``password`` have been set, and raise an
        exception if not.
        Nz!username and password must be set)
r,r-rrrrZadd_passwordr.rr)r ZpmÚ_r!r%r%r&r2fszPackageIndex.check_credentialscCs\| ¡| ¡| ¡}d|d<| | ¡g¡}| |¡}d|d<| | ¡g¡}| |¡S)aq
        Register a distribution on PyPI, using the provided metadata.

        :param metadata: A :class:`Metadata` instance defining at least a name
                         and version number for the distribution to be
                         registered.
        :return: The HTTP response received from PyPI upon submission of the
                request.
        Zverifyú:actionZsubmit)r2ÚvalidateÚtodictÚencode_requestÚitemsÚsend_request)r Úmetadatar*ÚrequestZresponser%r%r&Úregisterrs

zPackageIndex.registercCsF| ¡}|sq:| d¡ ¡}| |¡t d||f¡q| ¡dS)ar
        Thread runner for reading lines of from a subprocess into a buffer.

        :param name: The logical name of the stream (used for logging only).
        :param stream: The stream to read from. This will typically a pipe
                       connected to the output stream of a subprocess.
        :param outbuf: The list to append the read lines to.
        úutf-8z%s: %sN)ÚreadlineÚdecodeÚrstripÚappendÚloggerÚdebugÚclose)r ÚnameÚstreamZoutbufr#r%r%r&Ú_reader†s

zPackageIndex._readerc	Csš|jdddg}|dkr|j}|r.| d|g¡|dk	rF| dddg¡t ¡}tj |tj |¡d	¡}| d
dd|d
||g¡t	 
dd |¡¡||fS)a‰
        Return a suitable command for signing a file.

        :param filename: The pathname to the file to be signed.
        :param signer: The identifier of the signer of the file.
        :param sign_password: The passphrase for the signer's
                              private key used for signing.
        :param keystore: The path to a directory which contains the keys
                         used in verification. If not specified, the
                         instance's ``gpg_home`` attribute is used instead.
        :return: The signing command as a list suitable to be
                 passed to :class:`subprocess.Popen`.
        ú--status-fdÚ2ú--no-ttyNú	--homedirz--batchz--passphrase-fdÚ0z.ascz
--detach-signz--armorz--local-userz--outputúinvoking: %sú )rrÚextendÚtempfileZmkdtemprr"ÚjoinÚbasenamerCrD)r ÚfilenameÚsignerÚ
sign_passwordÚkeystoreÚcmdZtdZsfr%r%r&Úget_sign_command˜s"
ÿzPackageIndex.get_sign_commandc	Cs´tjtjdœ}|dk	r tj|d<g}g}tj|f|Ž}t|jd|j|fd�}| ¡t|jd|j|fd�}| ¡|dk	r�|j 	|¡|j 
¡| ¡| ¡| ¡|j
||fS)aæ
        Run a command in a child process , passing it any input data specified.

        :param cmd: The command to run.
        :param input_data: If specified, this must be a byte string containing
                           data to be sent to the child process.
        :return: A tuple consisting of the subprocess' exit code, a list of
                 lines read from the subprocess' ``stdout``, and a list of
                 lines read from the subprocess' ``stderr``.
        rNÚstdinr)ÚtargetÚargsr)rÚPIPEÚPopenrrHrÚstartrrZÚwriterEÚwaitrRÚ
returncode)	r rXZ
input_dataÚkwargsrrÚpÚt1Út2r%r%r&Úrun_commandµs&þ

zPackageIndex.run_commandc
CsD| ||||¡\}}| || d¡¡\}}}	|dkr@td|ƒ‚|S)aR
        Sign a file.

        :param filename: The pathname to the file to be signed.
        :param signer: The identifier of the signer of the file.
        :param sign_password: The passphrase for the signer's
                              private key used for signing.
        :param keystore: The path to a directory which contains the keys
                         used in signing. If not specified, the instance's
                         ``gpg_home`` attribute is used instead.
        :return: The absolute pathname of the file where the signature is
                 stored.
        r>rz&sign command failed with error code %s)rYrgÚencoder)
r rTrUrVrWrXÚsig_filer$rrr%r%r&Ú	sign_fileØs
ÿÿ
ÿzPackageIndex.sign_fileÚsdistÚsourcec	Cs(| ¡tj |¡s td|ƒ‚| ¡| ¡}d}	|rZ|jsJt 	d¡n| 
||||¡}	t|dƒ�}
|
 ¡}W5QRXt
 |¡ ¡}t
 |¡ ¡}
| dd||||
dœ¡dtj |¡|fg}|	�rt|	dƒ�}
|
 ¡}W5QRX| d	tj |	¡|f¡t tj |	¡¡| | ¡|¡}| |¡S)
a´
        Upload a release file to the index.

        :param metadata: A :class:`Metadata` instance defining at least a name
                         and version number for the file to be uploaded.
        :param filename: The pathname of the file to be uploaded.
        :param signer: The identifier of the signer of the file.
        :param sign_password: The passphrase for the signer's
                              private key used for signing.
        :param filetype: The type of the file being uploaded. This is the
                        distutils command which produced that file, e.g.
                        ``sdist`` or ``bdist_wheel``.
        :param pyversion: The version of Python which the release relates
                          to. For code compatible with any Python, this would
                          be ``source``, otherwise it would be e.g. ``3.2``.
        :param keystore: The path to a directory which contains the keys
                         used in signing. If not specified, the instance's
                         ``gpg_home`` attribute is used instead.
        :return: The HTTP response received from PyPI upon submission of the
                request.
        z
not found: %sNz)no signing program available - not signedÚrbZfile_uploadÚ1)r5Zprotocol_versionÚfiletypeÚ	pyversionÚ
md5_digestÚ
sha256_digestÚcontentZ
gpg_signature)r2rr"Úexistsrr6r7rrCZwarningrjrÚreadÚhashlibÚmd5Ú	hexdigestZsha256ÚupdaterSrBÚshutilZrmtreeÚdirnamer8r9r:)r r;rTrUrVrorprWr*riÚfZ	file_datarqrrÚfilesZsig_datar<r%r%r&Úupload_fileïsD
ÿúÿzPackageIndex.upload_filec
Csœ| ¡tj |¡s td|ƒ‚tj |d¡}tj |¡sFtd|ƒ‚| ¡|j|j	}}t
|ƒ ¡}dd|fd|fg}d||fg}| ||¡}	| 
|	¡S)a2
        Upload documentation to the index.

        :param metadata: A :class:`Metadata` instance defining at least a name
                         and version number for the documentation to be
                         uploaded.
        :param doc_dir: The pathname of the directory which contains the
                        documentation. This should be the directory that
                        contains the ``index.html`` for the documentation.
        :return: The HTTP response received from PyPI upon submission of the
                request.
        znot a directory: %rz
index.htmlz
not found: %r)r5Z
doc_uploadrFÚversionrs)r2rr"ÚisdirrrRrtr6rFrrÚgetvaluer8r:)
r r;Zdoc_dirÚfnrFrZzip_dataÚfieldsr}r<r%r%r&Úupload_documentation(s 
ÿz!PackageIndex.upload_documentationcCsT|jdddg}|dkr|j}|r.| d|g¡| d||g¡t dd |¡¡|S)	a|
        Return a suitable command for verifying a file.

        :param signature_filename: The pathname to the file containing the
                                   signature.
        :param data_filename: The pathname to the file containing the
                              signed data.
        :param keystore: The path to a directory which contains the keys
                         used in verification. If not specified, the
                         instance's ``gpg_home`` attribute is used instead.
        :return: The verifying command as a list suitable to be
                 passed to :class:`subprocess.Popen`.
        rIrJrKNrLz--verifyrNrO)rrrPrCrDrR)r Úsignature_filenameÚ
data_filenamerWrXr%r%r&Úget_verify_commandDszPackageIndex.get_verify_commandcCsH|jstdƒ‚| |||¡}| |¡\}}}|dkr@td|ƒ‚|dkS)a6
        Verify a signature for a file.

        :param signature_filename: The pathname to the file containing the
                                   signature.
        :param data_filename: The pathname to the file containing the
                              signed data.
        :param keystore: The path to a directory which contains the keys
                         used in verification. If not specified, the
                         instance's ``gpg_home`` attribute is used instead.
        :return: True if the signature was verified, else False.
        z0verification unavailable because gpg unavailable)rrz(verify command failed with error code %sr)rrr‡rg)r r…r†rWrXr$rrr%r%r&Úverify_signature\sÿÿzPackageIndex.verify_signaturec	Csl|dkrd}t d¡n6t|ttfƒr0|\}}nd}tt|ƒƒ}t d|¡t|dƒ�®}| t	|ƒ¡}zŽ| ¡}	d}
d}d}d}
d	|	kr–t|	d
ƒ}|r¦||
|
|ƒ| 
|
¡}|s¶qô|t|ƒ7}| |¡|rÚ| |¡|
d7}
|r¦||
|
|ƒq¦W5| 
¡XW5QRX|dk�r0||k�r0td||fƒ‚|�rh| ¡}||k�r\td
||||fƒ‚t d|¡dS)a
        This is a convenience method for downloading a file from an URL.
        Normally, this will be a file from the index, though currently
        no check is made for this (i.e. a file can be downloaded from
        anywhere).

        The method is just like the :func:`urlretrieve` function in the
        standard library, except that it allows digest computation to be
        done during download and checking that the downloaded data
        matched any expected value.

        :param url: The URL of the file to be downloaded (assumed to be
                    available via an HTTP GET request).
        :param destfile: The pathname where the downloaded file is to be
                         saved.
        :param digest: If specified, this must be a (hasher, value)
                       tuple, where hasher is the algorithm used (e.g.
                       ``'md5'``) and ``value`` is the expected value.
        :param reporthook: The same as for :func:`urlretrieve` in the
                           standard library.
        NzNo digest specifiedrwzDigest specified: %sÚwbi éÿÿÿÿrzcontent-lengthzContent-Lengthrz1retrieval incomplete: got only %d out of %d bytesz.%s digest mismatch for %s: expected %s, got %szDigest verified: %s)rCrDÚ
isinstanceÚlistÚtupleÚgetattrrvrr:rrEÚinfoÚintruÚlenr`ryrrx)r rZdestfileZdigestZ
reporthookZdigesterZhasherZdfpZsfpÚheadersZ	blocksizeÚsizeruZblocknumÚblockÚactualr%r%r&Ú
download_fileus^



ÿÿ
ÿÿzPackageIndex.download_filecCs:g}|jr| |j¡|jr(| |j¡t|Ž}| |¡S)zÝ
        Send a standard library :class:`Request` to PyPI and return its
        response.

        :param req: The request to send.
        :return: The HTTP response from PyPI (a standard library HTTPResponse).
        )rrBrr	r)r ZreqZhandlersZopenerr%r%r&r:ÂszPackageIndex.send_requestc
CsØg}|j}|D]L\}}t|ttfƒs*|g}|D]*}| d|d| d¡d| d¡f¡q.q|D].\}}	}
| d|d||	f d¡d|
f¡q`| d|ddf¡d |¡}d|}|tt|ƒƒdœ}
t	|j
||
ƒS)	a&
        Encode fields and files for posting to an HTTP server.

        :param fields: The fields to send as a list of (fieldname, value)
                       tuples.
        :param files: The files to send as a list of (fieldname, filename,
                      file_bytes) tuple.
        s--z)Content-Disposition: form-data; name="%s"r>óz8Content-Disposition: form-data; name="%s"; filename="%s"s
smultipart/form-data; boundary=)zContent-typezContent-length)Úboundaryr‹rŒr�rPrhrRÚstrr‘rr)r rƒr}Úpartsr˜ÚkÚvaluesÚvÚkeyrTÚvalueZbodyZctr’r%r%r&r8ÒsDÿÿû
ÿÿû

þzPackageIndex.encode_requestcCsFt|tƒrd|i}t|jdd�}z| ||p.d¡W¢S|dƒƒXdS)NrFg@)ZtimeoutrEÚand)r‹r
r
rÚsearch)r ZtermsÚoperatorZ	rpc_proxyr%r%r&r¡ýs
zPackageIndex.search)N)N)N)N)NNrkrlN)N)N)NN)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r˜r'r+rr3r2r=rHrYrgrjr~r„r‡rˆr–r:r8r¡r%r%r%r&rs6

ÿ

#
ÿ
9ÿ
ÿ

M+r)rvZloggingrrzrrQZ	threadingrÚImportErrorZdummy_threadingÚrÚcompatrrrrr	r
Úutilrrr
Z	getLoggerr£rCrZ
DEFAULT_REALMÚobjectrr%r%r%r&Ús  
PKÕ¶N]Xã~I®c®cBsite-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-38.pycnu„[µü¤U

ÀÒ.eõ�ã@sŽddlmZddlZddlZddlZddlZddlmZddl	Z	ddl
Z
ddlZddl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
¡�rLdZ5nej6dk�r^dZ5ndZ5e 8d¡Z9e9�s„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#k�rBd$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
zMounter.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
edd„ƒZdd„Z
edd„ƒ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.tagscCstj |j|j¡}d|j|jf}d|}t d¡}t	|dƒ�Ö}| 
|¡}|d dd¡}tdd	„|Dƒƒ}|d
kr€t
tdg}	nt
tg}	d}
|	D]f}zLt ||¡}| |¡�,}
||
ƒ}t|d�}
|
rÔW5QR£WqøW5QRXWq�tk
rôYq�Xq�|
�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.infocCsÔ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<ÚrecordsZrecord_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!s~|dkri}tt‡fdd„dƒƒd}|dkrFd}tg}tg}tg}nd}tg}d	g}d
g}| d|¡|_| d|¡|_| d
|¡|_	ˆ|}	d|j
|jf}
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]´\}}}||k�rt|ƒD]8\}}t|ƒ}| d¡�rÄtj
 ||¡}||=�qþ�qÄ|�stdƒ‚|D]H}t|ƒ d¡�r(�qtj
 ||¡}ttj
 ||¡ƒ}|
 ||f¡�q�q¨t |¡}|D]B}|dk�rlttj
 ||¡ƒ}ttj
 ||¡ƒ}|
 ||f¡�qld|�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-infoz(.dist-info directory expected, not found)z.pycz.pyo)r¸Z	INSTALLERZSHAREDr�zWheel-Version: %d.%dzGenerator: distlib %szRoot-Is-Purelib: %sz
Tag: %s-%s-%sr�rÂÚ
)$r­rÚIMPVERÚABIÚARCHr\Úgetr]r^r_rbrcr6rGÚisdirÚwalkr	r*r¯r®r)Úendswithr€r¹r rÆÚ	enumerateÚAssertionErrorÚlistdirÚ
wheel_versionrrorÁrardrÇ)!r<rÉrorÜZlibkeyZis_pureZ
default_pyverZdefault_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–




ýzWheel.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_entrycCKsf|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|ƒ|ddk�r|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
¡}%| "|%¡�r�qÊ||%}|d�r4t#|#j$ƒ|dk�r4t%d|%ƒ‚|d�r–|d dd¡\}&}'| |$¡�}| &¡}(W5QRX| '|(|&¡\})}*|*|'k�r–t%d|$ƒ‚|�r¼|% (||f¡�r¼t) *d |%¡�qÊ|% (|¡�oÒ|% +d!¡}+|% (|¡�r
|% d"d¡\})},}-tj ||,t,|-ƒ¡}.n$|%|
|fk�r�qÊtj |t,|%ƒ¡}.|+�s
| |$¡�}| -||.¡W5QRX|! .|.¡|�s´|d�r´t|.d#ƒ�4}| &¡}(| '|(|&¡\})}/|/|*k�rª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}5�nnd}6|j6d}|d*k�rzt	 |d+¡}7z˜| |7¡�}t7|ƒ}8W5QRXi}6d,D]l}9d-|9}:|:|8k�ræ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ØrZcopy_streamr)Zbyte_compileÚ	ExceptionZwarningÚbasenameZmakeZset_executable_modeÚextendrlrÚvaluesròÚsuffixÚflagsÚjsonÚloadrÖr‚Úitemsrr�Zwrite_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†Úbwfr�r‘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_scriptsZgui_scriptsZ
script_dirZscriptZoptionsr,r,r-ÚinstallÄsT


 

ÿ

ÿ
ÿ

þÿÿ







ÿ
z
Wheel.installcCs4tdkr0tj tƒtdƒtjdd…¡}t|ƒatS)Nzdylib-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Œr�r@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"

zWheel.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†r	r�r‘rˆr‰r±rŒr
rµr³rrår
rrrž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$||k�r$|||ƒ|dk�rNtjd
d|
d�\}}t |¡n*tj |¡�shtd|ƒ‚tj ||j¡}t| ¡ƒ}tj |
|¡}||f}| ||
|¡| ||¡|dk�rÊ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|d�j}||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||d�t 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)rr�rhr*rrÄrÅr
rcrØrrÆ)rcrGÚupdatedrDryr+Zmdr,r,r,r-Úupdate_versionUs.

 ÿ
ÿ

ÿz$Wheel.update..update_versionrprqr¸rsrrr&r'Nz.whlz
wheel-update-)rròÚdirzNot a directory: %r)r6rGr*rardrbrcrrrr÷rør
rªrrrrõZmkstempÚcloserÖr­rrÁrÇröZcopyfile)r<ZmodifierZdest_dirrr*r.r?rƒr„rrr†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	k�rŽt d
t¡}|�rŽ| ¡\}	}}}
t|ƒ}|
g}|
dkrø| d¡|
d
k�r| d¡|
dk�r | d¡|
dk�r4| d¡|
dk�rH| d¡|dk�rŽ|D]*}d|	|||f}
|
tk�rV| |
¡�qV|d8}�qH|D]0}|D]$}
| d t|df¡||
f¡�qš�q’t|ƒD]L\}}| d t|f¡ddf¡|dk�rÌ| d t|df¡ddf¡�qÌt|ƒD]L\}}| d d|f¡ddf¡|dk�r"| 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)r6r7Úx86_64Zfat3)Úppc64r8Zfat64)r6r8Úintel)r6r8r:r7r9Z	universalz%s_%s_%s_%srYr)r'ÚrangerJÚversion_infor)r*rùrMZget_suffixesrûrhr°rÓr rÔÚplatformÚrerfrœrvÚ
IMP_PREFIXrÙÚset)ZversionsÚmajorÚminorZabisrr rHZarchesr#rbr_Zmatchesrfrr^ryrcr,r,r-Úcompatible_tagsŸs`












&
"
"rCcCs\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
rZdatabaser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!rVrCrDrr,r,r,r-ÚsŠ,


	
ø

ü


#>PKÕ¶N]ºéºÜ*Ü*Lsite-packages/pip/_vendor/distlib/__pycache__/resources.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.e*ã	@sˆddlmZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlmZddl
mZmZmZmZe e¡ZdaGdd„deƒZGdd	„d	eƒZGd
d„deƒZGdd
„d
eƒZGdd„deƒZGdd„deƒZedƒee
jeiZzFzddl Z!Wne"k
�r$ddl#Z!YnXeee!j$<eee!j%<[!Wne"e&fk
�rXYnXdd„Z'iZ(dd„Z)e	 *e+dƒ¡Z,dd„Z-dS)é)Úunicode_literalsNé)ÚDistlibException)Úcached_propertyÚget_cache_baseÚpath_to_cache_dirÚCachecs.eZdZd‡fdd„	Zdd„Zdd„Z‡ZS)	Ú
ResourceCacheNcs0|dkrtj tƒtdƒ¡}tt|ƒ |¡dS)Nzresource-cache)ÚosÚpathÚjoinrÚstrÚsuperr	Ú__init__)ÚselfÚbase©Ú	__class__©úA/usr/lib/python3.8/site-packages/pip/_vendor/distlib/resources.pyrszResourceCache.__init__cCsdS)zã
        Is the cache stale for the given resource?

        :param resource: The :class:`Resource` being cached.
        :param path: The path of the resource in the cache.
        :return: True if the cache is stale.
        Tr©rÚresourcerrrrÚis_stale#s	zResourceCache.is_stalec	Cs |j |¡\}}|dkr|}n~tj |j| |¡|¡}tj |¡}tj |¡sXt 	|¡tj 
|¡sjd}n| ||¡}|rœt|dƒ�}| 
|j¡W5QRX|S)z¤
        Get a resource into the cache,

        :param resource: A :class:`Resource` instance.
        :return: The pathname of the resource in the cache.
        NTÚwb)ÚfinderÚget_cache_infor
rrrZ
prefix_to_dirÚdirnameÚisdirÚmakedirsÚexistsrÚopenÚwriteÚbytes)rrÚprefixrÚresultrZstaleÚfrrrÚget.s
zResourceCache.get)N)Ú__name__Ú
__module__Ú__qualname__rrr&Ú
__classcell__rrrrr	sr	c@seZdZdd„ZdS)ÚResourceBasecCs||_||_dS©N)rÚname)rrr-rrrrIszResourceBase.__init__N)r'r(r)rrrrrr+Hsr+c@s@eZdZdZdZdd„Zedd„ƒZedd„ƒZed	d
„ƒZ	dS)ÚResourcezÇ
    A class representing an in-package resource, such as a data file. This is
    not normally instantiated by user code, but rather by a
    :class:`ResourceFinder` which manages the resource.
    FcCs|j |¡S)z’
        Get the resource as a stream.

        This is not a property to make it obvious that it returns a new stream
        each time.
        )rÚ
get_stream©rrrrÚ	as_streamVszResource.as_streamcCstdkrtƒat |¡Sr,)Úcacher	r&r0rrrÚ	file_path_szResource.file_pathcCs|j |¡Sr,)rÚ	get_bytesr0rrrr"fszResource.bytescCs|j |¡Sr,)rÚget_sizer0rrrÚsizejsz
Resource.sizeN)
r'r(r)Ú__doc__Úis_containerr1rr3r"r6rrrrr.Ns	

r.c@seZdZdZedd„ƒZdS)ÚResourceContainerTcCs|j |¡Sr,)rÚ
get_resourcesr0rrrÚ	resourcesrszResourceContainer.resourcesN)r'r(r)r8rr;rrrrr9osr9c@s’eZdZdZej d¡rdZndZdd„Zdd„Z	d	d
„Z
dd„Zd
d„Zdd„Z
dd„Zdd„Zdd„Zdd„Zdd„ZeejjƒZdd„ZdS)ÚResourceFinderz4
    Resource finder for file system resources.
    Újava)ú.pycú.pyoz.class)r>r?cCs.||_t|ddƒ|_tj t|ddƒ¡|_dS)NÚ
__loader__Ú__file__Ú)ÚmoduleÚgetattrÚloaderr
rrr)rrCrrrr�szResourceFinder.__init__cCstj |¡Sr,)r
rÚrealpath©rrrrrÚ_adjust_path†szResourceFinder._adjust_pathcCsBt|tƒrd}nd}| |¡}| d|j¡tjj|Ž}| |¡S)Nó/ú/r)	Ú
isinstancer"ÚsplitÚinsertrr
rrrH)rÚ
resource_nameÚsepÚpartsr$rrrÚ
_make_path‰s

zResourceFinder._make_pathcCstj |¡Sr,)r
rrrGrrrÚ_find•szResourceFinder._findcCs
d|jfSr,)r©rrrrrr˜szResourceFinder.get_cache_infocCsD| |¡}| |¡sd}n&| |¡r0t||ƒ}n
t||ƒ}||_|Sr,)rQrRÚ
_is_directoryr9r.r)rrNrr$rrrÚfind›s



zResourceFinder.findcCst|jdƒS©NÚrb)r rrSrrrr/§szResourceFinder.get_streamc
Cs,t|jdƒ�}| ¡W5QR£SQRXdSrV)r rÚread)rrr%rrrr4ªszResourceFinder.get_bytescCstj |j¡Sr,)r
rÚgetsizerSrrrr5®szResourceFinder.get_sizecs*‡fdd„‰t‡fdd„t |j¡DƒƒS)Ncs|dko| ˆj¡S)NÚ__pycache__)ÚendswithÚskipped_extensions)r%r0rrÚallowed²s
ÿz-ResourceFinder.get_resources..allowedcsg|]}ˆ|ƒr|‘qSrr)Ú.0r%)r]rrÚ
µsz0ResourceFinder.get_resources..)Úsetr
ÚlistdirrrSr)r]rrr:±szResourceFinder.get_resourcescCs| |j¡Sr,)rTrrSrrrr8·szResourceFinder.is_containerccs„| |¡}|dk	r€|g}|r€| d¡}|V|jr|j}|jD]>}|sL|}nd ||g¡}| |¡}|jrv| |¡q>|Vq>qdS)NrrJ)rUÚpopr8r-r;rÚappend)rrNrZtodoZrnamer-Únew_nameZchildrrrÚiterator¼s 



zResourceFinder.iteratorN)r'r(r)r7ÚsysÚplatformÚ
startswithr\rrHrQrRrrUr/r4r5r:r8Ústaticmethodr
rrrTrerrrrr<ws"r<cs`eZdZdZ‡fdd„Zdd„Zdd„Zdd	„Zd
d„Zdd
„Z	dd„Z
dd„Zdd„Z‡Z
S)ÚZipResourceFinderz6
    Resource finder for resources in .zip files.
    csZtt|ƒ |¡|jj}dt|ƒ|_t|jdƒr>|jj|_nt	j
||_t|jƒ|_dS)NrÚ_files)
rrjrrEÚarchiveÚlenÚ
prefix_lenÚhasattrrkÚ	zipimportÚ_zip_directory_cacheÚsortedÚindex)rrCrlrrrrÕszZipResourceFinder.__init__cCs|Sr,rrGrrrrHàszZipResourceFinder._adjust_pathcCs¤||jd…}||jkrd}nX|r:|dtjkr:|tj}t |j|¡}z|j| |¡}Wntk
rtd}YnX|sŽt 	d||j
j¡nt 	d||j
j¡|S)NTéÿÿÿÿFz_find failed: %r %rz_find worked: %r %r)rnrkr
rOÚbisectrsrhÚ
IndexErrorÚloggerÚdebugrEr#)rrr$ÚirrrrRãs


zZipResourceFinder._findcCs&|jj}|jdt|ƒd…}||fS)Nr)rErlrrm)rrr#rrrrrõsz ZipResourceFinder.get_cache_infocCs|j |j¡Sr,)rEÚget_datarrSrrrr4úszZipResourceFinder.get_bytescCst | |¡¡Sr,)ÚioÚBytesIOr4rSrrrr/ýszZipResourceFinder.get_streamcCs|j|jd…}|j|dS)Né)rrnrkrrrrr5szZipResourceFinder.get_sizecCs |j|jd…}|r,|dtjkr,|tj7}t|ƒ}tƒ}t |j|¡}|t|jƒkrœ|j| |¡shqœ|j||d…}| 	| 
tjd¡d¡|d7}qH|S)Nrtrr)rrnr
rOrmr`rursrhÚaddrL)rrrZplenr$ryÚsrrrr:s

zZipResourceFinder.get_resourcescCsj||jd…}|r*|dtjkr*|tj7}t |j|¡}z|j| |¡}Wntk
rdd}YnX|S)NrtF)rnr
rOrursrhrv)rrryr$rrrrTs

zZipResourceFinder._is_directory)r'r(r)r7rrHrRrr4r/r5r:rTr*rrrrrjÑsrjcCs|tt|ƒ<dSr,)Ú_finder_registryÚtype)rEÚfinder_makerrrrÚregister_finder0srƒcCsŒ|tkrt|}nv|tjkr$t|ƒtj|}t|ddƒ}|dkrJtdƒ‚t|ddƒ}t t|ƒ¡}|dkrxtd|ƒ‚||ƒ}|t|<|S)zŸ
    Return a resource finder for a package.
    :param package: The name of the package.
    :return: A :class:`ResourceFinder` instance for the package.
    Ú__path__Nz8You cannot get a finder for a module, only for a packager@zUnable to locate finder for %r)	Ú
_finder_cacherfÚmodulesÚ
__import__rDrr€r&r�)Úpackager$rCrrEr‚rrrr6s


rZ	__dummy__cCsRd}t |¡tj |¡}t t|ƒ¡}|rNt}tj	 
|d¡|_||_||ƒ}|S)z¬
    Return a resource finder for a path, which should represent a container.

    :param path: The path.
    :return: A :class:`ResourceFinder` instance for the path.
    NrB)
ÚpkgutilZget_importerrfÚpath_importer_cacher&r€r�Ú
_dummy_moduler
rrrAr@)rr$rErrCrrrÚfinder_for_pathRs
rŒ).Z
__future__rrur{Zloggingr
r‰ZshutilrfÚtypesrprBrÚutilrrrrZ	getLoggerr'rwr2r	Úobjectr+r.r9r<rjr�Úzipimporterr€Ú_frozen_importlib_externalZ_fiÚImportErrorÚ_frozen_importlibÚSourceFileLoaderÚ
FileFinderÚAttributeErrorrƒr…rÚ
ModuleTyper
r‹rŒrrrrÚsN
,!ZNþ

PKÕ¶N]¾JE**Jsite-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.e¢?ã@s¬ddlmZddlZddlZddlZddlZddlZddlmZm	Z	m
Z
ddlmZddl
mZmZmZmZmZe e¡Zd ¡Ze d¡Zd	Zd
d„ZGdd
„d
eƒZdS)é)ÚBytesIONé)Ú	sysconfigÚdetect_encodingÚZipFile)Úfinder)ÚFileOperatorÚget_export_entryÚconvert_pathÚget_executableÚin_venvañ


 

 
 
 
 
 
 
 
 
s^#!.*pythonw?[0-9.]*([ 	].*)?$zÍ# -*- coding: utf-8 -*-
import re
import sys
from %(module)s import %(import_name)s
if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
    sys.exit(%(func)s())
cCsXd|krT| d¡rB| dd¡\}}d|krT| d¡sTd||f}n| d¡sTd|}|S)Nú z
/usr/bin/env rú"z%s "%s"z"%s")Ú
startswithÚsplit)Ú
executableÚenvZ_executable©rú?/usr/lib/python3.8/site-packages/pip/_vendor/distlib/scripts.pyÚ_enquote_executable3s

rc@sÚeZdZdZeZdZd'dd„Zdd„Ze	j
 d	¡rBd
d„Zdd
„Z
dd„Zd(dd„Zdd„ZeZdd„Zdd„Zd)dd„Zdd„Zedd„ƒZejdd„ƒZejd ksºejd	krÂejd krÂd!d"„Zd*d#d$„Zd+d%d&„ZdS),ÚScriptMakerz_
    A class to copy or create scripts from source scripts or callable
    specifications.
    NTFcCsz||_||_||_d|_d|_tjdkp:tjdko:tjdk|_t	dƒ|_
|pRt|ƒ|_tjdkprtjdkortjdk|_
dS)NFÚposixÚjava)ÚúX.YÚnt)Ú
source_dirÚ
target_dirÚ
add_launchersÚforceÚclobberÚosÚnameÚ_nameÚset_modeÚsetÚvariantsrÚ_fileopÚ_is_nt)ÚselfrrrÚdry_runZfileoprrrÚ__init__Lsÿ

ÿzScriptMaker.__init__cCs@| dd¡r<|jr %srspythonwr|rd)!r!r/r1rr
rr`rr'Znewerr:ror6r9r*Úreadliner;Zget_command_nameÚ
FIRST_LINE_REÚmatchr0ÚgroupÚcloseZ	copy_filer$rprqÚinforÚseekrUryr7)r)r€rsZadjustrvÚfZ
first_liner…rIrSÚlinesrTrtrwrrrÚ_copy_script)sX
ÿÿ


zScriptMaker._copy_scriptcCs|jjSr_©r'r*)r)rrrr*]szScriptMaker.dry_runcCs||j_dSr_r�)r)Úvaluerrrr*asrcCsHt d¡dkrd}nd}d||f}t dd¡d}t|ƒ |¡j}|S)	NÚPéZ64Z32z%s%s.exerVrr)ÚstructÚcalcsizeÚ__name__ÚrsplitrÚfindÚbytes)r)ZkindÚbitsr"Zdistlib_packagerJrrrrhiszScriptMaker._get_launchercCs6g}t|ƒ}|dkr"| ||¡n|j|||d�|S)aÓ
        Make a script.

        :param specification: The specification, which is either a valid export
                              entry specification (to make a script from a
                              callable) or a filename (to make a script by
                              copying from a source location).
        :param options: A dictionary of options controlling script generation.
        :return: A list of all absolute pathnames written to.
        Nrz)r	rŒr�)r)Ú
specificationr2rsr]rrrÚmakewszScriptMaker.makecCs$g}|D]}| | ||¡¡q|S)zÂ
        Take a list of specifications and make scripts from them,
        :param specifications: A list of specifications.
        :return: A list of all absolute pathnames written to,
        )Úextendr™)r)Zspecificationsr2rsr˜rrrÚ
make_multipleŠszScriptMaker.make_multiple)TFN)rLN)N)N)N) r“Ú
__module__Ú__qualname__Ú__doc__ÚSCRIPT_TEMPLATErYrr+r4rGrHrr=r@rKrUr^Ú_DEFAULT_MANIFESTrarcryr�rŒÚpropertyr*Úsetterr!r"r#rhr™r›rrrrrCs6ÿ

84
4


r)ÚiorZloggingr!Úrer‘rGÚcompatrrrZ	resourcesrÚutilrr	r
rrZ	getLoggerr“r:Ústripr Úcompiler„rŸrÚobjectrrrrrÚs


PKÕ¶N]¾JE**Dsite-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-38.pycnu„[µü¤U

ÀÒ.e¢?ã@s¬ddlmZddlZddlZddlZddlZddlZddlmZm	Z	m
Z
ddlmZddl
mZmZmZmZmZe e¡Zd ¡Ze d¡Zd	Zd
d„ZGdd
„d
eƒZdS)é)ÚBytesIONé)Ú	sysconfigÚdetect_encodingÚZipFile)Úfinder)ÚFileOperatorÚget_export_entryÚconvert_pathÚget_executableÚin_venvañ


 

 
 
 
 
 
 
 
 
s^#!.*pythonw?[0-9.]*([ 	].*)?$zÍ# -*- coding: utf-8 -*-
import re
import sys
from %(module)s import %(import_name)s
if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
    sys.exit(%(func)s())
cCsXd|krT| d¡rB| dd¡\}}d|krT| d¡sTd||f}n| d¡sTd|}|S)Nú z
/usr/bin/env rú"z%s "%s"z"%s")Ú
startswithÚsplit)Ú
executableÚenvZ_executable©rú?/usr/lib/python3.8/site-packages/pip/_vendor/distlib/scripts.pyÚ_enquote_executable3s

rc@sÚeZdZdZeZdZd'dd„Zdd„Ze	j
 d	¡rBd
d„Zdd
„Z
dd„Zd(dd„Zdd„ZeZdd„Zdd„Zd)dd„Zdd„Zedd„ƒZejdd„ƒZejd ksºejd	krÂejd krÂd!d"„Zd*d#d$„Zd+d%d&„ZdS),ÚScriptMakerz_
    A class to copy or create scripts from source scripts or callable
    specifications.
    NTFcCsz||_||_||_d|_d|_tjdkp:tjdko:tjdk|_t	dƒ|_
|pRt|ƒ|_tjdkprtjdkortjdk|_
dS)NFÚposixÚjava)ÚúX.YÚnt)Ú
source_dirÚ
target_dirÚ
add_launchersÚforceÚclobberÚosÚnameÚ_nameÚset_modeÚsetÚvariantsrÚ_fileopÚ_is_nt)ÚselfrrrÚdry_runZfileoprrrÚ__init__Lsÿ

ÿzScriptMaker.__init__cCs@| dd¡r<|jr %srspythonwr|rd)!r!r/r1rr
rr`rr'Znewerr:ror6r9r*Úreadliner;Zget_command_nameÚ
FIRST_LINE_REÚmatchr0ÚgroupÚcloseZ	copy_filer$rprqÚinforÚseekrUryr7)r)r€rsZadjustrvÚfZ
first_liner…rIrSÚlinesrTrtrwrrrÚ_copy_script)sX
ÿÿ


zScriptMaker._copy_scriptcCs|jjSr_©r'r*)r)rrrr*]szScriptMaker.dry_runcCs||j_dSr_r�)r)Úvaluerrrr*asrcCsHt d¡dkrd}nd}d||f}t dd¡d}t|ƒ |¡j}|S)	NÚPéZ64Z32z%s%s.exerVrr)ÚstructÚcalcsizeÚ__name__ÚrsplitrÚfindÚbytes)r)ZkindÚbitsr"Zdistlib_packagerJrrrrhiszScriptMaker._get_launchercCs6g}t|ƒ}|dkr"| ||¡n|j|||d�|S)aÓ
        Make a script.

        :param specification: The specification, which is either a valid export
                              entry specification (to make a script from a
                              callable) or a filename (to make a script by
                              copying from a source location).
        :param options: A dictionary of options controlling script generation.
        :return: A list of all absolute pathnames written to.
        Nrz)r	rŒr�)r)Ú
specificationr2rsr]rrrÚmakewszScriptMaker.makecCs$g}|D]}| | ||¡¡q|S)zÂ
        Take a list of specifications and make scripts from them,
        :param specifications: A list of specifications.
        :return: A list of all absolute pathnames written to,
        )Úextendr™)r)Zspecificationsr2rsr˜rrrÚ
make_multipleŠszScriptMaker.make_multiple)TFN)rLN)N)N)N) r“Ú
__module__Ú__qualname__Ú__doc__ÚSCRIPT_TEMPLATErYrr+r4rGrHrr=r@rKrUr^Ú_DEFAULT_MANIFESTrarcryr�rŒÚpropertyr*Úsetterr!r"r#rhr™r›rrrrrCs6ÿ

84
4


r)ÚiorZloggingr!Úrer‘rGÚcompatrrrZ	resourcesrÚutilrr	r
rrZ	getLoggerr“r:Ústripr Úcompiler„rŸrÚobjectrrrrrÚs


PKÕ¶N]ç*ŸzHHJsite-packages/pip/_vendor/distlib/__pycache__/markers.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.e#ã@sŠdZddlZddlZddlZddlZddlmZmZmZddl	m
Z
mZdgZdd„Z
Gd	d
„d
eƒZdd„ZeƒZ[eƒZdd
d„ZdS)zG
Parser for the environment markers micro-language defined in PEP 508.
éNé)Úpython_implementationÚurlparseÚstring_types)Úin_venvÚparse_markerÚ	interpretcCst|tƒr|sdS|ddkS)NFrú'")Ú
isinstancer)Úo©rú?/usr/lib/python3.8/site-packages/pip/_vendor/distlib/markers.pyÚ_is_literalsrc
@sfeZdZdZdd„dd„dd„dd„dd„dd„d	d„d
d„dd„dd„d
d„dd„dœZdd„ZdS)Ú	Evaluatorz;
    This class is used to evaluate marker expessions.
    cCs||kS©Nr©ÚxÚyrrr
Ú$ózEvaluator.cCs||kSrrrrrr
r%rcCs||kp||kSrrrrrr
r&rcCs||kSrrrrrr
r'rcCs||kSrrrrrr
r(rcCs||kp||kSrrrrrr
r)rcCs||kSrrrrrr
r*rcCs||kp||kSrrrrrr
r+rcCs|o|Srrrrrr
r,rcCs|p|Srrrrrr
r-rcCs||kSrrrrrr
r.rcCs||kSrrrrrr
r/r)z==z===z~=z!=úz>=ÚandÚorÚinznot inc	CsÆt|tƒrB|ddkr$|dd…}qÂ||kr8td|ƒ‚||}n€|d}||jkr`td|ƒ‚|d}|d	}t|dƒršt|d	ƒrštd
|||fƒ‚| ||¡}| ||¡}|j|||ƒ}|S)zƒ
        Evaluate a marker expression returned by the :func:`parse_requirement`
        function in the specified context.
        rr	réÿÿÿÿzunknown variable: %sÚopzop not implemented: %sÚlhsÚrhszinvalid comparison: %s %s %s)r
rÚSyntaxErrorÚ
operationsÚNotImplementedErrorrÚevaluate)	ÚselfÚexprÚcontextÚresultrZelhsZerhsrrrrr
r"2s"


zEvaluator.evaluateN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r r"rrrr
rsôrc
Cs€dd„}ttdƒr(|tjjƒ}tjj}nd}d}||tjt ¡t ¡t 	¡t 
¡t ¡ttƒƒt 
¡t 
¡dd…tjdœ}|S)NcSs<d|j|j|jf}|j}|dkr8||dt|jƒ7}|S)Nz%s.%s.%sÚfinalr)ÚmajorÚminorÚmicroÚreleaselevelÚstrÚserial)ÚinfoÚversionZkindrrr
Úformat_full_versionNs
z,default_context..format_full_versionÚimplementationÚ0Úé)Úimplementation_nameÚimplementation_versionZos_nameZplatform_machineZplatform_python_implementationZplatform_releaseZplatform_systemZplatform_versionZplatform_in_venvZpython_full_versionÚpython_versionZsys_platform)ÚhasattrÚsysr5r3ÚnameÚosÚplatformÚmachinerÚreleaseÚsystemr0rr;)r4r:r9r&rrr
Údefault_contextMs(

ôrDc
Cs†zt|ƒ\}}Wn2tk
rB}ztd||fƒ‚W5d}~XYnX|rd|ddkrdtd||fƒ‚ttƒ}|rz| |¡t ||¡S)zò
    Interpret a marker and return a result depending on environment.

    :param marker: The marker to interpret.
    :type marker: str
    :param execution_context: The context used for name lookup.
    :type execution_context: mapping
    z)Unable to interpret marker syntax: %s: %sNrú#z*unexpected trailing data in marker: %s: %s)rÚ	ExceptionrÚdictÚDEFAULT_CONTEXTÚupdateÚ	evaluatorr")ZmarkerZexecution_contextr$ÚrestÚer%rrr
rqs	"
)N)r*r?r=r@ÚreÚcompatrrrÚutilrrÚ__all__rÚobjectrrDrHrJrrrrr
Ús/PKÕ¶N]2‡õFT¤T¤Ksite-packages/pip/_vendor/distlib/__pycache__/database.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eUÇã@s”dZddlmZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlm
Z
mZddlmZddlmZmZddlmZmZmZmZdd	lmZmZmZmZmZmZm Z d
ddd
dgZ!e "e#¡Z$dZ%dZ&deddde%dfZ'dZ(Gdd„de)ƒZ*Gdd„de)ƒZ+Gdd
„d
e)ƒZ,Gdd„de,ƒZ-Gdd„de-ƒZ.Gdd
„d
e-ƒZ/e.Z0e/Z1Gdd„de)ƒZ2d)d!d"„Z3d#d$„Z4d%d&„Z5d'd(„Z6dS)*zPEP 376 implementation.é)Úunicode_literalsNé)ÚDistlibExceptionÚ	resources)ÚStringIO)Ú
get_schemeÚUnsupportedVersionError)ÚMetadataÚMETADATA_FILENAMEÚWHEEL_METADATA_FILENAMEÚLEGACY_METADATA_FILENAME)Úparse_requirementÚcached_propertyÚparse_name_and_versionÚread_exportsÚ
write_exportsÚ	CSVReaderÚ	CSVWriterÚDistributionÚBaseInstalledDistributionÚInstalledDistributionÚEggInfoDistributionÚDistributionPathzpydist-exports.jsonzpydist-commands.jsonZ	INSTALLERÚRECORDÚ	REQUESTEDÚ	RESOURCESÚSHAREDz
.dist-infoc@s(eZdZdZdd„Zdd„Zdd„ZdS)	Ú_CachezL
    A simple cache mapping names and .dist-info paths to distributions
    cCsi|_i|_d|_dS)zZ
        Initialise an instance. There is normally one for each DistributionPath.
        FN)ÚnameÚpathÚ	generated©Úself©r#ú@/usr/lib/python3.8/site-packages/pip/_vendor/distlib/database.pyÚ__init__1sz_Cache.__init__cCs|j ¡|j ¡d|_dS)zC
        Clear the cache, setting it to its initial state.
        FN)rÚclearrr r!r#r#r$r&9s

z_Cache.clearcCs2|j|jkr.||j|j<|j |jg¡ |¡dS)z`
        Add a distribution to the cache.
        :param dist: The distribution to add.
        N)rrÚ
setdefaultÚkeyÚappend©r"Údistr#r#r$ÚaddAsz
_Cache.addN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r%r&r,r#r#r#r$r-src@s„eZdZdZddd„Zdd„Zdd	„ZeeeƒZd
d„Z	dd
„Z
dd„Zedd„ƒZ
dd„Zdd„Zddd„Zdd„Zddd„ZdS)rzU
    Represents a set of distributions installed on a path (typically sys.path).
    NFcCsD|dkrtj}||_d|_||_tƒ|_tƒ|_d|_tdƒ|_	dS)a 
        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.
        NTÚdefault)
ÚsysrÚ
_include_distÚ_include_eggrÚ_cacheÚ
_cache_eggÚ_cache_enabledrÚ_scheme)r"rZinclude_eggr#r#r$r%Os	zDistributionPath.__init__cCs|jS©N©r7r!r#r#r$Ú_get_cache_enabledcsz#DistributionPath._get_cache_enabledcCs
||_dSr9r:)r"Úvaluer#r#r$Ú_set_cache_enabledfsz#DistributionPath._set_cache_enabledcCs|j ¡|j ¡dS)z,
        Clears the internal cache.
        N)r5r&r6r!r#r#r$Úclear_cacheks
zDistributionPath.clear_cachec
csDtƒ}|jD�]0}t |¡}|dkr&q| d¡}|r|js| ¡|jj ¡D]
}|Vq0|jrZ|jj ¡D]
}|VqNdS)a5
        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)r7r\r^r5rÚvaluesr4r6r*r#r#r$Úget_distributionsÈs	
z"DistributionPath.get_distributionscCs€d}| ¡}|js4| ¡D]}|j|kr|}q|qnH| ¡||jjkrZ|jj|d}n"|jr|||jjkr||jj|d}|S)a=
        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``
        Nr)	Úlowerr7r\r(r^r5rr4r6)r"rÚresultr+r#r#r$Úget_distributionÞs

z!DistributionPath.get_distributionc	csÈd}|dk	rJz|j d||f¡}Wn$tk
rHtd||fƒ‚YnX| ¡D]p}t|dƒsnt d|¡qR|j}|D]H}t	|ƒ\}}|dkr¤||krÀ|VqRqx||krx| 
|¡rx|VqRqxqRdS)a
        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
        Nú%s (%s)zinvalid name or version: %r, %rÚprovideszNo "provides": %s)r8ÚmatcherÚ
ValueErrorrrfÚhasattrrSrTrkrÚmatch)	r"rrcrlr+ÚprovidedÚpÚp_nameÚp_verr#r#r$Úprovides_distributionøs*ÿ
z&DistributionPath.provides_distributioncCs(| |¡}|dkrtd|ƒ‚| |¡S)z5
        Return the path to a resource file.
        Nzno distribution named %r found)riÚLookupErrorÚget_resource_path)r"rÚ
relative_pathr+r#r#r$Ú
get_file_path!s
zDistributionPath.get_file_pathccsX| ¡D]J}|j}||kr||}|dk	r>||krR||Vq| ¡D]
}|VqFqdS)zÙ
        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)rfÚexportsre)r"Úcategoryrr+rYÚdÚvr#r#r$Úget_exported_entries*sz%DistributionPath.get_exported_entries)NF)N)N)r-r.r/r0r%r;r=ÚpropertyZ
cache_enabledr>r\r^Úclassmethodrdrfrirtrxr}r#r#r#r$rKs

,

)	c@s¬eZdZdZdZdZdd„Zedd„ƒZeZ	edd„ƒZ
ed	d
„ƒZdd„Zed
d„ƒZ
edd„ƒZedd„ƒZedd„ƒZedd„ƒZdd„Zdd„Zdd„Zdd„ZdS) rzª
    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.
    FcCsL||_|j|_|j ¡|_|j|_d|_d|_d|_d|_t	ƒ|_
i|_dS)zŠ
        Initialise an instance.
        :param metadata: The instance of :class:`Metadata` describing this
        distribution.
        N)rDrrgr(rcZlocatorÚdigestÚextrasÚcontextrHZ
download_urlsZdigests)r"rDr#r#r$r%OszDistribution.__init__cCs|jjS)zH
        The source archive download URL for this distribution.
        )rDÚ
source_urlr!r#r#r$rƒ`szDistribution.source_urlcCsd|j|jfS)zX
        A utility property which displays the name and version in parentheses.
        rj©rrcr!r#r#r$Úname_and_versioniszDistribution.name_and_versioncCs.|jj}d|j|jf}||kr*| |¡|S)z�
        A set of distribution names and versions provided by this distribution.
        :return: A set of "name (version)" strings.
        rj)rDrkrrcr))r"ZplistÚsr#r#r$rkps

zDistribution.providescCs8|j}t d| ¡¡t||ƒ}t|j||j|jd�ƒS)Nz%Getting requirements from metadata %r)r�rE)	rDrSrTZtodictÚgetattrrHZget_requirementsr�r‚)r"Zreq_attrÚmdZreqtsr#r#r$Ú_get_requirements|s
ÿzDistribution._get_requirementscCs
| d¡S)NÚrun_requires©r‰r!r#r#r$rŠƒszDistribution.run_requirescCs
| d¡S)NÚ
meta_requiresr‹r!r#r#r$rŒ‡szDistribution.meta_requirescCs
| d¡S)NÚbuild_requiresr‹r!r#r#r$r�‹szDistribution.build_requirescCs
| d¡S)NÚ
test_requiresr‹r!r#r#r$rŽ�szDistribution.test_requirescCs
| d¡S)NÚdev_requiresr‹r!r#r#r$r�“szDistribution.dev_requiresc
	Cs¶t|ƒ}t|jjƒ}z| |j¡}Wn6tk
rZt d|¡| 	¡d}| |¡}YnX|j
}d}|jD]D}t|ƒ\}}	||kr†qlz| 
|	¡}Wq²Wqltk
r®YqlXql|S)z¿
        Say if this instance matches (fulfills) a requirement.
        :param req: The requirement to match.
        :rtype req: str
        :return: True if it matches, else False.
        ú+could not read version %r - using name onlyrF)r
rrDrCrlÚrequirementrrSÚwarningÚsplitr(rkrro)
r"ÚreqrYrCrlrrhrqrrrsr#r#r$Úmatches_requirement—s,	ÿ


z Distribution.matches_requirementcCs(|jrd|j}nd}d|j|j|fS)zC
        Return a textual representation of this instance,
        z [%s]r?z)rƒrrc)r"Úsuffixr#r#r$Ú__repr__¹szDistribution.__repr__cCs>t|ƒt|ƒk	rd}n$|j|jko8|j|jko8|j|jk}|S)a<
        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.
        F)Útyperrcrƒ)r"Úotherrhr#r#r$Ú__eq__Ãs
ÿ
þzDistribution.__eq__cCst|jƒt|jƒt|jƒS)zH
        Compute hash in a way which matches the equality test.
        )Úhashrrcrƒr!r#r#r$Ú__hash__ÓszDistribution.__hash__N)r-r.r/r0Zbuild_time_dependencyÚ	requestedr%r~rƒZdownload_urlr…rkr‰rŠrŒr�rŽr�r•r—ršrœr#r#r#r$r=s4







"
cs0eZdZdZdZd‡fdd„	Zddd„Z‡ZS)	rz]
    This is the base class for installed distributions (whether PEP 376 or
    legacy).
    Ncs tt|ƒ |¡||_||_dS)a
        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)Úsuperrr%rÚ	dist_path)r"rDrrE©Ú	__class__r#r$r%âsz"BaseInstalledDistribution.__init__cCsd|dkr|j}|dkr"tj}d}ntt|ƒ}d|j}||ƒ ¡}t |¡ d¡ d¡}d||fS)a”
        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
        Nr?z%s=ó=Úasciiú%s%s)	ÚhasherÚhashlibÚmd5r‡r€Úbase64Zurlsafe_b64encodeÚrstripÚdecode)r"Údatar¥Úprefixr€r#r#r$Úget_hashñs

z"BaseInstalledDistribution.get_hash)N)N)r-r.r/r0r¥r%r­Ú
__classcell__r#r#r r$rÚscs¸eZdZdZdZd'‡fdd„	Zdd„Zdd	„Zd
d„Ze	dd
„ƒZ
dd„Zdd„Zdd„Z
dd„Zd(dd„Zdd„Ze	dd„ƒZd)dd„Zdd „Zd!d"„Zd#d$„Zd%d&„ZejZ‡ZS)*ra
    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).
    Zsha256Nc
	sJg|_t |¡|_}|dkr*td|ƒ‚|rP|jrP||jjkrP|jj|j}nt|dkrÄ| 	t
¡}|dkrt| 	t¡}|dkr†| 	d¡}|dkržtdt
|fƒ‚t 
| ¡¡�}t|dd�}W5QRXtt|ƒ |||¡|rî|jrî|j |¡| 	d¡}|dk	|_tj |d¡}tj |¡�rFt|dƒ�}| ¡}	W5QRX|	 ¡|_dS)	Nzfinder unavailable for %sZMETADATAzno %s found in %sr@rArú
top_level.txtÚrb)ÚmodulesrrIrXrmr7r5rrDrJr
rrPrQrRr	ržrr%r,r�ÚosrOÚexistsÚopenÚreadÚ
splitlines)
r"rrDrErXrYr[rqÚfr«r r#r$r%s8


ÿ


zInstalledDistribution.__init__cCsd|j|j|jfS)Nz#©rrcrr!r#r#r$r—=s
ÿzInstalledDistribution.__repr__cCsd|j|jfS©Nz%s %sr„r!r#r#r$Ú__str__AszInstalledDistribution.__str__c

Cs‚g}| d¡}t | ¡¡�\}t|d��F}|D]:}dd„tt|ƒdƒDƒ}||\}}}	| |||	f¡q.W5QRXW5QRX|S)a"
        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).
        r©r[cSsg|]}d‘qSr9r#)Ú.0Úir#r#r$Ú
Ssz6InstalledDistribution._get_records..é)Úget_distinfo_resourcerPrQrRrÚrangeÚlenr))
r"ÚresultsrYr[Z
record_readerÚrowÚmissingrÚchecksumÚsizer#r#r$Ú_get_recordsDs
&z"InstalledDistribution._get_recordscCsi}| t¡}|r| ¡}|S)a
        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.
        )rÀÚEXPORTS_FILENAMEr)r"rhrYr#r#r$ry[s

zInstalledDistribution.exportsc	Cs8i}| t¡}|r4t | ¡¡�}t|ƒ}W5QRX|S)zý
        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.
        )rÀrÉrPrQrRr)r"rhrYr[r#r#r$ris
z"InstalledDistribution.read_exportsc	Cs.| t¡}t|dƒ�}t||ƒW5QRXdS)a
        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.
        ÚwN)Úget_distinfo_filerÉr´r)r"ryZrfr·r#r#r$rxs
z#InstalledDistribution.write_exportscCs€| d¡}t | ¡¡�R}t|d��<}|D]0\}}||kr*|W5QR£W5QR£Sq*W5QRXW5QRXtd|ƒ‚dS)aW
        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.
        rr»z3no resource file with relative path %r is installedN)rÀrPrQrRrÚKeyError)r"rwrYr[Zresources_readerÚrelativeZdestinationr#r#r$rvƒs
6ÿz'InstalledDistribution.get_resource_pathccs| ¡D]
}|VqdS)zª
        Iterates over the ``RECORD`` entries and returns a tuple
        ``(path, hash, size)`` for each line.

        :returns: iterator of (path, hash, size)
        N)rÈ)r"rhr#r#r$Úlist_installed_files—sz*InstalledDistribution.list_installed_filesFcCs(tj |d¡}tj |j¡}| |¡}tj |d¡}| d¡}t d|¡|rRdSt|ƒ�Ä}|D]Ž}tj 	|¡sz| 
d¡r„d}	}
n4dtj |¡}
t|dƒ�}| 
| ¡¡}	W5QRX| |¡sÐ|rÞ| |¡rÞtj ||¡}| ||	|
f¡q`| |¡�r
tj ||¡}| |ddf¡W5QRX|S)zÖ
        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.
        r?rúcreating %sN©z.pycz.pyoz%dr°)r²rrOÚdirnameÚ
startswithrËrSÚinforÚisdirrLÚgetsizer´r­rµÚrelpathZwriterow)r"Úpathsr¬Údry_runÚbaseZbase_under_prefixÚrecord_pathÚwriterrÚ
hash_valuerÇÚfpr#r#r$Úwrite_installed_files¡s0



ÿz+InstalledDistribution.write_installed_filesc
Csg}tj |j¡}| d¡}| ¡D]î\}}}tj |¡sHtj ||¡}||krRq$tj |¡sr| |dddf¡q$tj 	|¡r$t
tj |¡ƒ}|r®||kr®| |d||f¡q$|r$d|krÌ| dd¡d}nd	}t
|d
ƒ�2}	| |	 ¡|¡}
|
|k�r| |d||
f¡W5QRXq$|S)á¨
        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.
        rr³TFrÇú=rrNr°r›)r²rrÑrËrÎÚisabsrOr³r)ÚisfileÚstrrÕr“r´r­rµ)r"Ú
mismatchesrÙrÚrrÜrÇZactual_sizer¥r·Zactual_hashr#r#r$Úcheck_installed_filesÄs.	

z+InstalledDistribution.check_installed_filesc	CsŠi}tj |jd¡}tj |¡r†tj|ddd��}| ¡ ¡}W5QRX|D]8}| dd¡\}}|dkr|| 	|g¡ 
|¡qL|||<qL|S)a 
        A dictionary of shared locations whose keys are in the set 'prefix',
        'purelib', 'platlib', 'scripts', 'headers', 'data' and 'namespace'.
        The corresponding value is the absolute path of that category for
        this distribution, and takes into account any paths selected by the
        user at installation time (e.g. via command-line arguments). In the
        case of the 'namespace' key, this would be a list of absolute paths
        for the roots of namespace packages in this distribution.

        The first time this property is accessed, the relevant information is
        read from the SHARED file in the .dist-info directory.
        rrYúutf-8©ÚencodingràrÚ	namespace)r²rrOrâÚcodecsr´rµr¶r“r'r))r"rhÚshared_pathr·ÚlinesÚliner(r<r#r#r$Úshared_locationsçs
z&InstalledDistribution.shared_locationsc		Cs¬tj |jd¡}t d|¡|r$dSg}dD].}||}tj ||¡r,| d||f¡q,| dd¡D]}| d|¡qhtj	|d	d
d��}| 
d |¡¡W5QRX|S)
aa
        Write shared location information to the SHARED file in .dist-info.
        :param paths: A dictionary as described in the documentation for
        :meth:`shared_locations`.
        :param dry_run: If True, the action is logged but no file is actually
                        written.
        :return: The path of the file written to.
        rrÏN)r¬ÚlibZheadersZscriptsr«z%s=%srér#znamespace=%srÊrærçÚ
)r²rrOrSrÓrÔr)Úgetrêr´Úwrite)	r"r×rØrërìr(rÚnsr·r#r#r$Úwrite_shared_locationss	z,InstalledDistribution.write_shared_locationscCsF|tkrtd||jfƒ‚t |j¡}|dkr.set_name_and_version)rrŸr7r6rDrrcÚ
_get_metadatar,ržrr%)r"rrErþrDr r#r$r%bs

zEggInfoDistribution.__init__c	sÐd}dd„‰‡fdd„}d}}| d¡rötj |¡r„tj |d¡}tj |d¡}t|dd	�}tj |d
¡}	tj |d¡}||	ƒ}npt |¡}
t|
 	d¡ 
d
¡ƒ}t|dd�}z,|
 	d¡}|
 	d¡ 
d¡}ˆ| 
d¡ƒ}Wntk
ròd}YnXnf| d¡�rPtj |¡�rBtj |d
¡}	||	ƒ}tj |d¡}tj |d¡}t|dd	�}ntd|ƒ‚|�rl| 
|¡|dk�r²|dk	�r²tj |¡�r²t|dƒ�}
|
 ¡ 
d¡}W5QRX|�s¾g}n| ¡}||_|S)NcSs¤g}| ¡}|D]Ž}| ¡}| d¡r6t d|¡q t|ƒ}|sPt d|¡q|jr`t d¡|jst| |j	¡qd 
dd„|jDƒ¡}| d|j	|f¡q|S)	z’Create a list of dependencies from a requires.txt file.

            *data*: the contents of a setuptools-produced requires.txt file.
            ú[z.Unexpected line: quitting requirement scan: %rz#Not recognised as a requirement: %rz4extra requirements in requires.txt are not supportedz, css|]}d|VqdS)r¤Nr#)r¼Úcr#r#r$Ú	‘szQEggInfoDistribution._get_metadata..parse_requires_data..rj)r¶ÚstriprÒrSr’r
r�Zconstraintsr)rrO)r«ÚreqsrìrírYZconsr#r#r$Úparse_requires_datazs(
ÿ
z>EggInfoDistribution._get_metadata..parse_requires_datac	sHg}z*t |dd¡�}ˆ| ¡ƒ}W5QRXWntk
rBYnX|S)z’Create a list of dependencies from a requires.txt file.

            *req_path*: the path to a setuptools-produced requires.txt file.
            rYræ)rêr´rµÚIOError)Úreq_pathrrÝ©rr#r$Úparse_requires_path•sz>EggInfoDistribution._get_metadata..parse_requires_pathrGzEGG-INFOzPKG-INFOr@)rrCzrequires.txtr¯zEGG-INFO/PKG-INFOÚutf8rAzEGG-INFO/requires.txtzEGG-INFO/top_level.txtrærFz,path must end with .egg-info or .egg, got %rr°)rLr²rrÔrOr	Ú	zipimportÚzipimporterrÚget_datarªrrZadd_requirementsr³r´rµr¶r±)r"rÚrequiresr	Ztl_pathZtl_datarqÚ	meta_pathrDrZzipfrBr«r·r#rr$rÿwsX


ÿ
ÿ

z!EggInfoDistribution._get_metadatacCsd|j|j|jfS)Nz!r¸r!r#r#r$r—Ñs
ÿzEggInfoDistribution.__repr__cCsd|j|jfSr¹r„r!r#r#r$rºÕszEggInfoDistribution.__str__cCs`g}tj |jd¡}tj |¡r\| ¡D]2\}}}||kr._md5cSst |¡jSr9)r²ÚstatÚst_size)rr#r#r$Ú_sizeûsz7EggInfoDistribution.list_installed_files.._sizerrYrærçzNon-existent file: %srÐN)
r²rrOr³rêr´rÚnormpathrSr’rLrÔr))r"rrrÚrhr·rírqr#r#r$rÎës"
$z(EggInfoDistribution.list_installed_filesFc	csštj |jd¡}tj |¡r–d}tj|ddd��`}|D]T}| ¡}|dkrPd}q6|s6tj tj |j|¡¡}| |j¡r6|r„|Vq6|Vq6W5QRXdS)	a
        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
        rTrYrærçz./FN)	r²rrOr³rêr´rrrÒ)r"ZabsoluterÚÚskipr·rírqr#r#r$rúsz'EggInfoDistribution.list_distinfo_filescCst|tƒo|j|jkSr9)r]rrrûr#r#r$rš.s

ÿzEggInfoDistribution.__eq__)N)F)r-r.r/r0r�rîr%rÿr—rºrårÎrúršrürœr®r#r#r r$rYsZ&
c@s^eZdZdZdd„Zdd„Zddd„Zd	d
„Zdd„Zddd„Z	ddd„Z
dd„Zdd„ZdS)ÚDependencyGraphaù
    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|_dSr9)Úadjacency_listÚreverse_listrÅr!r#r#r$r%IszDependencyGraph.__init__cCsg|j|<g|j|<dS)zÍAdd the *distribution* to the graph.

        :type distribution: :class:`distutils2.database.InstalledDistribution`
                            or :class:`distutils2.database.EggInfoDistribution`
        N)rr)r"Údistributionr#r#r$Úadd_distributionNs
z DependencyGraph.add_distributionNcCs6|j| ||f¡||j|kr2|j| |¡dS)ašAdd an edge from distribution *x* to distribution *y* with the given
        *label*.

        :type x: :class:`distutils2.database.InstalledDistribution` or
                 :class:`distutils2.database.EggInfoDistribution`
        :type y: :class:`distutils2.database.InstalledDistribution` or
                 :class:`distutils2.database.EggInfoDistribution`
        :type label: ``str`` or ``None``
        N)rr)r)r"ÚxÚyÚlabelr#r#r$Úadd_edgeXs
zDependencyGraph.add_edgecCs&t d||¡|j |g¡ |¡dS)a
        Add a missing *requirement* for the given *distribution*.

        :type distribution: :class:`distutils2.database.InstalledDistribution`
                            or :class:`distutils2.database.EggInfoDistribution`
        :type requirement: ``str``
        z
%s missing %rN)rSrTrÅr'r))r"rr‘r#r#r$Úadd_missinggszDependencyGraph.add_missingcCsd|j|jfSr¹r„r*r#r#r$Ú
_repr_distrszDependencyGraph._repr_distrcCsŠ| |¡g}|j|D]h\}}| |¡}|dk	r| d|j|jf¡q>q|sÞt|ƒdkrÞ| d¡| d¡| d¡|D]}| d	|j¡| d
¡q´| d¡| d¡dS)a9Writes a DOT output for the graph to the provided file *f*.

        If *skip_disconnected* is set to ``True``, then all distributions
        that are not dependent on any other distribution are skipped.

        :type f: has to support ``file``-like operations
        :type skip_disconnected: ``bool``
        zdigraph dependencies {
rNz"%s" -> "%s" [label="%s"]
z
"%s" -> "%s"
zsubgraph disconnected {
zlabel = "Disconnected"
zbgcolor = red
z"%s"rðz}
)ròrÚitemsrÂr)r)r"r·Zskip_disconnectedZdisconnectedr+Úadjsr™rr#r#r$Úto_dot‚s(	

ÿ



zDependencyGraph.to_dotcsÂg}i}|j ¡D]\}}|dd…||<qg‰t| ¡ƒdd…D]\}}|sDˆ |¡||=qDˆshq²| ¡D]\}}‡fdd„|Dƒ||<qpt ddd„ˆDƒ¡| ˆ¡q,|t| ¡ƒfS)aa
        Perform a topological sort of the graph.
        :return: A tuple, the first element of which is a topologically sorted
                 list of distributions, and the second element of which is a
                 list of distributions that cannot be sorted because they have
                 circular dependencies and so form a cycle.
        Ncs g|]\}}|ˆkr||f‘qSr#r#)r¼r{rY©Z	to_remover#r$r¾»sz4DependencyGraph.topological_sort..zMoving to result: %scSsg|]}d|j|jf‘qS)rjr„)r¼r{r#r#r$r¾½s)rr'Úlistr)rSrTr$Úkeys)r"rhZalistÚkr|r#r*r$Útopological_sort¢s$
ÿz DependencyGraph.topological_sortcCs2g}|j ¡D]\}}| | |¡¡qd |¡S)zRepresentation of the graphrð)rr'r)r#rO)r"r&r+r(r#r#r$r—ÁszDependencyGraph.__repr__)N)r)T)
r-r.r/r0r%rr r!r"r#r)r.r—r#r#r#r$r9s



 rr1cCsVt|ƒ}tƒ}i}|D]L}| |¡|jD]6}t|ƒ\}}t d|||¡| |g¡ ||f¡q*q|D]è}|j	|j
B|jB|jB}|D]Æ}	z| 
|	¡}
Wn6tk
rÐt d|	¡|	 ¡d}| 
|¡}
YnX|
j}d}||k�r>||D]N\}}z|
 |¡}
Wntk
�rd}
YnX|
rî| |||	¡d}�q>qî|sˆ| ||	¡qˆqh|S)a6Makes a dependency graph from the given distributions.

    :parameter dists: a list of distributions
    :type dists: list of :class:`distutils2.database.InstalledDistribution` and
                 :class:`distutils2.database.EggInfoDistribution` instances
    :rtype: a :class:`DependencyGraph` instance
    zAdd to provided: %s, %s, %sr�rFT)rrrrkrrSrTr'r)rŠrŒr�r�rlrr’r“r(ror r!)ÚdistsrCÚgraphrpr+rqrrcrr”rlZmatchedZproviderror#r#r$Ú
make_graphÉsN


ÿÿÿ

r1cCsv||krtd|jƒ‚t|ƒ}|g}|j|}|rh| ¡}| |¡|j|D]}||krN| |¡qNq.| d¡|S)zÚRecursively generate a list of distributions from *dists* that are
    dependent on *dist*.

    :param dists: a list of distributions
    :param dist: a distribution, member of *dists* for which we are interested
    ú1given distribution %r is not a member of the listr)rrr1rÚpopr))r/r+r0ZdepÚtodor{Zsuccr#r#r$Úget_dependent_distsÿsÿ


r5cCsn||krtd|jƒ‚t|ƒ}g}|j|}|rj| ¡d}| |¡|j|D]}||krP| |¡qPq,|S)zÙRecursively generate a list of distributions from *dists* that are
    required by *dist*.

    :param dists: a list of distributions
    :param dist: a distribution, member of *dists* for which we are interested
    r2r)rrr1rr3r))r/r+r0r”r4r{Zpredr#r#r$Úget_required_distssÿ

r6cKs4| dd¡}tf|Ž}||_||_|p(d|_t|ƒS)zO
    A convenience method for making a dist given just a name and version.
    ÚsummaryzPlaceholder for summary)r3r	rrcr7r)rrcÚkwargsr7rˆr#r#r$Ú	make_dist2s

r9)r1)7r0Z
__future__rr¨rêrPr¦Zloggingr²rNr2rr?rrÚcompatrrcrrrDr	r
rrÚutilr
rrrrrrÚ__all__Z	getLoggerr-rSrÉZCOMMANDS_FILENAMErörMrürrrrrrrUrVrr1r5r6r9r#r#r#r$Ús`$þ
ÿs7J]
6PKÕ¶N]D�ÌŽdcdcHsite-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eõ�ã@sŽddlmZddlZddlZddlZddlZddlmZddl	Z	ddl
Z
ddlZddl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
¡�rLdZ5nej6dk�r^dZ5ndZ5e 8d¡Z9e9�s„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#k�rBd$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
zMounter.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
edd„ƒZdd„Z
edd„ƒ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.tagscCstj |j|j¡}d|j|jf}d|}t d¡}t	|dƒ�Ö}| 
|¡}|d dd¡}tdd	„|Dƒƒ}|d
kr€t
tdg}	nt
tg}	d}
|	D]f}zLt ||¡}| |¡�,}
||
ƒ}t|d�}
|
rÔW5QR£WqøW5QRXWq�tk
rôYq�Xq�|
�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.infocCsÔ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<ÚrecordsZrecord_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
|jf}
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]¦\}}}||k�rþt|ƒD]8\}}t|ƒ}| d¡�rÄtj
 ||¡}||=�qþ�qÄ|D]H}t|ƒ d¡�r�qtj
 ||¡}ttj
 ||¡ƒ}|
 ||f¡�q�q¨t |¡}|D]B}|dk�r^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	INSTALLERZSHAREDr�zWheel-Version: %d.%dzGenerator: distlib %szRoot-Is-Purelib: %sz
Tag: %s-%s-%sr�rÂÚ
)#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_pyverZdefault_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”




ýzWheel.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_entrycCKsf|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|ƒ|ddk�r|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
¡}%| "|%¡�r�qÊ||%}|d�r4t#|#j$ƒ|dk�r4t%d|%ƒ‚|d�r–|d dd¡\}&}'| |$¡�}| &¡}(W5QRX| '|(|&¡\})}*|*|'k�r–t%d|$ƒ‚|�r¼|% (||f¡�r¼t) *d |%¡�qÊ|% (|¡�oÒ|% +d!¡}+|% (|¡�r
|% d"d¡\})},}-tj ||,t,|-ƒ¡}.n$|%|
|fk�r�qÊtj |t,|%ƒ¡}.|+�s
| |$¡�}| -||.¡W5QRX|! .|.¡|�s´|d�r´t|.d#ƒ�4}| &¡}(| '|(|&¡\})}/|/|*k�rª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}5�nnd}6|j6d}|d*k�rzt	 |d+¡}7z˜| |7¡�}t7|ƒ}8W5QRXi}6d,D]l}9d-|9}:|:|8k�ræ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ØrZcopy_streamr)Zbyte_compileÚ	ExceptionZwarningÚbasenameZmakeZset_executable_modeÚextendrlrÚvaluesrñÚsuffixÚflagsÚjsonÚloadrÖr‚Úitemsrr�Zwrite_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†Úbwfr�r‘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_scriptsZgui_scriptsZ
script_dirZscriptZoptionsr,r,r-ÚinstallÄsT


 

ÿ

ÿ
ÿ

þÿÿ







ÿ
z
Wheel.installcCs4tdkr0tj tƒtdƒtjdd…¡}t|ƒatS)Nzdylib-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Œr�r@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"

zWheel.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†rr�r‘rˆr‰r±rŒr	rµr³rrä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$||k�r$|||ƒ|dk�rNtjd
d|
d�\}}t |¡n*tj |¡�shtd|ƒ‚tj ||j¡}t| ¡ƒ}tj |
|¡}||f}| ||
|¡| ||¡|dk�rÊ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|d�j}||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||d�t 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)rr�rhr*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(rrä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	k�rŽt d
t¡}|�rŽ| ¡\}	}}}
t|ƒ}|
g}|
dkrø| d¡|
d
k�r| d¡|
dk�r | d¡|
dk�r4| d¡|
dk�rH| d¡|dk�rŽ|D]*}d|	|||f}
|
tk�rV| |
¡�qV|d8}�qH|D]0}|D]$}
| d t|df¡||
f¡�qš�q’t|ƒD]L\}}| d t|f¡ddf¡|dk�rÌ| d t|df¡ddf¡�qÌt|ƒD]L\}}| d d|f¡ddf¡|dk�r"| 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
rZdatabaser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Š,


	
ø

ü


#>PKÕ¶N]j´dYkOkODsite-packages/pip/_vendor/distlib/__pycache__/version.cpython-38.pycnu„[µü¤U

ÀÒ.e_[ã@sfdZddlZddlZddlmZddlmZdddd	d
ddd
gZe e	¡Z
Gdd„deƒZGdd„de
ƒZGdd„de
ƒZe d¡Zdd„ZeZGdd„deƒZdd„ZGdd„deƒZe d¡dfe d¡dfe d¡dfe d¡d fe d!¡d"fe d#¡d"fe d$¡d%fe d&¡d'fe d(¡d)fe d*¡d+ff
Ze d,¡dfe d-¡dfe d.¡d%fe d$¡d%fe d/¡dffZe d0¡Zd1d2„Zd3d4„Ze d5ej¡Zd6d6d7d6d8ddd9œZd:d;„ZGdej¡Z"d?d@„Z#dAdB„Z$GdCd
„d
eƒZ%GdDd„deƒZ&GdEdF„dFe
ƒZ'e'eeeƒe'ee!dGdH„ƒe'e$e&eƒdIœZ(e(dJe(dK<dLd
„Z)dS)Mz~
Implementation of a flexible versioning scheme providing support for PEP-440,
setuptools-compatible and semantic versioning.
éNé)Ústring_types©Úparse_requirementÚNormalizedVersionÚNormalizedMatcherÚ
LegacyVersionÚ
LegacyMatcherÚSemanticVersionÚSemanticMatcherÚUnsupportedVersionErrorÚ
get_schemec@seZdZdZdS)rzThis is an unsupported version.N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__©rrú?/usr/lib/python3.8/site-packages/pip/_vendor/distlib/version.pyrsc@sxeZdZdd„Zdd„Zdd„Zdd„Zd	d
„Zdd„Zd
d„Z	dd„Z
dd„Zdd„Zdd„Z
dd„Zedd„ƒZdS)ÚVersioncCs@| ¡|_}| |¡|_}t|tƒs,t‚t|ƒdksTózMatcher.cCs||kSr)rr>rrrrBUrCcCs||kp||kSr)rr>rrrrBVrCcCs||kp||kSr)rr>rrrrBWrCcCs||kSr)rr>rrrrBXrCcCs||kSr)rr>rrrrBYrCcCs||kp||kSr)rr>rrrrB[rCcCs||kSr)rr>rrrrB\rC)ú<ú>ú<=ú>=ú==ú===ú~=ú!=cCst|ƒSr)rr#rrrraszMatcher.parse_requirementcCsÒ|jdkrtdƒ‚| ¡|_}| |¡}|s:td|ƒ‚|j|_|j ¡|_g}|jrÄ|jD]d\}}| 	d¡r¢|dkr„td|ƒ‚|dd…d}}| |¡n| |¡d}}| 
|||f¡q^t|ƒ|_dS)	NzPlease specify a version classz
Not valid: %rz.*)rHrKz#'.*' not allowed for %r constraintséþÿÿÿTF)
Ú
version_classÚ
ValueErrorrrrÚnameÚlowerÚkeyZconstraintsÚendswithÚappendrr)rrÚrZclistÚopZvnÚprefixrrrr ds*


ÿzMatcher.__init__cCsxt|tƒr| |¡}|jD]X\}}}|j |¡}t|tƒrDt||ƒ}|s`d||jjf}t	|ƒ‚||||ƒsdSqdS)zÉ
        Check if the provided version matches the constraints.

        :param version: The version to match against this instance.
        :type version: String or :class:`Version` instance.
        z%r not implemented for %sFT)
rrrMrÚ
_operatorsÚgetÚgetattrr7rr")rÚversionÚoperatorÚ
constraintrVÚfÚmsgrrrÚmatch�s




ÿz
Matcher.matchcCs6d}t|jƒdkr2|jdddkr2|jdd}|S)Nrr)rHrI)rr)rÚresultrrrÚ
exact_version–s zMatcher.exact_versioncCs0t|ƒt|ƒks|j|jkr,td||fƒ‚dS)Nzcannot compare %s and %s)r$rOr%r&rrrr(�szMatcher._check_compatiblecCs"| |¡|j|jko |j|jkSr))r(rQrr&rrrr+¡s
zMatcher.__eq__cCs| |¡Sr)r,r&rrrr-¥szMatcher.__ne__cCst|jƒt|jƒSr))r3rQrr4rrrr5©szMatcher.__hash__cCsd|jj|jfS)Nz%s(%r)r6r4rrrr8¬szMatcher.__repr__cCs|jSr)r9r4rrrr:¯szMatcher.__str__)rrrrMrWrr r_r<rar(r+r-r5r8r:rrrrr=Os*÷
r=zk^v?(\d+!)?(\d+(\.\d+)*)((a|b|c|rc)(\d+))?(\.(post)(\d+))?(\.(dev)(\d+))?(\+([a-zA-Z\d]+(\.[a-zA-Z\d]+)?))?$cCs²| ¡}t |¡}|s"td|ƒ‚| ¡}tdd„|d d¡Dƒƒ}t|ƒdkrl|ddkrl|dd…}qF|dszd}nt|dƒ}|dd	…}|d
d…}|dd
…}|d}|dkrÀd}n|dt|dƒf}|dkrâd}n|dt|dƒf}|dk�rd}n|dt|dƒf}|dk�r*d}nHg}	| d¡D]0}
|
 	¡�rTdt|
ƒf}
nd|
f}
|	 
|
¡�q8t|	ƒ}|�sŽ|�sŠ|�rŠd}nd}|�s˜d}|�s¢d}||||||fS)NzNot a valid version: %scss|]}t|ƒVqdSr)©Úint©Ú.0r?rrrÚ	¾sz_pep_440_key..rÚ.éÿÿÿÿréééé	é
éé
)NNr)Úarh)Úz)Ú_)Úfinal)rÚPEP440_VERSION_REr_rÚgroupsrÚsplitrrcÚisdigitrS)rÚmruZnumsZepochÚpreZpostÚdevZlocalrÚpartrrrÚ_pep_440_key¸sT



r|c@s6eZdZdZdd„ZedddddgƒZed	d
„ƒZdS)raIA rational version.

    Good:
        1.2         # equivalent to "1.2.0"
        1.2.0
        1.2a1
        1.2.3a2
        1.2.3b1
        1.2.3c1
        1.2.3.4
        TODO: fill this out

    Bad:
        1           # minimum two numbers
        1.2a        # release level must have a release serial
        1.2.3b
    cCs<t|ƒ}t |¡}| ¡}tdd„|d d¡Dƒƒ|_|S)Ncss|]}t|ƒVqdSr)rbrdrrrrfsz*NormalizedVersion.parse..rrg)Ú_normalized_keyrtr_rurrvÚ_release_clause)rrr`rxrurrrr
s

zNormalizedVersion.parserpÚbr@Úrcrzcst‡fdd„ˆjDƒƒS)Nc3s |]}|r|dˆjkVqdS)rN)ÚPREREL_TAGS)reÚtr4rrrfsz2NormalizedVersion.is_prerelease..)Úanyrr4rr4rr;szNormalizedVersion.is_prereleaseN)	rrrrrÚsetr�r<r;rrrrrøs
cCs>t|ƒ}t|ƒ}||krdS| |¡s*dSt|ƒ}||dkS)NTFrg)ÚstrÚ
startswithr)ÚxÚyÚnrrrÚ
_match_prefixs
rŠc	@sneZdZeZddddddddd	œZd
d„Zdd
„Zdd„Zdd„Z	dd„Z
dd„Zdd„Zdd„Z
dd„ZdS)rÚ_match_compatibleÚ	_match_ltÚ	_match_gtÚ	_match_leÚ	_match_geÚ	_match_eqÚ_match_arbitraryÚ	_match_ne)rJrDrErFrGrHrIrKcCsV|rd|ko|jd}n|jdo,|jd}|rN|j dd¡d}| |¡}||fS)Nú+rhrr)rrrvrM)rrZr\rVZstrip_localrrrrÚ
_adjust_local6s
zNormalizedMatcher._adjust_localcCsD| |||¡\}}||krdS|j}d dd„|Dƒ¡}t||ƒS)NFrgcSsg|]}t|ƒ‘qSr©r…©reÚirrrÚ
Isz/NormalizedMatcher._match_lt..©r”r~ÚjoinrŠ©rrZr\rVZrelease_clauseZpfxrrrrŒDszNormalizedMatcher._match_ltcCsD| |||¡\}}||krdS|j}d dd„|Dƒ¡}t||ƒS)NFrgcSsg|]}t|ƒ‘qSrr•r–rrrr˜Qsz/NormalizedMatcher._match_gt..r™r›rrrr�LszNormalizedMatcher._match_gtcCs| |||¡\}}||kSr)©r”©rrZr\rVrrrrŽTszNormalizedMatcher._match_lecCs| |||¡\}}||kSr)rœr�rrrr�XszNormalizedMatcher._match_gecCs.| |||¡\}}|s ||k}n
t||ƒ}|Sr)©r”rŠ©rrZr\rVr`rrrr�\s


zNormalizedMatcher._match_eqcCst|ƒt|ƒkSr)r•r�rrrr‘dsz"NormalizedMatcher._match_arbitrarycCs0| |||¡\}}|s ||k}nt||ƒ}|Sr)ržrŸrrrr’gs

zNormalizedMatcher._match_necCsf| |||¡\}}||krdS||kr*dS|j}t|ƒdkrH|dd…}d dd„|Dƒ¡}t||ƒS)NTFrrhrgcSsg|]}t|ƒ‘qSrr•r–rrrr˜zsz7NormalizedMatcher._match_compatible..)r”r~rršrŠr›rrrr‹osz#NormalizedMatcher._match_compatibleN)rrrrrMrWr”rŒr�rŽr�r�r‘r’r‹rrrrr's&øz[.+-]$Úz^[.](\d)z0.\1z^[.-]z
^\((.*)\)$ú\1z^v(ersion)?\s*(\d+)z\2z^r(ev)?\s*(\d+)z[.]{2,}rgz\b(alfa|apha)\bÚalphaz\b(pre-alpha|prealpha)\bz	pre.alphaz	\(beta\)$Úbetaz
^[:~._+-]+z
[,*")([\]]z[~:+_ -]z\.$z
(\d+(\.\d+)*)cCsL| ¡ ¡}tD]\}}| ||¡}q|s.d}t |¡}|sFd}|}nª| ¡d d¡}dd„|Dƒ}t|ƒdkr~| 	d¡qft|ƒdkrœ|| 
¡d…}n8d dd„|dd…Dƒ¡|| 
¡d…}|dd…}d d	d„|Dƒ¡}| ¡}|�rtD]\}}| ||¡}qú|�s|}nd
|k�r*dnd}|||}t
|ƒ�sHd}|S)
z€
    Try to suggest a semantic form for a version for which
    _suggest_normalized_version couldn't come up with anything.
    z0.0.0rrgcSsg|]}t|ƒ‘qSrrbr–rrrr˜ªsz-_suggest_semantic_version..éNcSsg|]}t|ƒ‘qSrr•r–rrrr˜°scSsg|]}t|ƒ‘qSrr•r–rrrr˜²srzú-r“)rrPÚ
_REPLACEMENTSÚsubÚ_NUMERIC_PREFIXr_rurvrrSÚendršÚ_SUFFIX_REPLACEMENTSÚ	is_semver)rr`ZpatÚreplrxrVÚsuffixÚseprrrÚ_suggest_semantic_version–s:
,
r¯cCshzt|ƒ|WStk
r"YnX| ¡}dD]\}}| ||¡}q0t dd|¡}t dd|¡}t dd|¡}t dd	|¡}t d
d|¡}| d¡r¢|d
d…}t dd|¡}t dd|¡}t dd|¡}t dd|¡}t dd|¡}t dd|¡}t dd|¡}t dd|¡}t dd|¡}t dd|¡}t dd |¡}zt|ƒWntk
�rbd}YnX|S)!aèSuggest a normalized version close to the given version string.

    If you have a version string that isn't rational (i.e. NormalizedVersion
    doesn't like it) then you might be able to get an equivalent (or close)
    rational version from this function.

    This does a number of simple normalizations to the given string, based
    on observation of versions currently in use on PyPI. Given a dump of
    those version during PyCon 2009, 4287 of them:
    - 2312 (53.93%) match NormalizedVersion without change
      with the automatic suggestion
    - 3474 (81.04%) match when using this suggestion method

    @param s {str} An irrational version string.
    @returns A rational version string, or None, if couldn't determine one.
    ))z-alpharp)z-betar)r¢rp)r£r)r€r@)z-finalr )z-prer@)z-releaser )z.releaser )z-stabler )r“rg)rrrg)ú r )z.finalr )rsr zpre$Zpre0zdev$Zdev0z([abc]|rc)[\-\.](\d+)$z\1\2z[\-\.](dev)[\-\.]?r?(\d+)$z.\1\2z[.~]?([abc])\.?r¡r?rNz\b0+(\d+)(?!\d)z(\d+[abc])$z\g<1>0z\.?(dev-r|dev\.r)\.?(\d+)$z.dev\2z-(a|b|c)(\d+)$z[\.\-](dev|devel)$z.dev0z(?![\.\-])dev$z(final|stable)$r z\.?(r|-|-r)\.?(\d+)$z.post\2z\.?(dev|git|bzr)\.?(\d+)$z\.?(pre|preview|-c)(\d+)$zc\g<2>zp(\d+)$z.post\1)r}rrPÚreplaceÚrer§r†)rZrsZorigr¬rrrÚ_suggest_normalized_versionÄs>
	
r³z([a-z]+|\d+|[\.-])r@zfinal-ú@)ryZpreviewr¥r€rzr rgcCsrdd„}g}||ƒD]T}| d¡r^|dkrD|rD|ddkrD| ¡q*|r^|ddkr^| ¡qD| |¡qt|ƒS)NcSstg}t | ¡¡D]R}t ||¡}|rd|dd…krBdkrRnn| d¡}nd|}| |¡q| d¡|S)NÚ0rÚ9éÚ*ú*final)Ú
_VERSION_PARTrvrPÚ_VERSION_REPLACErXÚzfillrS)rr`rArrrÚ	get_partsCs 
z_legacy_key..get_partsr¸r¹rhz*final-Z00000000)r†ÚpoprSr)rr½r`rArrrÚ_legacy_keyBs



r¿c@s eZdZdd„Zedd„ƒZdS)rcCst|ƒSr))r¿r#rrrr]szLegacyVersion.parsecCs8d}|jD](}t|tƒr
| d¡r
|dkr
d}q4q
|S)NFr¸r¹T)rrrr†)rr`r‡rrrr;`s
ÿzLegacyVersion.is_prereleaseN©rrrrr<r;rrrrr\sc@s4eZdZeZeejƒZded<e 	d¡Z
dd„ZdS)r	r‹rJz^(\d+(\.\d+)*)cCs`||krdS|j t|ƒ¡}|s2t d||¡dS| ¡d}d|krV| dd¡d}t||ƒS)NFzACannot compute compatible match for version %s  and constraint %sTrrgr)Ú
numeric_rer_r…ÚloggerZwarningruÚrsplitrŠ)rrZr\rVrxrrrrr‹ssÿzLegacyMatcher._match_compatibleN)rrrrrMÚdictr=rWr²ÚcompilerÁr‹rrrrr	ks


zN^(\d+)\.(\d+)\.(\d+)(-[a-z0-9]+(\.[a-z0-9-]+)*)?(\+[a-z0-9]+(\.[a-z0-9-]+)*)?$cCs
t |¡Sr))Ú
_SEMVER_REr_)rrrrr«‰sr«c	Csndd„}t|ƒ}|st|ƒ‚| ¡}dd„|dd…Dƒ\}}}||ddƒ||ddƒ}}|||f||fS)	NcSs8|dkr|f}n$|dd… d¡}tdd„|Dƒƒ}|S)NrrgcSs"g|]}| ¡r| d¡n|‘qS)r·)rwr¼)rerArrrr˜•sz5_semantic_key..make_tuple..)rvr)rZabsentr`rrrrÚ
make_tupleŽs
z!_semantic_key..make_tuplecSsg|]}t|ƒ‘qSrrbr–rrrr˜œsz!_semantic_key..r¤ú|ér¸)r«rru)	rrÇrxruÚmajorÚminorZpatchryZbuildrrrÚ
_semantic_key�s
rÌc@s eZdZdd„Zedd„ƒZdS)r
cCst|ƒSr))rÌr#rrrr£szSemanticVersion.parsecCs|jdddkS)NrrrÈ)rr4rrrr;¦szSemanticVersion.is_prereleaseNrÀrrrrr
¢sc@seZdZeZdS)rN)rrrr
rMrrrrr«sc@s6eZdZddd„Zdd„Zdd„Zdd	„Zd
d„ZdS)
Ú
VersionSchemeNcCs||_||_||_dSr))rQÚmatcherÚ	suggester)rrQrÎrÏrrrr °szVersionScheme.__init__cCs2z|j |¡d}Wntk
r,d}YnX|S©NTF)rÎrMr©rrr`rrrÚis_valid_versionµs
zVersionScheme.is_valid_versioncCs0z| |¡d}Wntk
r*d}YnX|SrÐ)rÎrrÑrrrÚis_valid_matcher½s

zVersionScheme.is_valid_matchercCs| d|¡S)z:
        Used for processing some metadata fields
        zdummy_name (%s))rÓr#rrrÚis_valid_constraint_listÅsz&VersionScheme.is_valid_constraint_listcCs|jdkrd}n
| |¡}|Sr))rÏrÑrrrÚsuggestËs

zVersionScheme.suggest)N)rrrr rÒrÓrÔrÕrrrrrͯs

rÍcCs|Sr)rr#rrrrBÕrCrB)Ú
normalizedÚlegacyZsemanticrÖÚdefaultcCs|tkrtd|ƒ‚t|S)Nzunknown scheme name: %r)Ú_SCHEMESrN)rOrrrr
Ýs)*rZloggingr²ÚcompatrÚutilrÚ__all__Z	getLoggerrrÂrNrÚobjectrr=rÅrtr|r}rrŠrr¦rªr¨r¯r³ÚIrºr»r¿rr	rÆr«rÌr
rrÍrÙr
rrrrÚs”ý
1d
=$Wÿõû
.rùþ	$ÿÿüPKÕ¶N]
u:Õ'Õ'Esite-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-38.pycnu„[µü¤U

ÀÒ.eÛ9ã@s¤dZddlZddlZddlZddlZddlZddlmZddlm	Z	ddl
mZdgZe 
e¡Ze dej¡Ze d	ejejB¡Zejdd
…ZGdd„deƒZdS)zu
Class representing the list of files in a distribution.

Equivalent to distutils.filelist, but fixes some problems.
éNé)ÚDistlibException)Úfsdecode©Úconvert_pathÚManifestz\\w*
z#.*?(?=
)|
(?=$)éc@szeZdZdZddd„Zdd„Zdd„Zd	d
„Zddd
„Zdd„Z	dd„Z
dd„Zddd„Zd dd„Z
d!dd„Zdd„ZdS)"rz~A list of files built by on exploring the filesystem and filtered by
    applying various patterns to what we find there.
    NcCs>tj tj |pt ¡¡¡|_|jtj|_d|_t	ƒ|_
dS)zd
        Initialise an instance.

        :param base: The base directory to explore under.
        N)ÚosÚpathÚabspathÚnormpathÚgetcwdÚbaseÚsepÚprefixÚallfilesÚsetÚfiles)Úselfr©rú@/usr/lib/python3.8/site-packages/pip/_vendor/distlib/manifest.pyÚ__init__*szManifest.__init__cCs¨ddlm}m}m}g|_}|j}|g}|j}|j}|r¤|ƒ}t 	|¡}	|	D]R}
tj
 ||
¡}t |¡}|j}
||
ƒrˆ| t
|ƒ¡qN||
ƒrN||
ƒsN||ƒqNq6dS)zmFind all files under the base and set ``allfiles`` to the absolute
        pathnames of files found.
        r)ÚS_ISREGÚS_ISDIRÚS_ISLNKN)ÚstatrrrrrÚpopÚappendr	Úlistdirr
ÚjoinÚst_moder)rrrrrÚrootÚstackrÚpushÚnamesÚnameÚfullnamerÚmoderrrÚfindall9s"


zManifest.findallcCs4| |j¡stj |j|¡}|j tj |¡¡dS)zz
        Add a file to the manifest.

        :param item: The pathname to add. This can be relative to the base.
        N)	Ú
startswithrr	r
rrrÚaddr)rÚitemrrrr*TszManifest.addcCs|D]}| |¡qdS)z†
        Add a list of files to the manifest.

        :param items: The pathnames to add. These can be relative to the base.
        N)r*)rÚitemsr+rrrÚadd_many^szManifest.add_manyFcsb‡‡fdd„‰tˆjƒ}|rFtƒ}|D]}ˆ|tj |¡ƒq&||O}dd„tdd„|DƒƒDƒS)z8
        Return sorted files in directory order
        csJ| |¡t d|¡|ˆjkrFtj |¡\}}|dks.add_dircSsg|]}tjj|Ž‘qSr)r	r
r)Ú.0Z
path_tuplerrrÚ
zsz#Manifest.sorted..css|]}tj |¡VqdS)N)r	r
r2)r:r
rrrÚ	{sz"Manifest.sorted..)rrr	r
ÚdirnameÚsorted)rZwantdirsÚresultr4Úfrr8rr>gs
ÿzManifest.sortedcCstƒ|_g|_dS)zClear all collected files.N)rrr)rrrrÚclear}szManifest.clearcCsj| |¡\}}}}|dkrB|D]}|j|dd�st d|¡q�n$|dkrf|D]}|j|dd�}qN�n|dkr”|D]}|j|dd�srt d|¡qrnÒ|d	kr¶|D]}|j|dd�}q n°|d
kræ|D] }|j||d�sÂt d||¡qÂn€|d
k�r
|D]}|j||d�}qôn\|dk�r2|jd|d��sft d|¡n4|dk�rZ|jd|d��sft d|¡ntd|ƒ‚dS)av
        Process a directive which either adds some files from ``allfiles`` to
        ``files``, or removes some files from ``files``.

        :param directive: The directive to process. This should be in a format
                     compatible with distutils ``MANIFEST.in`` files:

                     http://docs.python.org/distutils/sourcedist.html#commands
        ÚincludeT)Úanchorzno files found matching %rÚexcludeúglobal-includeFz3no files found matching %r anywhere in distributionúglobal-excludeúrecursive-include)rz-no files found matching %r under directory %rúrecursive-excludeÚgraftNz no directories found matching %rÚprunez4no previously-included directories found matching %rzinvalid action %r)Ú_parse_directiveÚ_include_patternr0ZwarningÚ_exclude_patternr)rÚ	directiveÚactionÚpatternsÚthedirZ
dirpatternÚpatternÚfoundrrrÚprocess_directive‚sPÿÿ

ÿ
ÿÿzManifest.process_directivecCs| ¡}t|ƒdkr,|ddkr,| dd¡|d}d}}}|dkrxt|ƒdkr`td|ƒ‚d	d
„|dd…Dƒ}n~|dkr¼t|ƒdkr˜td
|ƒ‚t|dƒ}dd
„|dd…Dƒ}n:|dkrêt|ƒdkrÜtd|ƒ‚t|dƒ}ntd|ƒ‚||||fS)zŸ
        Validate a directive.
        :param directive: The directive to validate.
        :return: A tuple of action, patterns, thedir, dir_patterns
        rr)rBrDrErFrGrHrIrJrBN)rBrDrErFrz$%r expects   ...cSsg|]}t|ƒ‘qSrr©r:Zwordrrrr;êsz-Manifest._parse_directive..)rGrHéz*%r expects    ...cSsg|]}t|ƒ‘qSrrrUrrrr;òs)rIrJz!%r expects a single zunknown action %r)r2ÚlenÚinsertrr)rrNZwordsrOrPrQZdir_patternrrrrKÑs4ÿÿÿzManifest._parse_directiveTcCsPd}| ||||¡}|jdkr&| ¡|jD]}| |¡r,|j |¡d}q,|S)a…Select strings (presumably filenames) from 'self.files' that
        match 'pattern', a Unix-style wildcard (glob) pattern.

        Patterns are not quite the same as implemented by the 'fnmatch'
        module: '*' and '?'  match non-special characters, where "special"
        is platform-dependent: slash on Unix; colon, slash, and backslash on
        DOS/Windows; and colon on Mac OS.

        If 'anchor' is true (the default), then the pattern match is more
        stringent: "*.py" will match "foo.py" but not "foo/bar.py".  If
        'anchor' is false, both of these will match.

        If 'prefix' is supplied, then only filenames starting with 'prefix'
        (itself a pattern) and ending with 'pattern', with anything in between
        them, will match.  'anchor' is ignored in this case.

        If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and
        'pattern' is assumed to be either a string containing a regex or a
        regex object -- no translation is done, the regex is just compiled
        and used as-is.

        Selected strings will be added to self.files.

        Return True if files are found.
        FNT)Ú_translate_patternrr(Úsearchrr*)rrRrCrÚis_regexrSÚ
pattern_rer%rrrrLs


zManifest._include_patterncCsBd}| ||||¡}t|jƒD]}| |¡r|j |¡d}q|S)atRemove strings (presumably filenames) from 'files' that match
        'pattern'.

        Other parameters are the same as for 'include_pattern()', above.
        The list 'self.files' is modified in place. Return True if files are
        found.

        This API is public to allow e.g. exclusion of SCM subdirs, e.g. when
        packaging source distributions
        FT)rYÚlistrrZÚremove)rrRrCrr[rSr\r@rrrrM)s
zManifest._exclude_patternc
Cs¨|rt|tƒrt |¡S|Stdkr:| d¡ d¡\}}}|rj| |¡}tdkrn| |¡rd| |¡snt	‚nd}t 
tj 
|jd¡¡}	|dk	�rftdkrº| d¡}
| |¡dt|
ƒ…}n>| |¡}| |¡rØ| |¡sÜt	‚|t|ƒt|ƒt|ƒ…}tj}tjdk�rd}tdk�r4d|	| 
|d|f¡}n0|t|ƒt|ƒt|ƒ…}d	||	||||f}n8|�ržtdk�r„d|	|}nd
||	|t|ƒd…f}t |¡S)aTranslate a shell-like wildcard pattern to a compiled regular
        expression.

        Return the compiled regex.  If 'is_regex' true,
        then 'pattern' is directly compiled to a regex (if it's a string)
        or just returned as-is (assumes it's a regex object).
        )rVrr7r.Nú\z\\ú^z.*z%s%s%s%s.*%s%sz%s%s%s)Ú
isinstanceÚstrÚreÚcompileÚ_PYTHON_VERSIONÚ_glob_to_reÚ	partitionr)Úendswithr3Úescaper	r
rrrWr)
rrRrCrr[Ústartr7Úendr\rZ
empty_patternZ	prefix_rerrrrrY=sH	






ÿ

ÿ
zManifest._translate_patterncCs8t |¡}tj}tjdkrd}d|}t d||¡}|S)z÷Translate a shell-like glob pattern to a regular expression.

        Return a string containing the regex.  Differs from
        'fnmatch.translate()' in that '*' does not match "special characters"
        (which are platform-specific).
        r_z\\\\z\1[^%s]z((?rArTrKrLrMrYrfrrrrr%s&

	
O/ÿ
)ÿ
ÿ
7)rrrlZloggingr	rcÚsysr.rÚcompatrÚutilrÚ__all__Z	getLoggerror0rdÚMZ_COLLAPSE_PATTERNÚSZ_COMMENTED_LINEÚversion_inforeÚobjectrrrrrÚs
PKÕ¶N]2‡õFT¤T¤Esite-packages/pip/_vendor/distlib/__pycache__/database.cpython-38.pycnu„[µü¤U

ÀÒ.eUÇã@s”dZddlmZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlm
Z
mZddlmZddlmZmZddlmZmZmZmZdd	lmZmZmZmZmZmZm Z d
ddd
dgZ!e "e#¡Z$dZ%dZ&deddde%dfZ'dZ(Gdd„de)ƒZ*Gdd„de)ƒZ+Gdd
„d
e)ƒZ,Gdd„de,ƒZ-Gdd„de-ƒZ.Gdd
„d
e-ƒZ/e.Z0e/Z1Gdd„de)ƒZ2d)d!d"„Z3d#d$„Z4d%d&„Z5d'd(„Z6dS)*zPEP 376 implementation.é)Úunicode_literalsNé)ÚDistlibExceptionÚ	resources)ÚStringIO)Ú
get_schemeÚUnsupportedVersionError)ÚMetadataÚMETADATA_FILENAMEÚWHEEL_METADATA_FILENAMEÚLEGACY_METADATA_FILENAME)Úparse_requirementÚcached_propertyÚparse_name_and_versionÚread_exportsÚ
write_exportsÚ	CSVReaderÚ	CSVWriterÚDistributionÚBaseInstalledDistributionÚInstalledDistributionÚEggInfoDistributionÚDistributionPathzpydist-exports.jsonzpydist-commands.jsonZ	INSTALLERÚRECORDÚ	REQUESTEDÚ	RESOURCESÚSHAREDz
.dist-infoc@s(eZdZdZdd„Zdd„Zdd„ZdS)	Ú_CachezL
    A simple cache mapping names and .dist-info paths to distributions
    cCsi|_i|_d|_dS)zZ
        Initialise an instance. There is normally one for each DistributionPath.
        FN)ÚnameÚpathÚ	generated©Úself©r#ú@/usr/lib/python3.8/site-packages/pip/_vendor/distlib/database.pyÚ__init__1sz_Cache.__init__cCs|j ¡|j ¡d|_dS)zC
        Clear the cache, setting it to its initial state.
        FN)rÚclearrr r!r#r#r$r&9s

z_Cache.clearcCs2|j|jkr.||j|j<|j |jg¡ |¡dS)z`
        Add a distribution to the cache.
        :param dist: The distribution to add.
        N)rrÚ
setdefaultÚkeyÚappend©r"Údistr#r#r$ÚaddAsz
_Cache.addN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r%r&r,r#r#r#r$r-src@s„eZdZdZddd„Zdd„Zdd	„ZeeeƒZd
d„Z	dd
„Z
dd„Zedd„ƒZ
dd„Zdd„Zddd„Zdd„Zddd„ZdS)rzU
    Represents a set of distributions installed on a path (typically sys.path).
    NFcCsD|dkrtj}||_d|_||_tƒ|_tƒ|_d|_tdƒ|_	dS)a 
        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.
        NTÚdefault)
ÚsysrÚ
_include_distÚ_include_eggrÚ_cacheÚ
_cache_eggÚ_cache_enabledrÚ_scheme)r"rZinclude_eggr#r#r$r%Os	zDistributionPath.__init__cCs|jS©N©r7r!r#r#r$Ú_get_cache_enabledcsz#DistributionPath._get_cache_enabledcCs
||_dSr9r:)r"Úvaluer#r#r$Ú_set_cache_enabledfsz#DistributionPath._set_cache_enabledcCs|j ¡|j ¡dS)z,
        Clears the internal cache.
        N)r5r&r6r!r#r#r$Úclear_cacheks
zDistributionPath.clear_cachec
csDtƒ}|jD�]0}t |¡}|dkr&q| d¡}|r|js| ¡|jj ¡D]
}|Vq0|jrZ|jj ¡D]
}|VqNdS)a5
        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)r7r\r^r5rÚvaluesr4r6r*r#r#r$Úget_distributionsÈs	
z"DistributionPath.get_distributionscCs€d}| ¡}|js4| ¡D]}|j|kr|}q|qnH| ¡||jjkrZ|jj|d}n"|jr|||jjkr||jj|d}|S)a=
        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``
        Nr)	Úlowerr7r\r(r^r5rr4r6)r"rÚresultr+r#r#r$Úget_distributionÞs

z!DistributionPath.get_distributionc	csÈd}|dk	rJz|j d||f¡}Wn$tk
rHtd||fƒ‚YnX| ¡D]p}t|dƒsnt d|¡qR|j}|D]H}t	|ƒ\}}|dkr¤||krÀ|VqRqx||krx| 
|¡rx|VqRqxqRdS)a
        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
        Nú%s (%s)zinvalid name or version: %r, %rÚprovideszNo "provides": %s)r8ÚmatcherÚ
ValueErrorrrfÚhasattrrSrTrkrÚmatch)	r"rrcrlr+ÚprovidedÚpÚp_nameÚp_verr#r#r$Úprovides_distributionøs*ÿ
z&DistributionPath.provides_distributioncCs(| |¡}|dkrtd|ƒ‚| |¡S)z5
        Return the path to a resource file.
        Nzno distribution named %r found)riÚLookupErrorÚget_resource_path)r"rÚ
relative_pathr+r#r#r$Ú
get_file_path!s
zDistributionPath.get_file_pathccsX| ¡D]J}|j}||kr||}|dk	r>||krR||Vq| ¡D]
}|VqFqdS)zÙ
        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)rfÚexportsre)r"Úcategoryrr+rYÚdÚvr#r#r$Úget_exported_entries*sz%DistributionPath.get_exported_entries)NF)N)N)r-r.r/r0r%r;r=ÚpropertyZ
cache_enabledr>r\r^Úclassmethodrdrfrirtrxr}r#r#r#r$rKs

,

)	c@s¬eZdZdZdZdZdd„Zedd„ƒZeZ	edd„ƒZ
ed	d
„ƒZdd„Zed
d„ƒZ
edd„ƒZedd„ƒZedd„ƒZedd„ƒZdd„Zdd„Zdd„Zdd„ZdS) rzª
    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.
    FcCsL||_|j|_|j ¡|_|j|_d|_d|_d|_d|_t	ƒ|_
i|_dS)zŠ
        Initialise an instance.
        :param metadata: The instance of :class:`Metadata` describing this
        distribution.
        N)rDrrgr(rcZlocatorÚdigestÚextrasÚcontextrHZ
download_urlsZdigests)r"rDr#r#r$r%OszDistribution.__init__cCs|jjS)zH
        The source archive download URL for this distribution.
        )rDÚ
source_urlr!r#r#r$rƒ`szDistribution.source_urlcCsd|j|jfS)zX
        A utility property which displays the name and version in parentheses.
        rj©rrcr!r#r#r$Úname_and_versioniszDistribution.name_and_versioncCs.|jj}d|j|jf}||kr*| |¡|S)z�
        A set of distribution names and versions provided by this distribution.
        :return: A set of "name (version)" strings.
        rj)rDrkrrcr))r"ZplistÚsr#r#r$rkps

zDistribution.providescCs8|j}t d| ¡¡t||ƒ}t|j||j|jd�ƒS)Nz%Getting requirements from metadata %r)r�rE)	rDrSrTZtodictÚgetattrrHZget_requirementsr�r‚)r"Zreq_attrÚmdZreqtsr#r#r$Ú_get_requirements|s
ÿzDistribution._get_requirementscCs
| d¡S)NÚrun_requires©r‰r!r#r#r$rŠƒszDistribution.run_requirescCs
| d¡S)NÚ
meta_requiresr‹r!r#r#r$rŒ‡szDistribution.meta_requirescCs
| d¡S)NÚbuild_requiresr‹r!r#r#r$r�‹szDistribution.build_requirescCs
| d¡S)NÚ
test_requiresr‹r!r#r#r$rŽ�szDistribution.test_requirescCs
| d¡S)NÚdev_requiresr‹r!r#r#r$r�“szDistribution.dev_requiresc
	Cs¶t|ƒ}t|jjƒ}z| |j¡}Wn6tk
rZt d|¡| 	¡d}| |¡}YnX|j
}d}|jD]D}t|ƒ\}}	||kr†qlz| 
|	¡}Wq²Wqltk
r®YqlXql|S)z¿
        Say if this instance matches (fulfills) a requirement.
        :param req: The requirement to match.
        :rtype req: str
        :return: True if it matches, else False.
        ú+could not read version %r - using name onlyrF)r
rrDrCrlÚrequirementrrSÚwarningÚsplitr(rkrro)
r"ÚreqrYrCrlrrhrqrrrsr#r#r$Úmatches_requirement—s,	ÿ


z Distribution.matches_requirementcCs(|jrd|j}nd}d|j|j|fS)zC
        Return a textual representation of this instance,
        z [%s]r?z)rƒrrc)r"Úsuffixr#r#r$Ú__repr__¹szDistribution.__repr__cCs>t|ƒt|ƒk	rd}n$|j|jko8|j|jko8|j|jk}|S)a<
        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.
        F)Útyperrcrƒ)r"Úotherrhr#r#r$Ú__eq__Ãs
ÿ
þzDistribution.__eq__cCst|jƒt|jƒt|jƒS)zH
        Compute hash in a way which matches the equality test.
        )Úhashrrcrƒr!r#r#r$Ú__hash__ÓszDistribution.__hash__N)r-r.r/r0Zbuild_time_dependencyÚ	requestedr%r~rƒZdownload_urlr…rkr‰rŠrŒr�rŽr�r•r—ršrœr#r#r#r$r=s4







"
cs0eZdZdZdZd‡fdd„	Zddd„Z‡ZS)	rz]
    This is the base class for installed distributions (whether PEP 376 or
    legacy).
    Ncs tt|ƒ |¡||_||_dS)a
        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)Úsuperrr%rÚ	dist_path)r"rDrrE©Ú	__class__r#r$r%âsz"BaseInstalledDistribution.__init__cCsd|dkr|j}|dkr"tj}d}ntt|ƒ}d|j}||ƒ ¡}t |¡ d¡ d¡}d||fS)a”
        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
        Nr?z%s=ó=Úasciiú%s%s)	ÚhasherÚhashlibÚmd5r‡r€Úbase64Zurlsafe_b64encodeÚrstripÚdecode)r"Údatar¥Úprefixr€r#r#r$Úget_hashñs

z"BaseInstalledDistribution.get_hash)N)N)r-r.r/r0r¥r%r­Ú
__classcell__r#r#r r$rÚscs¸eZdZdZdZd'‡fdd„	Zdd„Zdd	„Zd
d„Ze	dd
„ƒZ
dd„Zdd„Zdd„Z
dd„Zd(dd„Zdd„Ze	dd„ƒZd)dd„Zdd „Zd!d"„Zd#d$„Zd%d&„ZejZ‡ZS)*ra
    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).
    Zsha256Nc
	sJg|_t |¡|_}|dkr*td|ƒ‚|rP|jrP||jjkrP|jj|j}nt|dkrÄ| 	t
¡}|dkrt| 	t¡}|dkr†| 	d¡}|dkržtdt
|fƒ‚t 
| ¡¡�}t|dd�}W5QRXtt|ƒ |||¡|rî|jrî|j |¡| 	d¡}|dk	|_tj |d¡}tj |¡�rFt|dƒ�}| ¡}	W5QRX|	 ¡|_dS)	Nzfinder unavailable for %sZMETADATAzno %s found in %sr@rArú
top_level.txtÚrb)ÚmodulesrrIrXrmr7r5rrDrJr
rrPrQrRr	ržrr%r,r�ÚosrOÚexistsÚopenÚreadÚ
splitlines)
r"rrDrErXrYr[rqÚfr«r r#r$r%s8


ÿ


zInstalledDistribution.__init__cCsd|j|j|jfS)Nz#©rrcrr!r#r#r$r—=s
ÿzInstalledDistribution.__repr__cCsd|j|jfS©Nz%s %sr„r!r#r#r$Ú__str__AszInstalledDistribution.__str__c

Cs‚g}| d¡}t | ¡¡�\}t|d��F}|D]:}dd„tt|ƒdƒDƒ}||\}}}	| |||	f¡q.W5QRXW5QRX|S)a"
        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).
        r©r[cSsg|]}d‘qSr9r#)Ú.0Úir#r#r$Ú
Ssz6InstalledDistribution._get_records..é)Úget_distinfo_resourcerPrQrRrÚrangeÚlenr))
r"ÚresultsrYr[Z
record_readerÚrowÚmissingrÚchecksumÚsizer#r#r$Ú_get_recordsDs
&z"InstalledDistribution._get_recordscCsi}| t¡}|r| ¡}|S)a
        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.
        )rÀÚEXPORTS_FILENAMEr)r"rhrYr#r#r$ry[s

zInstalledDistribution.exportsc	Cs8i}| t¡}|r4t | ¡¡�}t|ƒ}W5QRX|S)zý
        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.
        )rÀrÉrPrQrRr)r"rhrYr[r#r#r$ris
z"InstalledDistribution.read_exportsc	Cs.| t¡}t|dƒ�}t||ƒW5QRXdS)a
        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.
        ÚwN)Úget_distinfo_filerÉr´r)r"ryZrfr·r#r#r$rxs
z#InstalledDistribution.write_exportscCs€| d¡}t | ¡¡�R}t|d��<}|D]0\}}||kr*|W5QR£W5QR£Sq*W5QRXW5QRXtd|ƒ‚dS)aW
        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.
        rr»z3no resource file with relative path %r is installedN)rÀrPrQrRrÚKeyError)r"rwrYr[Zresources_readerÚrelativeZdestinationr#r#r$rvƒs
6ÿz'InstalledDistribution.get_resource_pathccs| ¡D]
}|VqdS)zª
        Iterates over the ``RECORD`` entries and returns a tuple
        ``(path, hash, size)`` for each line.

        :returns: iterator of (path, hash, size)
        N)rÈ)r"rhr#r#r$Úlist_installed_files—sz*InstalledDistribution.list_installed_filesFcCs(tj |d¡}tj |j¡}| |¡}tj |d¡}| d¡}t d|¡|rRdSt|ƒ�Ä}|D]Ž}tj 	|¡sz| 
d¡r„d}	}
n4dtj |¡}
t|dƒ�}| 
| ¡¡}	W5QRX| |¡sÐ|rÞ| |¡rÞtj ||¡}| ||	|
f¡q`| |¡�r
tj ||¡}| |ddf¡W5QRX|S)zÖ
        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.
        r?rúcreating %sN©z.pycz.pyoz%dr°)r²rrOÚdirnameÚ
startswithrËrSÚinforÚisdirrLÚgetsizer´r­rµÚrelpathZwriterow)r"Úpathsr¬Údry_runÚbaseZbase_under_prefixÚrecord_pathÚwriterrÚ
hash_valuerÇÚfpr#r#r$Úwrite_installed_files¡s0



ÿz+InstalledDistribution.write_installed_filesc
Csg}tj |j¡}| d¡}| ¡D]î\}}}tj |¡sHtj ||¡}||krRq$tj |¡sr| |dddf¡q$tj 	|¡r$t
tj |¡ƒ}|r®||kr®| |d||f¡q$|r$d|krÌ| dd¡d}nd	}t
|d
ƒ�2}	| |	 ¡|¡}
|
|k�r| |d||
f¡W5QRXq$|S)á¨
        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.
        rr³TFrÇú=rrNr°r›)r²rrÑrËrÎÚisabsrOr³r)ÚisfileÚstrrÕr“r´r­rµ)r"Ú
mismatchesrÙrÚrrÜrÇZactual_sizer¥r·Zactual_hashr#r#r$Úcheck_installed_filesÄs.	

z+InstalledDistribution.check_installed_filesc	CsŠi}tj |jd¡}tj |¡r†tj|ddd��}| ¡ ¡}W5QRX|D]8}| dd¡\}}|dkr|| 	|g¡ 
|¡qL|||<qL|S)a 
        A dictionary of shared locations whose keys are in the set 'prefix',
        'purelib', 'platlib', 'scripts', 'headers', 'data' and 'namespace'.
        The corresponding value is the absolute path of that category for
        this distribution, and takes into account any paths selected by the
        user at installation time (e.g. via command-line arguments). In the
        case of the 'namespace' key, this would be a list of absolute paths
        for the roots of namespace packages in this distribution.

        The first time this property is accessed, the relevant information is
        read from the SHARED file in the .dist-info directory.
        rrYúutf-8©ÚencodingràrÚ	namespace)r²rrOrâÚcodecsr´rµr¶r“r'r))r"rhÚshared_pathr·ÚlinesÚliner(r<r#r#r$Úshared_locationsçs
z&InstalledDistribution.shared_locationsc		Cs¬tj |jd¡}t d|¡|r$dSg}dD].}||}tj ||¡r,| d||f¡q,| dd¡D]}| d|¡qhtj	|d	d
d��}| 
d |¡¡W5QRX|S)
aa
        Write shared location information to the SHARED file in .dist-info.
        :param paths: A dictionary as described in the documentation for
        :meth:`shared_locations`.
        :param dry_run: If True, the action is logged but no file is actually
                        written.
        :return: The path of the file written to.
        rrÏN)r¬ÚlibZheadersZscriptsr«z%s=%srér#znamespace=%srÊrærçÚ
)r²rrOrSrÓrÔr)Úgetrêr´Úwrite)	r"r×rØrërìr(rÚnsr·r#r#r$Úwrite_shared_locationss	z,InstalledDistribution.write_shared_locationscCsF|tkrtd||jfƒ‚t |j¡}|dkr.set_name_and_version)rrŸr7r6rDrrcÚ
_get_metadatar,ržrr%)r"rrErþrDr r#r$r%bs

zEggInfoDistribution.__init__c	sÐd}dd„‰‡fdd„}d}}| d¡rötj |¡r„tj |d¡}tj |d¡}t|dd	�}tj |d
¡}	tj |d¡}||	ƒ}npt |¡}
t|
 	d¡ 
d
¡ƒ}t|dd�}z,|
 	d¡}|
 	d¡ 
d¡}ˆ| 
d¡ƒ}Wntk
ròd}YnXnf| d¡�rPtj |¡�rBtj |d
¡}	||	ƒ}tj |d¡}tj |d¡}t|dd	�}ntd|ƒ‚|�rl| 
|¡|dk�r²|dk	�r²tj |¡�r²t|dƒ�}
|
 ¡ 
d¡}W5QRX|�s¾g}n| ¡}||_|S)NcSs¤g}| ¡}|D]Ž}| ¡}| d¡r6t d|¡q t|ƒ}|sPt d|¡q|jr`t d¡|jst| |j	¡qd 
dd„|jDƒ¡}| d|j	|f¡q|S)	z’Create a list of dependencies from a requires.txt file.

            *data*: the contents of a setuptools-produced requires.txt file.
            ú[z.Unexpected line: quitting requirement scan: %rz#Not recognised as a requirement: %rz4extra requirements in requires.txt are not supportedz, css|]}d|VqdS)r¤Nr#)r¼Úcr#r#r$Ú	‘szQEggInfoDistribution._get_metadata..parse_requires_data..rj)r¶ÚstriprÒrSr’r
r�Zconstraintsr)rrO)r«ÚreqsrìrírYZconsr#r#r$Úparse_requires_datazs(
ÿ
z>EggInfoDistribution._get_metadata..parse_requires_datac	sHg}z*t |dd¡�}ˆ| ¡ƒ}W5QRXWntk
rBYnX|S)z’Create a list of dependencies from a requires.txt file.

            *req_path*: the path to a setuptools-produced requires.txt file.
            rYræ)rêr´rµÚIOError)Úreq_pathrrÝ©rr#r$Úparse_requires_path•sz>EggInfoDistribution._get_metadata..parse_requires_pathrGzEGG-INFOzPKG-INFOr@)rrCzrequires.txtr¯zEGG-INFO/PKG-INFOÚutf8rAzEGG-INFO/requires.txtzEGG-INFO/top_level.txtrærFz,path must end with .egg-info or .egg, got %rr°)rLr²rrÔrOr	Ú	zipimportÚzipimporterrÚget_datarªrrZadd_requirementsr³r´rµr¶r±)r"rÚrequiresr	Ztl_pathZtl_datarqÚ	meta_pathrDrZzipfrBr«r·r#rr$rÿwsX


ÿ
ÿ

z!EggInfoDistribution._get_metadatacCsd|j|j|jfS)Nz!r¸r!r#r#r$r—Ñs
ÿzEggInfoDistribution.__repr__cCsd|j|jfSr¹r„r!r#r#r$rºÕszEggInfoDistribution.__str__cCs`g}tj |jd¡}tj |¡r\| ¡D]2\}}}||kr._md5cSst |¡jSr9)r²ÚstatÚst_size)rr#r#r$Ú_sizeûsz7EggInfoDistribution.list_installed_files.._sizerrYrærçzNon-existent file: %srÐN)
r²rrOr³rêr´rÚnormpathrSr’rLrÔr))r"rrrÚrhr·rírqr#r#r$rÎës"
$z(EggInfoDistribution.list_installed_filesFc	csštj |jd¡}tj |¡r–d}tj|ddd��`}|D]T}| ¡}|dkrPd}q6|s6tj tj |j|¡¡}| |j¡r6|r„|Vq6|Vq6W5QRXdS)	a
        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
        rTrYrærçz./FN)	r²rrOr³rêr´rrrÒ)r"ZabsoluterÚÚskipr·rírqr#r#r$rúsz'EggInfoDistribution.list_distinfo_filescCst|tƒo|j|jkSr9)r]rrrûr#r#r$rš.s

ÿzEggInfoDistribution.__eq__)N)F)r-r.r/r0r�rîr%rÿr—rºrårÎrúršrürœr®r#r#r r$rYsZ&
c@s^eZdZdZdd„Zdd„Zddd„Zd	d
„Zdd„Zddd„Z	ddd„Z
dd„Zdd„ZdS)ÚDependencyGraphaù
    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|_dSr9)Úadjacency_listÚreverse_listrÅr!r#r#r$r%IszDependencyGraph.__init__cCsg|j|<g|j|<dS)zÍAdd the *distribution* to the graph.

        :type distribution: :class:`distutils2.database.InstalledDistribution`
                            or :class:`distutils2.database.EggInfoDistribution`
        N)rr)r"Údistributionr#r#r$Úadd_distributionNs
z DependencyGraph.add_distributionNcCs6|j| ||f¡||j|kr2|j| |¡dS)ašAdd an edge from distribution *x* to distribution *y* with the given
        *label*.

        :type x: :class:`distutils2.database.InstalledDistribution` or
                 :class:`distutils2.database.EggInfoDistribution`
        :type y: :class:`distutils2.database.InstalledDistribution` or
                 :class:`distutils2.database.EggInfoDistribution`
        :type label: ``str`` or ``None``
        N)rr)r)r"ÚxÚyÚlabelr#r#r$Úadd_edgeXs
zDependencyGraph.add_edgecCs&t d||¡|j |g¡ |¡dS)a
        Add a missing *requirement* for the given *distribution*.

        :type distribution: :class:`distutils2.database.InstalledDistribution`
                            or :class:`distutils2.database.EggInfoDistribution`
        :type requirement: ``str``
        z
%s missing %rN)rSrTrÅr'r))r"rr‘r#r#r$Úadd_missinggszDependencyGraph.add_missingcCsd|j|jfSr¹r„r*r#r#r$Ú
_repr_distrszDependencyGraph._repr_distrcCsŠ| |¡g}|j|D]h\}}| |¡}|dk	r| d|j|jf¡q>q|sÞt|ƒdkrÞ| d¡| d¡| d¡|D]}| d	|j¡| d
¡q´| d¡| d¡dS)a9Writes a DOT output for the graph to the provided file *f*.

        If *skip_disconnected* is set to ``True``, then all distributions
        that are not dependent on any other distribution are skipped.

        :type f: has to support ``file``-like operations
        :type skip_disconnected: ``bool``
        zdigraph dependencies {
rNz"%s" -> "%s" [label="%s"]
z
"%s" -> "%s"
zsubgraph disconnected {
zlabel = "Disconnected"
zbgcolor = red
z"%s"rðz}
)ròrÚitemsrÂr)r)r"r·Zskip_disconnectedZdisconnectedr+Úadjsr™rr#r#r$Úto_dot‚s(	

ÿ



zDependencyGraph.to_dotcsÂg}i}|j ¡D]\}}|dd…||<qg‰t| ¡ƒdd…D]\}}|sDˆ |¡||=qDˆshq²| ¡D]\}}‡fdd„|Dƒ||<qpt ddd„ˆDƒ¡| ˆ¡q,|t| ¡ƒfS)aa
        Perform a topological sort of the graph.
        :return: A tuple, the first element of which is a topologically sorted
                 list of distributions, and the second element of which is a
                 list of distributions that cannot be sorted because they have
                 circular dependencies and so form a cycle.
        Ncs g|]\}}|ˆkr||f‘qSr#r#)r¼r{rY©Z	to_remover#r$r¾»sz4DependencyGraph.topological_sort..zMoving to result: %scSsg|]}d|j|jf‘qS)rjr„)r¼r{r#r#r$r¾½s)rr'Úlistr)rSrTr$Úkeys)r"rhZalistÚkr|r#r*r$Útopological_sort¢s$
ÿz DependencyGraph.topological_sortcCs2g}|j ¡D]\}}| | |¡¡qd |¡S)zRepresentation of the graphrð)rr'r)r#rO)r"r&r+r(r#r#r$r—ÁszDependencyGraph.__repr__)N)r)T)
r-r.r/r0r%rr r!r"r#r)r.r—r#r#r#r$r9s



 rr1cCsVt|ƒ}tƒ}i}|D]L}| |¡|jD]6}t|ƒ\}}t d|||¡| |g¡ ||f¡q*q|D]è}|j	|j
B|jB|jB}|D]Æ}	z| 
|	¡}
Wn6tk
rÐt d|	¡|	 ¡d}| 
|¡}
YnX|
j}d}||k�r>||D]N\}}z|
 |¡}
Wntk
�rd}
YnX|
rî| |||	¡d}�q>qî|sˆ| ||	¡qˆqh|S)a6Makes a dependency graph from the given distributions.

    :parameter dists: a list of distributions
    :type dists: list of :class:`distutils2.database.InstalledDistribution` and
                 :class:`distutils2.database.EggInfoDistribution` instances
    :rtype: a :class:`DependencyGraph` instance
    zAdd to provided: %s, %s, %sr�rFT)rrrrkrrSrTr'r)rŠrŒr�r�rlrr’r“r(ror r!)ÚdistsrCÚgraphrpr+rqrrcrr”rlZmatchedZproviderror#r#r$Ú
make_graphÉsN


ÿÿÿ

r1cCsv||krtd|jƒ‚t|ƒ}|g}|j|}|rh| ¡}| |¡|j|D]}||krN| |¡qNq.| d¡|S)zÚRecursively generate a list of distributions from *dists* that are
    dependent on *dist*.

    :param dists: a list of distributions
    :param dist: a distribution, member of *dists* for which we are interested
    ú1given distribution %r is not a member of the listr)rrr1rÚpopr))r/r+r0ZdepÚtodor{Zsuccr#r#r$Úget_dependent_distsÿsÿ


r5cCsn||krtd|jƒ‚t|ƒ}g}|j|}|rj| ¡d}| |¡|j|D]}||krP| |¡qPq,|S)zÙRecursively generate a list of distributions from *dists* that are
    required by *dist*.

    :param dists: a list of distributions
    :param dist: a distribution, member of *dists* for which we are interested
    r2r)rrr1rr3r))r/r+r0r”r4r{Zpredr#r#r$Úget_required_distssÿ

r6cKs4| dd¡}tf|Ž}||_||_|p(d|_t|ƒS)zO
    A convenience method for making a dist given just a name and version.
    ÚsummaryzPlaceholder for summary)r3r	rrcr7r)rrcÚkwargsr7rˆr#r#r$Ú	make_dist2s

r9)r1)7r0Z
__future__rr¨rêrPr¦Zloggingr²rNr2rr?rrÚcompatrrcrrrDr	r
rrÚutilr
rrrrrrÚ__all__Z	getLoggerr-rSrÉZCOMMANDS_FILENAMErörMrürrrrrrrUrVrr1r5r6r9r#r#r#r$Ús`$þ
ÿs7J]
6PKÕ¶N]~ÕRǻǻGsite-packages/pip/_vendor/distlib/__pycache__/util.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eøëã@s¸ddlZddlmZddlZddlZddlmZddlZddl	Z	ddl
Z
ddlZddlZddl
Z
ddlZzddlZWnek
rŒdZYnXddlZddlZddlZddlZddlZzddlZWnek
rÞddlZYnXddlZddlmZddlmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0e
 1e2¡Z3e
 4d¡Z5e
 4d¡Z6e
 4d	¡Z7e
 4d
¡Z8e
 4d¡Z9e
 4d¡Z:e
 4d
¡Z;e
 4d¡Zdd„Z?dd„Z@dd„ZAdˆdd„ZBdd„ZCdd„ZDdd „ZEejFd!d"„ƒZGejFd#d$„ƒZHejFd‰d&d'„ƒZIGd(d)„d)eJƒZKd*d+„ZLGd,d-„d-eJƒZMd.d/„ZNGd0d1„d1eJƒZOe
 4d2e
jP¡ZQd3d4„ZRdŠd5d6„ZSd7d8„ZTd9d:„ZUd;d<„ZVd=d>„ZWd?d@„ZXe
 4dAe
jY¡ZZe
 4dB¡Z[d‹dCdD„Z\e
 4dE¡Z]dFdG„Z^dHdI„Z_dJdK„Z`dLZadMdN„ZbdOdP„ZcGdQdR„dReJƒZdGdSdT„dTeJƒZeGdUdV„dVeJƒZfdWZgdŒdYdZ„Zhd[d\„Zid]ZjGd^d_„d_eJƒZke
 4d`¡Zle
 4da¡Zme
 4db¡Zndcdd„Zdedf„Zoe�rÖddglmpZqmrZrmsZsGdhdi„die$jtƒZtGdjdk„dkeqƒZpGdldm„dmepe'ƒZuejvddn…Zwewdok�rGdpdq„dqe$jxƒZxe�rGdrds„dse$jyƒZyGdtdu„due%jzƒZze�rBGdvdw„dwe%j{ƒZ{Gdxdy„dye%j|ƒZ|dzd{„Z}Gd|d}„d}eJƒZ~Gd~d„de~ƒZGd€d�„d�e~ƒZ€Gd‚dƒ„dƒe(ƒZ�Gd„d…„d…eJƒZ‚d†d‡„ZƒdS)�éN)Údeque)Úiglobé)ÚDistlibException)Ústring_typesÚ	text_typeÚshutilÚ	raw_inputÚStringIOÚcache_from_sourceÚurlopenÚurljoinÚhttplibÚ	xmlrpclibÚ	splittypeÚHTTPHandlerÚBaseConfiguratorÚvalid_identÚ	ContainerÚconfigparserÚURLErrorÚZipFileÚfsdecodeÚunquoteÚurlparsez^([\w\.-]+)\s*z^([\w\.*+-]+)\s*z^(<=?|>=?|={2,3}|[~!]=)\s*z*^((<=?)|(>=?)|={2,3}|[~!]=|in|not\s+in)\s*z^or\b\s*z	^and\b\s*z(\S+)\s*z(([\s\w\.{}()*+#:;,/?!~`@$%^&=|<>\[\]-]+)cs6dd„‰‡‡fdd„‰‡fdd„‰‡fdd„‰ˆ|ƒS)	ae
    Parse a marker string and return a dictionary containing a marker expression.

    The dictionary will contain keys "op", "lhs" and "rhs" for non-terminals in
    the expression grammar, or strings. A string contained in quotes is to be
    interpreted as a literal string, and a string not contained in quotes is a
    variable (such as os_name).
    cSs.t |¡}|r,| ¡d}|| ¡d…}nú|s:tdƒ‚nì|d}|dkrVtd|ƒ‚d |d¡}|dd…}|g}|rì|d|krŠ�qqt|d|kr®| |¡|dd…}qtt |¡}|sÈtd|ƒ‚| | ¡d¡|| ¡d…}qtd |¡}td|ƒ‚| |¡d |¡}|dd… 	¡}||fS)	Nrzunexpected end of inputz'"zinvalid expression: %sÚrzerror in string literal: %szunterminated string: %s)
Ú
IDENTIFIERÚmatchÚgroupsÚendÚSyntaxErrorÚreplaceÚappendÚSTRING_CHUNKÚjoinÚlstrip)Ú	remainingÚmÚresultÚqZoqÚpartsÚs©r,ú.marker_varcs´|rR|ddkrRˆ|dd… ¡ƒ\}}|ddkr@td|ƒ‚|dd… ¡}nZˆ|ƒ\}}|r¨t |¡}|srq¨| ¡d}|| ¡d…}ˆ|ƒ\}}|||dœ}q^|}||fS)Nrú(rú)úunterminated parenthesis: %s©ÚopÚlhsÚrhs)r%r Ú	MARKER_OPrrr)r&r(r4r'r3r5)Úmarkerr.r,r-Úmarker_expres 
z!parse_marker..marker_exprcsRˆ|ƒ\}}|rJt |¡}|s qJ|| ¡d…}ˆ|ƒ\}}d||dœ}q||fS)NÚandr2)ÚANDrr©r&r4r'r5)r8r,r-Ú
marker_andxs
z parse_marker..marker_andcsRˆ|ƒ\}}|rJt |¡}|s qJ|| ¡d…}ˆ|ƒ\}}d||dœ}q||fS)NÚorr2)ÚORrrr;)r<r,r-r7ƒs
zparse_marker..markerr,)Z
marker_stringr,)r7r<r8r.r-Úparse_marker8s
	$r?cCs0| ¡}|r| d¡rdSt |¡}|s4td|ƒ‚| ¡d}|| ¡d…}d}}}}|�r:|ddk�r:| dd¡}|dkr”td|ƒ‚|d|…}	||dd… ¡}g}|	�r0t |	¡}|sØtd	|	ƒ‚| 	| ¡d¡|	| ¡d…}	|	�s�q0|	dd
k�rtd|	ƒ‚|	dd… ¡}	q¸|�s:d}|�r˜|ddk�rÀ|dd… ¡}t
 |¡}|�sztd
|ƒ‚| ¡d}t|ƒ}
|
j�rž|
j
�sªtd|ƒ‚|| ¡d… ¡}nØdd„}|ddk�rä||ƒ\}}n´| dd¡}|dk�rtd|ƒ‚|d|…}	||dd… ¡}t |	¡�r@||	ƒ\}}nXt |	¡}|�s\td|	ƒ‚| ¡d}
|	| ¡d… ¡}	|	�rŽtd|	ƒ‚d|
fg}|�rÔ|ddk�r¸td|ƒ‚|dd… ¡}t|ƒ\}}|�rô|ddk�rôtd|ƒ‚|�s|}nd|d dd„|Dƒ¡f}t||||||d�S)zŠ
    Parse a requirement passed in as a string. Return a Container
    whose attributes contain the various parts of the requirement.
    ú#Nzname expected: %srú[ú]rzunterminated extra: %szmalformed extra: %sú,zcomma expected in extras: %sú@zinvalid URI: %szInvalid URL: %scSsÄt |¡}d}|r¼g}| ¡d}|| ¡d…}t |¡}|sLtd|ƒ‚| ¡d}| ||f¡|| ¡d…}|r´|ddkrˆq´|dd… ¡}t |¡}|std|ƒ‚q|s¼d}||fS)z|
                Return a list of operator, version tuples if any are
                specified, else None.
                Nrzinvalid version: %srCrúinvalid constraint: %s)Ú
COMPARE_OPrrrÚVERSION_IDENTIFIERr r"r%)Z
ver_remainingr'Úversionsr3Úvr,r,r-Úget_versionsÅs*


z'parse_requirement..get_versionsr/r0r1rEz~=ú;zinvalid requirement: %szunexpected trailing data: %sú%s %sú, cSsg|]}d|‘qS)rLr,)Ú.0Zconr,r,r-Ú
sz%parse_requirement..)ÚnameÚextrasZconstraintsr7ÚurlZrequirement)ÚstripÚ
startswithrrr rrÚfindr%r"Ú	NON_SPACErÚschemeÚnetlocrFrGr?r$r)Úreqr&r'ZdistnamerQZ	mark_exprrHÚuriÚir+ÚtrJÚ_rIZrsr,r,r-Úparse_requirement‘s’





ÿr^cCs¨dd„}i}|D]’\}}}tj ||¡}t|ƒD]p}tj ||¡}	t|	ƒD]T}
|||
ƒ}|dkrn| |d¡qJ|||
ƒ}| tjjd¡ d¡}
|
d|||<qJq0q|S)z%Find destinations for resources filescSs6| tjjd¡}| tjjd¡}|t|ƒd… d¡S©Nú/)r!ÚosÚpathÚsepÚlenr%)Úrootrbr,r,r-Úget_rel_path
sz)get_resources_dests..get_rel_pathNr`)rarbr$rÚpopr!rcÚrstrip)Zresources_rootZrulesrfZdestinationsÚbaseÚsuffixÚdestÚprefixZabs_baseZabs_globZabs_pathZ
resource_fileZrel_pathZrel_destr,r,r-Úget_resources_dests
s

rmcCs(ttdƒrd}ntjttdtjƒk}|S)NZreal_prefixTÚbase_prefix)ÚhasattrÚsysrlÚgetattr©r(r,r,r-Úin_venv$s
rscCs$tj tj¡}t|tƒs t|ƒ}|S©N)rarbÚnormcaserpÚ
executableÚ
isinstancerrrrr,r,r-Úget_executable.s

rxcCsN|}t|ƒ}|}|s|r|}|r|d ¡}||kr6qJ|rd|||f}q|S)Nrz	%c: %s
%s)r	Úlower)ÚpromptZ
allowed_charsZerror_promptÚdefaultÚpr+Úcr,r,r-Úproceed>sr~cCs8t|tƒr| ¡}i}|D]}||kr||||<q|Srt)rwrÚsplit)ÚdÚkeysr(Úkeyr,r,r-Úextract_by_keyNs
rƒcCs`tjddkrt d¡|ƒ}| ¡}t|ƒ}z`t |¡}|ddd}| ¡D]6\}}| ¡D]$\}}d||f}t	|ƒ}	|	||<q`qP|WSt
k
r¬| dd¡YnXdd	„}
t 
¡}z|
||ƒWn<tjk
�r| ¡t |¡}t|ƒ}|
||ƒYnXi}| ¡D]D}i||<}| |¡D]&\}
}d|
|f}t	|ƒ}	|	||
<�q0�q|S)
Nréúutf-8Ú
extensionszpython.exportsÚexportsz%s = %scSs$t|dƒr| |¡n
| |¡dS)NÚ	read_file)rorˆZreadfp)ÚcpÚstreamr,r,r-Úread_streamks
z!read_exports..read_stream)rpÚversion_infoÚcodecsÚ	getreaderÚreadr
ÚjsonÚloadÚitemsÚget_export_entryÚ	ExceptionÚseekrÚConfigParserZMissingSectionHeaderErrorÚcloseÚtextwrapÚdedentZsections)rŠÚdataZjdatar(ÚgroupÚentriesÚkrIr+Úentryr‹r‰r‚rPÚvaluer,r,r-Úread_exportsWs@

r cCs¨tjddkrt d¡|ƒ}t ¡}| ¡D]l\}}| |¡| ¡D]P}|j	dkr\|j
}nd|j
|j	f}|jr†d|d |j¡f}| 
||j|¡qFq,| |¡dS)Nrr„r…z%s:%sz%s [%s]rM)rprŒr�Ú	getwriterrr–r’Zadd_sectionÚvaluesrjrlÚflagsr$ÚsetrPÚwrite)r‡rŠr‰r�rIržr+r,r,r-Ú
write_exports†s

r¦c	cs$t ¡}z
|VW5t |¡XdSrt)ÚtempfileÚmkdtemprÚrmtree)Ztdr,r,r-Útempdir™s
rªc	cs.t ¡}zt |¡dVW5t |¡XdSrt)raÚgetcwdÚchdir)r€Úcwdr,r,r-r¬¡s


r¬éc	cs.t ¡}zt |¡dVW5t |¡XdSrt)ÚsocketZgetdefaulttimeoutZsetdefaulttimeout)ZsecondsZctor,r,r-Úsocket_timeout«s


r°c@seZdZdd„Zddd„ZdS)Úcached_propertycCs
||_dSrt)Úfunc)Úselfr²r,r,r-Ú__init__¶szcached_property.__init__NcCs,|dkr|S| |¡}t ||jj|¡|Srt)r²ÚobjectÚ__setattr__Ú__name__)r³ÚobjÚclsrŸr,r,r-Ú__get__»s

zcached_property.__get__)N)r·Ú
__module__Ú__qualname__r´rºr,r,r,r-r±µsr±cCs~tjdkr|S|s|S|ddkr.td|ƒ‚|ddkrFtd|ƒ‚| d¡}tj|krh| tj¡qP|srtjStjj|ŽS)aÐReturn 'pathname' as a name that will work on the native filesystem.

    The path is split on '/' and put back together again using the current
    directory separator.  Needed because filenames in the setup script are
    always supplied in Unix style, and have to be converted to the local
    convention before we can actually use them in the filesystem.  Raises
    ValueError on non-Unix-ish systems if 'pathname' either starts or
    ends with a slash.
    r`rzpath '%s' cannot be absoluteéÿÿÿÿzpath '%s' cannot end with '/')rarcÚ
ValueErrorrÚcurdirÚremoverbr$)ÚpathnameÚpathsr,r,r-Úconvert_pathÃs



rÃc@s”eZdZd$dd„Zdd„Zdd„Zdd	„Zd%dd„Zd&dd„Zdd„Z	dd„Z
dd„Zdd„Zdd„Z
d'dd„Zdd„Zdd„Zd d!„Zd"d#„Zd
S)(ÚFileOperatorFcCs||_tƒ|_| ¡dSrt)Údry_runr¤ÚensuredÚ_init_record)r³rÅr,r,r-r´ßszFileOperator.__init__cCsd|_tƒ|_tƒ|_dS©NF)Úrecordr¤Ú
files_writtenÚdirs_created©r³r,r,r-rÇäszFileOperator._init_recordcCs|jr|j |¡dSrt)rÉrÊÚadd)r³rbr,r,r-Úrecord_as_writtenészFileOperator.record_as_writtencCsHtj |¡s tdtj |¡ƒ‚tj |¡s0dSt |¡jt |¡jkS)aÎTell if the target is newer than the source.

        Returns true if 'source' exists and is more recently modified than
        'target', or if 'source' exists and 'target' doesn't.

        Returns false if both exist and 'target' is the same age or younger
        than 'source'. Raise PackagingFileError if 'source' does not exist.

        Note that this test is not very accurate: files created in the same
        second will have the same "age".
        zfile '%r' does not existT)rarbÚexistsrÚabspathÚstatÚst_mtime)r³ÚsourceÚtargetr,r,r-Únewerís
ÿzFileOperator.newerTcCsŽ| tj |¡¡t d||¡|js€d}|rdtj |¡rDd|}n tj |¡rdtj 	|¡sdd|}|rtt
|dƒ‚t ||¡| 
|¡dS)z8Copy a file respecting dry-run and force flags.
        zCopying %s to %sNz%s is a symlinkz%s is a non-regular filez which would be overwritten)Ú
ensure_dirrarbÚdirnameÚloggerÚinforÅÚislinkrÏÚisfiler¾rZcopyfilerÎ)r³ZinfileÚoutfileÚcheckÚmsgr,r,r-Ú	copy_files
zFileOperator.copy_fileNcCst| tj |¡¡t d||¡|jsf|dkr:t|dƒ}ntj|d|d�}zt
 ||¡W5| 	¡X| |¡dS)NzCopying stream %s to %sÚwbÚw©Úencoding)
rÖrarbr×rØrÙrÅÚopenr�r—rZcopyfileobjrÎ)r³ZinstreamrÜrãZ	outstreamr,r,r-Úcopy_streams
zFileOperator.copy_streamc	Cs\| tj |¡¡|jsNtj |¡r.t |¡t|dƒ�}| |¡W5QRX| 	|¡dS)Nrà)
rÖrarbr×rÅrÏrÀrär¥rÎ)r³rbršÚfr,r,r-Úwrite_binary_file!s
zFileOperator.write_binary_filecCs| || |¡¡dSrt)rçÚencode)r³rbršrãr,r,r-Úwrite_text_file*szFileOperator.write_text_filecCsntjdkstjdkrjtjdkrj|D]F}|jr:t d|¡q"t |¡j|B|@}t d||¡t ||¡q"dS)NÚposixÚjavazchanging mode of %szchanging mode of %s to %o)	rarPÚ_namerÅrØrÙrÑÚst_modeÚchmod)r³ÚbitsÚmaskÚfilesræÚmoder,r,r-Úset_mode-szFileOperator.set_modecCs| dd|¡S)Nimiÿ)ró)r+rær,r,r-Ú9ózFileOperator.cCs|tj |¡}||jkrxtj |¡sx|j |¡tj |¡\}}| |¡t 	d|¡|j
sft |¡|jrx|j
 |¡dS)NzCreating %s)rarbrÐrÆrÏrÍrrÖrØrÙrÅÚmkdirrÉrË)r³rbr€rær,r,r-rÖ;s

zFileOperator.ensure_dirc	CsŠt||ƒ}t d||¡|js||s0| ||¡rJ|s:d}n|t|ƒd…}i}|rhttdƒrhtjj	|d<tj
|||df|Ž| |¡|S)NzByte-compiling %s to %sÚPycInvalidationModeÚinvalidation_modeT)rrØrÙrÅrÕrdroÚ
py_compiler÷ÚCHECKED_HASHÚcompilerÎ)	r³rbÚoptimizeÚforcerlZhashed_invalidationZdpathZdiagpathZcompile_kwargsr,r,r-Úbyte_compileGs
zFileOperator.byte_compilecCs²tj |¡r®tj |¡r^tj |¡s^t d|¡|js@t 	|¡|j
r®||jkr®|j |¡nPtj |¡rpd}nd}t d||¡|js’t |¡|j
r®||j
kr®|j
 |¡dS)NzRemoving directory tree at %sÚlinkÚfilezRemoving %s %s)rarbrÏÚisdirrÚrØÚdebugrÅrr©rÉrËrÀrÊ)r³rbr+r,r,r-Úensure_removedXs"



zFileOperator.ensure_removedcCsDd}|s@tj |¡r$t |tj¡}q@tj |¡}||kr:q@|}q|SrÈ)rarbrÏÚaccessÚW_OKr×)r³rbr(Úparentr,r,r-Úis_writablemszFileOperator.is_writablecCs|j|jf}| ¡|S)zV
        Commit recorded changes, turn off recording, return
        changes.
        )rÊrËrÇ)r³r(r,r,r-ÚcommityszFileOperator.commitcCs„|jsxt|jƒD]}tj |¡rt |¡qt|jdd�}|D]8}t 	|¡}|rltj 
||d¡}t |¡t |¡q>| ¡dS)NT)Úreverser)
rÅÚlistrÊrarbrÏrÀÚsortedrËÚlistdirr$ÚrmdirrÇ)r³ræÚdirsr€ÚflistZsdr,r,r-Úrollbackƒs

zFileOperator.rollback)F)T)N)FFNF)r·r»r¼r´rÇrÎrÕrßrårçréróZset_executable_moderÖrþrrrrr,r,r,r-rÄÞs 


	

rÄcCs^|tjkrtj|}nt|ƒ}|dkr,|}n.| d¡}t|| d¡ƒ}|D]}t||ƒ}qJ|S)NÚ.r)rpÚmodulesÚ
__import__rrqrg)Zmodule_nameZdotted_pathÚmodr(r*r|r,r,r-Úresolve•s

rc@s6eZdZdd„Zedd„ƒZdd„Zdd„Zej	Z	d	S)
ÚExportEntrycCs||_||_||_||_dSrt©rPrlrjr£)r³rPrlrjr£r,r,r-r´¥szExportEntry.__init__cCst|j|jƒSrt)rrlrjrÌr,r,r-rŸ«szExportEntry.valuecCsd|j|j|j|jfS)NzrrÌr,r,r-Ú__repr__¯s
ÿzExportEntry.__repr__cCsDt|tƒsd}n0|j|jko>|j|jko>|j|jko>|j|jk}|SrÈ)rwrrPrlrjr£)r³Úotherr(r,r,r-Ú__eq__³s

ÿ
þ
ýzExportEntry.__eq__N)
r·r»r¼r´r±rŸrrrµÚ__hash__r,r,r,r-r¤s

rzµ(?P(\w|[-.+])+)
                      \s*=\s*(?P(\w+)([:\.]\w+)*)
                      \s*(\[\s*(?P\w+(=\w+)?(,\s*\w+(=\w+)?)*)\s*\])?
                      c
Csàt |¡}|s0d}d|ks"d|krÜtd|ƒ‚n¬| ¡}|d}|d}| d¡}|dkrf|d}}n"|dkrztd|ƒ‚| d¡\}}|d	}	|	dkrºd|ks¨d|kr´td|ƒ‚g}	nd
d„|	 d¡Dƒ}	t||||	ƒ}|S)
NrArBzInvalid specification '%s'rPÚcallableú:rrr£cSsg|]}| ¡‘qSr,)rS)rNrær,r,r-rOßsz$get_export_entry..rC)ÚENTRY_REÚsearchrÚ	groupdictÚcountrr)
Z
specificationr'r(r€rPrbZcolonsrlrjr£r,r,r-r“Ås8
ÿ
ÿÿr“cCsÈ|dkrd}tjdkr.dtjkr.tj d¡}ntj d¡}tj |¡rft |tj¡}|s¢t	 
d|¡n| dd¡\}}d|kr.|}n| dd¡\}}|rJt|ƒ}|rVt|ƒ}|||fS)NrDrr)Úrsplitrr)rXZusernameZpasswordrlr,r,r-Úparse_credentials$sr1cCst d¡}t |¡|S)Né)raÚumaskrrr,r,r-Úget_process_umask3s

r4cCs0d}d}t|ƒD]\}}t|tƒsd}q,q|S)NTF)Ú	enumeraterwr)Úseqr(r[r+r,r,r-Úis_string_sequence8s
r7z3([a-z0-9_]+([.-][a-z_][a-z0-9_]*)*)-([a-z0-9_.+-]+)z
-py(\d\.?\d?)cCsÈd}d}t|ƒ dd¡}t |¡}|r@| d¡}|d| ¡…}|r˜t|ƒt|ƒdkr˜t t 	|¡d|¡}|r˜| 
¡}|d|…||dd…|f}|dkrÄt |¡}|rÄ| d¡| d¡|f}|S)zw
    Extract name, version, python version from a filename (no extension)

    Return name, version, pyver or None
    Nú ú-rz\br„)rr!ÚPYTHON_VERSIONrr›ÚstartrdÚrerÚescaperÚPROJECT_NAME_AND_VERSION)ÚfilenameZproject_namer(Zpyverr'Únr,r,r-Úsplit_filenameGs"


rAz-(?P[\w .-]+)\s*\(\s*(?P[^\s)]+)\)$cCs:t |¡}|std|ƒ‚| ¡}|d ¡ ¡|dfS)zÇ
    A utility method used to get name and version from a string.

    From e.g. a Provides-Dist value.

    :param p: A value in a form 'foo (1.0)'
    :return: The name and version as a tuple.
    z$Ill-formed name/version string: '%s'rPZver)ÚNAME_VERSION_RErrr rSry)r|r'r€r,r,r-Úparse_name_and_versioncs
	
rCcCsºtƒ}t|pgƒ}t|pgƒ}d|kr8| d¡||O}|D]x}|dkrT| |¡q<| d¡r”|dd…}||kr€t d|¡||kr´| |¡q<||krªt d|¡| |¡q<|S)NÚ*r9rzundeclared extra: %s)r¤rÀrÍrTrØr()Z	requestedZ	availabler(ÚrZunwantedr,r,r-Ú
get_extrasrs&

rFc
Csˆi}zNt|ƒ}| ¡}| d¡}| d¡s8t d|¡nt d¡|ƒ}t 	|¡}Wn0t
k
r‚}zt d||¡W5d}~XYnX|S)NzContent-Typezapplication/jsonz(Unexpected response for JSON request: %sr…z&Failed to get external data for %s: %s)rrÙÚgetrTrØrr�rŽr�r‘r”Ú	exception)rRr(ZrespZheadersZctÚreaderÚer,r,r-Ú_get_external_data‹s

 rKz'https://www.red-dove.com/pypi/projects/cCs*d|d ¡|f}tt|ƒ}t|ƒ}|S)Nz%s/%s/project.jsonr©Úupperr
Ú_external_data_base_urlrK)rPrRr(r,r,r-Úget_project_data¡s
rOcCs(d|d ¡||f}tt|ƒ}t|ƒS)Nz%s/%s/package-%s.jsonrrL)rPÚversionrRr,r,r-Úget_package_data§s
rQc@s(eZdZdZdd„Zdd„Zdd„ZdS)	ÚCachezæ
    A class implementing a cache for resources that need to live in the file system
    e.g. shared libraries. This class was moved from resources to here because it
    could be used by other modules, e.g. the wheel module.
    cCsPtj |¡st |¡t |¡jd@dkr6t d|¡tj tj 	|¡¡|_
dS)zu
        Initialise an instance.

        :param base: The base directory where the cache should be located.
        é?rzDirectory '%s' is not privateN)rarbrr)rÑrírØr(rÐÚnormpathri)r³rir,r,r-r´´s

zCache.__init__cCst|ƒS)zN
        Converts a resource prefix to a directory name in the cache.
        )r-)r³rlr,r,r-Ú
prefix_to_dirÂszCache.prefix_to_dirc	Csˆg}t |j¡D]r}tj |j|¡}z>tj |¡s>tj |¡rJt |¡ntj |¡r`t	 
|¡Wqtk
r€| |¡YqXq|S)z"
        Clear the cache.
        )
rarrirbr$rÚrÛrÀrrr©r”r")r³Znot_removedÚfnr,r,r-ÚclearÈszCache.clearN)r·r»r¼Ú__doc__r´rUrWr,r,r,r-rR­srRc@s:eZdZdZdd„Zddd„Zdd„Zd	d
„Zdd„Zd
S)Ú
EventMixinz1
    A very simple publish/subscribe system.
    cCs
i|_dSrt)Ú_subscribersrÌr,r,r-r´ÝszEventMixin.__init__TcCsD|j}||krt|gƒ||<n"||}|r6| |¡n
| |¡dS)a`
        Add a subscriber for an event.

        :param event: The name of an event.
        :param subscriber: The subscriber to be added (and called when the
                           event is published).
        :param append: Whether to append or prepend the subscriber to an
                       existing subscriber list for the event.
        N)rZrr"Ú
appendleft)r³ÚeventÚ
subscriberr"ÚsubsZsqr,r,r-rÍàs
zEventMixin.addcCs,|j}||krtd|ƒ‚|| |¡dS)z™
        Remove a subscriber for an event.

        :param event: The name of an event.
        :param subscriber: The subscriber to be removed.
        zNo subscribers: %rN)rZr¾rÀ)r³r\r]r^r,r,r-rÀôszEventMixin.removecCst|j |d¡ƒS)z�
        Return an iterator for the subscribers for an event.
        :param event: The event to return subscribers for.
        r,)ÚiterrZrG)r³r\r,r,r-Úget_subscribersszEventMixin.get_subscribersc	Oslg}| |¡D]F}z||f|ž|Ž}Wn"tk
rHt d¡d}YnX| |¡qt d||||¡|S)a^
        Publish a event and return a list of values returned by its
        subscribers.

        :param event: The event to publish.
        :param args: The positional arguments to pass to the event's
                     subscribers.
        :param kwargs: The keyword arguments to pass to the event's
                       subscribers.
        z"Exception during event publicationNz/publish %s: args = %s, kwargs = %s, result = %s)r`r”rØrHr"r)r³r\ÚargsÚkwargsr(r]rŸr,r,r-Úpublishs

ÿzEventMixin.publishN)T)	r·r»r¼rXr´rÍrÀr`rcr,r,r,r-rYÙs
rYc@s^eZdZdd„Zdd„Zddd„Zdd	„Zd
d„Zdd
„Zdd„Z	e
dd„ƒZe
dd„ƒZdS)Ú	SequencercCsi|_i|_tƒ|_dSrt)Ú_predsÚ_succsr¤Ú_nodesrÌr,r,r-r´"szSequencer.__init__cCs|j |¡dSrt)rgrÍ©r³Únoder,r,r-Úadd_node'szSequencer.add_nodeFcCs®||jkr|j |¡|rªt|j |d¡ƒD]}| ||¡q,t|j |d¡ƒD]}| ||¡qPt|j ¡ƒD]\}}|sp|j|=qpt|j ¡ƒD]\}}|s”|j|=q”dS)Nr,)rgrÀr¤rerGrfr
r’)r³riZedgesr|r+r�rIr,r,r-Úremove_node*s

zSequencer.remove_nodecCs0|j |tƒ¡ |¡|j |tƒ¡ |¡dSrt)reÚ
setdefaultr¤rÍrf)r³ÚpredÚsuccr,r,r-rÍ:sz
Sequencer.addcCs|z|j|}|j|}Wn tk
r8td|ƒ‚YnXz| |¡| |¡Wn$tk
rvtd||fƒ‚YnXdS)Nz%r not a successor of anythingz%r not a successor of %r)rerfÚKeyErrorr¾rÀ)r³rmrnÚpredsZsuccsr,r,r-rÀ?s

zSequencer.removecCs||jkp||jkp||jkSrt)rerfrg)r³Ústepr,r,r-Úis_stepLsÿzSequencer.is_stepcCs˜| |¡std|ƒ‚g}g}tƒ}| |¡|r�| d¡}||krb||krŽ| |¡| |¡q.| |¡| |¡|j |d¡}| 	|¡q.t
|ƒS)NzUnknown: %rrr,)rrr¾r¤r"rgrÀrÍrerGÚextendÚreversed)r³Úfinalr(ZtodoÚseenrqrpr,r,r-Ú	get_stepsPs"





zSequencer.get_stepscsRdg‰g‰i‰i‰g‰|j‰‡‡‡‡‡‡‡fdd„‰ˆD]}|ˆkr8ˆ|ƒq8ˆS)Nrcsðˆdˆ|<ˆdˆ|<ˆdd7<ˆ |¡zˆ|}Wntk
rVg}YnX|D]J}|ˆkrˆˆ|ƒtˆ|ˆ|ƒˆ|<q\|ˆkr\tˆ|ˆ|ƒˆ|<q\ˆ|ˆ|krìg}ˆ ¡}| |¡||kr¼qÚq¼t|ƒ}ˆ |¡dS)Nrr)r"r”ÚminrgÚtuple)riZ
successorsZ	successorZconnected_componentZ	component©ZgraphÚindexZ
index_counterZlowlinksr(ÚstackÚ
strongconnectr,r-r}ts,


z3Sequencer.strong_connections..strongconnect)rfrhr,rzr-Ústrong_connectionsis"
zSequencer.strong_connectionscCsfdg}|jD]*}|j|}|D]}| d||f¡qq|jD]}| d|¡q>| d¡d |¡S)Nzdigraph G {z  %s -> %s;z  %s;Ú}Ú
)rer"rgr$)r³r(rnrprmrir,r,r-Údotœs



z
Sequencer.dotN)F)
r·r»r¼r´rjrkrÍrÀrrrwÚpropertyr~r�r,r,r,r-rd!s


2rd)ú.tar.gzú.tar.bz2ú.tarú.zipú.tgzú.tbzú.whlTcsZ‡‡fdd„}tj ˆ¡‰tˆƒ‰d}|dkr†| d¡r>d}nH| d¡rRd}d}n4| d¡rfd	}d
}n | d¡rzd}d
}ntd|ƒ‚z¾|dkrºt|d
ƒ}|rä| ¡}|D]}||ƒqªn*t	 
||¡}|rä| ¡}|D]}||ƒqÖ|dk�r*tj
ddk�r*| ¡D]"}	t|	jtƒ�s|	j d¡|	_�qdd„}
|
|_| ˆ¡W5|�rT| ¡XdS)NcsRt|tƒs| d¡}tj tj ˆ|¡¡}| ˆ¡rB|ˆtjkrNt	d|ƒ‚dS)Nr…zpath outside destination: %r)
rwrÚdecoderarbrÐr$rTrcr¾)rbr|©Údest_dirZplenr,r-Ú
check_path±s


zunarchive..check_path)r†r‰Úzip)rƒr‡Ztgzzr:gz)r„rˆZtbzzr:bz2r…ZtarrEzUnknown format for %rrr„r…c
SsDzt ||¡WStjk
r>}ztt|ƒƒ‚W5d}~XYnXdS)z:Run tarfile.tar_fillter, but raise the expected ValueErrorN)ÚtarfileZ
tar_filterZFilterErrorr¾Ústr)ÚmemberrbÚexcr,r,r-Úextraction_filterâsz$unarchive..extraction_filter)rarbrÐrdr.r¾r—rZnamelistr�räZgetnamesrprŒZ
getmembersrwrPrrŠr“Z
extractall)Zarchive_filenamerŒÚformatrÝr�ÚarchiveròÚnamesrPZtarinfor“r,r‹r-Ú	unarchive¯sL





r—c	Cs~t ¡}t|ƒ}t|dƒ�Z}t |¡D]H\}}}|D]8}tj ||¡}||d…}	tj |	|¡}
| ||
¡q4q&W5QRX|S)z*zip a directory tree into a BytesIO objectráN)	ÚioÚBytesIOrdrraÚwalkrbr$r¥)Z	directoryr(ZdlenZzfrerrñrPZfullZrelrkr,r,r-Úzip_diròsr›)rÚKÚMÚGÚTÚPc@sreZdZdZddd„Zdd„Zdd	„Zd
d„Zdd
„Ze	dd„ƒZ
e	dd„ƒZdd„Ze	dd„ƒZ
e	dd„ƒZdS)ÚProgressZUNKNOWNrédcCs(||_|_||_d|_d|_d|_dS)NrF)rxÚcurÚmaxÚstartedÚelapsedÚdone)r³ZminvalZmaxvalr,r,r-r´	s
zProgress.__init__cCs0||_t ¡}|jdkr ||_n||j|_dSrt)r£Útimer¥r¦)r³ZcurvalZnowr,r,r-Úupdates

zProgress.updatecCs| |j|¡dSrt)r©r£)r³Zincrr,r,r-Ú	incrementszProgress.incrementcCs| |j¡|Srt)r©rxrÌr,r,r-r;szProgress.startcCs |jdk	r| |j¡d|_dS)NT)r¤r©r§rÌr,r,r-Ústop#s
z
Progress.stopcCs|jdkr|jS|jSrt)r¤ÚunknownrÌr,r,r-Úmaximum(szProgress.maximumcCsD|jrd}n4|jdkrd}n$d|j|j|j|j}d|}|S)Nz100 %z ?? %gY@z%3d %%)r§r¤r£rx)r³r(rIr,r,r-Ú
percentage,s
zProgress.percentagecCs:|dkr|jdks|j|jkr$d}nt dt |¡¡}|S)Nrz??:??:??z%H:%M:%S)r¤r£rxr¨ÚstrftimeÚgmtime)r³Zdurationr(r,r,r-Úformat_duration7szProgress.format_durationcCs‚|jrd}|j}n^d}|jdkr&d}nJ|jdks<|j|jkrBd}n.t|j|jƒ}||j|j}|d|j}d|| |¡fS)NZDonezETA r½rrz%s: %s)r§r¦r¤r£rxÚfloatr±)r³rlr\r,r,r-ÚETA@s
zProgress.ETAcCsL|jdkrd}n|j|j|j}tD]}|dkr6q@|d}q&d||fS)Nrgièg@�@z%d %sB/s)r¦r£rxÚUNITS)r³r(Zunitr,r,r-ÚspeedSs

zProgress.speedN)rr¢)r·r»r¼r¬r´r©rªr;r«r‚r­r®r±r³rµr,r,r,r-r¡s




	
r¡z\{([^}]*)\}z[^/\\,{]\*\*|\*\*[^/\\,}]z^[^{]*\}|\{[^}]*$cCs<t |¡rd}t||ƒ‚t |¡r4d}t||ƒ‚t|ƒS)zAExtended globbing function that supports ** and {opt1,opt2,opt3}.z7invalid glob %r: recursive glob "**" must be used alonez2invalid glob %r: mismatching set marker '{' or '}')Ú_CHECK_RECURSIVE_GLOBrr¾Ú_CHECK_MISMATCH_SETÚ_iglob)Ú	path_globrÞr,r,r-rhs

rccsôt |d¡}t|ƒdkrT|\}}}| d¡D]$}td |||f¡ƒD]
}|VqDq,nœd|krrt|ƒD]
}|Vqdn~| dd¡\}}|dkrŽd}|dkrœd}n| d¡}| d¡}t |¡D]4\}}}	tj	 
|¡}ttj	 ||¡ƒD]
}
|
VqâqºdS)	NrrCrz**rrDr`ú\)Ú	RICH_GLOBrrdr¸r$Ú	std_iglobr%raršrbrT)r¹Zrich_path_globrlr¤rjÚitemrbZradicalÚdirrñrVr,r,r-r¸ss(



r¸)ÚHTTPSHandlerÚmatch_hostnameÚCertificateErrorc@seZdZdZdZdd„ZdS)ÚHTTPSConnectionNTcCsRt |j|jf|j¡}t|ddƒr0||_| ¡tt	dƒsp|j
rHt	j}nt	j}t	j
||j|j|t	j|j
d�|_nxt	 t	j¡}|jt	jO_|jr¢| |j|j¡i}|j
rØt	j|_|j|j
d�tt	ddƒrØ|j|d<|j
|f|Ž|_|j
�rN|j�rNz$t|j ¡|jƒt d|j¡Wn0tk
�rL|j tj¡|j ¡‚YnXdS)	NZ_tunnel_hostFÚ
SSLContext)Ú	cert_reqsZssl_versionÚca_certs)ZcafileZHAS_SNIZserver_hostnamezHost verified: %s) r¯Zcreate_connectionÚhostÚportÚtimeoutrqÚsockZ_tunnelroÚsslrÅZ
CERT_REQUIREDZ	CERT_NONEZwrap_socketZkey_fileZ	cert_fileZPROTOCOL_SSLv23rÃZoptionsZOP_NO_SSLv2Zload_cert_chainZverify_modeZload_verify_locationsÚcheck_domainrÀZgetpeercertrØrrÁZshutdownZ	SHUT_RDWRr—)r³rÉrÄÚcontextrbr,r,r-Úconnectœs@
ý


zHTTPSConnection.connect)r·r»r¼rÅrËrÍr,r,r,r-r—srÂc@s&eZdZd	dd„Zdd„Zdd„ZdS)
r¿TcCst |¡||_||_dSrt)ÚBaseHTTPSHandlerr´rÅrË)r³rÅrËr,r,r-r´Âs
zHTTPSHandler.__init__cOs$t||Ž}|jr |j|_|j|_|S)a
            This is called to create a connection instance. Normally you'd
            pass a connection class to do_open, but it doesn't actually check for
            a class, and just expects a callable. As long as we behave just as a
            constructor would have, we should be OK. If it ever changes so that
            we *must* pass a class, we'll create an UnsafeHTTPSConnection class
            which just sets check_domain to False in the class definition, and
            choose which one to pass to do_open.
            )rÂrÅrË)r³rarbr(r,r,r-Ú_conn_makerÇs


zHTTPSHandler._conn_makerc
CsXz| |j|¡WStk
rR}z$dt|jƒkr@td|jƒ‚n‚W5d}~XYnXdS)Nzcertificate verify failedz*Unable to verify server certificate for %s)Zdo_openrÏrr�ÚreasonrÁrÆ)r³rYrJr,r,r-Ú
https_open×sÿzHTTPSHandler.https_openN)T)r·r»r¼r´rÏrÑr,r,r,r-r¿Ás
r¿c@seZdZdd„ZdS)ÚHTTPSOnlyHandlercCstd|ƒ‚dS)NzAUnexpected HTTP request on what should be a secure connection: %s)r)r³rYr,r,r-Ú	http_openësÿzHTTPSOnlyHandler.http_openN)r·r»r¼rÓr,r,r,r-rÒêsrÒé©rÔéc@seZdZddd„ZdS)ÚHTTPrNcKs&|dkrd}| |j||f|Ž¡dS©Nr©Ú_setupZ_connection_class©r³rÆrÇrbr,r,r-r´÷sz
HTTP.__init__)rN©r·r»r¼r´r,r,r,r-r×ösr×c@seZdZddd„ZdS)ÚHTTPSrNcKs&|dkrd}| |j||f|Ž¡dSrØrÙrÛr,r,r-r´ÿszHTTPS.__init__)rNrÜr,r,r,r-rÝþsrÝc@seZdZddd„Zdd„ZdS)Ú	TransportrcCs||_tj ||¡dSrt)rÈrrÞr´©r³rÈÚuse_datetimer,r,r-r´szTransport.__init__cCs`| |¡\}}}tdkr(t||jd�}n4|jr<||jdkrR||_|t |¡f|_|jd}|S)NrÕ)rÈrr)Ú
get_host_infoÚ	_ver_infor×rÈÚ_connectionÚ_extra_headersrZHTTPConnection)r³rÆÚhÚehZx509r(r,r,r-Úmake_connection
s
zTransport.make_connectionN)r©r·r»r¼r´rçr,r,r,r-rÞs
rÞc@seZdZddd„Zdd„ZdS)Ú
SafeTransportrcCs||_tj ||¡dSrt)rÈrrér´rßr,r,r-r´szSafeTransport.__init__cCsx| |¡\}}}|si}|j|d<tdkr:t|df|Ž}n:|jrN||jdkrj||_|tj|df|Žf|_|jd}|S)NrÈrÕrr)rárÈrârÝrãrärrÂ)r³rÆrårærbr(r,r,r-rçs
ÿ
zSafeTransport.make_connectionN)rrèr,r,r,r-rés
réc@seZdZdd„ZdS)ÚServerProxyc	Kst| dd¡|_}|dk	r^t|ƒ\}}| dd¡}|dkr@t}nt}|||d�|d<}||_tjj	||f|ŽdS)NrÈràrZhttps)ràÚ	transport)
rgrÈrrGrérÞrërrêr´)	r³rZrbrÈrWr]ràZtclsr\r,r,r-r´,szServerProxy.__init__NrÜr,r,r,r-rê+srêcKs6tjddkr|d7}nd|d<d|d<t||f|ŽS)Nrr„ÚbrÚnewliner…rã)rprŒrä)rVròrbr,r,r-Ú	_csv_open@s

rîc@s4eZdZedƒedƒedƒdœZdd„Zdd„Zd	S)
ÚCSVBaserCú"r€)Z	delimiterZ	quotecharZlineterminatorcCs|Srtr,rÌr,r,r-Ú	__enter__RszCSVBase.__enter__cGs|j ¡dSrt)rŠr—)r³r$r,r,r-Ú__exit__UszCSVBase.__exit__N)r·r»r¼r�Údefaultsrñròr,r,r,r-rïKsýrïc@s(eZdZdd„Zdd„Zdd„ZeZdS)Ú	CSVReadercKs\d|kr4|d}tjddkr,t d¡|ƒ}||_nt|ddƒ|_tj|jf|jŽ|_dS)NrŠrr„r…rbrE)	rprŒr�rŽrŠrîÚcsvrIró)r³rbrŠr,r,r-r´ZszCSVReader.__init__cCs|Srtr,rÌr,r,r-Ú__iter__eszCSVReader.__iter__cCsFt|jƒ}tjddkrBt|ƒD] \}}t|tƒs | d¡||<q |S©Nrr„r…)ÚnextrIrprŒr5rwrrŠ)r³r(r[r½r,r,r-røhs

zCSVReader.nextN)r·r»r¼r´rörøÚ__next__r,r,r,r-rôYsrôc@seZdZdd„Zdd„ZdS)Ú	CSVWritercKs$t|dƒ|_tj|jf|jŽ|_dS)Nrá)rîrŠrõÚwriterró)r³rVrbr,r,r-r´sszCSVWriter.__init__cCsNtjddkr>g}|D]"}t|tƒr.| d¡}| |¡q|}|j |¡dSr÷)rprŒrwrrèr"rûÚwriterow)r³ÚrowrEr½r,r,r-rüws

zCSVWriter.writerowN)r·r»r¼r´rür,r,r,r-rúrsrúcsHeZdZeejƒZded<d‡fdd„	Zdd„Zdd	„Zd
d„Z	‡Z
S)
ÚConfiguratorÚinc_convertZincNcs"tt|ƒ |¡|pt ¡|_dSrt)Úsuperrþr´rar«ri)r³Úconfigri©Ú	__class__r,r-r´ŠszConfigurator.__init__c
s¬‡‡fdd„‰ˆ d¡}t|ƒs*ˆ |¡}ˆ dd¡}ˆ dd¡}|r\t‡fdd„|Dƒƒ}‡‡fd	d„ˆDƒ}t|ƒ}|||Ž}|r¨| ¡D]\}}	t||ˆ|	ƒƒqŽ|S)
Ncsvt|ttfƒr*t|ƒ‡fdd„|Dƒƒ}nHt|tƒrhd|krHˆ |¡}qri}|D]}ˆ||ƒ||<qPn
ˆ |¡}|S)Ncsg|]}ˆ|ƒ‘qSr,r,)rNr[©Úconvertr,r-rO‘szBConfigurator.configure_custom..convert..ú())rwr
ryÚtypeÚdictÚconfigure_customr)Úor(r�)rr³r,r-r�s

z.Configurator.configure_custom..convertrrz[]r,csg|]}ˆ|ƒ‘qSr,r,)rNr
rr,r-rO¤sz1Configurator.configure_custom..cs$g|]}t|ƒr|ˆˆ|ƒf‘qSr,)r)rNr�)rrr,r-rO¥s)rgrrryrr’Úsetattr)
r³rr}Zpropsrar’rbr(r@rIr,)rrr³r-r	Žs


zConfigurator.configure_customcCs4|j|}t|tƒr0d|kr0| |¡|j|<}|S)Nr)rrwrr	)r³r‚r(r,r,r-Ú__getitem__­s
zConfigurator.__getitem__c	CsFtj |¡stj |j|¡}tj|ddd��}t |¡}W5QRX|S)z*Default converter for the inc:// protocol.rEr…râ)	rarbÚisabsr$rir�rär�r‘)r³rŸrær(r,r,r-rÿ³s
zConfigurator.inc_convert)N)r·r»r¼rrZvalue_convertersr´r	rrÿÚ
__classcell__r,r,rr-rþ…s
rþc@s*eZdZdZd
dd„Zdd„Zdd	„ZdS)ÚSubprocessMixinzC
    Mixin for running subprocesses and capturing their output
    FNcCs||_||_dSrt)ÚverboseÚprogress)r³rrr,r,r-r´ÀszSubprocessMixin.__init__cCsj|j}|j}| ¡}|sq^|dk	r.|||ƒq|s@tj d¡ntj | d¡¡tj ¡q| ¡dS)z¨
        Read lines from a subprocess' output stream and either pass to a progress
        callable (if specified) or write progress information to sys.stderr.
        Nrr…)	rrÚreadlinerpÚstderrr¥rŠÚflushr—)r³rŠrÌrrr+r,r,r-rIÄszSubprocessMixin.readercKsžtj|ftjtjdœ|—Ž}tj|j|jdfd�}| ¡tj|j|jdfd�}| ¡| 	¡| 
¡| 
¡|jdk	rˆ| dd¡n|jršt
j d¡|S)N)Ústdoutrr)rÔrarzdone.Úmainzdone.
)Ú
subprocessÚPopenÚPIPEÚ	threadingZThreadrIrr;rÚwaitr$rrrpr¥)r³Úcmdrbr|Út1Út2r,r,r-Úrun_commandÙs"ÿÿ
zSubprocessMixin.run_command)FN)r·r»r¼rXr´rIrr,r,r,r-r¼s
rcCst dd|¡ ¡S)z,Normalize a python package name a la PEP 503z[-_.]+r9)r<Úsubry)rPr,r,r-Únormalize_nameêsr!)NN)r®)N)N)NT)„r�ÚcollectionsrÚ
contextlibrõZglobrr¼r˜r�Zloggingrarùr<r¯rÊÚImportErrorrrpr�r§r˜rZdummy_threadingr¨rrÚcompatrrrr	r
rrr
rrrrrrrrrrrrrZ	getLoggerr·rØrûrrGrFr6r>r:rVr#r?r^rmrsrxr~rƒr r¦Úcontextmanagerrªr¬r°rµr±rÃrÄrrÚVERBOSErr“r+r-r/r1r4r7ÚIr>r:rArBrCrFrKrNrOrQrRrYrdZARCHIVE_EXTENSIONSr—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þrr!r,r,r,r-Úsä
\








Yy

	/

		8ý
)
ÿ


,H
C]


*)	
7.PKÕ¶N]ŽÝ„**.site-packages/pip/_vendor/distlib/resources.pynu„[µü¤# -*- coding: utf-8 -*-
#
# Copyright (C) 2013-2017 Vinay Sajip.
# Licensed to the Python Software Foundation under a contributor agreement.
# See LICENSE.txt and CONTRIBUTORS.txt.
#
from __future__ import unicode_literals

import bisect
import io
import logging
import os
import pkgutil
import shutil
import sys
import types
import zipimport

from . import DistlibException
from .util import cached_property, get_cache_base, path_to_cache_dir, Cache

logger = logging.getLogger(__name__)


cache = None    # created when needed


class ResourceCache(Cache):
    def __init__(self, base=None):
        if base is None:
            # Use native string to avoid issues on 2.x: see Python #20140.
            base = os.path.join(get_cache_base(), str('resource-cache'))
        super(ResourceCache, self).__init__(base)

    def is_stale(self, resource, path):
        """
        Is the cache stale for the given resource?

        :param resource: The :class:`Resource` being cached.
        :param path: The path of the resource in the cache.
        :return: True if the cache is stale.
        """
        # Cache invalidation is a hard problem :-)
        return True

    def get(self, resource):
        """
        Get a resource into the cache,

        :param resource: A :class:`Resource` instance.
        :return: The pathname of the resource in the cache.
        """
        prefix, path = resource.finder.get_cache_info(resource)
        if prefix is None:
            result = path
        else:
            result = os.path.join(self.base, self.prefix_to_dir(prefix), path)
            dirname = os.path.dirname(result)
            if not os.path.isdir(dirname):
                os.makedirs(dirname)
            if not os.path.exists(result):
                stale = True
            else:
                stale = self.is_stale(resource, path)
            if stale:
                # write the bytes of the resource to the cache location
                with open(result, 'wb') as f:
                    f.write(resource.bytes)
        return result


class ResourceBase(object):
    def __init__(self, finder, name):
        self.finder = finder
        self.name = name


class Resource(ResourceBase):
    """
    A class representing an in-package resource, such as a data file. This is
    not normally instantiated by user code, but rather by a
    :class:`ResourceFinder` which manages the resource.
    """
    is_container = False        # Backwards compatibility

    def as_stream(self):
        """
        Get the resource as a stream.

        This is not a property to make it obvious that it returns a new stream
        each time.
        """
        return self.finder.get_stream(self)

    @cached_property
    def file_path(self):
        global cache
        if cache is None:
            cache = ResourceCache()
        return cache.get(self)

    @cached_property
    def bytes(self):
        return self.finder.get_bytes(self)

    @cached_property
    def size(self):
        return self.finder.get_size(self)


class ResourceContainer(ResourceBase):
    is_container = True     # Backwards compatibility

    @cached_property
    def resources(self):
        return self.finder.get_resources(self)


class ResourceFinder(object):
    """
    Resource finder for file system resources.
    """

    if sys.platform.startswith('java'):
        skipped_extensions = ('.pyc', '.pyo', '.class')
    else:
        skipped_extensions = ('.pyc', '.pyo')

    def __init__(self, module):
        self.module = module
        self.loader = getattr(module, '__loader__', None)
        self.base = os.path.dirname(getattr(module, '__file__', ''))

    def _adjust_path(self, path):
        return os.path.realpath(path)

    def _make_path(self, resource_name):
        # Issue #50: need to preserve type of path on Python 2.x
        # like os.path._get_sep
        if isinstance(resource_name, bytes):    # should only happen on 2.x
            sep = b'/'
        else:
            sep = '/'
        parts = resource_name.split(sep)
        parts.insert(0, self.base)
        result = os.path.join(*parts)
        return self._adjust_path(result)

    def _find(self, path):
        return os.path.exists(path)

    def get_cache_info(self, resource):
        return None, resource.path

    def find(self, resource_name):
        path = self._make_path(resource_name)
        if not self._find(path):
            result = None
        else:
            if self._is_directory(path):
                result = ResourceContainer(self, resource_name)
            else:
                result = Resource(self, resource_name)
            result.path = path
        return result

    def get_stream(self, resource):
        return open(resource.path, 'rb')

    def get_bytes(self, resource):
        with open(resource.path, 'rb') as f:
            return f.read()

    def get_size(self, resource):
        return os.path.getsize(resource.path)

    def get_resources(self, resource):
        def allowed(f):
            return (f != '__pycache__' and not
                    f.endswith(self.skipped_extensions))
        return set([f for f in os.listdir(resource.path) if allowed(f)])

    def is_container(self, resource):
        return self._is_directory(resource.path)

    _is_directory = staticmethod(os.path.isdir)

    def iterator(self, resource_name):
        resource = self.find(resource_name)
        if resource is not None:
            todo = [resource]
            while todo:
                resource = todo.pop(0)
                yield resource
                if resource.is_container:
                    rname = resource.name
                    for name in resource.resources:
                        if not rname:
                            new_name = name
                        else:
                            new_name = '/'.join([rname, name])
                        child = self.find(new_name)
                        if child.is_container:
                            todo.append(child)
                        else:
                            yield child


class ZipResourceFinder(ResourceFinder):
    """
    Resource finder for resources in .zip files.
    """
    def __init__(self, module):
        super(ZipResourceFinder, self).__init__(module)
        archive = self.loader.archive
        self.prefix_len = 1 + len(archive)
        # PyPy doesn't have a _files attr on zipimporter, and you can't set one
        if hasattr(self.loader, '_files'):
            self._files = self.loader._files
        else:
            self._files = zipimport._zip_directory_cache[archive]
        self.index = sorted(self._files)

    def _adjust_path(self, path):
        return path

    def _find(self, path):
        path = path[self.prefix_len:]
        if path in self._files:
            result = True
        else:
            if path and path[-1] != os.sep:
                path = path + os.sep
            i = bisect.bisect(self.index, path)
            try:
                result = self.index[i].startswith(path)
            except IndexError:
                result = False
        if not result:
            logger.debug('_find failed: %r %r', path, self.loader.prefix)
        else:
            logger.debug('_find worked: %r %r', path, self.loader.prefix)
        return result

    def get_cache_info(self, resource):
        prefix = self.loader.archive
        path = resource.path[1 + len(prefix):]
        return prefix, path

    def get_bytes(self, resource):
        return self.loader.get_data(resource.path)

    def get_stream(self, resource):
        return io.BytesIO(self.get_bytes(resource))

    def get_size(self, resource):
        path = resource.path[self.prefix_len:]
        return self._files[path][3]

    def get_resources(self, resource):
        path = resource.path[self.prefix_len:]
        if path and path[-1] != os.sep:
            path += os.sep
        plen = len(path)
        result = set()
        i = bisect.bisect(self.index, path)
        while i < len(self.index):
            if not self.index[i].startswith(path):
                break
            s = self.index[i][plen:]
            result.add(s.split(os.sep, 1)[0])   # only immediate children
            i += 1
        return result

    def _is_directory(self, path):
        path = path[self.prefix_len:]
        if path and path[-1] != os.sep:
            path += os.sep
        i = bisect.bisect(self.index, path)
        try:
            result = self.index[i].startswith(path)
        except IndexError:
            result = False
        return result

_finder_registry = {
    type(None): ResourceFinder,
    zipimport.zipimporter: ZipResourceFinder
}

try:
    # In Python 3.6, _frozen_importlib -> _frozen_importlib_external
    try:
        import _frozen_importlib_external as _fi
    except ImportError:
        import _frozen_importlib as _fi
    _finder_registry[_fi.SourceFileLoader] = ResourceFinder
    _finder_registry[_fi.FileFinder] = ResourceFinder
    del _fi
except (ImportError, AttributeError):
    pass


def register_finder(loader, finder_maker):
    _finder_registry[type(loader)] = finder_maker

_finder_cache = {}


def finder(package):
    """
    Return a resource finder for a package.
    :param package: The name of the package.
    :return: A :class:`ResourceFinder` instance for the package.
    """
    if package in _finder_cache:
        result = _finder_cache[package]
    else:
        if package not in sys.modules:
            __import__(package)
        module = sys.modules[package]
        path = getattr(module, '__path__', None)
        if path is None:
            raise DistlibException('You cannot get a finder for a module, '
                                   'only for a package')
        loader = getattr(module, '__loader__', None)
        finder_maker = _finder_registry.get(type(loader))
        if finder_maker is None:
            raise DistlibException('Unable to locate finder for %r' % package)
        result = finder_maker(module)
        _finder_cache[package] = result
    return result


_dummy_module = types.ModuleType(str('__dummy__'))


def finder_for_path(path):
    """
    Return a resource finder for a path, which should represent a container.

    :param path: The path.
    :return: A :class:`ResourceFinder` instance for the path.
    """
    result = None
    # calls any path hooks, gets importer into cache
    pkgutil.get_importer(path)
    loader = sys.path_importer_cache.get(path)
    finder = _finder_registry.get(type(loader))
    if finder:
        module = _dummy_module
        module.__file__ = os.path.join(path, '')
        module.__loader__ = loader
        result = finder(module)
    return result
PKÕ¶N]fÚÒ鼡¼¡+site-packages/pip/_vendor/distlib/compat.pynu„[µü¤# -*- coding: utf-8 -*-
#
# Copyright (C) 2013-2017 Vinay Sajip.
# Licensed to the Python Software Foundation under a contributor agreement.
# See LICENSE.txt and CONTRIBUTORS.txt.
#
from __future__ import absolute_import

import os
import re
import sys

try:
    import ssl
except ImportError:  # pragma: no cover
    ssl = None

if sys.version_info[0] < 3:  # pragma: no cover
    from StringIO import StringIO
    string_types = basestring,
    text_type = unicode
    from types import FileType as file_type
    import __builtin__ as builtins
    import ConfigParser as configparser
    from ._backport import shutil
    from urlparse import urlparse, urlunparse, urljoin, urlsplit, urlunsplit
    from urllib import (urlretrieve, quote as _quote, unquote, url2pathname,
                        pathname2url, ContentTooShortError, splittype)

    def quote(s):
        if isinstance(s, unicode):
            s = s.encode('utf-8')
        return _quote(s)

    import urllib2
    from urllib2 import (Request, urlopen, URLError, HTTPError,
                         HTTPBasicAuthHandler, HTTPPasswordMgr,
                         HTTPHandler, HTTPRedirectHandler,
                         build_opener)
    if ssl:
        from urllib2 import HTTPSHandler
    import httplib
    import xmlrpclib
    import Queue as queue
    from HTMLParser import HTMLParser
    import htmlentitydefs
    raw_input = raw_input
    from itertools import ifilter as filter
    from itertools import ifilterfalse as filterfalse

    _userprog = None
    def splituser(host):
        """splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'."""
        global _userprog
        if _userprog is None:
            import re
            _userprog = re.compile('^(.*)@(.*)$')

        match = _userprog.match(host)
        if match: return match.group(1, 2)
        return None, host

else:  # pragma: no cover
    from io import StringIO
    string_types = str,
    text_type = str
    from io import TextIOWrapper as file_type
    import builtins
    import configparser
    import shutil
    from urllib.parse import (urlparse, urlunparse, urljoin, splituser, quote,
                              unquote, urlsplit, urlunsplit, splittype)
    from urllib.request import (urlopen, urlretrieve, Request, url2pathname,
                                pathname2url,
                                HTTPBasicAuthHandler, HTTPPasswordMgr,
                                HTTPHandler, HTTPRedirectHandler,
                                build_opener)
    if ssl:
        from urllib.request import HTTPSHandler
    from urllib.error import HTTPError, URLError, ContentTooShortError
    import http.client as httplib
    import urllib.request as urllib2
    import xmlrpc.client as xmlrpclib
    import queue
    from html.parser import HTMLParser
    import html.entities as htmlentitydefs
    raw_input = input
    from itertools import filterfalse
    filter = filter

try:
    from ssl import match_hostname, CertificateError
except ImportError: # pragma: no cover
    class CertificateError(ValueError):
        pass


    def _dnsname_match(dn, hostname, max_wildcards=1):
        """Matching according to RFC 6125, section 6.4.3

        http://tools.ietf.org/html/rfc6125#section-6.4.3
        """
        pats = []
        if not dn:
            return False

        parts = dn.split('.')
        leftmost, remainder = parts[0], parts[1:]

        wildcards = leftmost.count('*')
        if wildcards > max_wildcards:
            # Issue #17980: avoid denials of service by refusing more
            # than one wildcard per fragment.  A survey of established
            # policy among SSL implementations showed it to be a
            # reasonable choice.
            raise CertificateError(
                "too many wildcards in certificate DNS name: " + repr(dn))

        # speed up common case w/o wildcards
        if not wildcards:
            return dn.lower() == hostname.lower()

        # RFC 6125, section 6.4.3, subitem 1.
        # The client SHOULD NOT attempt to match a presented identifier in which
        # the wildcard character comprises a label other than the left-most label.
        if leftmost == '*':
            # When '*' is a fragment by itself, it matches a non-empty dotless
            # fragment.
            pats.append('[^.]+')
        elif leftmost.startswith('xn--') or hostname.startswith('xn--'):
            # RFC 6125, section 6.4.3, subitem 3.
            # The client SHOULD NOT attempt to match a presented identifier
            # where the wildcard character is embedded within an A-label or
            # U-label of an internationalized domain name.
            pats.append(re.escape(leftmost))
        else:
            # Otherwise, '*' matches any dotless string, e.g. www*
            pats.append(re.escape(leftmost).replace(r'\*', '[^.]*'))

        # add the remaining fragments, ignore any wildcards
        for frag in remainder:
            pats.append(re.escape(frag))

        pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE)
        return pat.match(hostname)


    def match_hostname(cert, hostname):
        """Verify that *cert* (in decoded format as returned by
        SSLSocket.getpeercert()) matches the *hostname*.  RFC 2818 and RFC 6125
        rules are followed, but IP addresses are not accepted for *hostname*.

        CertificateError is raised on failure. On success, the function
        returns nothing.
        """
        if not cert:
            raise ValueError("empty or no certificate, match_hostname needs a "
                             "SSL socket or SSL context with either "
                             "CERT_OPTIONAL or CERT_REQUIRED")
        dnsnames = []
        san = cert.get('subjectAltName', ())
        for key, value in san:
            if key == 'DNS':
                if _dnsname_match(value, hostname):
                    return
                dnsnames.append(value)
        if not dnsnames:
            # The subject is only checked when there is no dNSName entry
            # in subjectAltName
            for sub in cert.get('subject', ()):
                for key, value in sub:
                    # XXX according to RFC 2818, the most specific Common Name
                    # must be used.
                    if key == 'commonName':
                        if _dnsname_match(value, hostname):
                            return
                        dnsnames.append(value)
        if len(dnsnames) > 1:
            raise CertificateError("hostname %r "
                "doesn't match either of %s"
                % (hostname, ', '.join(map(repr, dnsnames))))
        elif len(dnsnames) == 1:
            raise CertificateError("hostname %r "
                "doesn't match %r"
                % (hostname, dnsnames[0]))
        else:
            raise CertificateError("no appropriate commonName or "
                "subjectAltName fields were found")


try:
    from types import SimpleNamespace as Container
except ImportError:  # pragma: no cover
    class Container(object):
        """
        A generic container for when multiple values need to be returned
        """
        def __init__(self, **kwargs):
            self.__dict__.update(kwargs)


try:
    from shutil import which
except ImportError:  # pragma: no cover
    # Implementation from Python 3.3
    def which(cmd, mode=os.F_OK | os.X_OK, path=None):
        """Given a command, mode, and a PATH string, return the path which
        conforms to the given mode on the PATH, or None if there is no such
        file.

        `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
        of os.environ.get("PATH"), or can be overridden with a custom search
        path.

        """
        # Check that a given file can be accessed with the correct mode.
        # Additionally check that `file` is not a directory, as on Windows
        # directories pass the os.access check.
        def _access_check(fn, mode):
            return (os.path.exists(fn) and os.access(fn, mode)
                    and not os.path.isdir(fn))

        # If we're given a path with a directory part, look it up directly rather
        # than referring to PATH directories. This includes checking relative to the
        # current directory, e.g. ./script
        if os.path.dirname(cmd):
            if _access_check(cmd, mode):
                return cmd
            return None

        if path is None:
            path = os.environ.get("PATH", os.defpath)
        if not path:
            return None
        path = path.split(os.pathsep)

        if sys.platform == "win32":
            # The current directory takes precedence on Windows.
            if not os.curdir in path:
                path.insert(0, os.curdir)

            # PATHEXT is necessary to check on Windows.
            pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
            # See if the given file matches any of the expected path extensions.
            # This will allow us to short circuit when given "python.exe".
            # If it does match, only test that one, otherwise we have to try
            # others.
            if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
                files = [cmd]
            else:
                files = [cmd + ext for ext in pathext]
        else:
            # On other platforms you don't have things like PATHEXT to tell you
            # what file suffixes are executable, so just pass on cmd as-is.
            files = [cmd]

        seen = set()
        for dir in path:
            normdir = os.path.normcase(dir)
            if not normdir in seen:
                seen.add(normdir)
                for thefile in files:
                    name = os.path.join(dir, thefile)
                    if _access_check(name, mode):
                        return name
        return None


# ZipFile is a context manager in 2.7, but not in 2.6

from zipfile import ZipFile as BaseZipFile

if hasattr(BaseZipFile, '__enter__'):  # pragma: no cover
    ZipFile = BaseZipFile
else:  # pragma: no cover
    from zipfile import ZipExtFile as BaseZipExtFile

    class ZipExtFile(BaseZipExtFile):
        def __init__(self, base):
            self.__dict__.update(base.__dict__)

        def __enter__(self):
            return self

        def __exit__(self, *exc_info):
            self.close()
            # return None, so if an exception occurred, it will propagate

    class ZipFile(BaseZipFile):
        def __enter__(self):
            return self

        def __exit__(self, *exc_info):
            self.close()
            # return None, so if an exception occurred, it will propagate

        def open(self, *args, **kwargs):
            base = BaseZipFile.open(self, *args, **kwargs)
            return ZipExtFile(base)

try:
    from platform import python_implementation
except ImportError: # pragma: no cover
    def python_implementation():
        """Return a string identifying the Python implementation."""
        if 'PyPy' in sys.version:
            return 'PyPy'
        if os.name == 'java':
            return 'Jython'
        if sys.version.startswith('IronPython'):
            return 'IronPython'
        return 'CPython'

try:
    import sysconfig
except ImportError: # pragma: no cover
    from ._backport import sysconfig

try:
    callable = callable
except NameError:   # pragma: no cover
    from collections import Callable

    def callable(obj):
        return isinstance(obj, Callable)


try:
    fsencode = os.fsencode
    fsdecode = os.fsdecode
except AttributeError:  # pragma: no cover
    # Issue #99: on some systems (e.g. containerised),
    # sys.getfilesystemencoding() returns None, and we need a real value,
    # so fall back to utf-8. From the CPython 2.7 docs relating to Unix and
    # sys.getfilesystemencoding(): the return value is "the user’s preference
    # according to the result of nl_langinfo(CODESET), or None if the
    # nl_langinfo(CODESET) failed."
    _fsencoding = sys.getfilesystemencoding() or 'utf-8'
    if _fsencoding == 'mbcs':
        _fserrors = 'strict'
    else:
        _fserrors = 'surrogateescape'

    def fsencode(filename):
        if isinstance(filename, bytes):
            return filename
        elif isinstance(filename, text_type):
            return filename.encode(_fsencoding, _fserrors)
        else:
            raise TypeError("expect bytes or str, not %s" %
                            type(filename).__name__)

    def fsdecode(filename):
        if isinstance(filename, text_type):
            return filename
        elif isinstance(filename, bytes):
            return filename.decode(_fsencoding, _fserrors)
        else:
            raise TypeError("expect bytes or str, not %s" %
                            type(filename).__name__)

try:
    from tokenize import detect_encoding
except ImportError: # pragma: no cover
    from codecs import BOM_UTF8, lookup
    import re

    cookie_re = re.compile(r"coding[:=]\s*([-\w.]+)")

    def _get_normal_name(orig_enc):
        """Imitates get_normal_name in tokenizer.c."""
        # Only care about the first 12 characters.
        enc = orig_enc[:12].lower().replace("_", "-")
        if enc == "utf-8" or enc.startswith("utf-8-"):
            return "utf-8"
        if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \
           enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")):
            return "iso-8859-1"
        return orig_enc

    def detect_encoding(readline):
        """
        The detect_encoding() function is used to detect the encoding that should
        be used to decode a Python source file.  It requires one argument, readline,
        in the same way as the tokenize() generator.

        It will call readline a maximum of twice, and return the encoding used
        (as a string) and a list of any lines (left as bytes) it has read in.

        It detects the encoding from the presence of a utf-8 bom or an encoding
        cookie as specified in pep-0263.  If both a bom and a cookie are present,
        but disagree, a SyntaxError will be raised.  If the encoding cookie is an
        invalid charset, raise a SyntaxError.  Note that if a utf-8 bom is found,
        'utf-8-sig' is returned.

        If no encoding is specified, then the default of 'utf-8' will be returned.
        """
        try:
            filename = readline.__self__.name
        except AttributeError:
            filename = None
        bom_found = False
        encoding = None
        default = 'utf-8'
        def read_or_stop():
            try:
                return readline()
            except StopIteration:
                return b''

        def find_cookie(line):
            try:
                # Decode as UTF-8. Either the line is an encoding declaration,
                # in which case it should be pure ASCII, or it must be UTF-8
                # per default encoding.
                line_string = line.decode('utf-8')
            except UnicodeDecodeError:
                msg = "invalid or missing encoding declaration"
                if filename is not None:
                    msg = '{} for {!r}'.format(msg, filename)
                raise SyntaxError(msg)

            matches = cookie_re.findall(line_string)
            if not matches:
                return None
            encoding = _get_normal_name(matches[0])
            try:
                codec = lookup(encoding)
            except LookupError:
                # This behaviour mimics the Python interpreter
                if filename is None:
                    msg = "unknown encoding: " + encoding
                else:
                    msg = "unknown encoding for {!r}: {}".format(filename,
                            encoding)
                raise SyntaxError(msg)

            if bom_found:
                if codec.name != 'utf-8':
                    # This behaviour mimics the Python interpreter
                    if filename is None:
                        msg = 'encoding problem: utf-8'
                    else:
                        msg = 'encoding problem for {!r}: utf-8'.format(filename)
                    raise SyntaxError(msg)
                encoding += '-sig'
            return encoding

        first = read_or_stop()
        if first.startswith(BOM_UTF8):
            bom_found = True
            first = first[3:]
            default = 'utf-8-sig'
        if not first:
            return default, []

        encoding = find_cookie(first)
        if encoding:
            return encoding, [first]

        second = read_or_stop()
        if not second:
            return default, [first]

        encoding = find_cookie(second)
        if encoding:
            return encoding, [first, second]

        return default, [first, second]

# For converting & <-> & etc.
try:
    from html import escape
except ImportError:
    from cgi import escape
if sys.version_info[:2] < (3, 4):
    unescape = HTMLParser().unescape
else:
    from html import unescape

try:
    from collections import ChainMap
except ImportError: # pragma: no cover
    from collections import MutableMapping

    try:
        from reprlib import recursive_repr as _recursive_repr
    except ImportError:
        def _recursive_repr(fillvalue='...'):
            '''
            Decorator to make a repr function return fillvalue for a recursive
            call
            '''

            def decorating_function(user_function):
                repr_running = set()

                def wrapper(self):
                    key = id(self), get_ident()
                    if key in repr_running:
                        return fillvalue
                    repr_running.add(key)
                    try:
                        result = user_function(self)
                    finally:
                        repr_running.discard(key)
                    return result

                # Can't use functools.wraps() here because of bootstrap issues
                wrapper.__module__ = getattr(user_function, '__module__')
                wrapper.__doc__ = getattr(user_function, '__doc__')
                wrapper.__name__ = getattr(user_function, '__name__')
                wrapper.__annotations__ = getattr(user_function, '__annotations__', {})
                return wrapper

            return decorating_function

    class ChainMap(MutableMapping):
        ''' A ChainMap groups multiple dicts (or other mappings) together
        to create a single, updateable view.

        The underlying mappings are stored in a list.  That list is public and can
        accessed or updated using the *maps* attribute.  There is no other state.

        Lookups search the underlying mappings successively until a key is found.
        In contrast, writes, updates, and deletions only operate on the first
        mapping.

        '''

        def __init__(self, *maps):
            '''Initialize a ChainMap by setting *maps* to the given mappings.
            If no mappings are provided, a single empty dictionary is used.

            '''
            self.maps = list(maps) or [{}]          # always at least one map

        def __missing__(self, key):
            raise KeyError(key)

        def __getitem__(self, key):
            for mapping in self.maps:
                try:
                    return mapping[key]             # can't use 'key in mapping' with defaultdict
                except KeyError:
                    pass
            return self.__missing__(key)            # support subclasses that define __missing__

        def get(self, key, default=None):
            return self[key] if key in self else default

        def __len__(self):
            return len(set().union(*self.maps))     # reuses stored hash values if possible

        def __iter__(self):
            return iter(set().union(*self.maps))

        def __contains__(self, key):
            return any(key in m for m in self.maps)

        def __bool__(self):
            return any(self.maps)

        @_recursive_repr()
        def __repr__(self):
            return '{0.__class__.__name__}({1})'.format(
                self, ', '.join(map(repr, self.maps)))

        @classmethod
        def fromkeys(cls, iterable, *args):
            'Create a ChainMap with a single dict created from the iterable.'
            return cls(dict.fromkeys(iterable, *args))

        def copy(self):
            'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]'
            return self.__class__(self.maps[0].copy(), *self.maps[1:])

        __copy__ = copy

        def new_child(self):                        # like Django's Context.push()
            'New ChainMap with a new dict followed by all previous maps.'
            return self.__class__({}, *self.maps)

        @property
        def parents(self):                          # like Django's Context.pop()
            'New ChainMap from maps[1:].'
            return self.__class__(*self.maps[1:])

        def __setitem__(self, key, value):
            self.maps[0][key] = value

        def __delitem__(self, key):
            try:
                del self.maps[0][key]
            except KeyError:
                raise KeyError('Key not found in the first mapping: {!r}'.format(key))

        def popitem(self):
            'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.'
            try:
                return self.maps[0].popitem()
            except KeyError:
                raise KeyError('No keys found in the first mapping.')

        def pop(self, key, *args):
            'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].'
            try:
                return self.maps[0].pop(key, *args)
            except KeyError:
                raise KeyError('Key not found in the first mapping: {!r}'.format(key))

        def clear(self):
            'Clear maps[0], leaving maps[1:] intact.'
            self.maps[0].clear()

try:
    from importlib.util import cache_from_source  # Python >= 3.4
except ImportError:  # pragma: no cover
    try:
        from imp import cache_from_source
    except ImportError:  # pragma: no cover
        def cache_from_source(path, debug_override=None):
            assert path.endswith('.py')
            if debug_override is None:
                debug_override = __debug__
            if debug_override:
                suffix = 'c'
            else:
                suffix = 'o'
            return path + suffix

try:
    from collections import OrderedDict
except ImportError: # pragma: no cover
## {{{ http://code.activestate.com/recipes/576693/ (r9)
# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy.
# Passes Python2.7's test suite and incorporates all the latest updates.
    try:
        from thread import get_ident as _get_ident
    except ImportError:
        from dummy_thread import get_ident as _get_ident

    try:
        from _abcoll import KeysView, ValuesView, ItemsView
    except ImportError:
        pass


    class OrderedDict(dict):
        'Dictionary that remembers insertion order'
        # An inherited dict maps keys to values.
        # The inherited dict provides __getitem__, __len__, __contains__, and get.
        # The remaining methods are order-aware.
        # Big-O running times for all methods are the same as for regular dictionaries.

        # The internal self.__map dictionary maps keys to links in a doubly linked list.
        # The circular doubly linked list starts and ends with a sentinel element.
        # The sentinel element never gets deleted (this simplifies the algorithm).
        # Each link is stored as a list of length three:  [PREV, NEXT, KEY].

        def __init__(self, *args, **kwds):
            '''Initialize an ordered dictionary.  Signature is the same as for
            regular dictionaries, but keyword arguments are not recommended
            because their insertion order is arbitrary.

            '''
            if len(args) > 1:
                raise TypeError('expected at most 1 arguments, got %d' % len(args))
            try:
                self.__root
            except AttributeError:
                self.__root = root = []                     # sentinel node
                root[:] = [root, root, None]
                self.__map = {}
            self.__update(*args, **kwds)

        def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
            'od.__setitem__(i, y) <==> od[i]=y'
            # Setting a new item creates a new link which goes at the end of the linked
            # list, and the inherited dictionary is updated with the new key/value pair.
            if key not in self:
                root = self.__root
                last = root[0]
                last[1] = root[0] = self.__map[key] = [last, root, key]
            dict_setitem(self, key, value)

        def __delitem__(self, key, dict_delitem=dict.__delitem__):
            'od.__delitem__(y) <==> del od[y]'
            # Deleting an existing item uses self.__map to find the link which is
            # then removed by updating the links in the predecessor and successor nodes.
            dict_delitem(self, key)
            link_prev, link_next, key = self.__map.pop(key)
            link_prev[1] = link_next
            link_next[0] = link_prev

        def __iter__(self):
            'od.__iter__() <==> iter(od)'
            root = self.__root
            curr = root[1]
            while curr is not root:
                yield curr[2]
                curr = curr[1]

        def __reversed__(self):
            'od.__reversed__() <==> reversed(od)'
            root = self.__root
            curr = root[0]
            while curr is not root:
                yield curr[2]
                curr = curr[0]

        def clear(self):
            'od.clear() -> None.  Remove all items from od.'
            try:
                for node in self.__map.itervalues():
                    del node[:]
                root = self.__root
                root[:] = [root, root, None]
                self.__map.clear()
            except AttributeError:
                pass
            dict.clear(self)

        def popitem(self, last=True):
            '''od.popitem() -> (k, v), return and remove a (key, value) pair.
            Pairs are returned in LIFO order if last is true or FIFO order if false.

            '''
            if not self:
                raise KeyError('dictionary is empty')
            root = self.__root
            if last:
                link = root[0]
                link_prev = link[0]
                link_prev[1] = root
                root[0] = link_prev
            else:
                link = root[1]
                link_next = link[1]
                root[1] = link_next
                link_next[0] = root
            key = link[2]
            del self.__map[key]
            value = dict.pop(self, key)
            return key, value

        # -- the following methods do not depend on the internal structure --

        def keys(self):
            'od.keys() -> list of keys in od'
            return list(self)

        def values(self):
            'od.values() -> list of values in od'
            return [self[key] for key in self]

        def items(self):
            'od.items() -> list of (key, value) pairs in od'
            return [(key, self[key]) for key in self]

        def iterkeys(self):
            'od.iterkeys() -> an iterator over the keys in od'
            return iter(self)

        def itervalues(self):
            'od.itervalues -> an iterator over the values in od'
            for k in self:
                yield self[k]

        def iteritems(self):
            'od.iteritems -> an iterator over the (key, value) items in od'
            for k in self:
                yield (k, self[k])

        def update(*args, **kwds):
            '''od.update(E, **F) -> None.  Update od from dict/iterable E and F.

            If E is a dict instance, does:           for k in E: od[k] = E[k]
            If E has a .keys() method, does:         for k in E.keys(): od[k] = E[k]
            Or if E is an iterable of items, does:   for k, v in E: od[k] = v
            In either case, this is followed by:     for k, v in F.items(): od[k] = v

            '''
            if len(args) > 2:
                raise TypeError('update() takes at most 2 positional '
                                'arguments (%d given)' % (len(args),))
            elif not args:
                raise TypeError('update() takes at least 1 argument (0 given)')
            self = args[0]
            # Make progressively weaker assumptions about "other"
            other = ()
            if len(args) == 2:
                other = args[1]
            if isinstance(other, dict):
                for key in other:
                    self[key] = other[key]
            elif hasattr(other, 'keys'):
                for key in other.keys():
                    self[key] = other[key]
            else:
                for key, value in other:
                    self[key] = value
            for key, value in kwds.items():
                self[key] = value

        __update = update  # let subclasses override update without breaking __init__

        __marker = object()

        def pop(self, key, default=__marker):
            '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value.
            If key is not found, d is returned if given, otherwise KeyError is raised.

            '''
            if key in self:
                result = self[key]
                del self[key]
                return result
            if default is self.__marker:
                raise KeyError(key)
            return default

        def setdefault(self, key, default=None):
            'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
            if key in self:
                return self[key]
            self[key] = default
            return default

        def __repr__(self, _repr_running=None):
            'od.__repr__() <==> repr(od)'
            if not _repr_running: _repr_running = {}
            call_key = id(self), _get_ident()
            if call_key in _repr_running:
                return '...'
            _repr_running[call_key] = 1
            try:
                if not self:
                    return '%s()' % (self.__class__.__name__,)
                return '%s(%r)' % (self.__class__.__name__, self.items())
            finally:
                del _repr_running[call_key]

        def __reduce__(self):
            'Return state information for pickling'
            items = [[k, self[k]] for k in self]
            inst_dict = vars(self).copy()
            for k in vars(OrderedDict()):
                inst_dict.pop(k, None)
            if inst_dict:
                return (self.__class__, (items,), inst_dict)
            return self.__class__, (items,)

        def copy(self):
            'od.copy() -> a shallow copy of od'
            return self.__class__(self)

        @classmethod
        def fromkeys(cls, iterable, value=None):
            '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
            and values equal to v (which defaults to None).

            '''
            d = cls()
            for key in iterable:
                d[key] = value
            return d

        def __eq__(self, other):
            '''od.__eq__(y) <==> od==y.  Comparison to another OD is order-sensitive
            while comparison to a regular mapping is order-insensitive.

            '''
            if isinstance(other, OrderedDict):
                return len(self)==len(other) and self.items() == other.items()
            return dict.__eq__(self, other)

        def __ne__(self, other):
            return not self == other

        # -- the following methods are only used in Python 2.7 --

        def viewkeys(self):
            "od.viewkeys() -> a set-like object providing a view on od's keys"
            return KeysView(self)

        def viewvalues(self):
            "od.viewvalues() -> an object providing a view on od's values"
            return ValuesView(self)

        def viewitems(self):
            "od.viewitems() -> a set-like object providing a view on od's items"
            return ItemsView(self)

try:
    from logging.config import BaseConfigurator, valid_ident
except ImportError: # pragma: no cover
    IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I)


    def valid_ident(s):
        m = IDENTIFIER.match(s)
        if not m:
            raise ValueError('Not a valid Python identifier: %r' % s)
        return True


    # The ConvertingXXX classes are wrappers around standard Python containers,
    # and they serve to convert any suitable values in the container. The
    # conversion converts base dicts, lists and tuples to their wrapped
    # equivalents, whereas strings which match a conversion format are converted
    # appropriately.
    #
    # Each wrapper should have a configurator attribute holding the actual
    # configurator to use for conversion.

    class ConvertingDict(dict):
        """A converting dictionary wrapper."""

        def __getitem__(self, key):
            value = dict.__getitem__(self, key)
            result = self.configurator.convert(value)
            #If the converted value is different, save for next time
            if value is not result:
                self[key] = result
                if type(result) in (ConvertingDict, ConvertingList,
                                    ConvertingTuple):
                    result.parent = self
                    result.key = key
            return result

        def get(self, key, default=None):
            value = dict.get(self, key, default)
            result = self.configurator.convert(value)
            #If the converted value is different, save for next time
            if value is not result:
                self[key] = result
                if type(result) in (ConvertingDict, ConvertingList,
                                    ConvertingTuple):
                    result.parent = self
                    result.key = key
            return result

    def pop(self, key, default=None):
        value = dict.pop(self, key, default)
        result = self.configurator.convert(value)
        if value is not result:
            if type(result) in (ConvertingDict, ConvertingList,
                                ConvertingTuple):
                result.parent = self
                result.key = key
        return result

    class ConvertingList(list):
        """A converting list wrapper."""
        def __getitem__(self, key):
            value = list.__getitem__(self, key)
            result = self.configurator.convert(value)
            #If the converted value is different, save for next time
            if value is not result:
                self[key] = result
                if type(result) in (ConvertingDict, ConvertingList,
                                    ConvertingTuple):
                    result.parent = self
                    result.key = key
            return result

        def pop(self, idx=-1):
            value = list.pop(self, idx)
            result = self.configurator.convert(value)
            if value is not result:
                if type(result) in (ConvertingDict, ConvertingList,
                                    ConvertingTuple):
                    result.parent = self
            return result

    class ConvertingTuple(tuple):
        """A converting tuple wrapper."""
        def __getitem__(self, key):
            value = tuple.__getitem__(self, key)
            result = self.configurator.convert(value)
            if value is not result:
                if type(result) in (ConvertingDict, ConvertingList,
                                    ConvertingTuple):
                    result.parent = self
                    result.key = key
            return result

    class BaseConfigurator(object):
        """
        The configurator base class which defines some useful defaults.
        """

        CONVERT_PATTERN = re.compile(r'^(?P[a-z]+)://(?P.*)$')

        WORD_PATTERN = re.compile(r'^\s*(\w+)\s*')
        DOT_PATTERN = re.compile(r'^\.\s*(\w+)\s*')
        INDEX_PATTERN = re.compile(r'^\[\s*(\w+)\s*\]\s*')
        DIGIT_PATTERN = re.compile(r'^\d+$')

        value_converters = {
            'ext' : 'ext_convert',
            'cfg' : 'cfg_convert',
        }

        # We might want to use a different one, e.g. importlib
        importer = staticmethod(__import__)

        def __init__(self, config):
            self.config = ConvertingDict(config)
            self.config.configurator = self

        def resolve(self, s):
            """
            Resolve strings to objects using standard import and attribute
            syntax.
            """
            name = s.split('.')
            used = name.pop(0)
            try:
                found = self.importer(used)
                for frag in name:
                    used += '.' + frag
                    try:
                        found = getattr(found, frag)
                    except AttributeError:
                        self.importer(used)
                        found = getattr(found, frag)
                return found
            except ImportError:
                e, tb = sys.exc_info()[1:]
                v = ValueError('Cannot resolve %r: %s' % (s, e))
                v.__cause__, v.__traceback__ = e, tb
                raise v

        def ext_convert(self, value):
            """Default converter for the ext:// protocol."""
            return self.resolve(value)

        def cfg_convert(self, value):
            """Default converter for the cfg:// protocol."""
            rest = value
            m = self.WORD_PATTERN.match(rest)
            if m is None:
                raise ValueError("Unable to convert %r" % value)
            else:
                rest = rest[m.end():]
                d = self.config[m.groups()[0]]
                #print d, rest
                while rest:
                    m = self.DOT_PATTERN.match(rest)
                    if m:
                        d = d[m.groups()[0]]
                    else:
                        m = self.INDEX_PATTERN.match(rest)
                        if m:
                            idx = m.groups()[0]
                            if not self.DIGIT_PATTERN.match(idx):
                                d = d[idx]
                            else:
                                try:
                                    n = int(idx) # try as number first (most likely)
                                    d = d[n]
                                except TypeError:
                                    d = d[idx]
                    if m:
                        rest = rest[m.end():]
                    else:
                        raise ValueError('Unable to convert '
                                         '%r at %r' % (value, rest))
            #rest should be empty
            return d

        def convert(self, value):
            """
            Convert values to an appropriate type. dicts, lists and tuples are
            replaced by their converting alternatives. Strings are checked to
            see if they have a conversion format and are converted if they do.
            """
            if not isinstance(value, ConvertingDict) and isinstance(value, dict):
                value = ConvertingDict(value)
                value.configurator = self
            elif not isinstance(value, ConvertingList) and isinstance(value, list):
                value = ConvertingList(value)
                value.configurator = self
            elif not isinstance(value, ConvertingTuple) and\
                     isinstance(value, tuple):
                value = ConvertingTuple(value)
                value.configurator = self
            elif isinstance(value, string_types):
                m = self.CONVERT_PATTERN.match(value)
                if m:
                    d = m.groupdict()
                    prefix = d['prefix']
                    converter = self.value_converters.get(prefix, None)
                    if converter:
                        suffix = d['suffix']
                        converter = getattr(self, converter)
                        value = converter(suffix)
            return value

        def configure_custom(self, config):
            """Configure an object with a user-supplied factory."""
            c = config.pop('()')
            if not callable(c):
                c = self.resolve(c)
            props = config.pop('.', None)
            # Check for valid identifiers
            kwargs = dict([(k, config[k]) for k in config if valid_ident(k)])
            result = c(**kwargs)
            if props:
                for name, value in props.items():
                    setattr(result, name, value)
            return result

        def as_tuple(self, value):
            """Utility function which converts lists to tuples."""
            if isinstance(value, list):
                value = tuple(value)
            return value
PKÕ¶N]ý¹È¢?¢?,site-packages/pip/_vendor/distlib/scripts.pynu„[µü¤# -*- coding: utf-8 -*-
#
# Copyright (C) 2013-2015 Vinay Sajip.
# Licensed to the Python Software Foundation under a contributor agreement.
# See LICENSE.txt and CONTRIBUTORS.txt.
#
from io import BytesIO
import logging
import os
import re
import struct
import sys

from .compat import sysconfig, detect_encoding, ZipFile
from .resources import finder
from .util import (FileOperator, get_export_entry, convert_path,
                   get_executable, in_venv)

logger = logging.getLogger(__name__)

_DEFAULT_MANIFEST = '''


 

 
 
 
 
 
 
 
 
'''.strip()

# check if Python is called on the first line with this expression
FIRST_LINE_RE = re.compile(b'^#!.*pythonw?[0-9.]*([ \t].*)?$')
SCRIPT_TEMPLATE = r'''# -*- coding: utf-8 -*-
import re
import sys
from %(module)s import %(import_name)s
if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
    sys.exit(%(func)s())
'''


def _enquote_executable(executable):
    if ' ' in executable:
        # make sure we quote only the executable in case of env
        # for example /usr/bin/env "/dir with spaces/bin/jython"
        # instead of "/usr/bin/env /dir with spaces/bin/jython"
        # otherwise whole
        if executable.startswith('/usr/bin/env '):
            env, _executable = executable.split(' ', 1)
            if ' ' in _executable and not _executable.startswith('"'):
                executable = '%s "%s"' % (env, _executable)
        else:
            if not executable.startswith('"'):
                executable = '"%s"' % executable
    return executable


class ScriptMaker(object):
    """
    A class to copy or create scripts from source scripts or callable
    specifications.
    """
    script_template = SCRIPT_TEMPLATE

    executable = None  # for shebangs

    def __init__(self, source_dir, target_dir, add_launchers=True,
                 dry_run=False, fileop=None):
        self.source_dir = source_dir
        self.target_dir = target_dir
        self.add_launchers = add_launchers
        self.force = False
        self.clobber = False
        # It only makes sense to set mode bits on POSIX.
        self.set_mode = (os.name == 'posix') or (os.name == 'java' and
                                                 os._name == 'posix')
        self.variants = set(('', 'X.Y'))
        self._fileop = fileop or FileOperator(dry_run)

        self._is_nt = os.name == 'nt' or (
            os.name == 'java' and os._name == 'nt')

    def _get_alternate_executable(self, executable, options):
        if options.get('gui', False) and self._is_nt:  # pragma: no cover
            dn, fn = os.path.split(executable)
            fn = fn.replace('python', 'pythonw')
            executable = os.path.join(dn, fn)
        return executable

    if sys.platform.startswith('java'):  # pragma: no cover
        def _is_shell(self, executable):
            """
            Determine if the specified executable is a script
            (contains a #! line)
            """
            try:
                with open(executable) as fp:
                    return fp.read(2) == '#!'
            except (OSError, IOError):
                logger.warning('Failed to open %s', executable)
                return False

        def _fix_jython_executable(self, executable):
            if self._is_shell(executable):
                # Workaround for Jython is not needed on Linux systems.
                import java

                if java.lang.System.getProperty('os.name') == 'Linux':
                    return executable
            elif executable.lower().endswith('jython.exe'):
                # Use wrapper exe for Jython on Windows
                return executable
            return '/usr/bin/env %s' % executable

    def _build_shebang(self, executable, post_interp):
        """
        Build a shebang line. In the simple case (on Windows, or a shebang line
        which is not too long or contains spaces) use a simple formulation for
        the shebang. Otherwise, use /bin/sh as the executable, with a contrived
        shebang which allows the script to run either under Python or sh, using
        suitable quoting. Thanks to Harald Nordgren for his input.

        See also: http://www.in-ulm.de/~mascheck/various/shebang/#length
                  https://hg.mozilla.org/mozilla-central/file/tip/mach
        """
        if os.name != 'posix':
            simple_shebang = True
        else:
            # Add 3 for '#!' prefix and newline suffix.
            shebang_length = len(executable) + len(post_interp) + 3
            if sys.platform == 'darwin':
                max_shebang_length = 512
            else:
                max_shebang_length = 127
            simple_shebang = ((b' ' not in executable) and
                              (shebang_length <= max_shebang_length))

        if simple_shebang:
            result = b'#!' + executable + post_interp + b'\n'
        else:
            result = b'#!/bin/sh\n'
            result += b"'''exec' " + executable + post_interp + b' "$0" "$@"\n'
            result += b"' '''"
        return result

    def _get_shebang(self, encoding, post_interp=b'', options=None):
        enquote = True
        if self.executable:
            executable = self.executable
            enquote = False     # assume this will be taken care of
        elif not sysconfig.is_python_build():
            executable = get_executable()
        elif in_venv():  # pragma: no cover
            executable = os.path.join(sysconfig.get_path('scripts'),
                            'python%s' % sysconfig.get_config_var('EXE'))
        else:  # pragma: no cover
            executable = os.path.join(
                sysconfig.get_config_var('BINDIR'),
               'python%s%s' % (sysconfig.get_config_var('VERSION'),
                               sysconfig.get_config_var('EXE')))
        if options:
            executable = self._get_alternate_executable(executable, options)

        if sys.platform.startswith('java'):  # pragma: no cover
            executable = self._fix_jython_executable(executable)
        # Normalise case for Windows
        executable = os.path.normcase(executable)
        # If the user didn't specify an executable, it may be necessary to
        # cater for executable paths with spaces (not uncommon on Windows)
        if enquote:
            executable = _enquote_executable(executable)
        # Issue #51: don't use fsencode, since we later try to
        # check that the shebang is decodable using utf-8.
        executable = executable.encode('utf-8')
        # in case of IronPython, play safe and enable frames support
        if (sys.platform == 'cli' and '-X:Frames' not in post_interp
            and '-X:FullFrames' not in post_interp):  # pragma: no cover
            post_interp += b' -X:Frames'
        shebang = self._build_shebang(executable, post_interp)
        # Python parser starts to read a script using UTF-8 until
        # it gets a #coding:xxx cookie. The shebang has to be the
        # first line of a file, the #coding:xxx cookie cannot be
        # written before. So the shebang has to be decodable from
        # UTF-8.
        try:
            shebang.decode('utf-8')
        except UnicodeDecodeError:  # pragma: no cover
            raise ValueError(
                'The shebang (%r) is not decodable from utf-8' % shebang)
        # If the script is encoded to a custom encoding (use a
        # #coding:xxx cookie), the shebang has to be decodable from
        # the script encoding too.
        if encoding != 'utf-8':
            try:
                shebang.decode(encoding)
            except UnicodeDecodeError:  # pragma: no cover
                raise ValueError(
                    'The shebang (%r) is not decodable '
                    'from the script encoding (%r)' % (shebang, encoding))
        return shebang

    def _get_script_text(self, entry):
        return self.script_template % dict(module=entry.prefix,
                                           import_name=entry.suffix.split('.')[0],
                                           func=entry.suffix)

    manifest = _DEFAULT_MANIFEST

    def get_manifest(self, exename):
        base = os.path.basename(exename)
        return self.manifest % base

    def _write_script(self, names, shebang, script_bytes, filenames, ext):
        use_launcher = self.add_launchers and self._is_nt
        linesep = os.linesep.encode('utf-8')
        if not shebang.endswith(linesep):
            shebang += linesep
        if not use_launcher:
            script_bytes = shebang + script_bytes
        else:  # pragma: no cover
            if ext == 'py':
                launcher = self._get_launcher('t')
            else:
                launcher = self._get_launcher('w')
            stream = BytesIO()
            with ZipFile(stream, 'w') as zf:
                zf.writestr('__main__.py', script_bytes)
            zip_data = stream.getvalue()
            script_bytes = launcher + shebang + zip_data
        for name in names:
            outname = os.path.join(self.target_dir, name)
            if use_launcher:  # pragma: no cover
                n, e = os.path.splitext(outname)
                if e.startswith('.py'):
                    outname = n
                outname = '%s.exe' % outname
                try:
                    self._fileop.write_binary_file(outname, script_bytes)
                except Exception:
                    # Failed writing an executable - it might be in use.
                    logger.warning('Failed to write executable - trying to '
                                   'use .deleteme logic')
                    dfname = '%s.deleteme' % outname
                    if os.path.exists(dfname):
                        os.remove(dfname)       # Not allowed to fail here
                    os.rename(outname, dfname)  # nor here
                    self._fileop.write_binary_file(outname, script_bytes)
                    logger.debug('Able to replace executable using '
                                 '.deleteme logic')
                    try:
                        os.remove(dfname)
                    except Exception:
                        pass    # still in use - ignore error
            else:
                if self._is_nt and not outname.endswith('.' + ext):  # pragma: no cover
                    outname = '%s.%s' % (outname, ext)
                if os.path.exists(outname) and not self.clobber:
                    logger.warning('Skipping existing file %s', outname)
                    continue
                self._fileop.write_binary_file(outname, script_bytes)
                if self.set_mode:
                    self._fileop.set_executable_mode([outname])
            filenames.append(outname)

    def _make_script(self, entry, filenames, options=None):
        post_interp = b''
        if options:
            args = options.get('interpreter_args', [])
            if args:
                args = ' %s' % ' '.join(args)
                post_interp = args.encode('utf-8')
        shebang = self._get_shebang('utf-8', post_interp, options=options)
        script = self._get_script_text(entry).encode('utf-8')
        name = entry.name
        scriptnames = set()
        if '' in self.variants:
            scriptnames.add(name)
        if 'X' in self.variants:
            scriptnames.add('%s%s' % (name, sys.version[0]))
        if 'X.Y' in self.variants:
            scriptnames.add('%s-%s' % (name, sys.version[:3]))
        if options and options.get('gui', False):
            ext = 'pyw'
        else:
            ext = 'py'
        self._write_script(scriptnames, shebang, script, filenames, ext)

    def _copy_script(self, script, filenames):
        adjust = False
        script = os.path.join(self.source_dir, convert_path(script))
        outname = os.path.join(self.target_dir, os.path.basename(script))
        if not self.force and not self._fileop.newer(script, outname):
            logger.debug('not copying %s (up-to-date)', script)
            return

        # Always open the file, but ignore failures in dry-run mode --
        # that way, we'll get accurate feedback if we can read the
        # script.
        try:
            f = open(script, 'rb')
        except IOError:  # pragma: no cover
            if not self.dry_run:
                raise
            f = None
        else:
            first_line = f.readline()
            if not first_line:  # pragma: no cover
                logger.warning('%s: %s is an empty file (skipping)',
                               self.get_command_name(),  script)
                return

            match = FIRST_LINE_RE.match(first_line.replace(b'\r\n', b'\n'))
            if match:
                adjust = True
                post_interp = match.group(1) or b''

        if not adjust:
            if f:
                f.close()
            self._fileop.copy_file(script, outname)
            if self.set_mode:
                self._fileop.set_executable_mode([outname])
            filenames.append(outname)
        else:
            logger.info('copying and adjusting %s -> %s', script,
                        self.target_dir)
            if not self._fileop.dry_run:
                encoding, lines = detect_encoding(f.readline)
                f.seek(0)
                shebang = self._get_shebang(encoding, post_interp)
                if b'pythonw' in first_line:  # pragma: no cover
                    ext = 'pyw'
                else:
                    ext = 'py'
                n = os.path.basename(outname)
                self._write_script([n], shebang, f.read(), filenames, ext)
            if f:
                f.close()

    @property
    def dry_run(self):
        return self._fileop.dry_run

    @dry_run.setter
    def dry_run(self, value):
        self._fileop.dry_run = value

    if os.name == 'nt' or (os.name == 'java' and os._name == 'nt'):  # pragma: no cover
        # Executable launcher support.
        # Launchers are from https://bitbucket.org/vinay.sajip/simple_launcher/

        def _get_launcher(self, kind):
            if struct.calcsize('P') == 8:   # 64-bit
                bits = '64'
            else:
                bits = '32'
            name = '%s%s.exe' % (kind, bits)
            # Issue 31: don't hardcode an absolute package name, but
            # determine it relative to the current package
            distlib_package = __name__.rsplit('.', 1)[0]
            result = finder(distlib_package).find(name).bytes
            return result

    # Public API follows

    def make(self, specification, options=None):
        """
        Make a script.

        :param specification: The specification, which is either a valid export
                              entry specification (to make a script from a
                              callable) or a filename (to make a script by
                              copying from a source location).
        :param options: A dictionary of options controlling script generation.
        :return: A list of all absolute pathnames written to.
        """
        filenames = []
        entry = get_export_entry(specification)
        if entry is None:
            self._copy_script(specification, filenames)
        else:
            self._make_script(entry, filenames, options=options)
        return filenames

    def make_multiple(self, specifications, options=None):
        """
        Take a list of specifications and make scripts from them,
        :param specifications: A list of specifications.
        :return: A list of all absolute pathnames written to,
        """
        filenames = []
        for specification in specifications:
            filenames.extend(self.make(specification, options))
        return filenames
PKÕ¶N]¼pGUÇUÇ-site-packages/pip/_vendor/distlib/database.pynu„[µü¤# -*- coding: utf-8 -*-
#
# Copyright (C) 2012-2017 The Python Software Foundation.
# See LICENSE.txt and CONTRIBUTORS.txt.
#
"""PEP 376 implementation."""

from __future__ import unicode_literals

import base64
import codecs
import contextlib
import hashlib
import logging
import os
import posixpath
import sys
import zipimport

from . import DistlibException, resources
from .compat import StringIO
from .version import get_scheme, UnsupportedVersionError
from .metadata import (Metadata, METADATA_FILENAME, WHEEL_METADATA_FILENAME,
                       LEGACY_METADATA_FILENAME)
from .util import (parse_requirement, cached_property, parse_name_and_version,
                   read_exports, write_exports, CSVReader, CSVWriter)


__all__ = ['Distribution', 'BaseInstalledDistribution',
           'InstalledDistribution', 'EggInfoDistribution',
           'DistributionPath']


logger = logging.getLogger(__name__)

EXPORTS_FILENAME = 'pydist-exports.json'
COMMANDS_FILENAME = 'pydist-commands.json'

DIST_FILES = ('INSTALLER', METADATA_FILENAME, 'RECORD', 'REQUESTED',
              'RESOURCES', EXPORTS_FILENAME, 'SHARED')

DISTINFO_EXT = '.dist-info'


class _Cache(object):
    """
    A simple cache mapping names and .dist-info paths to distributions
    """
    def __init__(self):
        """
        Initialise an instance. There is normally one for each DistributionPath.
        """
        self.name = {}
        self.path = {}
        self.generated = False

    def clear(self):
        """
        Clear the cache, setting it to its initial state.
        """
        self.name.clear()
        self.path.clear()
        self.generated = False

    def add(self, dist):
        """
        Add a distribution to the cache.
        :param dist: The distribution to add.
        """
        if dist.path not in self.path:
            self.path[dist.path] = dist
            self.name.setdefault(dist.key, []).append(dist)


class DistributionPath(object):
    """
    Represents a set of distributions installed on a path (typically sys.path).
    """
    def __init__(self, path=None, include_egg=False):
        """
        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.
        """
        if path is None:
            path = sys.path
        self.path = path
        self._include_dist = True
        self._include_egg = include_egg

        self._cache = _Cache()
        self._cache_egg = _Cache()
        self._cache_enabled = True
        self._scheme = get_scheme('default')

    def _get_cache_enabled(self):
        return self._cache_enabled

    def _set_cache_enabled(self, value):
        self._cache_enabled = value

    cache_enabled = property(_get_cache_enabled, _set_cache_enabled)

    def clear_cache(self):
        """
        Clears the internal cache.
        """
        self._cache.clear()
        self._cache_egg.clear()


    def _yield_distributions(self):
        """
        Yield .dist-info and/or .egg(-info) distributions.
        """
        # We need to check if we've seen some resources already, because on
        # some Linux systems (e.g. some Debian/Ubuntu variants) there are
        # symlinks which alias other files in the environment.
        seen = set()
        for path in self.path:
            finder = resources.finder_for_path(path)
            if finder is None:
                continue
            r = finder.find('')
            if not r or not r.is_container:
                continue
            rset = sorted(r.resources)
            for entry in rset:
                r = finder.find(entry)
                if not r or r.path in seen:
                    continue
                if self._include_dist and entry.endswith(DISTINFO_EXT):
                    possible_filenames = [METADATA_FILENAME,
                                          WHEEL_METADATA_FILENAME,
                                          LEGACY_METADATA_FILENAME]
                    for metadata_filename in possible_filenames:
                        metadata_path = posixpath.join(entry, metadata_filename)
                        pydist = finder.find(metadata_path)
                        if pydist:
                            break
                    else:
                        continue

                    with contextlib.closing(pydist.as_stream()) as stream:
                        metadata = Metadata(fileobj=stream, scheme='legacy')
                    logger.debug('Found %s', r.path)
                    seen.add(r.path)
                    yield new_dist_class(r.path, metadata=metadata,
                                         env=self)
                elif self._include_egg and entry.endswith(('.egg-info',
                                                          '.egg')):
                    logger.debug('Found %s', r.path)
                    seen.add(r.path)
                    yield old_dist_class(r.path, self)

    def _generate_cache(self):
        """
        Scan the path for distributions and populate the cache with
        those that are found.
        """
        gen_dist = not self._cache.generated
        gen_egg = self._include_egg and not self._cache_egg.generated
        if gen_dist or gen_egg:
            for dist in self._yield_distributions():
                if isinstance(dist, InstalledDistribution):
                    self._cache.add(dist)
                else:
                    self._cache_egg.add(dist)

            if gen_dist:
                self._cache.generated = True
            if gen_egg:
                self._cache_egg.generated = True

    @classmethod
    def distinfo_dirname(cls, name, version):
        """
        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: string"""
        name = name.replace('-', '_')
        return '-'.join([name, version]) + DISTINFO_EXT

    def get_distributions(self):
        """
        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
        """
        if not self._cache_enabled:
            for dist in self._yield_distributions():
                yield dist
        else:
            self._generate_cache()

            for dist in self._cache.path.values():
                yield dist

            if self._include_egg:
                for dist in self._cache_egg.path.values():
                    yield dist

    def get_distribution(self, name):
        """
        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``
        """
        result = None
        name = name.lower()
        if not self._cache_enabled:
            for dist in self._yield_distributions():
                if dist.key == name:
                    result = dist
                    break
        else:
            self._generate_cache()

            if name in self._cache.name:
                result = self._cache.name[name][0]
            elif self._include_egg and name in self._cache_egg.name:
                result = self._cache_egg.name[name][0]
        return result

    def provides_distribution(self, name, version=None):
        """
        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
        """
        matcher = None
        if version is not None:
            try:
                matcher = self._scheme.matcher('%s (%s)' % (name, version))
            except ValueError:
                raise DistlibException('invalid name or version: %r, %r' %
                                      (name, version))

        for dist in self.get_distributions():
            # We hit a problem on Travis where enum34 was installed and doesn't
            # have a provides attribute ...
            if not hasattr(dist, 'provides'):
                logger.debug('No "provides": %s', dist)
            else:
                provided = dist.provides

                for p in provided:
                    p_name, p_ver = parse_name_and_version(p)
                    if matcher is None:
                        if p_name == name:
                            yield dist
                            break
                    else:
                        if p_name == name and matcher.match(p_ver):
                            yield dist
                            break

    def get_file_path(self, name, relative_path):
        """
        Return the path to a resource file.
        """
        dist = self.get_distribution(name)
        if dist is None:
            raise LookupError('no distribution named %r found' % name)
        return dist.get_resource_path(relative_path)

    def get_exported_entries(self, category, name=None):
        """
        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.
        """
        for dist in self.get_distributions():
            r = dist.exports
            if category in r:
                d = r[category]
                if name is not None:
                    if name in d:
                        yield d[name]
                else:
                    for v in d.values():
                        yield v


class Distribution(object):
    """
    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.
    """

    build_time_dependency = False
    """
    Set to True if it's known to be only a build-time dependency (i.e.
    not needed after installation).
    """

    requested = False
    """A boolean that indicates whether the ``REQUESTED`` metadata file is
    present (in other words, whether the package was installed by user
    request or it was installed as a dependency)."""

    def __init__(self, metadata):
        """
        Initialise an instance.
        :param metadata: The instance of :class:`Metadata` describing this
        distribution.
        """
        self.metadata = metadata
        self.name = metadata.name
        self.key = self.name.lower()    # for case-insensitive comparisons
        self.version = metadata.version
        self.locator = None
        self.digest = None
        self.extras = None      # additional features requested
        self.context = None     # environment marker overrides
        self.download_urls = set()
        self.digests = {}

    @property
    def source_url(self):
        """
        The source archive download URL for this distribution.
        """
        return self.metadata.source_url

    download_url = source_url   # Backward compatibility

    @property
    def name_and_version(self):
        """
        A utility property which displays the name and version in parentheses.
        """
        return '%s (%s)' % (self.name, self.version)

    @property
    def provides(self):
        """
        A set of distribution names and versions provided by this distribution.
        :return: A set of "name (version)" strings.
        """
        plist = self.metadata.provides
        s = '%s (%s)' % (self.name, self.version)
        if s not in plist:
            plist.append(s)
        return plist

    def _get_requirements(self, req_attr):
        md = self.metadata
        logger.debug('Getting requirements from metadata %r', md.todict())
        reqts = getattr(md, req_attr)
        return set(md.get_requirements(reqts, extras=self.extras,
                                       env=self.context))

    @property
    def run_requires(self):
        return self._get_requirements('run_requires')

    @property
    def meta_requires(self):
        return self._get_requirements('meta_requires')

    @property
    def build_requires(self):
        return self._get_requirements('build_requires')

    @property
    def test_requires(self):
        return self._get_requirements('test_requires')

    @property
    def dev_requires(self):
        return self._get_requirements('dev_requires')

    def matches_requirement(self, req):
        """
        Say if this instance matches (fulfills) a requirement.
        :param req: The requirement to match.
        :rtype req: str
        :return: True if it matches, else False.
        """
        # Requirement may contain extras - parse to lose those
        # from what's passed to the matcher
        r = parse_requirement(req)
        scheme = get_scheme(self.metadata.scheme)
        try:
            matcher = scheme.matcher(r.requirement)
        except UnsupportedVersionError:
            # XXX compat-mode if cannot read the version
            logger.warning('could not read version %r - using name only',
                           req)
            name = req.split()[0]
            matcher = scheme.matcher(name)

        name = matcher.key   # case-insensitive

        result = False
        for p in self.provides:
            p_name, p_ver = parse_name_and_version(p)
            if p_name != name:
                continue
            try:
                result = matcher.match(p_ver)
                break
            except UnsupportedVersionError:
                pass
        return result

    def __repr__(self):
        """
        Return a textual representation of this instance,
        """
        if self.source_url:
            suffix = ' [%s]' % self.source_url
        else:
            suffix = ''
        return '' % (self.name, self.version, suffix)

    def __eq__(self, other):
        """
        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.
        """
        if type(other) is not type(self):
            result = False
        else:
            result = (self.name == other.name and
                      self.version == other.version and
                      self.source_url == other.source_url)
        return result

    def __hash__(self):
        """
        Compute hash in a way which matches the equality test.
        """
        return hash(self.name) + hash(self.version) + hash(self.source_url)


class BaseInstalledDistribution(Distribution):
    """
    This is the base class for installed distributions (whether PEP 376 or
    legacy).
    """

    hasher = None

    def __init__(self, metadata, path, env=None):
        """
        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.
        """
        super(BaseInstalledDistribution, self).__init__(metadata)
        self.path = path
        self.dist_path = env

    def get_hash(self, data, hasher=None):
        """
        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
        """
        if hasher is None:
            hasher = self.hasher
        if hasher is None:
            hasher = hashlib.md5
            prefix = ''
        else:
            hasher = getattr(hashlib, hasher)
            prefix = '%s=' % self.hasher
        digest = hasher(data).digest()
        digest = base64.urlsafe_b64encode(digest).rstrip(b'=').decode('ascii')
        return '%s%s' % (prefix, digest)


class InstalledDistribution(BaseInstalledDistribution):
    """
    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).
    """

    hasher = 'sha256'

    def __init__(self, path, metadata=None, env=None):
        self.modules = []
        self.finder = finder = resources.finder_for_path(path)
        if finder is None:
            raise ValueError('finder unavailable for %s' % path)
        if env and env._cache_enabled and path in env._cache.path:
            metadata = env._cache.path[path].metadata
        elif metadata is None:
            r = finder.find(METADATA_FILENAME)
            # Temporary - for Wheel 0.23 support
            if r is None:
                r = finder.find(WHEEL_METADATA_FILENAME)
            # Temporary - for legacy support
            if r is None:
                r = finder.find('METADATA')
            if r is None:
                raise ValueError('no %s found in %s' % (METADATA_FILENAME,
                                                        path))
            with contextlib.closing(r.as_stream()) as stream:
                metadata = Metadata(fileobj=stream, scheme='legacy')

        super(InstalledDistribution, self).__init__(metadata, path, env)

        if env and env._cache_enabled:
            env._cache.add(self)

        r = finder.find('REQUESTED')
        self.requested = r is not None
        p  = os.path.join(path, 'top_level.txt')
        if os.path.exists(p):
            with open(p, 'rb') as f:
                data = f.read()
            self.modules = data.splitlines()

    def __repr__(self):
        return '' % (
            self.name, self.version, self.path)

    def __str__(self):
        return "%s %s" % (self.name, self.version)

    def _get_records(self):
        """
        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).
        """
        results = []
        r = self.get_distinfo_resource('RECORD')
        with contextlib.closing(r.as_stream()) as stream:
            with CSVReader(stream=stream) as record_reader:
                # Base location is parent dir of .dist-info dir
                #base_location = os.path.dirname(self.path)
                #base_location = os.path.abspath(base_location)
                for row in record_reader:
                    missing = [None for i in range(len(row), 3)]
                    path, checksum, size = row + missing
                    #if not os.path.isabs(path):
                    #    path = path.replace('/', os.sep)
                    #    path = os.path.join(base_location, path)
                    results.append((path, checksum, size))
        return results

    @cached_property
    def exports(self):
        """
        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.
        """
        result = {}
        r = self.get_distinfo_resource(EXPORTS_FILENAME)
        if r:
            result = self.read_exports()
        return result

    def read_exports(self):
        """
        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.
        """
        result = {}
        r = self.get_distinfo_resource(EXPORTS_FILENAME)
        if r:
            with contextlib.closing(r.as_stream()) as stream:
                result = read_exports(stream)
        return result

    def write_exports(self, exports):
        """
        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.
        """
        rf = self.get_distinfo_file(EXPORTS_FILENAME)
        with open(rf, 'w') as f:
            write_exports(exports, f)

    def get_resource_path(self, relative_path):
        """
        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.
        """
        r = self.get_distinfo_resource('RESOURCES')
        with contextlib.closing(r.as_stream()) as stream:
            with CSVReader(stream=stream) as resources_reader:
                for relative, destination in resources_reader:
                    if relative == relative_path:
                        return destination
        raise KeyError('no resource file with relative path %r '
                       'is installed' % relative_path)

    def list_installed_files(self):
        """
        Iterates over the ``RECORD`` entries and returns a tuple
        ``(path, hash, size)`` for each line.

        :returns: iterator of (path, hash, size)
        """
        for result in self._get_records():
            yield result

    def write_installed_files(self, paths, prefix, dry_run=False):
        """
        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.
        """
        prefix = os.path.join(prefix, '')
        base = os.path.dirname(self.path)
        base_under_prefix = base.startswith(prefix)
        base = os.path.join(base, '')
        record_path = self.get_distinfo_file('RECORD')
        logger.info('creating %s', record_path)
        if dry_run:
            return None
        with CSVWriter(record_path) as writer:
            for path in paths:
                if os.path.isdir(path) or path.endswith(('.pyc', '.pyo')):
                    # do not put size and hash, as in PEP-376
                    hash_value = size = ''
                else:
                    size = '%d' % os.path.getsize(path)
                    with open(path, 'rb') as fp:
                        hash_value = self.get_hash(fp.read())
                if path.startswith(base) or (base_under_prefix and
                                             path.startswith(prefix)):
                    path = os.path.relpath(path, base)
                writer.writerow((path, hash_value, size))

            # add the RECORD file itself
            if record_path.startswith(base):
                record_path = os.path.relpath(record_path, base)
            writer.writerow((record_path, '', ''))
        return record_path

    def check_installed_files(self):
        """
        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.
        """
        mismatches = []
        base = os.path.dirname(self.path)
        record_path = self.get_distinfo_file('RECORD')
        for path, hash_value, size in self.list_installed_files():
            if not os.path.isabs(path):
                path = os.path.join(base, path)
            if path == record_path:
                continue
            if not os.path.exists(path):
                mismatches.append((path, 'exists', True, False))
            elif os.path.isfile(path):
                actual_size = str(os.path.getsize(path))
                if size and actual_size != size:
                    mismatches.append((path, 'size', size, actual_size))
                elif hash_value:
                    if '=' in hash_value:
                        hasher = hash_value.split('=', 1)[0]
                    else:
                        hasher = None

                    with open(path, 'rb') as f:
                        actual_hash = self.get_hash(f.read(), hasher)
                        if actual_hash != hash_value:
                            mismatches.append((path, 'hash', hash_value, actual_hash))
        return mismatches

    @cached_property
    def shared_locations(self):
        """
        A dictionary of shared locations whose keys are in the set 'prefix',
        'purelib', 'platlib', 'scripts', 'headers', 'data' and 'namespace'.
        The corresponding value is the absolute path of that category for
        this distribution, and takes into account any paths selected by the
        user at installation time (e.g. via command-line arguments). In the
        case of the 'namespace' key, this would be a list of absolute paths
        for the roots of namespace packages in this distribution.

        The first time this property is accessed, the relevant information is
        read from the SHARED file in the .dist-info directory.
        """
        result = {}
        shared_path = os.path.join(self.path, 'SHARED')
        if os.path.isfile(shared_path):
            with codecs.open(shared_path, 'r', encoding='utf-8') as f:
                lines = f.read().splitlines()
            for line in lines:
                key, value = line.split('=', 1)
                if key == 'namespace':
                    result.setdefault(key, []).append(value)
                else:
                    result[key] = value
        return result

    def write_shared_locations(self, paths, dry_run=False):
        """
        Write shared location information to the SHARED file in .dist-info.
        :param paths: A dictionary as described in the documentation for
        :meth:`shared_locations`.
        :param dry_run: If True, the action is logged but no file is actually
                        written.
        :return: The path of the file written to.
        """
        shared_path = os.path.join(self.path, 'SHARED')
        logger.info('creating %s', shared_path)
        if dry_run:
            return None
        lines = []
        for key in ('prefix', 'lib', 'headers', 'scripts', 'data'):
            path = paths[key]
            if os.path.isdir(paths[key]):
                lines.append('%s=%s' % (key,  path))
        for ns in paths.get('namespace', ()):
            lines.append('namespace=%s' % ns)

        with codecs.open(shared_path, 'w', encoding='utf-8') as f:
            f.write('\n'.join(lines))
        return shared_path

    def get_distinfo_resource(self, path):
        if path not in DIST_FILES:
            raise DistlibException('invalid path for a dist-info file: '
                                   '%r at %r' % (path, self.path))
        finder = resources.finder_for_path(self.path)
        if finder is None:
            raise DistlibException('Unable to get a finder for %s' % self.path)
        return finder.find(path)

    def get_distinfo_file(self, path):
        """
        Returns a path located under the ``.dist-info`` directory. Returns a
        string representing the path.

        :parameter path: a ``'/'``-separated path relative to the
                         ``.dist-info`` directory or an absolute path;
                         If *path* is an absolute path and doesn't start
                         with the ``.dist-info`` directory path,
                         a :class:`DistlibException` is raised
        :type path: str
        :rtype: str
        """
        # Check if it is an absolute path  # XXX use relpath, add tests
        if path.find(os.sep) >= 0:
            # it's an absolute path?
            distinfo_dirname, path = path.split(os.sep)[-2:]
            if distinfo_dirname != self.path.split(os.sep)[-1]:
                raise DistlibException(
                    'dist-info file %r does not belong to the %r %s '
                    'distribution' % (path, self.name, self.version))

        # The file must be relative
        if path not in DIST_FILES:
            raise DistlibException('invalid path for a dist-info file: '
                                   '%r at %r' % (path, self.path))

        return os.path.join(self.path, path)

    def list_distinfo_files(self):
        """
        Iterates over the ``RECORD`` entries and returns paths for each line if
        the path is pointing to a file located in the ``.dist-info`` directory
        or one of its subdirectories.

        :returns: iterator of paths
        """
        base = os.path.dirname(self.path)
        for path, checksum, size in self._get_records():
            # XXX add separator or use real relpath algo
            if not os.path.isabs(path):
                path = os.path.join(base, path)
            if path.startswith(self.path):
                yield path

    def __eq__(self, other):
        return (isinstance(other, InstalledDistribution) and
                self.path == other.path)

    # See http://docs.python.org/reference/datamodel#object.__hash__
    __hash__ = object.__hash__


class EggInfoDistribution(BaseInstalledDistribution):
    """Created with the *path* of the ``.egg-info`` directory or file provided
    to the constructor. It reads the metadata contained in the file itself, or
    if the given path happens to be a directory, the metadata is read from the
    file ``PKG-INFO`` under that directory."""

    requested = True    # as we have no way of knowing, assume it was
    shared_locations = {}

    def __init__(self, path, env=None):
        def set_name_and_version(s, n, v):
            s.name = n
            s.key = n.lower()   # for case-insensitive comparisons
            s.version = v

        self.path = path
        self.dist_path = env
        if env and env._cache_enabled and path in env._cache_egg.path:
            metadata = env._cache_egg.path[path].metadata
            set_name_and_version(self, metadata.name, metadata.version)
        else:
            metadata = self._get_metadata(path)

            # Need to be set before caching
            set_name_and_version(self, metadata.name, metadata.version)

            if env and env._cache_enabled:
                env._cache_egg.add(self)
        super(EggInfoDistribution, self).__init__(metadata, path, env)

    def _get_metadata(self, path):
        requires = None

        def parse_requires_data(data):
            """Create a list of dependencies from a requires.txt file.

            *data*: the contents of a setuptools-produced requires.txt file.
            """
            reqs = []
            lines = data.splitlines()
            for line in lines:
                line = line.strip()
                if line.startswith('['):
                    logger.warning('Unexpected line: quitting requirement scan: %r',
                                   line)
                    break
                r = parse_requirement(line)
                if not r:
                    logger.warning('Not recognised as a requirement: %r', line)
                    continue
                if r.extras:
                    logger.warning('extra requirements in requires.txt are '
                                   'not supported')
                if not r.constraints:
                    reqs.append(r.name)
                else:
                    cons = ', '.join('%s%s' % c for c in r.constraints)
                    reqs.append('%s (%s)' % (r.name, cons))
            return reqs

        def parse_requires_path(req_path):
            """Create a list of dependencies from a requires.txt file.

            *req_path*: the path to a setuptools-produced requires.txt file.
            """

            reqs = []
            try:
                with codecs.open(req_path, 'r', 'utf-8') as fp:
                    reqs = parse_requires_data(fp.read())
            except IOError:
                pass
            return reqs

        tl_path = tl_data = None
        if path.endswith('.egg'):
            if os.path.isdir(path):
                p = os.path.join(path, 'EGG-INFO')
                meta_path = os.path.join(p, 'PKG-INFO')
                metadata = Metadata(path=meta_path, scheme='legacy')
                req_path = os.path.join(p, 'requires.txt')
                tl_path = os.path.join(p, 'top_level.txt')
                requires = parse_requires_path(req_path)
            else:
                # FIXME handle the case where zipfile is not available
                zipf = zipimport.zipimporter(path)
                fileobj = StringIO(
                    zipf.get_data('EGG-INFO/PKG-INFO').decode('utf8'))
                metadata = Metadata(fileobj=fileobj, scheme='legacy')
                try:
                    data = zipf.get_data('EGG-INFO/requires.txt')
                    tl_data = zipf.get_data('EGG-INFO/top_level.txt').decode('utf-8')
                    requires = parse_requires_data(data.decode('utf-8'))
                except IOError:
                    requires = None
        elif path.endswith('.egg-info'):
            if os.path.isdir(path):
                req_path = os.path.join(path, 'requires.txt')
                requires = parse_requires_path(req_path)
                path = os.path.join(path, 'PKG-INFO')
                tl_path = os.path.join(path, 'top_level.txt')
            metadata = Metadata(path=path, scheme='legacy')
        else:
            raise DistlibException('path must end with .egg-info or .egg, '
                                   'got %r' % path)

        if requires:
            metadata.add_requirements(requires)
        # look for top-level modules in top_level.txt, if present
        if tl_data is None:
            if tl_path is not None and os.path.exists(tl_path):
                with open(tl_path, 'rb') as f:
                    tl_data = f.read().decode('utf-8')
        if not tl_data:
            tl_data = []
        else:
            tl_data = tl_data.splitlines()
        self.modules = tl_data
        return metadata

    def __repr__(self):
        return '' % (
            self.name, self.version, self.path)

    def __str__(self):
        return "%s %s" % (self.name, self.version)

    def check_installed_files(self):
        """
        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.
        """
        mismatches = []
        record_path = os.path.join(self.path, 'installed-files.txt')
        if os.path.exists(record_path):
            for path, _, _ in self.list_installed_files():
                if path == record_path:
                    continue
                if not os.path.exists(path):
                    mismatches.append((path, 'exists', True, False))
        return mismatches

    def list_installed_files(self):
        """
        Iterates over the ``installed-files.txt`` entries and returns a tuple
        ``(path, hash, size)`` for each line.

        :returns: a list of (path, hash, size)
        """

        def _md5(path):
            f = open(path, 'rb')
            try:
                content = f.read()
            finally:
                f.close()
            return hashlib.md5(content).hexdigest()

        def _size(path):
            return os.stat(path).st_size

        record_path = os.path.join(self.path, 'installed-files.txt')
        result = []
        if os.path.exists(record_path):
            with codecs.open(record_path, 'r', encoding='utf-8') as f:
                for line in f:
                    line = line.strip()
                    p = os.path.normpath(os.path.join(self.path, line))
                    # "./" is present as a marker between installed files
                    # and installation metadata files
                    if not os.path.exists(p):
                        logger.warning('Non-existent file: %s', p)
                        if p.endswith(('.pyc', '.pyo')):
                            continue
                        #otherwise fall through and fail
                    if not os.path.isdir(p):
                        result.append((p, _md5(p), _size(p)))
            result.append((record_path, None, None))
        return result

    def list_distinfo_files(self, absolute=False):
        """
        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
        """
        record_path = os.path.join(self.path, 'installed-files.txt')
        if os.path.exists(record_path):
            skip = True
            with codecs.open(record_path, 'r', encoding='utf-8') as f:
                for line in f:
                    line = line.strip()
                    if line == './':
                        skip = False
                        continue
                    if not skip:
                        p = os.path.normpath(os.path.join(self.path, line))
                        if p.startswith(self.path):
                            if absolute:
                                yield p
                            else:
                                yield line

    def __eq__(self, other):
        return (isinstance(other, EggInfoDistribution) and
                self.path == other.path)

    # See http://docs.python.org/reference/datamodel#object.__hash__
    __hash__ = object.__hash__

new_dist_class = InstalledDistribution
old_dist_class = EggInfoDistribution


class DependencyGraph(object):
    """
    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.
    """

    def __init__(self):
        self.adjacency_list = {}
        self.reverse_list = {}
        self.missing = {}

    def add_distribution(self, distribution):
        """Add the *distribution* to the graph.

        :type distribution: :class:`distutils2.database.InstalledDistribution`
                            or :class:`distutils2.database.EggInfoDistribution`
        """
        self.adjacency_list[distribution] = []
        self.reverse_list[distribution] = []
        #self.missing[distribution] = []

    def add_edge(self, x, y, label=None):
        """Add an edge from distribution *x* to distribution *y* with the given
        *label*.

        :type x: :class:`distutils2.database.InstalledDistribution` or
                 :class:`distutils2.database.EggInfoDistribution`
        :type y: :class:`distutils2.database.InstalledDistribution` or
                 :class:`distutils2.database.EggInfoDistribution`
        :type label: ``str`` or ``None``
        """
        self.adjacency_list[x].append((y, label))
        # multiple edges are allowed, so be careful
        if x not in self.reverse_list[y]:
            self.reverse_list[y].append(x)

    def add_missing(self, distribution, requirement):
        """
        Add a missing *requirement* for the given *distribution*.

        :type distribution: :class:`distutils2.database.InstalledDistribution`
                            or :class:`distutils2.database.EggInfoDistribution`
        :type requirement: ``str``
        """
        logger.debug('%s missing %r', distribution, requirement)
        self.missing.setdefault(distribution, []).append(requirement)

    def _repr_dist(self, dist):
        return '%s %s' % (dist.name, dist.version)

    def repr_node(self, dist, level=1):
        """Prints only a subgraph"""
        output = [self._repr_dist(dist)]
        for other, label in self.adjacency_list[dist]:
            dist = self._repr_dist(other)
            if label is not None:
                dist = '%s [%s]' % (dist, label)
            output.append('    ' * level + str(dist))
            suboutput = self.repr_node(other, level + 1)
            subs = suboutput.split('\n')
            output.extend(subs[1:])
        return '\n'.join(output)

    def to_dot(self, f, skip_disconnected=True):
        """Writes a DOT output for the graph to the provided file *f*.

        If *skip_disconnected* is set to ``True``, then all distributions
        that are not dependent on any other distribution are skipped.

        :type f: has to support ``file``-like operations
        :type skip_disconnected: ``bool``
        """
        disconnected = []

        f.write("digraph dependencies {\n")
        for dist, adjs in self.adjacency_list.items():
            if len(adjs) == 0 and not skip_disconnected:
                disconnected.append(dist)
            for other, label in adjs:
                if not label is None:
                    f.write('"%s" -> "%s" [label="%s"]\n' %
                            (dist.name, other.name, label))
                else:
                    f.write('"%s" -> "%s"\n' % (dist.name, other.name))
        if not skip_disconnected and len(disconnected) > 0:
            f.write('subgraph disconnected {\n')
            f.write('label = "Disconnected"\n')
            f.write('bgcolor = red\n')

            for dist in disconnected:
                f.write('"%s"' % dist.name)
                f.write('\n')
            f.write('}\n')
        f.write('}\n')

    def topological_sort(self):
        """
        Perform a topological sort of the graph.
        :return: A tuple, the first element of which is a topologically sorted
                 list of distributions, and the second element of which is a
                 list of distributions that cannot be sorted because they have
                 circular dependencies and so form a cycle.
        """
        result = []
        # Make a shallow copy of the adjacency list
        alist = {}
        for k, v in self.adjacency_list.items():
            alist[k] = v[:]
        while True:
            # See what we can remove in this run
            to_remove = []
            for k, v in list(alist.items())[:]:
                if not v:
                    to_remove.append(k)
                    del alist[k]
            if not to_remove:
                # What's left in alist (if anything) is a cycle.
                break
            # Remove from the adjacency list of others
            for k, v in alist.items():
                alist[k] = [(d, r) for d, r in v if d not in to_remove]
            logger.debug('Moving to result: %s',
                         ['%s (%s)' % (d.name, d.version) for d in to_remove])
            result.extend(to_remove)
        return result, list(alist.keys())

    def __repr__(self):
        """Representation of the graph"""
        output = []
        for dist, adjs in self.adjacency_list.items():
            output.append(self.repr_node(dist))
        return '\n'.join(output)


def make_graph(dists, scheme='default'):
    """Makes a dependency graph from the given distributions.

    :parameter dists: a list of distributions
    :type dists: list of :class:`distutils2.database.InstalledDistribution` and
                 :class:`distutils2.database.EggInfoDistribution` instances
    :rtype: a :class:`DependencyGraph` instance
    """
    scheme = get_scheme(scheme)
    graph = DependencyGraph()
    provided = {}  # maps names to lists of (version, dist) tuples

    # first, build the graph and find out what's provided
    for dist in dists:
        graph.add_distribution(dist)

        for p in dist.provides:
            name, version = parse_name_and_version(p)
            logger.debug('Add to provided: %s, %s, %s', name, version, dist)
            provided.setdefault(name, []).append((version, dist))

    # now make the edges
    for dist in dists:
        requires = (dist.run_requires | dist.meta_requires |
                    dist.build_requires | dist.dev_requires)
        for req in requires:
            try:
                matcher = scheme.matcher(req)
            except UnsupportedVersionError:
                # XXX compat-mode if cannot read the version
                logger.warning('could not read version %r - using name only',
                               req)
                name = req.split()[0]
                matcher = scheme.matcher(name)

            name = matcher.key   # case-insensitive

            matched = False
            if name in provided:
                for version, provider in provided[name]:
                    try:
                        match = matcher.match(version)
                    except UnsupportedVersionError:
                        match = False

                    if match:
                        graph.add_edge(dist, provider, req)
                        matched = True
                        break
            if not matched:
                graph.add_missing(dist, req)
    return graph


def get_dependent_dists(dists, dist):
    """Recursively generate a list of distributions from *dists* that are
    dependent on *dist*.

    :param dists: a list of distributions
    :param dist: a distribution, member of *dists* for which we are interested
    """
    if dist not in dists:
        raise DistlibException('given distribution %r is not a member '
                               'of the list' % dist.name)
    graph = make_graph(dists)

    dep = [dist]  # dependent distributions
    todo = graph.reverse_list[dist]  # list of nodes we should inspect

    while todo:
        d = todo.pop()
        dep.append(d)
        for succ in graph.reverse_list[d]:
            if succ not in dep:
                todo.append(succ)

    dep.pop(0)  # remove dist from dep, was there to prevent infinite loops
    return dep


def get_required_dists(dists, dist):
    """Recursively generate a list of distributions from *dists* that are
    required by *dist*.

    :param dists: a list of distributions
    :param dist: a distribution, member of *dists* for which we are interested
    """
    if dist not in dists:
        raise DistlibException('given distribution %r is not a member '
                               'of the list' % dist.name)
    graph = make_graph(dists)

    req = []  # required distributions
    todo = graph.adjacency_list[dist]  # list of nodes we should inspect

    while todo:
        d = todo.pop()[0]
        req.append(d)
        for pred in graph.adjacency_list[d]:
            if pred not in req:
                todo.append(pred)

    return req


def make_dist(name, version, **kwargs):
    """
    A convenience method for making a dist given just a name and version.
    """
    summary = kwargs.pop('summary', 'Placeholder for summary')
    md = Metadata(**kwargs)
    md.name = name
    md.version = version
    md.summary = summary or 'Placeholder for summary'
    return Distribution(md)
PKÕ¶N]öh(,_[_[,site-packages/pip/_vendor/distlib/version.pynu„[µü¤# -*- coding: utf-8 -*-
#
# Copyright (C) 2012-2017 The Python Software Foundation.
# See LICENSE.txt and CONTRIBUTORS.txt.
#
"""
Implementation of a flexible versioning scheme providing support for PEP-440,
setuptools-compatible and semantic versioning.
"""

import logging
import re

from .compat import string_types
from .util import parse_requirement

__all__ = ['NormalizedVersion', 'NormalizedMatcher',
           'LegacyVersion', 'LegacyMatcher',
           'SemanticVersion', 'SemanticMatcher',
           'UnsupportedVersionError', 'get_scheme']

logger = logging.getLogger(__name__)


class UnsupportedVersionError(ValueError):
    """This is an unsupported version."""
    pass


class Version(object):
    def __init__(self, s):
        self._string = s = s.strip()
        self._parts = parts = self.parse(s)
        assert isinstance(parts, tuple)
        assert len(parts) > 0

    def parse(self, s):
        raise NotImplementedError('please implement in a subclass')

    def _check_compatible(self, other):
        if type(self) != type(other):
            raise TypeError('cannot compare %r and %r' % (self, other))

    def __eq__(self, other):
        self._check_compatible(other)
        return self._parts == other._parts

    def __ne__(self, other):
        return not self.__eq__(other)

    def __lt__(self, other):
        self._check_compatible(other)
        return self._parts < other._parts

    def __gt__(self, other):
        return not (self.__lt__(other) or self.__eq__(other))

    def __le__(self, other):
        return self.__lt__(other) or self.__eq__(other)

    def __ge__(self, other):
        return self.__gt__(other) or self.__eq__(other)

    # See http://docs.python.org/reference/datamodel#object.__hash__
    def __hash__(self):
        return hash(self._parts)

    def __repr__(self):
        return "%s('%s')" % (self.__class__.__name__, self._string)

    def __str__(self):
        return self._string

    @property
    def is_prerelease(self):
        raise NotImplementedError('Please implement in subclasses.')


class Matcher(object):
    version_class = None

    # value is either a callable or the name of a method
    _operators = {
        '<': lambda v, c, p: v < c,
        '>': lambda v, c, p: v > c,
        '<=': lambda v, c, p: v == c or v < c,
        '>=': lambda v, c, p: v == c or v > c,
        '==': lambda v, c, p: v == c,
        '===': lambda v, c, p: v == c,
        # by default, compatible => >=.
        '~=': lambda v, c, p: v == c or v > c,
        '!=': lambda v, c, p: v != c,
    }

    # this is a method only to support alternative implementations
    # via overriding
    def parse_requirement(self, s):
        return parse_requirement(s)

    def __init__(self, s):
        if self.version_class is None:
            raise ValueError('Please specify a version class')
        self._string = s = s.strip()
        r = self.parse_requirement(s)
        if not r:
            raise ValueError('Not valid: %r' % s)
        self.name = r.name
        self.key = self.name.lower()    # for case-insensitive comparisons
        clist = []
        if r.constraints:
            # import pdb; pdb.set_trace()
            for op, s in r.constraints:
                if s.endswith('.*'):
                    if op not in ('==', '!='):
                        raise ValueError('\'.*\' not allowed for '
                                         '%r constraints' % op)
                    # Could be a partial version (e.g. for '2.*') which
                    # won't parse as a version, so keep it as a string
                    vn, prefix = s[:-2], True
                    # Just to check that vn is a valid version
                    self.version_class(vn)
                else:
                    # Should parse as a version, so we can create an
                    # instance for the comparison
                    vn, prefix = self.version_class(s), False
                clist.append((op, vn, prefix))
        self._parts = tuple(clist)

    def match(self, version):
        """
        Check if the provided version matches the constraints.

        :param version: The version to match against this instance.
        :type version: String or :class:`Version` instance.
        """
        if isinstance(version, string_types):
            version = self.version_class(version)
        for operator, constraint, prefix in self._parts:
            f = self._operators.get(operator)
            if isinstance(f, string_types):
                f = getattr(self, f)
            if not f:
                msg = ('%r not implemented '
                       'for %s' % (operator, self.__class__.__name__))
                raise NotImplementedError(msg)
            if not f(version, constraint, prefix):
                return False
        return True

    @property
    def exact_version(self):
        result = None
        if len(self._parts) == 1 and self._parts[0][0] in ('==', '==='):
            result = self._parts[0][1]
        return result

    def _check_compatible(self, other):
        if type(self) != type(other) or self.name != other.name:
            raise TypeError('cannot compare %s and %s' % (self, other))

    def __eq__(self, other):
        self._check_compatible(other)
        return self.key == other.key and self._parts == other._parts

    def __ne__(self, other):
        return not self.__eq__(other)

    # See http://docs.python.org/reference/datamodel#object.__hash__
    def __hash__(self):
        return hash(self.key) + hash(self._parts)

    def __repr__(self):
        return "%s(%r)" % (self.__class__.__name__, self._string)

    def __str__(self):
        return self._string


PEP440_VERSION_RE = re.compile(r'^v?(\d+!)?(\d+(\.\d+)*)((a|b|c|rc)(\d+))?'
                               r'(\.(post)(\d+))?(\.(dev)(\d+))?'
                               r'(\+([a-zA-Z\d]+(\.[a-zA-Z\d]+)?))?$')


def _pep_440_key(s):
    s = s.strip()
    m = PEP440_VERSION_RE.match(s)
    if not m:
        raise UnsupportedVersionError('Not a valid version: %s' % s)
    groups = m.groups()
    nums = tuple(int(v) for v in groups[1].split('.'))
    while len(nums) > 1 and nums[-1] == 0:
        nums = nums[:-1]

    if not groups[0]:
        epoch = 0
    else:
        epoch = int(groups[0])
    pre = groups[4:6]
    post = groups[7:9]
    dev = groups[10:12]
    local = groups[13]
    if pre == (None, None):
        pre = ()
    else:
        pre = pre[0], int(pre[1])
    if post == (None, None):
        post = ()
    else:
        post = post[0], int(post[1])
    if dev == (None, None):
        dev = ()
    else:
        dev = dev[0], int(dev[1])
    if local is None:
        local = ()
    else:
        parts = []
        for part in local.split('.'):
            # to ensure that numeric compares as > lexicographic, avoid
            # comparing them directly, but encode a tuple which ensures
            # correct sorting
            if part.isdigit():
                part = (1, int(part))
            else:
                part = (0, part)
            parts.append(part)
        local = tuple(parts)
    if not pre:
        # either before pre-release, or final release and after
        if not post and dev:
            # before pre-release
            pre = ('a', -1)     # to sort before a0
        else:
            pre = ('z',)        # to sort after all pre-releases
    # now look at the state of post and dev.
    if not post:
        post = ('_',)   # sort before 'a'
    if not dev:
        dev = ('final',)

    #print('%s -> %s' % (s, m.groups()))
    return epoch, nums, pre, post, dev, local


_normalized_key = _pep_440_key


class NormalizedVersion(Version):
    """A rational version.

    Good:
        1.2         # equivalent to "1.2.0"
        1.2.0
        1.2a1
        1.2.3a2
        1.2.3b1
        1.2.3c1
        1.2.3.4
        TODO: fill this out

    Bad:
        1           # minimum two numbers
        1.2a        # release level must have a release serial
        1.2.3b
    """
    def parse(self, s):
        result = _normalized_key(s)
        # _normalized_key loses trailing zeroes in the release
        # clause, since that's needed to ensure that X.Y == X.Y.0 == X.Y.0.0
        # However, PEP 440 prefix matching needs it: for example,
        # (~= 1.4.5.0) matches differently to (~= 1.4.5.0.0).
        m = PEP440_VERSION_RE.match(s)      # must succeed
        groups = m.groups()
        self._release_clause = tuple(int(v) for v in groups[1].split('.'))
        return result

    PREREL_TAGS = set(['a', 'b', 'c', 'rc', 'dev'])

    @property
    def is_prerelease(self):
        return any(t[0] in self.PREREL_TAGS for t in self._parts if t)


def _match_prefix(x, y):
    x = str(x)
    y = str(y)
    if x == y:
        return True
    if not x.startswith(y):
        return False
    n = len(y)
    return x[n] == '.'


class NormalizedMatcher(Matcher):
    version_class = NormalizedVersion

    # value is either a callable or the name of a method
    _operators = {
        '~=': '_match_compatible',
        '<': '_match_lt',
        '>': '_match_gt',
        '<=': '_match_le',
        '>=': '_match_ge',
        '==': '_match_eq',
        '===': '_match_arbitrary',
        '!=': '_match_ne',
    }

    def _adjust_local(self, version, constraint, prefix):
        if prefix:
            strip_local = '+' not in constraint and version._parts[-1]
        else:
            # both constraint and version are
            # NormalizedVersion instances.
            # If constraint does not have a local component,
            # ensure the version doesn't, either.
            strip_local = not constraint._parts[-1] and version._parts[-1]
        if strip_local:
            s = version._string.split('+', 1)[0]
            version = self.version_class(s)
        return version, constraint

    def _match_lt(self, version, constraint, prefix):
        version, constraint = self._adjust_local(version, constraint, prefix)
        if version >= constraint:
            return False
        release_clause = constraint._release_clause
        pfx = '.'.join([str(i) for i in release_clause])
        return not _match_prefix(version, pfx)

    def _match_gt(self, version, constraint, prefix):
        version, constraint = self._adjust_local(version, constraint, prefix)
        if version <= constraint:
            return False
        release_clause = constraint._release_clause
        pfx = '.'.join([str(i) for i in release_clause])
        return not _match_prefix(version, pfx)

    def _match_le(self, version, constraint, prefix):
        version, constraint = self._adjust_local(version, constraint, prefix)
        return version <= constraint

    def _match_ge(self, version, constraint, prefix):
        version, constraint = self._adjust_local(version, constraint, prefix)
        return version >= constraint

    def _match_eq(self, version, constraint, prefix):
        version, constraint = self._adjust_local(version, constraint, prefix)
        if not prefix:
            result = (version == constraint)
        else:
            result = _match_prefix(version, constraint)
        return result

    def _match_arbitrary(self, version, constraint, prefix):
        return str(version) == str(constraint)

    def _match_ne(self, version, constraint, prefix):
        version, constraint = self._adjust_local(version, constraint, prefix)
        if not prefix:
            result = (version != constraint)
        else:
            result = not _match_prefix(version, constraint)
        return result

    def _match_compatible(self, version, constraint, prefix):
        version, constraint = self._adjust_local(version, constraint, prefix)
        if version == constraint:
            return True
        if version < constraint:
            return False
#        if not prefix:
#            return True
        release_clause = constraint._release_clause
        if len(release_clause) > 1:
            release_clause = release_clause[:-1]
        pfx = '.'.join([str(i) for i in release_clause])
        return _match_prefix(version, pfx)

_REPLACEMENTS = (
    (re.compile('[.+-]$'), ''),                     # remove trailing puncts
    (re.compile(r'^[.](\d)'), r'0.\1'),             # .N -> 0.N at start
    (re.compile('^[.-]'), ''),                      # remove leading puncts
    (re.compile(r'^\((.*)\)$'), r'\1'),             # remove parentheses
    (re.compile(r'^v(ersion)?\s*(\d+)'), r'\2'),    # remove leading v(ersion)
    (re.compile(r'^r(ev)?\s*(\d+)'), r'\2'),        # remove leading v(ersion)
    (re.compile('[.]{2,}'), '.'),                   # multiple runs of '.'
    (re.compile(r'\b(alfa|apha)\b'), 'alpha'),      # misspelt alpha
    (re.compile(r'\b(pre-alpha|prealpha)\b'),
                'pre.alpha'),                       # standardise
    (re.compile(r'\(beta\)$'), 'beta'),             # remove parentheses
)

_SUFFIX_REPLACEMENTS = (
    (re.compile('^[:~._+-]+'), ''),                   # remove leading puncts
    (re.compile('[,*")([\\]]'), ''),                  # remove unwanted chars
    (re.compile('[~:+_ -]'), '.'),                    # replace illegal chars
    (re.compile('[.]{2,}'), '.'),                   # multiple runs of '.'
    (re.compile(r'\.$'), ''),                       # trailing '.'
)

_NUMERIC_PREFIX = re.compile(r'(\d+(\.\d+)*)')


def _suggest_semantic_version(s):
    """
    Try to suggest a semantic form for a version for which
    _suggest_normalized_version couldn't come up with anything.
    """
    result = s.strip().lower()
    for pat, repl in _REPLACEMENTS:
        result = pat.sub(repl, result)
    if not result:
        result = '0.0.0'

    # Now look for numeric prefix, and separate it out from
    # the rest.
    #import pdb; pdb.set_trace()
    m = _NUMERIC_PREFIX.match(result)
    if not m:
        prefix = '0.0.0'
        suffix = result
    else:
        prefix = m.groups()[0].split('.')
        prefix = [int(i) for i in prefix]
        while len(prefix) < 3:
            prefix.append(0)
        if len(prefix) == 3:
            suffix = result[m.end():]
        else:
            suffix = '.'.join([str(i) for i in prefix[3:]]) + result[m.end():]
            prefix = prefix[:3]
        prefix = '.'.join([str(i) for i in prefix])
        suffix = suffix.strip()
    if suffix:
        #import pdb; pdb.set_trace()
        # massage the suffix.
        for pat, repl in _SUFFIX_REPLACEMENTS:
            suffix = pat.sub(repl, suffix)

    if not suffix:
        result = prefix
    else:
        sep = '-' if 'dev' in suffix else '+'
        result = prefix + sep + suffix
    if not is_semver(result):
        result = None
    return result


def _suggest_normalized_version(s):
    """Suggest a normalized version close to the given version string.

    If you have a version string that isn't rational (i.e. NormalizedVersion
    doesn't like it) then you might be able to get an equivalent (or close)
    rational version from this function.

    This does a number of simple normalizations to the given string, based
    on observation of versions currently in use on PyPI. Given a dump of
    those version during PyCon 2009, 4287 of them:
    - 2312 (53.93%) match NormalizedVersion without change
      with the automatic suggestion
    - 3474 (81.04%) match when using this suggestion method

    @param s {str} An irrational version string.
    @returns A rational version string, or None, if couldn't determine one.
    """
    try:
        _normalized_key(s)
        return s   # already rational
    except UnsupportedVersionError:
        pass

    rs = s.lower()

    # part of this could use maketrans
    for orig, repl in (('-alpha', 'a'), ('-beta', 'b'), ('alpha', 'a'),
                       ('beta', 'b'), ('rc', 'c'), ('-final', ''),
                       ('-pre', 'c'),
                       ('-release', ''), ('.release', ''), ('-stable', ''),
                       ('+', '.'), ('_', '.'), (' ', ''), ('.final', ''),
                       ('final', '')):
        rs = rs.replace(orig, repl)

    # if something ends with dev or pre, we add a 0
    rs = re.sub(r"pre$", r"pre0", rs)
    rs = re.sub(r"dev$", r"dev0", rs)

    # if we have something like "b-2" or "a.2" at the end of the
    # version, that is probably beta, alpha, etc
    # let's remove the dash or dot
    rs = re.sub(r"([abc]|rc)[\-\.](\d+)$", r"\1\2", rs)

    # 1.0-dev-r371 -> 1.0.dev371
    # 0.1-dev-r79 -> 0.1.dev79
    rs = re.sub(r"[\-\.](dev)[\-\.]?r?(\d+)$", r".\1\2", rs)

    # Clean: 2.0.a.3, 2.0.b1, 0.9.0~c1
    rs = re.sub(r"[.~]?([abc])\.?", r"\1", rs)

    # Clean: v0.3, v1.0
    if rs.startswith('v'):
        rs = rs[1:]

    # Clean leading '0's on numbers.
    #TODO: unintended side-effect on, e.g., "2003.05.09"
    # PyPI stats: 77 (~2%) better
    rs = re.sub(r"\b0+(\d+)(?!\d)", r"\1", rs)

    # Clean a/b/c with no version. E.g. "1.0a" -> "1.0a0". Setuptools infers
    # zero.
    # PyPI stats: 245 (7.56%) better
    rs = re.sub(r"(\d+[abc])$", r"\g<1>0", rs)

    # the 'dev-rNNN' tag is a dev tag
    rs = re.sub(r"\.?(dev-r|dev\.r)\.?(\d+)$", r".dev\2", rs)

    # clean the - when used as a pre delimiter
    rs = re.sub(r"-(a|b|c)(\d+)$", r"\1\2", rs)

    # a terminal "dev" or "devel" can be changed into ".dev0"
    rs = re.sub(r"[\.\-](dev|devel)$", r".dev0", rs)

    # a terminal "dev" can be changed into ".dev0"
    rs = re.sub(r"(?![\.\-])dev$", r".dev0", rs)

    # a terminal "final" or "stable" can be removed
    rs = re.sub(r"(final|stable)$", "", rs)

    # The 'r' and the '-' tags are post release tags
    #   0.4a1.r10       ->  0.4a1.post10
    #   0.9.33-17222    ->  0.9.33.post17222
    #   0.9.33-r17222   ->  0.9.33.post17222
    rs = re.sub(r"\.?(r|-|-r)\.?(\d+)$", r".post\2", rs)

    # Clean 'r' instead of 'dev' usage:
    #   0.9.33+r17222   ->  0.9.33.dev17222
    #   1.0dev123       ->  1.0.dev123
    #   1.0.git123      ->  1.0.dev123
    #   1.0.bzr123      ->  1.0.dev123
    #   0.1a0dev.123    ->  0.1a0.dev123
    # PyPI stats:  ~150 (~4%) better
    rs = re.sub(r"\.?(dev|git|bzr)\.?(\d+)$", r".dev\2", rs)

    # Clean '.pre' (normalized from '-pre' above) instead of 'c' usage:
    #   0.2.pre1        ->  0.2c1
    #   0.2-c1         ->  0.2c1
    #   1.0preview123   ->  1.0c123
    # PyPI stats: ~21 (0.62%) better
    rs = re.sub(r"\.?(pre|preview|-c)(\d+)$", r"c\g<2>", rs)

    # Tcl/Tk uses "px" for their post release markers
    rs = re.sub(r"p(\d+)$", r".post\1", rs)

    try:
        _normalized_key(rs)
    except UnsupportedVersionError:
        rs = None
    return rs

#
#   Legacy version processing (distribute-compatible)
#

_VERSION_PART = re.compile(r'([a-z]+|\d+|[\.-])', re.I)
_VERSION_REPLACE = {
    'pre': 'c',
    'preview': 'c',
    '-': 'final-',
    'rc': 'c',
    'dev': '@',
    '': None,
    '.': None,
}


def _legacy_key(s):
    def get_parts(s):
        result = []
        for p in _VERSION_PART.split(s.lower()):
            p = _VERSION_REPLACE.get(p, p)
            if p:
                if '0' <= p[:1] <= '9':
                    p = p.zfill(8)
                else:
                    p = '*' + p
                result.append(p)
        result.append('*final')
        return result

    result = []
    for p in get_parts(s):
        if p.startswith('*'):
            if p < '*final':
                while result and result[-1] == '*final-':
                    result.pop()
            while result and result[-1] == '00000000':
                result.pop()
        result.append(p)
    return tuple(result)


class LegacyVersion(Version):
    def parse(self, s):
        return _legacy_key(s)

    @property
    def is_prerelease(self):
        result = False
        for x in self._parts:
            if (isinstance(x, string_types) and x.startswith('*') and
                x < '*final'):
                result = True
                break
        return result


class LegacyMatcher(Matcher):
    version_class = LegacyVersion

    _operators = dict(Matcher._operators)
    _operators['~='] = '_match_compatible'

    numeric_re = re.compile(r'^(\d+(\.\d+)*)')

    def _match_compatible(self, version, constraint, prefix):
        if version < constraint:
            return False
        m = self.numeric_re.match(str(constraint))
        if not m:
            logger.warning('Cannot compute compatible match for version %s '
                           ' and constraint %s', version, constraint)
            return True
        s = m.groups()[0]
        if '.' in s:
            s = s.rsplit('.', 1)[0]
        return _match_prefix(version, s)

#
#   Semantic versioning
#

_SEMVER_RE = re.compile(r'^(\d+)\.(\d+)\.(\d+)'
                        r'(-[a-z0-9]+(\.[a-z0-9-]+)*)?'
                        r'(\+[a-z0-9]+(\.[a-z0-9-]+)*)?$', re.I)


def is_semver(s):
    return _SEMVER_RE.match(s)


def _semantic_key(s):
    def make_tuple(s, absent):
        if s is None:
            result = (absent,)
        else:
            parts = s[1:].split('.')
            # We can't compare ints and strings on Python 3, so fudge it
            # by zero-filling numeric values so simulate a numeric comparison
            result = tuple([p.zfill(8) if p.isdigit() else p for p in parts])
        return result

    m = is_semver(s)
    if not m:
        raise UnsupportedVersionError(s)
    groups = m.groups()
    major, minor, patch = [int(i) for i in groups[:3]]
    # choose the '|' and '*' so that versions sort correctly
    pre, build = make_tuple(groups[3], '|'), make_tuple(groups[5], '*')
    return (major, minor, patch), pre, build


class SemanticVersion(Version):
    def parse(self, s):
        return _semantic_key(s)

    @property
    def is_prerelease(self):
        return self._parts[1][0] != '|'


class SemanticMatcher(Matcher):
    version_class = SemanticVersion


class VersionScheme(object):
    def __init__(self, key, matcher, suggester=None):
        self.key = key
        self.matcher = matcher
        self.suggester = suggester

    def is_valid_version(self, s):
        try:
            self.matcher.version_class(s)
            result = True
        except UnsupportedVersionError:
            result = False
        return result

    def is_valid_matcher(self, s):
        try:
            self.matcher(s)
            result = True
        except UnsupportedVersionError:
            result = False
        return result

    def is_valid_constraint_list(self, s):
        """
        Used for processing some metadata fields
        """
        return self.is_valid_matcher('dummy_name (%s)' % s)

    def suggest(self, s):
        if self.suggester is None:
            result = None
        else:
            result = self.suggester(s)
        return result

_SCHEMES = {
    'normalized': VersionScheme(_normalized_key, NormalizedMatcher,
                                _suggest_normalized_version),
    'legacy': VersionScheme(_legacy_key, LegacyMatcher, lambda self, s: s),
    'semantic': VersionScheme(_semantic_key, SemanticMatcher,
                              _suggest_semantic_version),
}

_SCHEMES['default'] = _SCHEMES['normalized']


def get_scheme(name):
    if name not in _SCHEMES:
        raise ValueError('unknown scheme name: %r' % name)
    return _SCHEMES[name]
PKÕ¶N]”8Ø*�*�-site-packages/pip/_vendor/distlib/metadata.pynu„[µü¤# -*- coding: utf-8 -*-
#
# Copyright (C) 2012 The Python Software Foundation.
# See LICENSE.txt and CONTRIBUTORS.txt.
#
"""Implementation of the Metadata for Python packages PEPs.

Supports all metadata formats (1.0, 1.1, 1.2, and 2.0 experimental).
"""
from __future__ import unicode_literals

import codecs
from email import message_from_file
import json
import logging
import re


from . import DistlibException, __version__
from .compat import StringIO, string_types, text_type
from .markers import interpret
from .util import extract_by_key, get_extras
from .version import get_scheme, PEP440_VERSION_RE

logger = logging.getLogger(__name__)


class MetadataMissingError(DistlibException):
    """A required metadata is missing"""


class MetadataConflictError(DistlibException):
    """Attempt to read or write metadata fields that are conflictual."""


class MetadataUnrecognizedVersionError(DistlibException):
    """Unknown metadata version number."""


class MetadataInvalidError(DistlibException):
    """A metadata value is invalid"""

# public API of this module
__all__ = ['Metadata', 'PKG_INFO_ENCODING', 'PKG_INFO_PREFERRED_VERSION']

# Encoding used for the PKG-INFO files
PKG_INFO_ENCODING = 'utf-8'

# preferred version. Hopefully will be changed
# to 1.2 once PEP 345 is supported everywhere
PKG_INFO_PREFERRED_VERSION = '1.1'

_LINE_PREFIX_1_2 = re.compile('\n       \\|')
_LINE_PREFIX_PRE_1_2 = re.compile('\n        ')
_241_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
               'Summary', 'Description',
               'Keywords', 'Home-page', 'Author', 'Author-email',
               'License')

_314_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
               'Supported-Platform', 'Summary', 'Description',
               'Keywords', 'Home-page', 'Author', 'Author-email',
               'License', 'Classifier', 'Download-URL', 'Obsoletes',
               'Provides', 'Requires')

_314_MARKERS = ('Obsoletes', 'Provides', 'Requires', 'Classifier',
                'Download-URL')

_345_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
               'Supported-Platform', 'Summary', 'Description',
               'Keywords', 'Home-page', 'Author', 'Author-email',
               'Maintainer', 'Maintainer-email', 'License',
               'Classifier', 'Download-URL', 'Obsoletes-Dist',
               'Project-URL', 'Provides-Dist', 'Requires-Dist',
               'Requires-Python', 'Requires-External')

_345_MARKERS = ('Provides-Dist', 'Requires-Dist', 'Requires-Python',
                'Obsoletes-Dist', 'Requires-External', 'Maintainer',
                'Maintainer-email', 'Project-URL')

_426_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
               'Supported-Platform', 'Summary', 'Description',
               'Keywords', 'Home-page', 'Author', 'Author-email',
               'Maintainer', 'Maintainer-email', 'License',
               'Classifier', 'Download-URL', 'Obsoletes-Dist',
               'Project-URL', 'Provides-Dist', 'Requires-Dist',
               'Requires-Python', 'Requires-External', 'Private-Version',
               'Obsoleted-By', 'Setup-Requires-Dist', 'Extension',
               'Provides-Extra')

_426_MARKERS = ('Private-Version', 'Provides-Extra', 'Obsoleted-By',
                'Setup-Requires-Dist', 'Extension')

# See issue #106: Sometimes 'Requires' and 'Provides' occur wrongly in
# the metadata. Include them in the tuple literal below to allow them
# (for now).
_566_FIELDS = _426_FIELDS + ('Description-Content-Type',
                             'Requires', 'Provides')

_566_MARKERS = ('Description-Content-Type',)

_ALL_FIELDS = set()
_ALL_FIELDS.update(_241_FIELDS)
_ALL_FIELDS.update(_314_FIELDS)
_ALL_FIELDS.update(_345_FIELDS)
_ALL_FIELDS.update(_426_FIELDS)
_ALL_FIELDS.update(_566_FIELDS)

EXTRA_RE = re.compile(r'''extra\s*==\s*("([^"]+)"|'([^']+)')''')


def _version2fieldlist(version):
    if version == '1.0':
        return _241_FIELDS
    elif version == '1.1':
        return _314_FIELDS
    elif version == '1.2':
        return _345_FIELDS
    elif version in ('1.3', '2.1'):
        return _345_FIELDS + _566_FIELDS
    elif version == '2.0':
        return _426_FIELDS
    raise MetadataUnrecognizedVersionError(version)


def _best_version(fields):
    """Detect the best version depending on the fields used."""
    def _has_marker(keys, markers):
        for marker in markers:
            if marker in keys:
                return True
        return False

    keys = []
    for key, value in fields.items():
        if value in ([], 'UNKNOWN', None):
            continue
        keys.append(key)

    possible_versions = ['1.0', '1.1', '1.2', '1.3', '2.0', '2.1']

    # first let's try to see if a field is not part of one of the version
    for key in keys:
        if key not in _241_FIELDS and '1.0' in possible_versions:
            possible_versions.remove('1.0')
            logger.debug('Removed 1.0 due to %s', key)
        if key not in _314_FIELDS and '1.1' in possible_versions:
            possible_versions.remove('1.1')
            logger.debug('Removed 1.1 due to %s', key)
        if key not in _345_FIELDS and '1.2' in possible_versions:
            possible_versions.remove('1.2')
            logger.debug('Removed 1.2 due to %s', key)
        if key not in _566_FIELDS and '1.3' in possible_versions:
            possible_versions.remove('1.3')
            logger.debug('Removed 1.3 due to %s', key)
        if key not in _566_FIELDS and '2.1' in possible_versions:
            if key != 'Description':  # In 2.1, description allowed after headers
                possible_versions.remove('2.1')
                logger.debug('Removed 2.1 due to %s', key)
        if key not in _426_FIELDS and '2.0' in possible_versions:
            possible_versions.remove('2.0')
            logger.debug('Removed 2.0 due to %s', key)

    # possible_version contains qualified versions
    if len(possible_versions) == 1:
        return possible_versions[0]   # found !
    elif len(possible_versions) == 0:
        logger.debug('Out of options - unknown metadata set: %s', fields)
        raise MetadataConflictError('Unknown metadata set')

    # let's see if one unique marker is found
    is_1_1 = '1.1' in possible_versions and _has_marker(keys, _314_MARKERS)
    is_1_2 = '1.2' in possible_versions and _has_marker(keys, _345_MARKERS)
    is_2_1 = '2.1' in possible_versions and _has_marker(keys, _566_MARKERS)
    is_2_0 = '2.0' in possible_versions and _has_marker(keys, _426_MARKERS)
    if int(is_1_1) + int(is_1_2) + int(is_2_1) + int(is_2_0) > 1:
        raise MetadataConflictError('You used incompatible 1.1/1.2/2.0/2.1 fields')

    # we have the choice, 1.0, or 1.2, or 2.0
    #   - 1.0 has a broken Summary field but works with all tools
    #   - 1.1 is to avoid
    #   - 1.2 fixes Summary but has little adoption
    #   - 2.0 adds more features and is very new
    if not is_1_1 and not is_1_2 and not is_2_1 and not is_2_0:
        # we couldn't find any specific marker
        if PKG_INFO_PREFERRED_VERSION in possible_versions:
            return PKG_INFO_PREFERRED_VERSION
    if is_1_1:
        return '1.1'
    if is_1_2:
        return '1.2'
    if is_2_1:
        return '2.1'

    return '2.0'

_ATTR2FIELD = {
    'metadata_version': 'Metadata-Version',
    'name': 'Name',
    'version': 'Version',
    'platform': 'Platform',
    'supported_platform': 'Supported-Platform',
    'summary': 'Summary',
    'description': 'Description',
    'keywords': 'Keywords',
    'home_page': 'Home-page',
    'author': 'Author',
    'author_email': 'Author-email',
    'maintainer': 'Maintainer',
    'maintainer_email': 'Maintainer-email',
    'license': 'License',
    'classifier': 'Classifier',
    'download_url': 'Download-URL',
    'obsoletes_dist': 'Obsoletes-Dist',
    'provides_dist': 'Provides-Dist',
    'requires_dist': 'Requires-Dist',
    'setup_requires_dist': 'Setup-Requires-Dist',
    'requires_python': 'Requires-Python',
    'requires_external': 'Requires-External',
    'requires': 'Requires',
    'provides': 'Provides',
    'obsoletes': 'Obsoletes',
    'project_url': 'Project-URL',
    'private_version': 'Private-Version',
    'obsoleted_by': 'Obsoleted-By',
    'extension': 'Extension',
    'provides_extra': 'Provides-Extra',
}

_PREDICATE_FIELDS = ('Requires-Dist', 'Obsoletes-Dist', 'Provides-Dist')
_VERSIONS_FIELDS = ('Requires-Python',)
_VERSION_FIELDS = ('Version',)
_LISTFIELDS = ('Platform', 'Classifier', 'Obsoletes',
               'Requires', 'Provides', 'Obsoletes-Dist',
               'Provides-Dist', 'Requires-Dist', 'Requires-External',
               'Project-URL', 'Supported-Platform', 'Setup-Requires-Dist',
               'Provides-Extra', 'Extension')
_LISTTUPLEFIELDS = ('Project-URL',)

_ELEMENTSFIELD = ('Keywords',)

_UNICODEFIELDS = ('Author', 'Maintainer', 'Summary', 'Description')

_MISSING = object()

_FILESAFE = re.compile('[^A-Za-z0-9.]+')


def _get_name_and_version(name, version, for_filename=False):
    """Return the distribution name with version.

    If for_filename is true, return a filename-escaped form."""
    if for_filename:
        # For both name and version any runs of non-alphanumeric or '.'
        # characters are replaced with a single '-'.  Additionally any
        # spaces in the version string become '.'
        name = _FILESAFE.sub('-', name)
        version = _FILESAFE.sub('-', version.replace(' ', '.'))
    return '%s-%s' % (name, version)


class LegacyMetadata(object):
    """The legacy metadata of a release.

    Supports versions 1.0, 1.1 and 1.2 (auto-detected). You can
    instantiate the class with one of these arguments (or none):
    - *path*, the path to a metadata file
    - *fileobj* give a file-like object with metadata as content
    - *mapping* is a dict-like object
    - *scheme* is a version scheme name
    """
    # TODO document the mapping API and UNKNOWN default key

    def __init__(self, path=None, fileobj=None, mapping=None,
                 scheme='default'):
        if [path, fileobj, mapping].count(None) < 2:
            raise TypeError('path, fileobj and mapping are exclusive')
        self._fields = {}
        self.requires_files = []
        self._dependencies = None
        self.scheme = scheme
        if path is not None:
            self.read(path)
        elif fileobj is not None:
            self.read_file(fileobj)
        elif mapping is not None:
            self.update(mapping)
            self.set_metadata_version()

    def set_metadata_version(self):
        self._fields['Metadata-Version'] = _best_version(self._fields)

    def _write_field(self, fileobj, name, value):
        fileobj.write('%s: %s\n' % (name, value))

    def __getitem__(self, name):
        return self.get(name)

    def __setitem__(self, name, value):
        return self.set(name, value)

    def __delitem__(self, name):
        field_name = self._convert_name(name)
        try:
            del self._fields[field_name]
        except KeyError:
            raise KeyError(name)

    def __contains__(self, name):
        return (name in self._fields or
                self._convert_name(name) in self._fields)

    def _convert_name(self, name):
        if name in _ALL_FIELDS:
            return name
        name = name.replace('-', '_').lower()
        return _ATTR2FIELD.get(name, name)

    def _default_value(self, name):
        if name in _LISTFIELDS or name in _ELEMENTSFIELD:
            return []
        return 'UNKNOWN'

    def _remove_line_prefix(self, value):
        if self.metadata_version in ('1.0', '1.1'):
            return _LINE_PREFIX_PRE_1_2.sub('\n', value)
        else:
            return _LINE_PREFIX_1_2.sub('\n', value)

    def __getattr__(self, name):
        if name in _ATTR2FIELD:
            return self[name]
        raise AttributeError(name)

    #
    # Public API
    #

#    dependencies = property(_get_dependencies, _set_dependencies)

    def get_fullname(self, filesafe=False):
        """Return the distribution name with version.

        If filesafe is true, return a filename-escaped form."""
        return _get_name_and_version(self['Name'], self['Version'], filesafe)

    def is_field(self, name):
        """return True if name is a valid metadata key"""
        name = self._convert_name(name)
        return name in _ALL_FIELDS

    def is_multi_field(self, name):
        name = self._convert_name(name)
        return name in _LISTFIELDS

    def read(self, filepath):
        """Read the metadata values from a file path."""
        fp = codecs.open(filepath, 'r', encoding='utf-8')
        try:
            self.read_file(fp)
        finally:
            fp.close()

    def read_file(self, fileob):
        """Read the metadata values from a file object."""
        msg = message_from_file(fileob)
        self._fields['Metadata-Version'] = msg['metadata-version']

        # When reading, get all the fields we can
        for field in _ALL_FIELDS:
            if field not in msg:
                continue
            if field in _LISTFIELDS:
                # we can have multiple lines
                values = msg.get_all(field)
                if field in _LISTTUPLEFIELDS and values is not None:
                    values = [tuple(value.split(',')) for value in values]
                self.set(field, values)
            else:
                # single line
                value = msg[field]
                if value is not None and value != 'UNKNOWN':
                    self.set(field, value)
        # logger.debug('Attempting to set metadata for %s', self)
        # self.set_metadata_version()

    def write(self, filepath, skip_unknown=False):
        """Write the metadata fields to filepath."""
        fp = codecs.open(filepath, 'w', encoding='utf-8')
        try:
            self.write_file(fp, skip_unknown)
        finally:
            fp.close()

    def write_file(self, fileobject, skip_unknown=False):
        """Write the PKG-INFO format data to a file object."""
        self.set_metadata_version()

        for field in _version2fieldlist(self['Metadata-Version']):
            values = self.get(field)
            if skip_unknown and values in ('UNKNOWN', [], ['UNKNOWN']):
                continue
            if field in _ELEMENTSFIELD:
                self._write_field(fileobject, field, ','.join(values))
                continue
            if field not in _LISTFIELDS:
                if field == 'Description':
                    if self.metadata_version in ('1.0', '1.1'):
                        values = values.replace('\n', '\n        ')
                    else:
                        values = values.replace('\n', '\n       |')
                values = [values]

            if field in _LISTTUPLEFIELDS:
                values = [','.join(value) for value in values]

            for value in values:
                self._write_field(fileobject, field, value)

    def update(self, other=None, **kwargs):
        """Set metadata values from the given iterable `other` and kwargs.

        Behavior is like `dict.update`: If `other` has a ``keys`` method,
        they are looped over and ``self[key]`` is assigned ``other[key]``.
        Else, ``other`` is an iterable of ``(key, value)`` iterables.

        Keys that don't match a metadata field or that have an empty value are
        dropped.
        """
        def _set(key, value):
            if key in _ATTR2FIELD and value:
                self.set(self._convert_name(key), value)

        if not other:
            # other is None or empty container
            pass
        elif hasattr(other, 'keys'):
            for k in other.keys():
                _set(k, other[k])
        else:
            for k, v in other:
                _set(k, v)

        if kwargs:
            for k, v in kwargs.items():
                _set(k, v)

    def set(self, name, value):
        """Control then set a metadata field."""
        name = self._convert_name(name)

        if ((name in _ELEMENTSFIELD or name == 'Platform') and
            not isinstance(value, (list, tuple))):
            if isinstance(value, string_types):
                value = [v.strip() for v in value.split(',')]
            else:
                value = []
        elif (name in _LISTFIELDS and
              not isinstance(value, (list, tuple))):
            if isinstance(value, string_types):
                value = [value]
            else:
                value = []

        if logger.isEnabledFor(logging.WARNING):
            project_name = self['Name']

            scheme = get_scheme(self.scheme)
            if name in _PREDICATE_FIELDS and value is not None:
                for v in value:
                    # check that the values are valid
                    if not scheme.is_valid_matcher(v.split(';')[0]):
                        logger.warning(
                            "'%s': '%s' is not valid (field '%s')",
                            project_name, v, name)
            # FIXME this rejects UNKNOWN, is that right?
            elif name in _VERSIONS_FIELDS and value is not None:
                if not scheme.is_valid_constraint_list(value):
                    logger.warning("'%s': '%s' is not a valid version (field '%s')",
                                   project_name, value, name)
            elif name in _VERSION_FIELDS and value is not None:
                if not scheme.is_valid_version(value):
                    logger.warning("'%s': '%s' is not a valid version (field '%s')",
                                   project_name, value, name)

        if name in _UNICODEFIELDS:
            if name == 'Description':
                value = self._remove_line_prefix(value)

        self._fields[name] = value

    def get(self, name, default=_MISSING):
        """Get a metadata field."""
        name = self._convert_name(name)
        if name not in self._fields:
            if default is _MISSING:
                default = self._default_value(name)
            return default
        if name in _UNICODEFIELDS:
            value = self._fields[name]
            return value
        elif name in _LISTFIELDS:
            value = self._fields[name]
            if value is None:
                return []
            res = []
            for val in value:
                if name not in _LISTTUPLEFIELDS:
                    res.append(val)
                else:
                    # That's for Project-URL
                    res.append((val[0], val[1]))
            return res

        elif name in _ELEMENTSFIELD:
            value = self._fields[name]
            if isinstance(value, string_types):
                return value.split(',')
        return self._fields[name]

    def check(self, strict=False):
        """Check if the metadata is compliant. If strict is True then raise if
        no Name or Version are provided"""
        self.set_metadata_version()

        # XXX should check the versions (if the file was loaded)
        missing, warnings = [], []

        for attr in ('Name', 'Version'):  # required by PEP 345
            if attr not in self:
                missing.append(attr)

        if strict and missing != []:
            msg = 'missing required metadata: %s' % ', '.join(missing)
            raise MetadataMissingError(msg)

        for attr in ('Home-page', 'Author'):
            if attr not in self:
                missing.append(attr)

        # checking metadata 1.2 (XXX needs to check 1.1, 1.0)
        if self['Metadata-Version'] != '1.2':
            return missing, warnings

        scheme = get_scheme(self.scheme)

        def are_valid_constraints(value):
            for v in value:
                if not scheme.is_valid_matcher(v.split(';')[0]):
                    return False
            return True

        for fields, controller in ((_PREDICATE_FIELDS, are_valid_constraints),
                                   (_VERSIONS_FIELDS,
                                    scheme.is_valid_constraint_list),
                                   (_VERSION_FIELDS,
                                    scheme.is_valid_version)):
            for field in fields:
                value = self.get(field, None)
                if value is not None and not controller(value):
                    warnings.append("Wrong value for '%s': %s" % (field, value))

        return missing, warnings

    def todict(self, skip_missing=False):
        """Return fields as a dict.

        Field names will be converted to use the underscore-lowercase style
        instead of hyphen-mixed case (i.e. home_page instead of Home-page).
        """
        self.set_metadata_version()

        mapping_1_0 = (
            ('metadata_version', 'Metadata-Version'),
            ('name', 'Name'),
            ('version', 'Version'),
            ('summary', 'Summary'),
            ('home_page', 'Home-page'),
            ('author', 'Author'),
            ('author_email', 'Author-email'),
            ('license', 'License'),
            ('description', 'Description'),
            ('keywords', 'Keywords'),
            ('platform', 'Platform'),
            ('classifiers', 'Classifier'),
            ('download_url', 'Download-URL'),
        )

        data = {}
        for key, field_name in mapping_1_0:
            if not skip_missing or field_name in self._fields:
                data[key] = self[field_name]

        if self['Metadata-Version'] == '1.2':
            mapping_1_2 = (
                ('requires_dist', 'Requires-Dist'),
                ('requires_python', 'Requires-Python'),
                ('requires_external', 'Requires-External'),
                ('provides_dist', 'Provides-Dist'),
                ('obsoletes_dist', 'Obsoletes-Dist'),
                ('project_url', 'Project-URL'),
                ('maintainer', 'Maintainer'),
                ('maintainer_email', 'Maintainer-email'),
            )
            for key, field_name in mapping_1_2:
                if not skip_missing or field_name in self._fields:
                    if key != 'project_url':
                        data[key] = self[field_name]
                    else:
                        data[key] = [','.join(u) for u in self[field_name]]

        elif self['Metadata-Version'] == '1.1':
            mapping_1_1 = (
                ('provides', 'Provides'),
                ('requires', 'Requires'),
                ('obsoletes', 'Obsoletes'),
            )
            for key, field_name in mapping_1_1:
                if not skip_missing or field_name in self._fields:
                    data[key] = self[field_name]

        return data

    def add_requirements(self, requirements):
        if self['Metadata-Version'] == '1.1':
            # we can't have 1.1 metadata *and* Setuptools requires
            for field in ('Obsoletes', 'Requires', 'Provides'):
                if field in self:
                    del self[field]
        self['Requires-Dist'] += requirements

    # Mapping API
    # TODO could add iter* variants

    def keys(self):
        return list(_version2fieldlist(self['Metadata-Version']))

    def __iter__(self):
        for key in self.keys():
            yield key

    def values(self):
        return [self[key] for key in self.keys()]

    def items(self):
        return [(key, self[key]) for key in self.keys()]

    def __repr__(self):
        return '<%s %s %s>' % (self.__class__.__name__, self.name,
                               self.version)


METADATA_FILENAME = 'pydist.json'
WHEEL_METADATA_FILENAME = 'metadata.json'
LEGACY_METADATA_FILENAME = 'METADATA'


class Metadata(object):
    """
    The metadata of a release. This implementation uses 2.0 (JSON)
    metadata where possible. If not possible, it wraps a LegacyMetadata
    instance which handles the key-value metadata format.
    """

    METADATA_VERSION_MATCHER = re.compile(r'^\d+(\.\d+)*$')

    NAME_MATCHER = re.compile('^[0-9A-Z]([0-9A-Z_.-]*[0-9A-Z])?$', re.I)

    VERSION_MATCHER = PEP440_VERSION_RE

    SUMMARY_MATCHER = re.compile('.{1,2047}')

    METADATA_VERSION = '2.0'

    GENERATOR = 'distlib (%s)' % __version__

    MANDATORY_KEYS = {
        'name': (),
        'version': (),
        'summary': ('legacy',),
    }

    INDEX_KEYS = ('name version license summary description author '
                  'author_email keywords platform home_page classifiers '
                  'download_url')

    DEPENDENCY_KEYS = ('extras run_requires test_requires build_requires '
                       'dev_requires provides meta_requires obsoleted_by '
                       'supports_environments')

    SYNTAX_VALIDATORS = {
        'metadata_version': (METADATA_VERSION_MATCHER, ()),
        'name': (NAME_MATCHER, ('legacy',)),
        'version': (VERSION_MATCHER, ('legacy',)),
        'summary': (SUMMARY_MATCHER, ('legacy',)),
    }

    __slots__ = ('_legacy', '_data', 'scheme')

    def __init__(self, path=None, fileobj=None, mapping=None,
                 scheme='default'):
        if [path, fileobj, mapping].count(None) < 2:
            raise TypeError('path, fileobj and mapping are exclusive')
        self._legacy = None
        self._data = None
        self.scheme = scheme
        #import pdb; pdb.set_trace()
        if mapping is not None:
            try:
                self._validate_mapping(mapping, scheme)
                self._data = mapping
            except MetadataUnrecognizedVersionError:
                self._legacy = LegacyMetadata(mapping=mapping, scheme=scheme)
                self.validate()
        else:
            data = None
            if path:
                with open(path, 'rb') as f:
                    data = f.read()
            elif fileobj:
                data = fileobj.read()
            if data is None:
                # Initialised with no args - to be added
                self._data = {
                    'metadata_version': self.METADATA_VERSION,
                    'generator': self.GENERATOR,
                }
            else:
                if not isinstance(data, text_type):
                    data = data.decode('utf-8')
                try:
                    self._data = json.loads(data)
                    self._validate_mapping(self._data, scheme)
                except ValueError:
                    # Note: MetadataUnrecognizedVersionError does not
                    # inherit from ValueError (it's a DistlibException,
                    # which should not inherit from ValueError).
                    # The ValueError comes from the json.load - if that
                    # succeeds and we get a validation error, we want
                    # that to propagate
                    self._legacy = LegacyMetadata(fileobj=StringIO(data),
                                                  scheme=scheme)
                    self.validate()

    common_keys = set(('name', 'version', 'license', 'keywords', 'summary'))

    none_list = (None, list)
    none_dict = (None, dict)

    mapped_keys = {
        'run_requires': ('Requires-Dist', list),
        'build_requires': ('Setup-Requires-Dist', list),
        'dev_requires': none_list,
        'test_requires': none_list,
        'meta_requires': none_list,
        'extras': ('Provides-Extra', list),
        'modules': none_list,
        'namespaces': none_list,
        'exports': none_dict,
        'commands': none_dict,
        'classifiers': ('Classifier', list),
        'source_url': ('Download-URL', None),
        'metadata_version': ('Metadata-Version', None),
    }

    del none_list, none_dict

    def __getattribute__(self, key):
        common = object.__getattribute__(self, 'common_keys')
        mapped = object.__getattribute__(self, 'mapped_keys')
        if key in mapped:
            lk, maker = mapped[key]
            if self._legacy:
                if lk is None:
                    result = None if maker is None else maker()
                else:
                    result = self._legacy.get(lk)
            else:
                value = None if maker is None else maker()
                if key not in ('commands', 'exports', 'modules', 'namespaces',
                               'classifiers'):
                    result = self._data.get(key, value)
                else:
                    # special cases for PEP 459
                    sentinel = object()
                    result = sentinel
                    d = self._data.get('extensions')
                    if d:
                        if key == 'commands':
                            result = d.get('python.commands', value)
                        elif key == 'classifiers':
                            d = d.get('python.details')
                            if d:
                                result = d.get(key, value)
                        else:
                            d = d.get('python.exports')
                            if not d:
                                d = self._data.get('python.exports')
                            if d:
                                result = d.get(key, value)
                    if result is sentinel:
                        result = value
        elif key not in common:
            result = object.__getattribute__(self, key)
        elif self._legacy:
            result = self._legacy.get(key)
        else:
            result = self._data.get(key)
        return result

    def _validate_value(self, key, value, scheme=None):
        if key in self.SYNTAX_VALIDATORS:
            pattern, exclusions = self.SYNTAX_VALIDATORS[key]
            if (scheme or self.scheme) not in exclusions:
                m = pattern.match(value)
                if not m:
                    raise MetadataInvalidError("'%s' is an invalid value for "
                                               "the '%s' property" % (value,
                                                                    key))

    def __setattr__(self, key, value):
        self._validate_value(key, value)
        common = object.__getattribute__(self, 'common_keys')
        mapped = object.__getattribute__(self, 'mapped_keys')
        if key in mapped:
            lk, _ = mapped[key]
            if self._legacy:
                if lk is None:
                    raise NotImplementedError
                self._legacy[lk] = value
            elif key not in ('commands', 'exports', 'modules', 'namespaces',
                             'classifiers'):
                self._data[key] = value
            else:
                # special cases for PEP 459
                d = self._data.setdefault('extensions', {})
                if key == 'commands':
                    d['python.commands'] = value
                elif key == 'classifiers':
                    d = d.setdefault('python.details', {})
                    d[key] = value
                else:
                    d = d.setdefault('python.exports', {})
                    d[key] = value
        elif key not in common:
            object.__setattr__(self, key, value)
        else:
            if key == 'keywords':
                if isinstance(value, string_types):
                    value = value.strip()
                    if value:
                        value = value.split()
                    else:
                        value = []
            if self._legacy:
                self._legacy[key] = value
            else:
                self._data[key] = value

    @property
    def name_and_version(self):
        return _get_name_and_version(self.name, self.version, True)

    @property
    def provides(self):
        if self._legacy:
            result = self._legacy['Provides-Dist']
        else:
            result = self._data.setdefault('provides', [])
        s = '%s (%s)' % (self.name, self.version)
        if s not in result:
            result.append(s)
        return result

    @provides.setter
    def provides(self, value):
        if self._legacy:
            self._legacy['Provides-Dist'] = value
        else:
            self._data['provides'] = value

    def get_requirements(self, reqts, extras=None, env=None):
        """
        Base method to get dependencies, given a set of extras
        to satisfy and an optional environment context.
        :param reqts: A list of sometimes-wanted dependencies,
                      perhaps dependent on extras and environment.
        :param extras: A list of optional components being requested.
        :param env: An optional environment for marker evaluation.
        """
        if self._legacy:
            result = reqts
        else:
            result = []
            extras = get_extras(extras or [], self.extras)
            for d in reqts:
                if 'extra' not in d and 'environment' not in d:
                    # unconditional
                    include = True
                else:
                    if 'extra' not in d:
                        # Not extra-dependent - only environment-dependent
                        include = True
                    else:
                        include = d.get('extra') in extras
                    if include:
                        # Not excluded because of extras, check environment
                        marker = d.get('environment')
                        if marker:
                            include = interpret(marker, env)
                if include:
                    result.extend(d['requires'])
            for key in ('build', 'dev', 'test'):
                e = ':%s:' % key
                if e in extras:
                    extras.remove(e)
                    # A recursive call, but it should terminate since 'test'
                    # has been removed from the extras
                    reqts = self._data.get('%s_requires' % key, [])
                    result.extend(self.get_requirements(reqts, extras=extras,
                                                        env=env))
        return result

    @property
    def dictionary(self):
        if self._legacy:
            return self._from_legacy()
        return self._data

    @property
    def dependencies(self):
        if self._legacy:
            raise NotImplementedError
        else:
            return extract_by_key(self._data, self.DEPENDENCY_KEYS)

    @dependencies.setter
    def dependencies(self, value):
        if self._legacy:
            raise NotImplementedError
        else:
            self._data.update(value)

    def _validate_mapping(self, mapping, scheme):
        if mapping.get('metadata_version') != self.METADATA_VERSION:
            raise MetadataUnrecognizedVersionError()
        missing = []
        for key, exclusions in self.MANDATORY_KEYS.items():
            if key not in mapping:
                if scheme not in exclusions:
                    missing.append(key)
        if missing:
            msg = 'Missing metadata items: %s' % ', '.join(missing)
            raise MetadataMissingError(msg)
        for k, v in mapping.items():
            self._validate_value(k, v, scheme)

    def validate(self):
        if self._legacy:
            missing, warnings = self._legacy.check(True)
            if missing or warnings:
                logger.warning('Metadata: missing: %s, warnings: %s',
                               missing, warnings)
        else:
            self._validate_mapping(self._data, self.scheme)

    def todict(self):
        if self._legacy:
            return self._legacy.todict(True)
        else:
            result = extract_by_key(self._data, self.INDEX_KEYS)
            return result

    def _from_legacy(self):
        assert self._legacy and not self._data
        result = {
            'metadata_version': self.METADATA_VERSION,
            'generator': self.GENERATOR,
        }
        lmd = self._legacy.todict(True)     # skip missing ones
        for k in ('name', 'version', 'license', 'summary', 'description',
                  'classifier'):
            if k in lmd:
                if k == 'classifier':
                    nk = 'classifiers'
                else:
                    nk = k
                result[nk] = lmd[k]
        kw = lmd.get('Keywords', [])
        if kw == ['']:
            kw = []
        result['keywords'] = kw
        keys = (('requires_dist', 'run_requires'),
                ('setup_requires_dist', 'build_requires'))
        for ok, nk in keys:
            if ok in lmd and lmd[ok]:
                result[nk] = [{'requires': lmd[ok]}]
        result['provides'] = self.provides
        author = {}
        maintainer = {}
        return result

    LEGACY_MAPPING = {
        'name': 'Name',
        'version': 'Version',
        'license': 'License',
        'summary': 'Summary',
        'description': 'Description',
        'classifiers': 'Classifier',
    }

    def _to_legacy(self):
        def process_entries(entries):
            reqts = set()
            for e in entries:
                extra = e.get('extra')
                env = e.get('environment')
                rlist = e['requires']
                for r in rlist:
                    if not env and not extra:
                        reqts.add(r)
                    else:
                        marker = ''
                        if extra:
                            marker = 'extra == "%s"' % extra
                        if env:
                            if marker:
                                marker = '(%s) and %s' % (env, marker)
                            else:
                                marker = env
                        reqts.add(';'.join((r, marker)))
            return reqts

        assert self._data and not self._legacy
        result = LegacyMetadata()
        nmd = self._data
        for nk, ok in self.LEGACY_MAPPING.items():
            if nk in nmd:
                result[ok] = nmd[nk]
        r1 = process_entries(self.run_requires + self.meta_requires)
        r2 = process_entries(self.build_requires + self.dev_requires)
        if self.extras:
            result['Provides-Extra'] = sorted(self.extras)
        result['Requires-Dist'] = sorted(r1)
        result['Setup-Requires-Dist'] = sorted(r2)
        # TODO: other fields such as contacts
        return result

    def write(self, path=None, fileobj=None, legacy=False, skip_unknown=True):
        if [path, fileobj].count(None) != 1:
            raise ValueError('Exactly one of path and fileobj is needed')
        self.validate()
        if legacy:
            if self._legacy:
                legacy_md = self._legacy
            else:
                legacy_md = self._to_legacy()
            if path:
                legacy_md.write(path, skip_unknown=skip_unknown)
            else:
                legacy_md.write_file(fileobj, skip_unknown=skip_unknown)
        else:
            if self._legacy:
                d = self._from_legacy()
            else:
                d = self._data
            if fileobj:
                json.dump(d, fileobj, ensure_ascii=True, indent=2,
                          sort_keys=True)
            else:
                with codecs.open(path, 'w', 'utf-8') as f:
                    json.dump(d, f, ensure_ascii=True, indent=2,
                              sort_keys=True)

    def add_requirements(self, requirements):
        if self._legacy:
            self._legacy.add_requirements(requirements)
        else:
            run_requires = self._data.setdefault('run_requires', [])
            always = None
            for entry in run_requires:
                if 'environment' not in entry and 'extra' not in entry:
                    always = entry
                    break
            if always is None:
                always = { 'requires': requirements }
                run_requires.insert(0, always)
            else:
                rset = set(always['requires']) | set(requirements)
                always['requires'] = sorted(rset)

    def __repr__(self):
        name = self.name or '(no name)'
        version = self.version or 'no version'
        return '<%s %s %s (%s)>' % (self.__class__.__name__,
                                    self.metadata_version, name, version)
PKÕ¶N]x¦5gÛ9Û9-site-packages/pip/_vendor/distlib/manifest.pynu„[µü¤# -*- coding: utf-8 -*-
#
# Copyright (C) 2012-2013 Python Software Foundation.
# See LICENSE.txt and CONTRIBUTORS.txt.
#
"""
Class representing the list of files in a distribution.

Equivalent to distutils.filelist, but fixes some problems.
"""
import fnmatch
import logging
import os
import re
import sys

from . import DistlibException
from .compat import fsdecode
from .util import convert_path


__all__ = ['Manifest']

logger = logging.getLogger(__name__)

# a \ followed by some spaces + EOL
_COLLAPSE_PATTERN = re.compile('\\\\w*\n', re.M)
_COMMENTED_LINE = re.compile('#.*?(?=\n)|\n(?=$)', re.M | re.S)

#
# Due to the different results returned by fnmatch.translate, we need
# to do slightly different processing for Python 2.7 and 3.2 ... this needed
# to be brought in for Python 3.6 onwards.
#
_PYTHON_VERSION = sys.version_info[:2]

class Manifest(object):
    """A list of files built by on exploring the filesystem and filtered by
    applying various patterns to what we find there.
    """

    def __init__(self, base=None):
        """
        Initialise an instance.

        :param base: The base directory to explore under.
        """
        self.base = os.path.abspath(os.path.normpath(base or os.getcwd()))
        self.prefix = self.base + os.sep
        self.allfiles = None
        self.files = set()

    #
    # Public API
    #

    def findall(self):
        """Find all files under the base and set ``allfiles`` to the absolute
        pathnames of files found.
        """
        from stat import S_ISREG, S_ISDIR, S_ISLNK

        self.allfiles = allfiles = []
        root = self.base
        stack = [root]
        pop = stack.pop
        push = stack.append

        while stack:
            root = pop()
            names = os.listdir(root)

            for name in names:
                fullname = os.path.join(root, name)

                # Avoid excess stat calls -- just one will do, thank you!
                stat = os.stat(fullname)
                mode = stat.st_mode
                if S_ISREG(mode):
                    allfiles.append(fsdecode(fullname))
                elif S_ISDIR(mode) and not S_ISLNK(mode):
                    push(fullname)

    def add(self, item):
        """
        Add a file to the manifest.

        :param item: The pathname to add. This can be relative to the base.
        """
        if not item.startswith(self.prefix):
            item = os.path.join(self.base, item)
        self.files.add(os.path.normpath(item))

    def add_many(self, items):
        """
        Add a list of files to the manifest.

        :param items: The pathnames to add. These can be relative to the base.
        """
        for item in items:
            self.add(item)

    def sorted(self, wantdirs=False):
        """
        Return sorted files in directory order
        """

        def add_dir(dirs, d):
            dirs.add(d)
            logger.debug('add_dir added %s', d)
            if d != self.base:
                parent, _ = os.path.split(d)
                assert parent not in ('', '/')
                add_dir(dirs, parent)

        result = set(self.files)    # make a copy!
        if wantdirs:
            dirs = set()
            for f in result:
                add_dir(dirs, os.path.dirname(f))
            result |= dirs
        return [os.path.join(*path_tuple) for path_tuple in
                sorted(os.path.split(path) for path in result)]

    def clear(self):
        """Clear all collected files."""
        self.files = set()
        self.allfiles = []

    def process_directive(self, directive):
        """
        Process a directive which either adds some files from ``allfiles`` to
        ``files``, or removes some files from ``files``.

        :param directive: The directive to process. This should be in a format
                     compatible with distutils ``MANIFEST.in`` files:

                     http://docs.python.org/distutils/sourcedist.html#commands
        """
        # Parse the line: split it up, make sure the right number of words
        # is there, and return the relevant words.  'action' is always
        # defined: it's the first word of the line.  Which of the other
        # three are defined depends on the action; it'll be either
        # patterns, (dir and patterns), or (dirpattern).
        action, patterns, thedir, dirpattern = self._parse_directive(directive)

        # OK, now we know that the action is valid and we have the
        # right number of words on the line for that action -- so we
        # can proceed with minimal error-checking.
        if action == 'include':
            for pattern in patterns:
                if not self._include_pattern(pattern, anchor=True):
                    logger.warning('no files found matching %r', pattern)

        elif action == 'exclude':
            for pattern in patterns:
                found = self._exclude_pattern(pattern, anchor=True)
                #if not found:
                #    logger.warning('no previously-included files '
                #                   'found matching %r', pattern)

        elif action == 'global-include':
            for pattern in patterns:
                if not self._include_pattern(pattern, anchor=False):
                    logger.warning('no files found matching %r '
                                   'anywhere in distribution', pattern)

        elif action == 'global-exclude':
            for pattern in patterns:
                found = self._exclude_pattern(pattern, anchor=False)
                #if not found:
                #    logger.warning('no previously-included files '
                #                   'matching %r found anywhere in '
                #                   'distribution', pattern)

        elif action == 'recursive-include':
            for pattern in patterns:
                if not self._include_pattern(pattern, prefix=thedir):
                    logger.warning('no files found matching %r '
                                   'under directory %r', pattern, thedir)

        elif action == 'recursive-exclude':
            for pattern in patterns:
                found = self._exclude_pattern(pattern, prefix=thedir)
                #if not found:
                #    logger.warning('no previously-included files '
                #                   'matching %r found under directory %r',
                #                   pattern, thedir)

        elif action == 'graft':
            if not self._include_pattern(None, prefix=dirpattern):
                logger.warning('no directories found matching %r',
                               dirpattern)

        elif action == 'prune':
            if not self._exclude_pattern(None, prefix=dirpattern):
                logger.warning('no previously-included directories found '
                               'matching %r', dirpattern)
        else:   # pragma: no cover
            # This should never happen, as it should be caught in
            # _parse_template_line
            raise DistlibException(
                'invalid action %r' % action)

    #
    # Private API
    #

    def _parse_directive(self, directive):
        """
        Validate a directive.
        :param directive: The directive to validate.
        :return: A tuple of action, patterns, thedir, dir_patterns
        """
        words = directive.split()
        if len(words) == 1 and words[0] not in ('include', 'exclude',
                                                'global-include',
                                                'global-exclude',
                                                'recursive-include',
                                                'recursive-exclude',
                                                'graft', 'prune'):
            # no action given, let's use the default 'include'
            words.insert(0, 'include')

        action = words[0]
        patterns = thedir = dir_pattern = None

        if action in ('include', 'exclude',
                      'global-include', 'global-exclude'):
            if len(words) < 2:
                raise DistlibException(
                    '%r expects   ...' % action)

            patterns = [convert_path(word) for word in words[1:]]

        elif action in ('recursive-include', 'recursive-exclude'):
            if len(words) < 3:
                raise DistlibException(
                    '%r expects    ...' % action)

            thedir = convert_path(words[1])
            patterns = [convert_path(word) for word in words[2:]]

        elif action in ('graft', 'prune'):
            if len(words) != 2:
                raise DistlibException(
                    '%r expects a single ' % action)

            dir_pattern = convert_path(words[1])

        else:
            raise DistlibException('unknown action %r' % action)

        return action, patterns, thedir, dir_pattern

    def _include_pattern(self, pattern, anchor=True, prefix=None,
                         is_regex=False):
        """Select strings (presumably filenames) from 'self.files' that
        match 'pattern', a Unix-style wildcard (glob) pattern.

        Patterns are not quite the same as implemented by the 'fnmatch'
        module: '*' and '?'  match non-special characters, where "special"
        is platform-dependent: slash on Unix; colon, slash, and backslash on
        DOS/Windows; and colon on Mac OS.

        If 'anchor' is true (the default), then the pattern match is more
        stringent: "*.py" will match "foo.py" but not "foo/bar.py".  If
        'anchor' is false, both of these will match.

        If 'prefix' is supplied, then only filenames starting with 'prefix'
        (itself a pattern) and ending with 'pattern', with anything in between
        them, will match.  'anchor' is ignored in this case.

        If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and
        'pattern' is assumed to be either a string containing a regex or a
        regex object -- no translation is done, the regex is just compiled
        and used as-is.

        Selected strings will be added to self.files.

        Return True if files are found.
        """
        # XXX docstring lying about what the special chars are?
        found = False
        pattern_re = self._translate_pattern(pattern, anchor, prefix, is_regex)

        # delayed loading of allfiles list
        if self.allfiles is None:
            self.findall()

        for name in self.allfiles:
            if pattern_re.search(name):
                self.files.add(name)
                found = True
        return found

    def _exclude_pattern(self, pattern, anchor=True, prefix=None,
                         is_regex=False):
        """Remove strings (presumably filenames) from 'files' that match
        'pattern'.

        Other parameters are the same as for 'include_pattern()', above.
        The list 'self.files' is modified in place. Return True if files are
        found.

        This API is public to allow e.g. exclusion of SCM subdirs, e.g. when
        packaging source distributions
        """
        found = False
        pattern_re = self._translate_pattern(pattern, anchor, prefix, is_regex)
        for f in list(self.files):
            if pattern_re.search(f):
                self.files.remove(f)
                found = True
        return found

    def _translate_pattern(self, pattern, anchor=True, prefix=None,
                           is_regex=False):
        """Translate a shell-like wildcard pattern to a compiled regular
        expression.

        Return the compiled regex.  If 'is_regex' true,
        then 'pattern' is directly compiled to a regex (if it's a string)
        or just returned as-is (assumes it's a regex object).
        """
        if is_regex:
            if isinstance(pattern, str):
                return re.compile(pattern)
            else:
                return pattern

        if _PYTHON_VERSION > (3, 2):
            # ditch start and end characters
            start, _, end = self._glob_to_re('_').partition('_')

        if pattern:
            pattern_re = self._glob_to_re(pattern)
            if _PYTHON_VERSION > (3, 2):
                assert pattern_re.startswith(start) and pattern_re.endswith(end)
        else:
            pattern_re = ''

        base = re.escape(os.path.join(self.base, ''))
        if prefix is not None:
            # ditch end of pattern character
            if _PYTHON_VERSION <= (3, 2):
                empty_pattern = self._glob_to_re('')
                prefix_re = self._glob_to_re(prefix)[:-len(empty_pattern)]
            else:
                prefix_re = self._glob_to_re(prefix)
                assert prefix_re.startswith(start) and prefix_re.endswith(end)
                prefix_re = prefix_re[len(start): len(prefix_re) - len(end)]
            sep = os.sep
            if os.sep == '\\':
                sep = r'\\'
            if _PYTHON_VERSION <= (3, 2):
                pattern_re = '^' + base + sep.join((prefix_re,
                                                    '.*' + pattern_re))
            else:
                pattern_re = pattern_re[len(start): len(pattern_re) - len(end)]
                pattern_re = r'%s%s%s%s.*%s%s' % (start, base, prefix_re, sep,
                                                  pattern_re, end)
        else:  # no prefix -- respect anchor flag
            if anchor:
                if _PYTHON_VERSION <= (3, 2):
                    pattern_re = '^' + base + pattern_re
                else:
                    pattern_re = r'%s%s%s' % (start, base, pattern_re[len(start):])

        return re.compile(pattern_re)

    def _glob_to_re(self, pattern):
        """Translate a shell-like glob pattern to a regular expression.

        Return a string containing the regex.  Differs from
        'fnmatch.translate()' in that '*' does not match "special characters"
        (which are platform-specific).
        """
        pattern_re = fnmatch.translate(pattern)

        # '?' and '*' in the glob pattern become '.' and '.*' in the RE, which
        # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix,
        # and by extension they shouldn't match such "special characters" under
        # any OS.  So change all non-escaped dots in the RE to match any
        # character except the special characters (currently: just os.sep).
        sep = os.sep
        if os.sep == '\\':
            # we're using a regex to manipulate a regex, so we need
            # to escape the backslash twice
            sep = r'\\\\'
        escaped = r'\1[^%s]' % sep
        pattern_re = re.sub(r'((?= 0 and read < size:
            raise DistlibException(
                'retrieval incomplete: got only %d out of %d bytes'
                % (read, size))
        # if we have a digest, it must match.
        if digester:
            actual = digester.hexdigest()
            if digest != actual:
                raise DistlibException('%s digest mismatch for %s: expected '
                                       '%s, got %s' % (hasher, destfile,
                                                       digest, actual))
            logger.debug('Digest verified: %s', digest)

    def send_request(self, req):
        """
        Send a standard library :class:`Request` to PyPI and return its
        response.

        :param req: The request to send.
        :return: The HTTP response from PyPI (a standard library HTTPResponse).
        """
        handlers = []
        if self.password_handler:
            handlers.append(self.password_handler)
        if self.ssl_verifier:
            handlers.append(self.ssl_verifier)
        opener = build_opener(*handlers)
        return opener.open(req)

    def encode_request(self, fields, files):
        """
        Encode fields and files for posting to an HTTP server.

        :param fields: The fields to send as a list of (fieldname, value)
                       tuples.
        :param files: The files to send as a list of (fieldname, filename,
                      file_bytes) tuple.
        """
        # Adapted from packaging, which in turn was adapted from
        # http://code.activestate.com/recipes/146306

        parts = []
        boundary = self.boundary
        for k, values in fields:
            if not isinstance(values, (list, tuple)):
                values = [values]

            for v in values:
                parts.extend((
                    b'--' + boundary,
                    ('Content-Disposition: form-data; name="%s"' %
                     k).encode('utf-8'),
                    b'',
                    v.encode('utf-8')))
        for key, filename, value in files:
            parts.extend((
                b'--' + boundary,
                ('Content-Disposition: form-data; name="%s"; filename="%s"' %
                 (key, filename)).encode('utf-8'),
                b'',
                value))

        parts.extend((b'--' + boundary + b'--', b''))

        body = b'\r\n'.join(parts)
        ct = b'multipart/form-data; boundary=' + boundary
        headers = {
            'Content-type': ct,
            'Content-length': str(len(body))
        }
        return Request(self.url, body, headers)

    def search(self, terms, operator=None):
        if isinstance(terms, string_types):
            terms = {'name': terms}
        rpc_proxy = ServerProxy(self.url, timeout=3.0)
        try:
            return rpc_proxy.search(terms, operator or 'and')
        finally:
            rpc_proxy('close')()
PKÕ¶N]¶·ˆf##,site-packages/pip/_vendor/distlib/markers.pynu„[µü¤# -*- coding: utf-8 -*-
#
# Copyright (C) 2012-2017 Vinay Sajip.
# Licensed to the Python Software Foundation under a contributor agreement.
# See LICENSE.txt and CONTRIBUTORS.txt.
#
"""
Parser for the environment markers micro-language defined in PEP 508.
"""

# Note: In PEP 345, the micro-language was Python compatible, so the ast
# module could be used to parse it. However, PEP 508 introduced operators such
# as ~= and === which aren't in Python, necessitating a different approach.

import os
import sys
import platform
import re

from .compat import python_implementation, urlparse, string_types
from .util import in_venv, parse_marker

__all__ = ['interpret']

def _is_literal(o):
    if not isinstance(o, string_types) or not o:
        return False
    return o[0] in '\'"'

class Evaluator(object):
    """
    This class is used to evaluate marker expessions.
    """

    operations = {
        '==': lambda x, y: x == y,
        '===': lambda x, y: x == y,
        '~=': lambda x, y: x == y or x > y,
        '!=': lambda x, y: x != y,
        '<':  lambda x, y: x < y,
        '<=':  lambda x, y: x == y or x < y,
        '>':  lambda x, y: x > y,
        '>=':  lambda x, y: x == y or x > y,
        'and': lambda x, y: x and y,
        'or': lambda x, y: x or y,
        'in': lambda x, y: x in y,
        'not in': lambda x, y: x not in y,
    }

    def evaluate(self, expr, context):
        """
        Evaluate a marker expression returned by the :func:`parse_requirement`
        function in the specified context.
        """
        if isinstance(expr, string_types):
            if expr[0] in '\'"':
                result = expr[1:-1]
            else:
                if expr not in context:
                    raise SyntaxError('unknown variable: %s' % expr)
                result = context[expr]
        else:
            assert isinstance(expr, dict)
            op = expr['op']
            if op not in self.operations:
                raise NotImplementedError('op not implemented: %s' % op)
            elhs = expr['lhs']
            erhs = expr['rhs']
            if _is_literal(expr['lhs']) and _is_literal(expr['rhs']):
                raise SyntaxError('invalid comparison: %s %s %s' % (elhs, op, erhs))

            lhs = self.evaluate(elhs, context)
            rhs = self.evaluate(erhs, context)
            result = self.operations[op](lhs, rhs)
        return result

def default_context():
    def format_full_version(info):
        version = '%s.%s.%s' % (info.major, info.minor, info.micro)
        kind = info.releaselevel
        if kind != 'final':
            version += kind[0] + str(info.serial)
        return version

    if hasattr(sys, 'implementation'):
        implementation_version = format_full_version(sys.implementation.version)
        implementation_name = sys.implementation.name
    else:
        implementation_version = '0'
        implementation_name = ''

    result = {
        'implementation_name': implementation_name,
        'implementation_version': implementation_version,
        'os_name': os.name,
        'platform_machine': platform.machine(),
        'platform_python_implementation': platform.python_implementation(),
        'platform_release': platform.release(),
        'platform_system': platform.system(),
        'platform_version': platform.version(),
        'platform_in_venv': str(in_venv()),
        'python_full_version': platform.python_version(),
        'python_version': platform.python_version()[:3],
        'sys_platform': sys.platform,
    }
    return result

DEFAULT_CONTEXT = default_context()
del default_context

evaluator = Evaluator()

def interpret(marker, execution_context=None):
    """
    Interpret a marker and return a result depending on environment.

    :param marker: The marker to interpret.
    :type marker: str
    :param execution_context: The context used for name lookup.
    :type execution_context: mapping
    """
    try:
        expr, rest = parse_marker(marker)
    except Exception as e:
        raise SyntaxError('Unable to interpret marker syntax: %s: %s' % (marker, e))
    if rest and rest[0] != '#':
        raise SyntaxError('unexpected trailing data in marker: %s: %s' % (marker, rest))
    context = dict(DEFAULT_CONTEXT)
    if execution_context:
        context.update(execution_context)
    return evaluator.evaluate(expr, context)
PKÕ¶N]#ïgü7site-packages/pip/_vendor/distlib/_backport/__init__.pynu„[µü¤"""Modules copied from Python 3 standard libraries, for internal use only.

Individual classes and functions are found in d2._backport.misc.  Intended
usage is to always import things missing from 3.1 from that module: the
built-in/stdlib objects will be used if found.
"""
PKÕ¶N]=Íìa¶=¶=Vsite-packages/pip/_vendor/distlib/_backport/__pycache__/sysconfig.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eTiã@s¢dZddlZddlZddlZddlZddlmZmZzddlZWne	k
r\ddl
ZYnXdddddd	d
ddd
dgZdd„Zej
ršej eej
ƒ¡Znee ¡ƒZejdkrÖdedd… ¡krÖeej ee¡ƒZejdk�rdedd… ¡k�reej eee¡ƒZejdk�rBdedd… ¡k�rBeej eee¡ƒZdd„ZeƒZdadd„Ze ¡Ze d¡Zdd„Zej ¡dZ ejdd …Z!e de d!Z"ej #ej$¡Z%ej #ej&¡Z'da(dZ)d"d#„Z*d$d%„Z+d&d'„Z,d(d)„Z-d*d+„Z.d,d-„Z/dEd.d/„Z0d0d„Z1d1d2„Z2d3d4„Z3dFd5d„Z4d6d„Z5d7d
„Z6d8d	„Z7e.ƒdd9fd:d
„Z8e.ƒdd9fd;d„Z9dd„ZdBdC„Z?e@dDk�rže?ƒdS)Gz-Access to Python's configuration information.éN)ÚpardirÚrealpathÚget_config_h_filenameÚget_config_varÚget_config_varsÚget_makefile_filenameÚget_pathÚget_path_namesÚ	get_pathsÚget_platformÚget_python_versionÚget_scheme_namesÚparse_config_hcCs(z
t|ƒWStk
r"|YSXdS©N)rÚOSError)Úpath©rúK/usr/lib/python3.8/site-packages/pip/_vendor/distlib/_backport/sysconfig.pyÚ_safe_realpath"s
rÚntZpcbuildiøÿÿÿz\pc\viöÿÿÿz\pcbuild\amd64iòÿÿÿcCs,dD]"}tj tj td|¡¡rdSqdS)N)z
Setup.distzSetup.localZModulesTF)ÚosrÚisfileÚjoinÚ
_PROJECT_BASE)ÚfnrrrÚis_python_build:srFc	Cs‚ts~ddlm}t dd¡d}||ƒ}| d¡}| ¡�}t |¡W5QRXt	rzdD] }t 
|dd	¡t 
|d
d¡qXdadS)
Né)ÚfinderÚ.érz
sysconfig.cfg)Úposix_prefixZ
posix_homeÚincludez{srcdir}/IncludeÚplatincludez{projectbase}/.T)Ú	_cfg_readZ	resourcesrÚ__name__ÚrsplitÚfindZ	as_streamÚ_SCHEMESZreadfpÚ
_PYTHON_BUILDÚset)rZbackport_packageZ_finderZ_cfgfileÚsÚschemerrrÚ_ensure_cfg_readDs

r,z\{([^{]*?)\}c
sÈtƒ| d¡r| d¡}ntƒ}| ¡}|D]8}|dkr._replacer)r,Zhas_sectionÚitemsÚtupleÚsectionsZ
has_optionr)Zremove_sectionÚdictÚ	_VAR_REPLÚsub)Úconfigr-r8ZsectionZoptionÚvaluer5rr3rÚ_expand_globalsYs$

r>ércs‡fdd„}t ||¡S)z»In the string `path`, replace tokens like {some.thing} with the
    corresponding value from the map `local_vars`.

    If there is no corresponding value, leave the token unchanged.
    cs8| d¡}|ˆkrˆ|S|tjkr.tj|S| d¡Sr.)r0rÚenvironr1©Ú
local_varsrrr5‹s


z_subst_vars.._replacer©r:r;)rrBr5rrArÚ_subst_vars…srDcCs0| ¡}| ¡D]\}}||kr"q|||<qdSr)Úkeysr6)Ztarget_dictZ
other_dictZtarget_keysÚkeyr=rrrÚ_extend_dict•s
rGcCs`i}|dkri}t|tƒƒt |¡D]4\}}tjdkrDtj |¡}tj t	||ƒ¡||<q&|S)N)Úposixr)
rGrr'r6rr2rÚ
expanduserÚnormpathrD)r+ÚvarsÚresrFr=rrrÚ_expand_vars�s
rMcs‡fdd„}t ||¡S)Ncs$| d¡}|ˆkrˆ|S| d¡Sr.r/r1©rKrrr5«s
zformat_value.._replacerrC)r=rKr5rrNrÚformat_valueªsrOcCstjdkrdStjS)NrHr )rr2rrrrÚ_get_default_scheme³s
rPcCs’tj dd¡}dd„}tjdkrBtj d¡p.d}|r8|S||dƒStjdkr|td	ƒ}|r||r`|S|dd
|dtjdd…ƒS|r„|S|dd
ƒSdS)NÚPYTHONUSERBASEcWstj tjj|Ž¡Sr)rrrIr)ÚargsrrrÚjoinuser½sz_getuserbase..joinuserrÚAPPDATAú~ÚPythonÚdarwinZPYTHONFRAMEWORKÚLibraryz%d.%drz.local)rr@Úgetr2ÚsysÚplatformrÚversion_info)Úenv_baserSÚbaseZ	frameworkrrrÚ_getuserbaseºs$



ÿr_c	Cst d¡}t d¡}t d¡}|dkr*i}i}i}tj|ddd��}| ¡}W5QRX|D]š}	|	 d¡sZ|	 ¡d	krvqZ| |	¡}
|
rZ|
 d
d¡\}}| ¡}| 	dd	¡}
d
|
krº|||<qZzt
|ƒ}Wn$tk
rê| 	dd
¡||<YqZX|||<qZt| 
¡ƒ}d}t|ƒdk�rÔt|ƒD�]°}||}| |¡�p>| |¡}
|
dk	�rº|
 d
¡}d}||k�rpt||ƒ}nˆ||k�r€d}nx|tjk�r˜tj|}n`||k�rì| d¡�rÆ|dd…|k�rÆd	}n$d||k�rÚd}nt|d|ƒ}nd	||<}|�rÌ||
 ¡d…}|d|
 ¡…||}d
|k�r:|||<n~zt
|ƒ}Wn"tk
�rh| ¡||<Yn
X|||<| |¡| d¡�rÌ|dd…|k�rÌ|dd…}||k�rÌ|||<n|||<| |¡�q�q| ¡D]"\}}t|tƒ�rÜ| ¡||<�qÜ| |¡|S)zÌParse a Makefile-style file.

    A dictionary containing name/value pairs is returned.  If an
    optional dictionary is passed in as the second argument, it is
    used instead of a new dictionary.
    z"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)z\$\(([A-Za-z][A-Za-z0-9_]*)\)z\${([A-Za-z][A-Za-z0-9_]*)}Nzutf-8Úsurrogateescape)ÚencodingÚerrorsú#Úrrz$$ú$)ÚCFLAGSÚLDFLAGSZCPPFLAGSrTFZPY_r?)ÚreÚcompileÚcodecsÚopenÚ	readlinesÚ
startswithÚstripÚmatchr0ÚreplaceÚintÚ
ValueErrorÚlistrEÚlenr7ÚsearchÚstrrr@ÚendÚstartÚremover6Ú
isinstanceÚupdate)ÚfilenamerKZ_variable_rxZ_findvar1_rxZ_findvar2_rxZdoneZnotdoneÚfÚlinesÚlineÚmÚnÚvZtmpvr4Zrenamed_variablesr2r=ÚfoundÚitemZafterÚkrrrÚ_parse_makefile×s�	










ÿ


ÿ


r†cCsDtrtj td¡Sttdƒr,dttjf}nd}tj t	dƒ|d¡S)z Return the path of the Makefile.ZMakefileÚabiflagszconfig-%s%sr<Ústdlib)
r(rrrrÚhasattrrZÚ_PY_VERSION_SHORTr‡r)Zconfig_dir_namerrrrMs
c
Csètƒ}zt||ƒWnJtk
r^}z,d|}t|dƒrF|d|j}t|ƒ‚W5d}~XYnXtƒ}z"t|ƒ�}t||ƒW5QRXWnJtk
rÒ}z,d|}t|dƒrº|d|j}t|ƒ‚W5d}~XYnXträ|d|d<dS)z7Initialize the module as appropriate for POSIX systems.z.invalid Python installation: unable to open %sÚstrerrorz (%s)NÚ	BLDSHAREDZLDSHARED)	rr†ÚIOErrorr‰r‹rrkrr()rKZmakefileÚeÚmsgZconfig_hr}rrrÚ_init_posixXs&


r�cCsVtdƒ|d<tdƒ|d<tdƒ|d<d|d<d	|d
<t|d<tj ttjƒ¡|d<d
S)z+Initialize the module as appropriate for NTrˆZLIBDESTZ
platstdlibZ
BINLIBDESTr!Z	INCLUDEPYz.pydZSOz.exeZEXEZVERSIONZBINDIRN)rÚ_PY_VERSION_SHORT_NO_DOTrrÚdirnamerrZÚ
executablerNrrrÚ_init_non_posixtsr”cCsš|dkri}t d¡}t d¡}| ¡}|s.q–| |¡}|rx| dd¡\}}zt|ƒ}Wntk
rlYnX|||<q | |¡}|r d|| d¡<q |S)zÌParse a config.h-style file.

    A dictionary containing name/value pairs is returned.  If an
    optional dictionary is passed in as the second argument, it is
    used instead of a new dictionary.
    Nz"#define ([A-Z][A-Za-z0-9_]+) (.*)
z&/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/
rrr)rhriÚreadlineror0rqrr)ÚfprKZ	define_rxZundef_rxrr€r�r‚rrrr„s&




cCs:tr$tjdkrtj td¡}q,t}ntdƒ}tj |d¡S)zReturn the path of pyconfig.h.rZPCr"z
pyconfig.h)r(rr2rrrr)Zinc_dirrrrr£s
cCsttt ¡ƒƒS)z,Return a tuple containing the schemes names.)r7Úsortedr'r8rrrrr
¯scCs
t d¡S)z*Return a tuple containing the paths names.r )r'Zoptionsrrrrr	´sTcCs&tƒ|rt||ƒStt |¡ƒSdS)z°Return a mapping containing an install scheme.

    ``scheme`` is the install scheme name. If not provided, it will
    return the default scheme for the current platform.
    N)r,rMr9r'r6)r+rKÚexpandrrrr
ºs
cCst|||ƒ|S)z[Return a path corresponding to the scheme.

    ``scheme`` is the install scheme name.
    )r
)r2r+rKr˜rrrrÇscGs¬tdk�rziattd<ttd<ttd<ttd<tdtdtd<ttd	<ttd
<ttd<ztjtd<Wntk
r„d
td<YnXt	j
dkr˜ttƒt	j
dkrªttƒtj
dkr¾tƒtd<dtkrÐttd<nttdƒtd<t�r\t	j
dk�r\t}zt	 ¡}Wntk
�rd}YnXt	j td¡�s\||k�r\t	j |td¡}t	j |¡td<tjdk�rzt	 ¡d}t| d¡dƒ}|dk�rÊdD]2}t|}t dd|¡}t dd|¡}|t|<�q”n°dt	jk�rt	jd}dD]0}t|}t dd|¡}|d|}|t|<�qät dd
¡}	t d|	¡}
|
dk	�rz|
  d¡}t	j !|¡�szdD]$}t|}t dd|¡}|t|<�qT|�r¤g}|D]}
| "t |
¡¡�qˆ|StSdS)ayWith no arguments, return a dictionary of all configuration
    variables relevant for the current platform.

    On Unix, this means every variable defined in Python's installed Makefile;
    On Windows and Mac OS it's a much smaller set.

    With arguments, return a list of values that result from looking up
    each argument in the configuration variable dictionary.
    NÚprefixÚexec_prefixZ
py_versionZpy_version_shortrrZpy_version_nodotr^ZplatbaseZprojectbaser‡rd)rZos2rHz2.6ÚuserbaseÚsrcdirrWré)rgZ
BASECFLAGSrfZ	PY_CFLAGSrŒz
-arch\s+\w+\sú z-isysroot [^ 	]*Z	ARCHFLAGSrfz-isysroot\s+(\S+)rz-isysroot\s+\S+(\s|$))#Ú_CONFIG_VARSÚ_PREFIXÚ_EXEC_PREFIXÚ_PY_VERSIONrŠrrZr‡ÚAttributeErrorrr2r”r�Úversionr_rr(ÚgetcwdrrÚisabsrrJr[ÚunamerqÚsplitrhr;r@rYrur0ÚexistsÚappend)rRr^ÚcwdrœZkernel_versionZ
major_versionrFÚflagsZarchrfr€ZsdkZvalsr2rrrrÏs‚






ÿ



cCstƒ |¡S)z“Return the value of a single variable using the dictionary returned by
    'get_config_vars()'.

    Equivalent to get_config_vars().get(name)
    )rrY)r2rrrrRscCs^tjdkrnd}tj |¡}|dkr(tjStj d|¡}tj|t|ƒ|… ¡}|dkr\dS|dkrhdStjStjd	ks‚ttd
ƒsˆtjSt 	¡\}}}}}| ¡ 
dd¡}| 
d
d¡}| 
dd¡}|dd…dkrÞd||fS|dd…dk�r&|ddk�rPd}dt|dƒd|dd…f}�n*|dd…dk�rDd||fS|dd…dk�rdd|||fS|dd…d k�r d }t 
d!¡}	|	 |¡}
|
�rP|
 ¡}�n°|dd…d"k�rPtƒ}| d#¡}|}
ztd$ƒ}Wntk
�rèYnJXzt d%| ¡¡}
W5| ¡X|
dk	�r2d& |
 d'¡ d&¡dd…¡}
|�s<|
}|�rP|}d(}|
d&d)k�rd*tƒ d+d¡ ¡k�rd,}tƒ d+¡}t d-|¡}ttt|ƒƒƒ}t|ƒd'k�r´|d}n^|d.k�rÄd,}nN|d/k�rÔd0}n>|d1k�räd2}n.|d3k�rôd4}n|d5k�rd6}ntd7|fƒ‚n<|d8k�r0tjd9k�rPd:}n |d;k�rPtjd9k�rLd<}nd=}d>|||fS)?a«Return a string that identifies the current platform.

    This is used mainly to distinguish platform-specific build directories and
    platform-specific built distributions.  Typically includes the OS name
    and version and the architecture (as supplied by 'os.uname()'),
    although the exact information included depends on the OS; eg. for IRIX
    the architecture isn't particularly important (IRIX only runs on SGI
    hardware), but for Linux the kernel version isn't particularly
    important.

    Examples of returned values:
       linux-i586
       linux-alpha (?)
       solaris-2.6-sun4u
       irix-5.3
       irix64-6.2

    Windows will return one of:
       win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
       win-ia64 (64bit Windows on Itanium)
       win32 (all others - specifically, sys.platform is returned)

    For other non-POSIX platforms, currently just returns 'sys.platform'.
    rz bit (éÿÿÿÿú)Zamd64z	win-amd64Zitaniumzwin-ia64rHr§ú/rdržÚ_ú-NéZlinuxz%s-%sZsunosrÚ5Zsolarisz%d.%sr?réZirixZaixz%s-%s.%séÚcygwinz[\d.]+rWZMACOSX_DEPLOYMENT_TARGETz0/System/Library/CoreServices/SystemVersion.plistz=ProductUserVisibleVersion\s*(.*?)rrZmacosxz10.4.z-archrfZfatz
-arch\s+(\S+))Úi386Úppc)r·Úx86_64Zintel)r·r¸r¹Zfat3)Úppc64r¹Zfat64)r·r¸rºr¹Z	universalz%Don't know machine value for archs=%rr·lr¹)ZPowerPCZPower_Macintoshrºr¸z%s-%s-%s) rr2rZr¤r&r[rtÚlowerr‰r§rprqrhriror0rrYrkr�ÚcloseruÚreadrr¨rnÚfindallr7r—r)rrÚmaxsize)r™ÚiÚjZlookZosnameZhostÚreleaser¤ÚmachineZrel_rer€ZcfgvarsZmacverZ
macreleaser}ZcflagsZarchsrrrr[s¨
$


ÿ

ÿ





ÿ

cCstSr)rŠrrrrrýscCsFtt| ¡ƒƒD]0\}\}}|dkr0td|ƒtd||fƒqdS)Nrz%s: z
	%s = "%s")Ú	enumerater—r6Úprint)ÚtitleÚdataÚindexrFr=rrrÚ_print_dictsrÉcCsRtdtƒƒtdtƒƒtdtƒƒtƒtdtƒƒtƒtdtƒƒdS)z*Display all information sysconfig detains.zPlatform: "%s"zPython version: "%s"z!Current installation scheme: "%s"ZPathsZ	VariablesN)rÅrrrPrÉr
rrrrrÚ_mainsrÊÚ__main__)N)N)AÚ__doc__rjrrhrZZos.pathrrZconfigparserÚImportErrorZConfigParserÚ__all__rr“rr’rr¥r2r»rrr(r#r,ZRawConfigParserr'rir:r>r¤r¨r¢rŠr‘rJr™r ršr¡rŸZ
_USER_BASErDrGrMrOrPr_r†rr�r”rrr
r	r
rrrrrrÉrÊr$rrrrÚsŽõ""
#
	
v

	#
PKÕ¶N]ÆâÛ""Ksite-packages/pip/_vendor/distlib/_backport/__pycache__/misc.cpython-38.pycnu„[µü¤U

ÀÒ.eËã@s¬dZddlZddlZdddgZzddlmZWnek
rLddd„ZYnXzeZWn(ek
r~dd	l	m
Z
d
d„ZYnXz
ejZWnek
r¦dd„ZYnXdS)
z/Backports for individual classes and functions.éNÚcache_from_sourceÚcallableÚfsencode)rTcCs|rdp
d}||S)NÚcÚo©)Zpy_fileÚdebugZextrrúF/usr/lib/python3.8/site-packages/pip/_vendor/distlib/_backport/misc.pyrs)ÚCallablecCs
t|tƒS)N)Ú
isinstancer
)Úobjrrr	rscCs<t|tƒr|St|tƒr&| t ¡¡Stdt|ƒjƒ‚dS)Nzexpect bytes or str, not %s)	rÚbytesÚstrÚencodeÚsysÚgetfilesystemencodingÚ	TypeErrorÚtypeÚ__name__)Úfilenamerrr	r"s

ÿ)T)
Ú__doc__ÚosrÚ__all__ZimprÚImportErrorrÚ	NameErrorÚcollectionsr
rÚAttributeErrorrrrr	Ús 

PKÕ¶N]Ïáß¿¿Usite-packages/pip/_vendor/distlib/_backport/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eã@sdZdS)aModules copied from Python 3 standard libraries, for internal use only.

Individual classes and functions are found in d2._backport.misc.  Intended
usage is to always import things missing from 3.1 from that module: the
built-in/stdlib objects will be used if found.
N)Ú__doc__©rrúJ/usr/lib/python3.8/site-packages/pip/_vendor/distlib/_backport/__init__.pyÚóPKÕ¶N]üÉ©""Qsite-packages/pip/_vendor/distlib/_backport/__pycache__/misc.cpython-38.opt-1.pycnu„[µü¤U

ÀÒ.eËã@s¬dZddlZddlZdddgZzddlmZWnek
rLddd„ZYnXzeZWn(ek
r~dd	l	m
Z
d
d„ZYnXz
ejZWnek
r¦dd„ZYnXdS)
z/Backports for individual classes and functions.éNÚcache_from_sourceÚcallableÚfsencode)rFcCs|rdp
d}||S)NÚcÚo©)Zpy_fileÚdebugZextrrúF/usr/lib/python3.8/site-packages/pip/_vendor/distlib/_backport/misc.pyrs)ÚCallablecCs
t|tƒS)N)Ú
isinstancer
)Úobjrrr	rscCs<t|tƒr|St|tƒr&| t ¡¡Stdt|ƒjƒ‚dS)Nzexpect bytes or str, not %s)	rÚbytesÚstrÚencodeÚsysÚgetfilesystemencodingÚ	TypeErrorÚtypeÚ__name__)Úfilenamerrr	r"s

ÿ)F)
Ú__doc__ÚosrÚ__all__ZimprÚImportErrorrÚ	NameErrorÚcollectionsr
rÚAttributeErrorrrrr	Ús 

PKÕ¶N]Ê`ò¾ê=ê=Psite-packages/pip/_vendor/distlib/_backport/__pycache__/sysconfig.cpython-38.pycnu„[µü¤U

ÀÒ.eTiã@s¢dZddlZddlZddlZddlZddlmZmZzddlZWne	k
r\ddl
ZYnXdddddd	d
ddd
dgZdd„Zej
ršej eej
ƒ¡Znee ¡ƒZejdkrÖdedd… ¡krÖeej ee¡ƒZejdk�rdedd… ¡k�reej eee¡ƒZejdk�rBdedd… ¡k�rBeej eee¡ƒZdd„ZeƒZdadd„Ze ¡Ze d¡Zdd„Zej ¡dZ ejdd …Z!e de d!Z"ej #ej$¡Z%ej #ej&¡Z'da(dZ)d"d#„Z*d$d%„Z+d&d'„Z,d(d)„Z-d*d+„Z.d,d-„Z/dEd.d/„Z0d0d„Z1d1d2„Z2d3d4„Z3dFd5d„Z4d6d„Z5d7d
„Z6d8d	„Z7e.ƒdd9fd:d
„Z8e.ƒdd9fd;d„Z9dd„ZdBdC„Z?e@dDk�rže?ƒdS)Gz-Access to Python's configuration information.éN)ÚpardirÚrealpathÚget_config_h_filenameÚget_config_varÚget_config_varsÚget_makefile_filenameÚget_pathÚget_path_namesÚ	get_pathsÚget_platformÚget_python_versionÚget_scheme_namesÚparse_config_hcCs(z
t|ƒWStk
r"|YSXdS©N)rÚOSError)Úpath©rúK/usr/lib/python3.8/site-packages/pip/_vendor/distlib/_backport/sysconfig.pyÚ_safe_realpath"s
rÚntZpcbuildiøÿÿÿz\pc\viöÿÿÿz\pcbuild\amd64iòÿÿÿcCs,dD]"}tj tj td|¡¡rdSqdS)N)z
Setup.distzSetup.localZModulesTF)ÚosrÚisfileÚjoinÚ
_PROJECT_BASE)ÚfnrrrÚis_python_build:srFc	CsŽtsŠddlm}t dd¡d}||ƒ}| d¡}|s>tdƒ‚| ¡�}t 	|¡W5QRXt
r†dD] }t |d	d
¡t |dd¡qdd
adS)Né)ÚfinderÚ.érz
sysconfig.cfgzsysconfig.cfg exists)Úposix_prefixZ
posix_homeÚincludez{srcdir}/IncludeÚplatincludez{projectbase}/.T)Ú	_cfg_readZ	resourcesrÚ__name__ÚrsplitÚfindÚAssertionErrorZ	as_streamÚ_SCHEMESZreadfpÚ
_PYTHON_BUILDÚset)rZbackport_packageZ_finderZ_cfgfileÚsÚschemerrrÚ_ensure_cfg_readDs

r-z\{([^{]*?)\}c
sÈtƒ| d¡r| d¡}ntƒ}| ¡}|D]8}|dkr._replacer)r-Zhas_sectionÚitemsÚtupleÚsectionsZ
has_optionr*Zremove_sectionÚdictÚ	_VAR_REPLÚsub)Úconfigr.r9ZsectionZoptionÚvaluer6rr4rÚ_expand_globalsYs$

r?ércs‡fdd„}t ||¡S)z»In the string `path`, replace tokens like {some.thing} with the
    corresponding value from the map `local_vars`.

    If there is no corresponding value, leave the token unchanged.
    cs8| d¡}|ˆkrˆ|S|tjkr.tj|S| d¡Sr/)r1rÚenvironr2©Ú
local_varsrrr6‹s


z_subst_vars.._replacer©r;r<)rrCr6rrBrÚ_subst_vars…srEcCs0| ¡}| ¡D]\}}||kr"q|||<qdSr)Úkeysr7)Ztarget_dictZ
other_dictZtarget_keysÚkeyr>rrrÚ_extend_dict•s
rHcCs`i}|dkri}t|tƒƒt |¡D]4\}}tjdkrDtj |¡}tj t	||ƒ¡||<q&|S)N)Úposixr)
rHrr(r7rr3rÚ
expanduserÚnormpathrE)r,ÚvarsÚresrGr>rrrÚ_expand_vars�s
rNcs‡fdd„}t ||¡S)Ncs$| d¡}|ˆkrˆ|S| d¡Sr/r0r2©rLrrr6«s
zformat_value.._replacerrD)r>rLr6rrOrÚformat_valueªsrPcCstjdkrdStjS)NrIr )rr3rrrrÚ_get_default_scheme³s
rQcCs’tj dd¡}dd„}tjdkrBtj d¡p.d}|r8|S||dƒStjdkr|td	ƒ}|r||r`|S|dd
|dtjdd…ƒS|r„|S|dd
ƒSdS)NÚPYTHONUSERBASEcWstj tjj|Ž¡Sr)rrrJr)ÚargsrrrÚjoinuser½sz_getuserbase..joinuserrÚAPPDATAú~ÚPythonÚdarwinZPYTHONFRAMEWORKÚLibraryz%d.%drz.local)rrAÚgetr3ÚsysÚplatformrÚversion_info)Úenv_baserTÚbaseZ	frameworkrrrÚ_getuserbaseºs$



ÿr`c	Cst d¡}t d¡}t d¡}|dkr*i}i}i}tj|ddd��}| ¡}W5QRX|D]š}	|	 d¡sZ|	 ¡d	krvqZ| |	¡}
|
rZ|
 d
d¡\}}| ¡}| 	dd	¡}
d
|
krº|||<qZzt
|ƒ}Wn$tk
rê| 	dd
¡||<YqZX|||<qZt| 
¡ƒ}d}t|ƒdk�rÔt|ƒD�]°}||}| |¡�p>| |¡}
|
dk	�rº|
 d
¡}d}||k�rpt||ƒ}nˆ||k�r€d}nx|tjk�r˜tj|}n`||k�rì| d¡�rÆ|dd…|k�rÆd	}n$d||k�rÚd}nt|d|ƒ}nd	||<}|�rÌ||
 ¡d…}|d|
 ¡…||}d
|k�r:|||<n~zt
|ƒ}Wn"tk
�rh| ¡||<Yn
X|||<| |¡| d¡�rÌ|dd…|k�rÌ|dd…}||k�rÌ|||<n|||<| |¡�q�q| ¡D]"\}}t|tƒ�rÜ| ¡||<�qÜ| |¡|S)zÌParse a Makefile-style file.

    A dictionary containing name/value pairs is returned.  If an
    optional dictionary is passed in as the second argument, it is
    used instead of a new dictionary.
    z"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)z\$\(([A-Za-z][A-Za-z0-9_]*)\)z\${([A-Za-z][A-Za-z0-9_]*)}Nzutf-8Úsurrogateescape)ÚencodingÚerrorsú#Úrrz$$ú$)ÚCFLAGSÚLDFLAGSZCPPFLAGSrTFZPY_r@)ÚreÚcompileÚcodecsÚopenÚ	readlinesÚ
startswithÚstripÚmatchr1ÚreplaceÚintÚ
ValueErrorÚlistrFÚlenr8ÚsearchÚstrrrAÚendÚstartÚremover7Ú
isinstanceÚupdate)ÚfilenamerLZ_variable_rxZ_findvar1_rxZ_findvar2_rxZdoneZnotdoneÚfÚlinesÚlineÚmÚnÚvZtmpvr5Zrenamed_variablesr3r>ÚfoundÚitemZafterÚkrrrÚ_parse_makefile×s�	










ÿ


ÿ


r‡cCsDtrtj td¡Sttdƒr,dttjf}nd}tj t	dƒ|d¡S)z Return the path of the Makefile.ZMakefileÚabiflagszconfig-%s%sr=Ústdlib)
r)rrrrÚhasattrr[Ú_PY_VERSION_SHORTrˆr)Zconfig_dir_namerrrrMs
c
Csètƒ}zt||ƒWnJtk
r^}z,d|}t|dƒrF|d|j}t|ƒ‚W5d}~XYnXtƒ}z"t|ƒ�}t||ƒW5QRXWnJtk
rÒ}z,d|}t|dƒrº|d|j}t|ƒ‚W5d}~XYnXträ|d|d<dS)z7Initialize the module as appropriate for POSIX systems.z.invalid Python installation: unable to open %sÚstrerrorz (%s)NÚ	BLDSHAREDZLDSHARED)	rr‡ÚIOErrorrŠrŒrrlrr))rLZmakefileÚeÚmsgZconfig_hr~rrrÚ_init_posixXs&


r‘cCsVtdƒ|d<tdƒ|d<tdƒ|d<d|d<d	|d
<t|d<tj ttjƒ¡|d<d
S)z+Initialize the module as appropriate for NTr‰ZLIBDESTZ
platstdlibZ
BINLIBDESTr!Z	INCLUDEPYz.pydZSOz.exeZEXEZVERSIONZBINDIRN)rÚ_PY_VERSION_SHORT_NO_DOTrrÚdirnamerr[Ú
executablerOrrrÚ_init_non_posixtsr•cCsš|dkri}t d¡}t d¡}| ¡}|s.q–| |¡}|rx| dd¡\}}zt|ƒ}Wntk
rlYnX|||<q | |¡}|r d|| d¡<q |S)zÌParse a config.h-style file.

    A dictionary containing name/value pairs is returned.  If an
    optional dictionary is passed in as the second argument, it is
    used instead of a new dictionary.
    Nz"#define ([A-Z][A-Za-z0-9_]+) (.*)
z&/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/
rrr)rirjÚreadlinerpr1rrrs)ÚfprLZ	define_rxZundef_rxr€r�r‚rƒrrrr„s&




cCs:tr$tjdkrtj td¡}q,t}ntdƒ}tj |d¡S)zReturn the path of pyconfig.h.rZPCr"z
pyconfig.h)r)rr3rrrr)Zinc_dirrrrr£s
cCsttt ¡ƒƒS)z,Return a tuple containing the schemes names.)r8Úsortedr(r9rrrrr
¯scCs
t d¡S)z*Return a tuple containing the paths names.r )r(Zoptionsrrrrr	´sTcCs&tƒ|rt||ƒStt |¡ƒSdS)z°Return a mapping containing an install scheme.

    ``scheme`` is the install scheme name. If not provided, it will
    return the default scheme for the current platform.
    N)r-rNr:r(r7)r,rLÚexpandrrrr
ºs
cCst|||ƒ|S)z[Return a path corresponding to the scheme.

    ``scheme`` is the install scheme name.
    )r
)r3r,rLr™rrrrÇscGs¬tdk�rziattd<ttd<ttd<ttd<tdtdtd<ttd	<ttd
<ttd<ztjtd<Wntk
r„d
td<YnXt	j
dkr˜ttƒt	j
dkrªttƒtj
dkr¾tƒtd<dtkrÐttd<nttdƒtd<t�r\t	j
dk�r\t}zt	 ¡}Wntk
�rd}YnXt	j td¡�s\||k�r\t	j |td¡}t	j |¡td<tjdk�rzt	 ¡d}t| d¡dƒ}|dk�rÊdD]2}t|}t dd|¡}t dd|¡}|t|<�q”n°dt	jk�rt	jd}dD]0}t|}t dd|¡}|d|}|t|<�qät dd
¡}	t d|	¡}
|
dk	�rz|
  d¡}t	j !|¡�szdD]$}t|}t dd|¡}|t|<�qT|�r¤g}|D]}
| "t |
¡¡�qˆ|StSdS)ayWith no arguments, return a dictionary of all configuration
    variables relevant for the current platform.

    On Unix, this means every variable defined in Python's installed Makefile;
    On Windows and Mac OS it's a much smaller set.

    With arguments, return a list of values that result from looking up
    each argument in the configuration variable dictionary.
    NÚprefixÚexec_prefixZ
py_versionZpy_version_shortrrZpy_version_nodotr_ZplatbaseZprojectbaserˆre)rZos2rIz2.6ÚuserbaseÚsrcdirrXré)rhZ
BASECFLAGSrgZ	PY_CFLAGSr�z
-arch\s+\w+\sú z-isysroot [^ 	]*Z	ARCHFLAGSrgz-isysroot\s+(\S+)rz-isysroot\s+\S+(\s|$))#Ú_CONFIG_VARSÚ_PREFIXÚ_EXEC_PREFIXÚ_PY_VERSIONr‹rr[rˆÚAttributeErrorrr3r•r‘Úversionr`rr)ÚgetcwdrrÚisabsrrKr\ÚunamerrÚsplitrir<rArZrvr1ÚexistsÚappend)rSr_Úcwdr�Zkernel_versionZ
major_versionrGÚflagsZarchrgr�ZsdkZvalsr3rrrrÏs‚






ÿ



cCstƒ |¡S)z“Return the value of a single variable using the dictionary returned by
    'get_config_vars()'.

    Equivalent to get_config_vars().get(name)
    )rrZ)r3rrrrRscCs^tjdkrnd}tj |¡}|dkr(tjStj d|¡}tj|t|ƒ|… ¡}|dkr\dS|dkrhdStjStjd	ks‚ttd
ƒsˆtjSt 	¡\}}}}}| ¡ 
dd¡}| 
d
d¡}| 
dd¡}|dd…dkrÞd||fS|dd…dk�r&|ddk�rPd}dt|dƒd|dd…f}�n*|dd…dk�rDd||fS|dd…dk�rdd|||fS|dd…d k�r d }t 
d!¡}	|	 |¡}
|
�rP|
 ¡}�n°|dd…d"k�rPtƒ}| d#¡}|}
ztd$ƒ}Wntk
�rèYnJXzt d%| ¡¡}
W5| ¡X|
dk	�r2d& |
 d'¡ d&¡dd…¡}
|�s<|
}|�rP|}d(}|
d&d)k�rd*tƒ d+d¡ ¡k�rd,}tƒ d+¡}t d-|¡}ttt|ƒƒƒ}t|ƒd'k�r´|d}n^|d.k�rÄd,}nN|d/k�rÔd0}n>|d1k�räd2}n.|d3k�rôd4}n|d5k�rd6}ntd7|fƒ‚n<|d8k�r0tjd9k�rPd:}n |d;k�rPtjd9k�rLd<}nd=}d>|||fS)?a«Return a string that identifies the current platform.

    This is used mainly to distinguish platform-specific build directories and
    platform-specific built distributions.  Typically includes the OS name
    and version and the architecture (as supplied by 'os.uname()'),
    although the exact information included depends on the OS; eg. for IRIX
    the architecture isn't particularly important (IRIX only runs on SGI
    hardware), but for Linux the kernel version isn't particularly
    important.

    Examples of returned values:
       linux-i586
       linux-alpha (?)
       solaris-2.6-sun4u
       irix-5.3
       irix64-6.2

    Windows will return one of:
       win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
       win-ia64 (64bit Windows on Itanium)
       win32 (all others - specifically, sys.platform is returned)

    For other non-POSIX platforms, currently just returns 'sys.platform'.
    rz bit (éÿÿÿÿú)Zamd64z	win-amd64Zitaniumzwin-ia64rIr¨ú/rerŸÚ_ú-NéZlinuxz%s-%sZsunosrÚ5Zsolarisz%d.%sr@réZirixZaixz%s-%s.%séÚcygwinz[\d.]+rXZMACOSX_DEPLOYMENT_TARGETz0/System/Library/CoreServices/SystemVersion.plistz=ProductUserVisibleVersion\s*(.*?)rrZmacosxz10.4.z-archrgZfatz
-arch\s+(\S+))Úi386Úppc)r¸Úx86_64Zintel)r¸r¹rºZfat3)Úppc64rºZfat64)r¸r¹r»rºZ	universalz%Don't know machine value for archs=%rr¸lrº)ZPowerPCZPower_Macintoshr»r¹z%s-%s-%s) rr3r[r¥r&r\ruÚlowerrŠr¨rqrrrirjrpr1rrZrlrŽÚcloservÚreadrr©roÚfindallr8r˜r*rsÚmaxsize)ršÚiÚjZlookZosnameZhostÚreleaser¥ÚmachineZrel_rer�ZcfgvarsZmacverZ
macreleaser~ZcflagsZarchsrrrr[s¨
$


ÿ

ÿ





ÿ

cCstSr)r‹rrrrrýscCsFtt| ¡ƒƒD]0\}\}}|dkr0td|ƒtd||fƒqdS)Nrz%s: z
	%s = "%s")Ú	enumerater˜r7Úprint)ÚtitleÚdataÚindexrGr>rrrÚ_print_dictsrÊcCsRtdtƒƒtdtƒƒtdtƒƒtƒtdtƒƒtƒtdtƒƒdS)z*Display all information sysconfig detains.zPlatform: "%s"zPython version: "%s"z!Current installation scheme: "%s"ZPathsZ	VariablesN)rÆrrrQrÊr
rrrrrÚ_mainsrËÚ__main__)N)N)AÚ__doc__rkrrir[Zos.pathrrZconfigparserÚImportErrorZConfigParserÚ__all__rr”rr“rr¦r3r¼rrr)r#r-ZRawConfigParserr(rjr;r?r¥r©r£r‹r’rKršr¡r›r¢r Z
_USER_BASErErHrNrPrQr`r‡rr‘r•rrr
r	r
rrrrrrÊrËr$rrrrÚsŽõ""
#
	
v

	#
PKÕ¶N]Ïáß¿¿Osite-packages/pip/_vendor/distlib/_backport/__pycache__/__init__.cpython-38.pycnu„[µü¤U

ÀÒ.eã@sdZdS)aModules copied from Python 3 standard libraries, for internal use only.

Individual classes and functions are found in d2._backport.misc.  Intended
usage is to always import things missing from 3.1 from that module: the
built-in/stdlib objects will be used if found.
N)Ú__doc__©rrúJ/usr/lib/python3.8/site-packages/pip/_vendor/distlib/_backport/__init__.pyÚóPKÕ¶N]o­9
9
9site-packages/pip/_vendor/distlib/_backport/sysconfig.cfgnu„[µü¤[posix_prefix]
# Configuration directories.  Some of these come straight out of the
# configure script.  They are for implementing the other variables, not to
# be used directly in [resource_locations].
confdir = /etc
datadir = /usr/share
libdir = /usr/lib
statedir = /var
# User resource directory
local = ~/.local/{distribution.name}

stdlib = {base}/lib/python{py_version_short}
platstdlib = {platbase}/lib/python{py_version_short}
purelib = {base}/lib/python{py_version_short}/site-packages
platlib = {platbase}/lib/python{py_version_short}/site-packages
include = {base}/include/python{py_version_short}{abiflags}
platinclude = {platbase}/include/python{py_version_short}{abiflags}
data = {base}

[posix_home]
stdlib = {base}/lib/python
platstdlib = {base}/lib/python
purelib = {base}/lib/python
platlib = {base}/lib/python
include = {base}/include/python
platinclude = {base}/include/python
scripts = {base}/bin
data = {base}

[nt]
stdlib = {base}/Lib
platstdlib = {base}/Lib
purelib = {base}/Lib/site-packages
platlib = {base}/Lib/site-packages
include = {base}/Include
platinclude = {base}/Include
scripts = {base}/Scripts
data = {base}

[os2]
stdlib = {base}/Lib
platstdlib = {base}/Lib
purelib = {base}/Lib/site-packages
platlib = {base}/Lib/site-packages
include = {base}/Include
platinclude = {base}/Include
scripts = {base}/Scripts
data = {base}

[os2_home]
stdlib = {userbase}/lib/python{py_version_short}
platstdlib = {userbase}/lib/python{py_version_short}
purelib = {userbase}/lib/python{py_version_short}/site-packages
platlib = {userbase}/lib/python{py_version_short}/site-packages
include = {userbase}/include/python{py_version_short}
scripts = {userbase}/bin
data = {userbase}

[nt_user]
stdlib = {userbase}/Python{py_version_nodot}
platstdlib = {userbase}/Python{py_version_nodot}
purelib = {userbase}/Python{py_version_nodot}/site-packages
platlib = {userbase}/Python{py_version_nodot}/site-packages
include = {userbase}/Python{py_version_nodot}/Include
scripts = {userbase}/Scripts
data = {userbase}

[posix_user]
stdlib = {userbase}/lib/python{py_version_short}
platstdlib = {userbase}/lib/python{py_version_short}
purelib = {userbase}/lib/python{py_version_short}/site-packages
platlib = {userbase}/lib/python{py_version_short}/site-packages
include = {userbase}/include/python{py_version_short}
scripts = {userbase}/bin
data = {userbase}

[osx_framework_user]
stdlib = {userbase}/lib/python
platstdlib = {userbase}/lib/python
purelib = {userbase}/lib/python/site-packages
platlib = {userbase}/lib/python/site-packages
include = {userbase}/include
scripts = {userbase}/bin
data = {userbase}
PKÕ¶N]¯Š/eËË3site-packages/pip/_vendor/distlib/_backport/misc.pynu„[µü¤# -*- coding: utf-8 -*-
#
# Copyright (C) 2012 The Python Software Foundation.
# See LICENSE.txt and CONTRIBUTORS.txt.
#
"""Backports for individual classes and functions."""

import os
import sys

__all__ = ['cache_from_source', 'callable', 'fsencode']


try:
    from imp import cache_from_source
except ImportError:
    def cache_from_source(py_file, debug=__debug__):
        ext = debug and 'c' or 'o'
        return py_file + ext


try:
    callable = callable
except NameError:
    from collections import Callable

    def callable(obj):
        return isinstance(obj, Callable)


try:
    fsencode = os.fsencode
except AttributeError:
    def fsencode(filename):
        if isinstance(filename, bytes):
            return filename
        elif isinstance(filename, str):
            return filename.encode(sys.getfilesystemencoding())
        else:
            raise TypeError("expect bytes or str, not %s" %
                            type(filename).__name__)
PKÕ¶N]ò©ßTiTi8site-packages/pip/_vendor/distlib/_backport/sysconfig.pynu„[µü¤# -*- coding: utf-8 -*-
#
# Copyright (C) 2012 The Python Software Foundation.
# See LICENSE.txt and CONTRIBUTORS.txt.
#
"""Access to Python's configuration information."""

import codecs
import os
import re
import sys
from os.path import pardir, realpath
try:
    import configparser
except ImportError:
    import ConfigParser as configparser


__all__ = [
    'get_config_h_filename',
    'get_config_var',
    'get_config_vars',
    'get_makefile_filename',
    'get_path',
    'get_path_names',
    'get_paths',
    'get_platform',
    'get_python_version',
    'get_scheme_names',
    'parse_config_h',
]


def _safe_realpath(path):
    try:
        return realpath(path)
    except OSError:
        return path


if sys.executable:
    _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
else:
    # sys.executable can be empty if argv[0] has been changed and Python is
    # unable to retrieve the real program name
    _PROJECT_BASE = _safe_realpath(os.getcwd())

if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower():
    _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir))
# PC/VS7.1
if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower():
    _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
# PC/AMD64
if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower():
    _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))


def is_python_build():
    for fn in ("Setup.dist", "Setup.local"):
        if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)):
            return True
    return False

_PYTHON_BUILD = is_python_build()

_cfg_read = False

def _ensure_cfg_read():
    global _cfg_read
    if not _cfg_read:
        from ..resources import finder
        backport_package = __name__.rsplit('.', 1)[0]
        _finder = finder(backport_package)
        _cfgfile = _finder.find('sysconfig.cfg')
        assert _cfgfile, 'sysconfig.cfg exists'
        with _cfgfile.as_stream() as s:
            _SCHEMES.readfp(s)
        if _PYTHON_BUILD:
            for scheme in ('posix_prefix', 'posix_home'):
                _SCHEMES.set(scheme, 'include', '{srcdir}/Include')
                _SCHEMES.set(scheme, 'platinclude', '{projectbase}/.')

        _cfg_read = True


_SCHEMES = configparser.RawConfigParser()
_VAR_REPL = re.compile(r'\{([^{]*?)\}')

def _expand_globals(config):
    _ensure_cfg_read()
    if config.has_section('globals'):
        globals = config.items('globals')
    else:
        globals = tuple()

    sections = config.sections()
    for section in sections:
        if section == 'globals':
            continue
        for option, value in globals:
            if config.has_option(section, option):
                continue
            config.set(section, option, value)
    config.remove_section('globals')

    # now expanding local variables defined in the cfg file
    #
    for section in config.sections():
        variables = dict(config.items(section))

        def _replacer(matchobj):
            name = matchobj.group(1)
            if name in variables:
                return variables[name]
            return matchobj.group(0)

        for option, value in config.items(section):
            config.set(section, option, _VAR_REPL.sub(_replacer, value))

#_expand_globals(_SCHEMES)

 # FIXME don't rely on sys.version here, its format is an implementation detail
 # of CPython, use sys.version_info or sys.hexversion
_PY_VERSION = sys.version.split()[0]
_PY_VERSION_SHORT = sys.version[:3]
_PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2]
_PREFIX = os.path.normpath(sys.prefix)
_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
_CONFIG_VARS = None
_USER_BASE = None


def _subst_vars(path, local_vars):
    """In the string `path`, replace tokens like {some.thing} with the
    corresponding value from the map `local_vars`.

    If there is no corresponding value, leave the token unchanged.
    """
    def _replacer(matchobj):
        name = matchobj.group(1)
        if name in local_vars:
            return local_vars[name]
        elif name in os.environ:
            return os.environ[name]
        return matchobj.group(0)
    return _VAR_REPL.sub(_replacer, path)


def _extend_dict(target_dict, other_dict):
    target_keys = target_dict.keys()
    for key, value in other_dict.items():
        if key in target_keys:
            continue
        target_dict[key] = value


def _expand_vars(scheme, vars):
    res = {}
    if vars is None:
        vars = {}
    _extend_dict(vars, get_config_vars())

    for key, value in _SCHEMES.items(scheme):
        if os.name in ('posix', 'nt'):
            value = os.path.expanduser(value)
        res[key] = os.path.normpath(_subst_vars(value, vars))
    return res


def format_value(value, vars):
    def _replacer(matchobj):
        name = matchobj.group(1)
        if name in vars:
            return vars[name]
        return matchobj.group(0)
    return _VAR_REPL.sub(_replacer, value)


def _get_default_scheme():
    if os.name == 'posix':
        # the default scheme for posix is posix_prefix
        return 'posix_prefix'
    return os.name


def _getuserbase():
    env_base = os.environ.get("PYTHONUSERBASE", None)

    def joinuser(*args):
        return os.path.expanduser(os.path.join(*args))

    # what about 'os2emx', 'riscos' ?
    if os.name == "nt":
        base = os.environ.get("APPDATA") or "~"
        if env_base:
            return env_base
        else:
            return joinuser(base, "Python")

    if sys.platform == "darwin":
        framework = get_config_var("PYTHONFRAMEWORK")
        if framework:
            if env_base:
                return env_base
            else:
                return joinuser("~", "Library", framework, "%d.%d" %
                                sys.version_info[:2])

    if env_base:
        return env_base
    else:
        return joinuser("~", ".local")


def _parse_makefile(filename, vars=None):
    """Parse a Makefile-style file.

    A dictionary containing name/value pairs is returned.  If an
    optional dictionary is passed in as the second argument, it is
    used instead of a new dictionary.
    """
    # Regexes needed for parsing Makefile (and similar syntaxes,
    # like old-style Setup files).
    _variable_rx = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
    _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
    _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")

    if vars is None:
        vars = {}
    done = {}
    notdone = {}

    with codecs.open(filename, encoding='utf-8', errors="surrogateescape") as f:
        lines = f.readlines()

    for line in lines:
        if line.startswith('#') or line.strip() == '':
            continue
        m = _variable_rx.match(line)
        if m:
            n, v = m.group(1, 2)
            v = v.strip()
            # `$$' is a literal `$' in make
            tmpv = v.replace('$$', '')

            if "$" in tmpv:
                notdone[n] = v
            else:
                try:
                    v = int(v)
                except ValueError:
                    # insert literal `$'
                    done[n] = v.replace('$$', '$')
                else:
                    done[n] = v

    # do variable interpolation here
    variables = list(notdone.keys())

    # Variables with a 'PY_' prefix in the makefile. These need to
    # be made available without that prefix through sysconfig.
    # Special care is needed to ensure that variable expansion works, even
    # if the expansion uses the name without a prefix.
    renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')

    while len(variables) > 0:
        for name in tuple(variables):
            value = notdone[name]
            m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
            if m is not None:
                n = m.group(1)
                found = True
                if n in done:
                    item = str(done[n])
                elif n in notdone:
                    # get it on a subsequent round
                    found = False
                elif n in os.environ:
                    # do it like make: fall back to environment
                    item = os.environ[n]

                elif n in renamed_variables:
                    if (name.startswith('PY_') and
                        name[3:] in renamed_variables):
                        item = ""

                    elif 'PY_' + n in notdone:
                        found = False

                    else:
                        item = str(done['PY_' + n])

                else:
                    done[n] = item = ""

                if found:
                    after = value[m.end():]
                    value = value[:m.start()] + item + after
                    if "$" in after:
                        notdone[name] = value
                    else:
                        try:
                            value = int(value)
                        except ValueError:
                            done[name] = value.strip()
                        else:
                            done[name] = value
                        variables.remove(name)

                        if (name.startswith('PY_') and
                            name[3:] in renamed_variables):

                            name = name[3:]
                            if name not in done:
                                done[name] = value

            else:
                # bogus variable reference (e.g. "prefix=$/opt/python");
                # just drop it since we can't deal
                done[name] = value
                variables.remove(name)

    # strip spurious spaces
    for k, v in done.items():
        if isinstance(v, str):
            done[k] = v.strip()

    # save the results in the global dictionary
    vars.update(done)
    return vars


def get_makefile_filename():
    """Return the path of the Makefile."""
    if _PYTHON_BUILD:
        return os.path.join(_PROJECT_BASE, "Makefile")
    if hasattr(sys, 'abiflags'):
        config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags)
    else:
        config_dir_name = 'config'
    return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')


def _init_posix(vars):
    """Initialize the module as appropriate for POSIX systems."""
    # load the installed Makefile:
    makefile = get_makefile_filename()
    try:
        _parse_makefile(makefile, vars)
    except IOError as e:
        msg = "invalid Python installation: unable to open %s" % makefile
        if hasattr(e, "strerror"):
            msg = msg + " (%s)" % e.strerror
        raise IOError(msg)
    # load the installed pyconfig.h:
    config_h = get_config_h_filename()
    try:
        with open(config_h) as f:
            parse_config_h(f, vars)
    except IOError as e:
        msg = "invalid Python installation: unable to open %s" % config_h
        if hasattr(e, "strerror"):
            msg = msg + " (%s)" % e.strerror
        raise IOError(msg)
    # On AIX, there are wrong paths to the linker scripts in the Makefile
    # -- these paths are relative to the Python source, but when installed
    # the scripts are in another directory.
    if _PYTHON_BUILD:
        vars['LDSHARED'] = vars['BLDSHARED']


def _init_non_posix(vars):
    """Initialize the module as appropriate for NT"""
    # set basic install directories
    vars['LIBDEST'] = get_path('stdlib')
    vars['BINLIBDEST'] = get_path('platstdlib')
    vars['INCLUDEPY'] = get_path('include')
    vars['SO'] = '.pyd'
    vars['EXE'] = '.exe'
    vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
    vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))

#
# public APIs
#


def parse_config_h(fp, vars=None):
    """Parse a config.h-style file.

    A dictionary containing name/value pairs is returned.  If an
    optional dictionary is passed in as the second argument, it is
    used instead of a new dictionary.
    """
    if vars is None:
        vars = {}
    define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
    undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")

    while True:
        line = fp.readline()
        if not line:
            break
        m = define_rx.match(line)
        if m:
            n, v = m.group(1, 2)
            try:
                v = int(v)
            except ValueError:
                pass
            vars[n] = v
        else:
            m = undef_rx.match(line)
            if m:
                vars[m.group(1)] = 0
    return vars


def get_config_h_filename():
    """Return the path of pyconfig.h."""
    if _PYTHON_BUILD:
        if os.name == "nt":
            inc_dir = os.path.join(_PROJECT_BASE, "PC")
        else:
            inc_dir = _PROJECT_BASE
    else:
        inc_dir = get_path('platinclude')
    return os.path.join(inc_dir, 'pyconfig.h')


def get_scheme_names():
    """Return a tuple containing the schemes names."""
    return tuple(sorted(_SCHEMES.sections()))


def get_path_names():
    """Return a tuple containing the paths names."""
    # xxx see if we want a static list
    return _SCHEMES.options('posix_prefix')


def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
    """Return a mapping containing an install scheme.

    ``scheme`` is the install scheme name. If not provided, it will
    return the default scheme for the current platform.
    """
    _ensure_cfg_read()
    if expand:
        return _expand_vars(scheme, vars)
    else:
        return dict(_SCHEMES.items(scheme))


def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
    """Return a path corresponding to the scheme.

    ``scheme`` is the install scheme name.
    """
    return get_paths(scheme, vars, expand)[name]


def get_config_vars(*args):
    """With no arguments, return a dictionary of all configuration
    variables relevant for the current platform.

    On Unix, this means every variable defined in Python's installed Makefile;
    On Windows and Mac OS it's a much smaller set.

    With arguments, return a list of values that result from looking up
    each argument in the configuration variable dictionary.
    """
    global _CONFIG_VARS
    if _CONFIG_VARS is None:
        _CONFIG_VARS = {}
        # Normalized versions of prefix and exec_prefix are handy to have;
        # in fact, these are the standard versions used most places in the
        # distutils2 module.
        _CONFIG_VARS['prefix'] = _PREFIX
        _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
        _CONFIG_VARS['py_version'] = _PY_VERSION
        _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
        _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
        _CONFIG_VARS['base'] = _PREFIX
        _CONFIG_VARS['platbase'] = _EXEC_PREFIX
        _CONFIG_VARS['projectbase'] = _PROJECT_BASE
        try:
            _CONFIG_VARS['abiflags'] = sys.abiflags
        except AttributeError:
            # sys.abiflags may not be defined on all platforms.
            _CONFIG_VARS['abiflags'] = ''

        if os.name in ('nt', 'os2'):
            _init_non_posix(_CONFIG_VARS)
        if os.name == 'posix':
            _init_posix(_CONFIG_VARS)
        # Setting 'userbase' is done below the call to the
        # init function to enable using 'get_config_var' in
        # the init-function.
        if sys.version >= '2.6':
            _CONFIG_VARS['userbase'] = _getuserbase()

        if 'srcdir' not in _CONFIG_VARS:
            _CONFIG_VARS['srcdir'] = _PROJECT_BASE
        else:
            _CONFIG_VARS['srcdir'] = _safe_realpath(_CONFIG_VARS['srcdir'])

        # Convert srcdir into an absolute path if it appears necessary.
        # Normally it is relative to the build directory.  However, during
        # testing, for example, we might be running a non-installed python
        # from a different directory.
        if _PYTHON_BUILD and os.name == "posix":
            base = _PROJECT_BASE
            try:
                cwd = os.getcwd()
            except OSError:
                cwd = None
            if (not os.path.isabs(_CONFIG_VARS['srcdir']) and
                base != cwd):
                # srcdir is relative and we are not in the same directory
                # as the executable. Assume executable is in the build
                # directory and make srcdir absolute.
                srcdir = os.path.join(base, _CONFIG_VARS['srcdir'])
                _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir)

        if sys.platform == 'darwin':
            kernel_version = os.uname()[2]  # Kernel version (8.4.3)
            major_version = int(kernel_version.split('.')[0])

            if major_version < 8:
                # On Mac OS X before 10.4, check if -arch and -isysroot
                # are in CFLAGS or LDFLAGS and remove them if they are.
                # This is needed when building extensions on a 10.3 system
                # using a universal build of python.
                for key in ('LDFLAGS', 'BASECFLAGS',
                        # a number of derived variables. These need to be
                        # patched up as well.
                        'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
                    flags = _CONFIG_VARS[key]
                    flags = re.sub(r'-arch\s+\w+\s', ' ', flags)
                    flags = re.sub('-isysroot [^ \t]*', ' ', flags)
                    _CONFIG_VARS[key] = flags
            else:
                # Allow the user to override the architecture flags using
                # an environment variable.
                # NOTE: This name was introduced by Apple in OSX 10.5 and
                # is used by several scripting languages distributed with
                # that OS release.
                if 'ARCHFLAGS' in os.environ:
                    arch = os.environ['ARCHFLAGS']
                    for key in ('LDFLAGS', 'BASECFLAGS',
                        # a number of derived variables. These need to be
                        # patched up as well.
                        'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):

                        flags = _CONFIG_VARS[key]
                        flags = re.sub(r'-arch\s+\w+\s', ' ', flags)
                        flags = flags + ' ' + arch
                        _CONFIG_VARS[key] = flags

                # If we're on OSX 10.5 or later and the user tries to
                # compiles an extension using an SDK that is not present
                # on the current machine it is better to not use an SDK
                # than to fail.
                #
                # The major usecase for this is users using a Python.org
                # binary installer  on OSX 10.6: that installer uses
                # the 10.4u SDK, but that SDK is not installed by default
                # when you install Xcode.
                #
                CFLAGS = _CONFIG_VARS.get('CFLAGS', '')
                m = re.search(r'-isysroot\s+(\S+)', CFLAGS)
                if m is not None:
                    sdk = m.group(1)
                    if not os.path.exists(sdk):
                        for key in ('LDFLAGS', 'BASECFLAGS',
                             # a number of derived variables. These need to be
                             # patched up as well.
                            'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):

                            flags = _CONFIG_VARS[key]
                            flags = re.sub(r'-isysroot\s+\S+(\s|$)', ' ', flags)
                            _CONFIG_VARS[key] = flags

    if args:
        vals = []
        for name in args:
            vals.append(_CONFIG_VARS.get(name))
        return vals
    else:
        return _CONFIG_VARS


def get_config_var(name):
    """Return the value of a single variable using the dictionary returned by
    'get_config_vars()'.

    Equivalent to get_config_vars().get(name)
    """
    return get_config_vars().get(name)


def get_platform():
    """Return a string that identifies the current platform.

    This is used mainly to distinguish platform-specific build directories and
    platform-specific built distributions.  Typically includes the OS name
    and version and the architecture (as supplied by 'os.uname()'),
    although the exact information included depends on the OS; eg. for IRIX
    the architecture isn't particularly important (IRIX only runs on SGI
    hardware), but for Linux the kernel version isn't particularly
    important.

    Examples of returned values:
       linux-i586
       linux-alpha (?)
       solaris-2.6-sun4u
       irix-5.3
       irix64-6.2

    Windows will return one of:
       win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
       win-ia64 (64bit Windows on Itanium)
       win32 (all others - specifically, sys.platform is returned)

    For other non-POSIX platforms, currently just returns 'sys.platform'.
    """
    if os.name == 'nt':
        # sniff sys.version for architecture.
        prefix = " bit ("
        i = sys.version.find(prefix)
        if i == -1:
            return sys.platform
        j = sys.version.find(")", i)
        look = sys.version[i+len(prefix):j].lower()
        if look == 'amd64':
            return 'win-amd64'
        if look == 'itanium':
            return 'win-ia64'
        return sys.platform

    if os.name != "posix" or not hasattr(os, 'uname'):
        # XXX what about the architecture? NT is Intel or Alpha,
        # Mac OS is M68k or PPC, etc.
        return sys.platform

    # Try to distinguish various flavours of Unix
    osname, host, release, version, machine = os.uname()

    # Convert the OS name to lowercase, remove '/' characters
    # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
    osname = osname.lower().replace('/', '')
    machine = machine.replace(' ', '_')
    machine = machine.replace('/', '-')

    if osname[:5] == "linux":
        # At least on Linux/Intel, 'machine' is the processor --
        # i386, etc.
        # XXX what about Alpha, SPARC, etc?
        return  "%s-%s" % (osname, machine)
    elif osname[:5] == "sunos":
        if release[0] >= "5":           # SunOS 5 == Solaris 2
            osname = "solaris"
            release = "%d.%s" % (int(release[0]) - 3, release[2:])
        # fall through to standard osname-release-machine representation
    elif osname[:4] == "irix":              # could be "irix64"!
        return "%s-%s" % (osname, release)
    elif osname[:3] == "aix":
        return "%s-%s.%s" % (osname, version, release)
    elif osname[:6] == "cygwin":
        osname = "cygwin"
        rel_re = re.compile(r'[\d.]+')
        m = rel_re.match(release)
        if m:
            release = m.group()
    elif osname[:6] == "darwin":
        #
        # For our purposes, we'll assume that the system version from
        # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set
        # to. This makes the compatibility story a bit more sane because the
        # machine is going to compile and link as if it were
        # MACOSX_DEPLOYMENT_TARGET.
        cfgvars = get_config_vars()
        macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET')

        if True:
            # Always calculate the release of the running machine,
            # needed to determine if we can build fat binaries or not.

            macrelease = macver
            # Get the system version. Reading this plist is a documented
            # way to get the system version (see the documentation for
            # the Gestalt Manager)
            try:
                f = open('/System/Library/CoreServices/SystemVersion.plist')
            except IOError:
                # We're on a plain darwin box, fall back to the default
                # behaviour.
                pass
            else:
                try:
                    m = re.search(r'ProductUserVisibleVersion\s*'
                                  r'(.*?)', f.read())
                finally:
                    f.close()
                if m is not None:
                    macrelease = '.'.join(m.group(1).split('.')[:2])
                # else: fall back to the default behaviour

        if not macver:
            macver = macrelease

        if macver:
            release = macver
            osname = "macosx"

            if ((macrelease + '.') >= '10.4.' and
                '-arch' in get_config_vars().get('CFLAGS', '').strip()):
                # The universal build will build fat binaries, but not on
                # systems before 10.4
                #
                # Try to detect 4-way universal builds, those have machine-type
                # 'universal' instead of 'fat'.

                machine = 'fat'
                cflags = get_config_vars().get('CFLAGS')

                archs = re.findall(r'-arch\s+(\S+)', cflags)
                archs = tuple(sorted(set(archs)))

                if len(archs) == 1:
                    machine = archs[0]
                elif archs == ('i386', 'ppc'):
                    machine = 'fat'
                elif archs == ('i386', 'x86_64'):
                    machine = 'intel'
                elif archs == ('i386', 'ppc', 'x86_64'):
                    machine = 'fat3'
                elif archs == ('ppc64', 'x86_64'):
                    machine = 'fat64'
                elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'):
                    machine = 'universal'
                else:
                    raise ValueError(
                       "Don't know machine value for archs=%r" % (archs,))

            elif machine == 'i386':
                # On OSX the machine type returned by uname is always the
                # 32-bit variant, even if the executable architecture is
                # the 64-bit variant
                if sys.maxsize >= 2**32:
                    machine = 'x86_64'

            elif machine in ('PowerPC', 'Power_Macintosh'):
                # Pick a sane name for the PPC architecture.
                # See 'i386' case
                if sys.maxsize >= 2**32:
                    machine = 'ppc64'
                else:
                    machine = 'ppc'

    return "%s-%s-%s" % (osname, release, machine)


def get_python_version():
    return _PY_VERSION_SHORT


def _print_dict(title, data):
    for index, (key, value) in enumerate(sorted(data.items())):
        if index == 0:
            print('%s: ' % (title))
        print('\t%s = "%s"' % (key, value))


def _main():
    """Display all information sysconfig detains."""
    print('Platform: "%s"' % get_platform())
    print('Python version: "%s"' % get_python_version())
    print('Current installation scheme: "%s"' % _get_default_scheme())
    print()
    _print_dict('Paths', get_paths())
    print()
    _print_dict('Variables', get_config_vars())


if __name__ == '__main__':
    _main()
PKÕ¶N]}-<Âttsite-packages/pip/__main__.pynu„[µü¤from __future__ import absolute_import

import os
import sys

# If we are running from a wheel, add the wheel to sys.path
# This allows the usage python pip-*.whl/pip install pip-*.whl
if __package__ == '':
    # __file__ is pip-*.whl/pip/__main__.py
    # first dirname call strips of '/__main__.py', second strips off '/pip'
    # Resulting path is the name of the wheel itself
    # Add that to sys.path so we can import pip
    path = os.path.dirname(os.path.dirname(__file__))
    sys.path.insert(0, path)

from pip._internal.main import main as _main  # isort:skip # noqa

if __name__ == '__main__':
    sys.exit(_main())
PK‹¶N]ªàFönn/site-packages/setuptools-41.6.0.dist-info/WHEELnu„[µü¤PK‹¶N]hBDÜ5Ü50Ísite-packages/setuptools-41.6.0.dist-info/RECORDnu„[µü¤PK‹¶N]7Ù_Ýïï>	7site-packages/setuptools-41.6.0.dist-info/dependency_links.txtnu„[µü¤PK‹¶N]P׫661f8site-packages/setuptools-41.6.0.dist-info/LICENSEnu„[µü¤PKŒ¶N]�¨ñ®®:ý<site-packages/setuptools-41.6.0.dist-info/entry_points.txtnu„[µü¤PKŒ¶N]“×22Isite-packages/setuptools-41.6.0.dist-info/zip-safenu„[µü¤PKŒ¶N]0\‘&&7xIsite-packages/setuptools-41.6.0.dist-info/top_level.txtnu„[µü¤PKŒ¶N]²Hlh

2Jsite-packages/setuptools-41.6.0.dist-info/METADATAnu„[µü¤PK�¶N]Ç—Â3‚Wsite-packages/setuptools-41.6.0.dist-info/INSTALLERnu„[µü¤PK޶N]M¸n=§=§'éWsite-packages/pkg_resources/__init__.pynu„[µü¤PK‘¶N]\0÷[ˆˆE}ÿsite-packages/pkg_resources/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK”¶N]@Õ·KXXGö‡site-packages/pkg_resources/__pycache__/py31compat.cpython-38.opt-1.pycnu„[µü¤PK•¶N]\0÷[ˆˆ?ÅŠsite-packages/pkg_resources/__pycache__/__init__.cpython-38.pycnu„[µü¤PK•¶N]@Õ·KXXA8site-packages/pkg_resources/__pycache__/py31compat.cpython-38.pycnu„[µü¤PK•¶N]‹À’F..)site-packages/pkg_resources/py31compat.pynu„[µü¤PK—¶N]f„±wŠwŠ0ˆsite-packages/pkg_resources/_vendor/pyparsing.pynu„[µü¤PKš¶N]/_£site-packages/pkg_resources/_vendor/__init__.pynu„[µü¤PKš¶N]“@sr¢¢H¾£site-packages/pkg_resources/_vendor/__pycache__/pyparsing.cpython-38.pycnu„[µü¤PKš¶N]#R¹��MØ·site-packages/pkg_resources/_vendor/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKš¶N]ßhÞPPFò¸site-packages/pkg_resources/_vendor/__pycache__/appdirs.cpython-38.pycnu„[µü¤PKš¶N]:ý³-n_n_H†	site-packages/pkg_resources/_vendor/__pycache__/six.cpython-38.opt-1.pycnu„[µü¤PKš¶N]nÒa`¢¢Nlisite-packages/pkg_resources/_vendor/__pycache__/pyparsing.cpython-38.opt-1.pycnu„[µü¤PKš¶N]#R¹��GŒ}site-packages/pkg_resources/_vendor/__pycache__/__init__.cpython-38.pycnu„[µü¤PKš¶N]:ý³-n_n_B ~site-packages/pkg_resources/_vendor/__pycache__/six.cpython-38.pycnu„[µü¤PK›¶N]ßhÞPPL€Þsite-packages/pkg_resources/_vendor/__pycache__/appdirs.cpython-38.opt-1.pycnu„[µü¤PK›¶N]úÞ½g`g`./site-packages/pkg_resources/_vendor/appdirs.pynu„[µü¤PK›¶N]�v–Ê9ß�site-packages/pkg_resources/_vendor/packaging/__init__.pynu„[µü¤PK›¶N]ôSò›!!WI’site-packages/pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK›¶N]E£KMKMSñ”site-packages/pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-38.pycnu„[µü¤PK›¶N]xLýóÃÃX¿âsite-packages/pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-38.opt-1.pycnu„[µü¤PK›¶N]˜ÜΓ×"×"P
æsite-packages/pkg_resources/_vendor/packaging/__pycache__/markers.cpython-38.pycnu„[µü¤PK›¶N]faßàË
Ë
Za	site-packages/pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-38.opt-1.pycnu„[µü¤PK›¶N]faßàË
Ë
T¶site-packages/pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-38.pycnu„[µü¤PK›¶N]Òu`ÕÕP site-packages/pkg_resources/_vendor/packaging/__pycache__/_compat.cpython-38.pycnu„[µü¤PK›¶N]Òu`ÕÕVZ$site-packages/pkg_resources/_vendor/packaging/__pycache__/_compat.cpython-38.opt-1.pycnu„[µü¤PK›¶N]ôSò›!!Qµ(site-packages/pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-38.pycnu„[µü¤PK›¶N]M?gŠ)Š)VW+site-packages/pkg_resources/_vendor/packaging/__pycache__/version.cpython-38.opt-1.pycnu„[µü¤PKœ¶N]Иkð&&[gUsite-packages/pkg_resources/_vendor/packaging/__pycache__/requirements.cpython-38.opt-1.pycnu„[µü¤PKœ¶N]³“ÍKÒÒTesite-packages/pkg_resources/_vendor/packaging/__pycache__/utils.cpython-38.opt-1.pycnu„[µü¤PKœ¶N]Иkð&&Ungsite-packages/pkg_resources/_vendor/packaging/__pycache__/requirements.cpython-38.pycnu„[µü¤PKœ¶N]±r"r"Vwsite-packages/pkg_resources/_vendor/packaging/__pycache__/markers.cpython-38.opt-1.pycnu„[µü¤PKœ¶N]xLýóÃÃRšsite-packages/pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-38.pycnu„[µü¤PKœ¶N]M?gŠ)Š)PV�site-packages/pkg_resources/_vendor/packaging/__pycache__/version.cpython-38.pycnu„[µü¤PKœ¶N]³“ÍKÒÒN`Çsite-packages/pkg_resources/_vendor/packaging/__pycache__/utils.cpython-38.pycnu„[µü¤PKœ¶N]E£KMKMY°Ésite-packages/pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-38.opt-1.pycnu„[µü¤PKœ¶N]úý¤ˆˆ<„site-packages/pkg_resources/_vendor/packaging/_structures.pynu„[µü¤PKœ¶N]æiJã\\8xsite-packages/pkg_resources/_vendor/packaging/_compat.pynu„[µü¤PKœ¶N]Åê'¥¥6Gsite-packages/setuptools/__pycache__/namespaces.cpython-38.opt-1.pycnu„[µü¤PK¡¶N]¥îϚϚ8ÒUsite-packages/setuptools/__pycache__/msvc.cpython-38.pycnu„[µü¤PK¢¶N]9Õì@##>	ñsite-packages/setuptools/__pycache__/pep425tags.cpython-38.pycnu„[µü¤PK¢¶N]Ç¢Ä$$:š
site-packages/setuptools/__pycache__/monkey.cpython-38.pycnu„[µü¤PK¢¶N]C¡„33B( site-packages/setuptools/__pycache__/dep_util.cpython-38.opt-1.pycnu„[µü¤PK¢¶N]K¬Ó¤Ó¤8Í#site-packages/setuptools/__pycache__/dist.cpython-38.pycnu„[µü¤PK¢¶N]»C;Ìbb>Ésite-packages/setuptools/__pycache__/_imp.cpython-38.opt-1.pycnu„[µü¤PK¢¶N]‹b'/úú9ØÐsite-packages/setuptools/__pycache__/glibc.cpython-38.pycnu„[µü¤PK£¶N]ôA¼¤88@;×site-packages/setuptools/__pycache__/launch.cpython-38.opt-1.pycnu„[µü¤PK£¶N]M÷]â/!/!>ãÚsite-packages/setuptools/__pycache__/build_meta.cpython-38.pycnu„[µü¤PK£¶N]tÓÕEÕE:€üsite-packages/setuptools/__pycache__/config.cpython-38.pycnu„[µü¤PK£¶N]5) XXB¿Bsite-packages/setuptools/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK£¶N]àÅØ¦ÝÝI‰asite-packages/setuptools/__pycache__/windows_support.cpython-38.opt-1.pycnu„[µü¤PK£¶N]Ç¢Ä$$@ßesite-packages/setuptools/__pycache__/monkey.cpython-38.opt-1.pycnu„[µü¤PK£¶N]�€site-packages/setuptools/__pycache__/py34compat.cpython-38.pycnu„[µü¤PK¤¶N]¥îϚϚ>¿‚site-packages/setuptools/__pycache__/msvc.cpython-38.opt-1.pycnu„[µü¤PK¤¶N]`['##Düsite-packages/setuptools/__pycache__/pep425tags.cpython-38.opt-1.pycnu„[µü¤PK¤¶N]‹b'/úú?“:site-packages/setuptools/__pycache__/glibc.cpython-38.opt-1.pycnu„[µü¤PK¤¶N]tÓÕEÕE@ü@site-packages/setuptools/__pycache__/config.cpython-38.opt-1.pycnu„[µü¤PK¤¶N]M]]FA‡site-packages/setuptools/__pycache__/archive_util.cpython-38.opt-1.pycnu„[µü¤PK¤¶N][£Îg``A¿›site-packages/setuptools/__pycache__/depends.cpython-38.opt-1.pycnu„[µü¤PK¤¶N]!ÀÁ§§D�°site-packages/setuptools/__pycache__/py31compat.cpython-38.opt-1.pycnu„[µü¤PK¤¶N]ïÕ¾�ÂÂ>«µsite-packages/setuptools/__pycache__/site-patch.cpython-38.pycnu„[µü¤PK¥¶N]è8¿HÇÇ?Û»site-packages/setuptools/__pycache__/ssl_support.cpython-38.pycnu„[µü¤PK¥¶N]M]]@×site-packages/setuptools/__pycache__/archive_util.cpython-38.pycnu„[µü¤PK¥¶N]•¡Üýcc>‰ësite-packages/setuptools/__pycache__/glob.cpython-38.opt-1.pycnu„[µü¤PK¥¶N]½\ŒÌÂÂDZúsite-packages/setuptools/__pycache__/py34compat.cpython-38.opt-1.pycnu„[µü¤PK¥¶N]A†éG�üsite-packages/setuptools/__pycache__/unicode_utils.cpython-38.opt-1.pycnu„[µü¤PK¥¶N]Tƒ-ëk	k	D†site-packages/setuptools/__pycache__/lib2to3_ex.cpython-38.opt-1.pycnu„[µü¤PK¥¶N]ïÕ¾�ÂÂDesite-packages/setuptools/__pycache__/site-patch.cpython-38.opt-1.pycnu„[µü¤PK¥¶N]¶>TH›site-packages/setuptools/__pycache__/_deprecation_warning.cpython-38.pycnu„[µü¤PK¥¶N]5) XX<site-packages/setuptools/__pycache__/__init__.cpython-38.pycnu„[µü¤PK¥¶N]Ö©À$$AÛ2site-packages/setuptools/__pycache__/version.cpython-38.opt-1.pycnu„[µü¤PK¥¶N]¥Ÿ�ÈÕÕDp4site-packages/setuptools/__pycache__/py27compat.cpython-38.opt-1.pycnu„[µü¤PK¥¶N]õsite-packages/setuptools/__pycache__/package_index.cpython-38.opt-1.pycnu„[µü¤PK¦¶N]ôA¼¤88:vsite-packages/setuptools/__pycache__/launch.cpython-38.pycnu„[µü¤PK¦¶N]A†éA!zsite-packages/setuptools/__pycache__/unicode_utils.cpython-38.pycnu„[µü¤PK¦¶N]C¡„33<site-packages/setuptools/__pycache__/dep_util.cpython-38.pycnu„[µü¤PK¦¶N]àÅØ¦ÝÝC°‚site-packages/setuptools/__pycache__/windows_support.cpython-38.pycnu„[µü¤PK¦¶N]\³h怀>‡site-packages/setuptools/__pycache__/py33compat.cpython-38.pycnu„[µü¤PK¦¶N]¥Ÿ�ÈÕÕ>îŒsite-packages/setuptools/__pycache__/py27compat.cpython-38.pycnu„[µü¤PK¦¶N]Tƒ-ëk	k	>1”site-packages/setuptools/__pycache__/lib2to3_ex.cpython-38.pycnu„[µü¤PK¦¶N]¶>TN
žsite-packages/setuptools/__pycache__/_deprecation_warning.cpython-38.opt-1.pycnu„[µü¤PK¦¶N]½’¦••8Œ site-packages/setuptools/__pycache__/glob.cpython-38.pycnu„[µü¤PK¦¶N][£Îg``;‰¯site-packages/setuptools/__pycache__/depends.cpython-38.pycnu„[µü¤PK¦¶N]\³h怀DTÄsite-packages/setuptools/__pycache__/py33compat.cpython-38.opt-1.pycnu„[µü¤PK¦¶N]@äŘtt?HÊsite-packages/setuptools/__pycache__/wheel.cpython-38.opt-1.pycnu„[µü¤PK¦¶N]Ö©À$$;+æsite-packages/setuptools/__pycache__/version.cpython-38.pycnu„[µü¤PK¦¶N]»C;Ìbb8ºçsite-packages/setuptools/__pycache__/_imp.cpython-38.pycnu„[µü¤PK¦¶N]ç{BB
!
!D„ïsite-packages/setuptools/__pycache__/build_meta.cpython-38.opt-1.pycnu„[µü¤PK¦¶N]ß§}…¤…¤>site-packages/setuptools/__pycache__/dist.cpython-38.opt-1.pycnu„[µü¤PK¦¶N]!ÀÁ§§>øµsite-packages/setuptools/__pycache__/py31compat.cpython-38.pycnu„[µü¤PK¦¶N]ã ò�  >
»site-packages/setuptools/__pycache__/namespaces.cpython-38.pycnu„[µü¤PK§¶N]dù~›"›Ésite-packages/setuptools/launch.pynu„[µü¤PK§¶N]ŒSšcÄ7Ä7#Ísite-packages/setuptools/sandbox.pynu„[µü¤PK§¶N]ÉÙ“6P6P"site-packages/setuptools/config.pynu„[µü¤PK§¶N]­*ƒ6þþ&ŸUsite-packages/setuptools/site-patch.pynu„[µü¤PK§¶N]êÁ½JJ!ó^site-packages/setuptools/glibc.pynu„[µü¤PK§¶N]¹ª‘îÁÁ%Žksite-packages/setuptools/extension.pynu„[µü¤PK§¶N]ÞË0âFF&¤rsite-packages/setuptools/py31compat.pynu„[µü¤PK§¶N]ùËî
ÊÊ+@vsite-packages/setuptools/windows_support.pynu„[µü¤PK§¶N]f„±wŠwŠ-eysite-packages/setuptools/_vendor/pyparsing.pynu„[µü¤PK§¶N],9 site-packages/setuptools/_vendor/__init__.pynu„[µü¤PK§¶N]õìè韟E• site-packages/setuptools/_vendor/__pycache__/pyparsing.cpython-38.pycnu„[µü¤PK§¶N]NÂB2ššJ©#site-packages/setuptools/_vendor/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK§¶N]ÀÊ3"@@G½#site-packages/setuptools/_vendor/__pycache__/ordered_set.cpython-38.pycnu„[µü¤PK§¶N]èŒL_k_k_EPZ#site-packages/setuptools/_vendor/__pycache__/six.cpython-38.opt-1.pycnu„[µü¤PK§¶N]~úûŸŸK0º#site-packages/setuptools/_vendor/__pycache__/pyparsing.cpython-38.opt-1.pycnu„[µü¤PK§¶N]ÀÊ3"@@MJÎ&site-packages/setuptools/_vendor/__pycache__/ordered_set.cpython-38.opt-1.pycnu„[µü¤PK¨¶N]NÂB2ššDã'site-packages/setuptools/_vendor/__pycache__/__init__.cpython-38.pycnu„[µü¤PK¨¶N]èŒL_k_k_?ñ'site-packages/setuptools/_vendor/__pycache__/six.cpython-38.pycnu„[µü¤PK¨¶N]DÃ*;;/Ëo'site-packages/setuptools/_vendor/ordered_set.pynu„[µü¤PK¨¶N]�v–Ê6D«'site-packages/setuptools/_vendor/packaging/__init__.pynu„[µü¤PK¨¶N]ÒrjT«­'site-packages/setuptools/_vendor/packaging/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK¨¶N]ðï*HMHMPM°'site-packages/setuptools/_vendor/packaging/__pycache__/specifiers.cpython-38.pycnu„[µü¤PK¨¶N]*µòqÀÀUþ'site-packages/setuptools/_vendor/packaging/__pycache__/__about__.cpython-38.opt-1.pycnu„[µü¤PK¨¶N]"­Ñ"Ñ"MZ(site-packages/setuptools/_vendor/packaging/__pycache__/markers.cpython-38.pycnu„[µü¤PK¨¶N]dRÁÎÈ
È
W¨$(site-packages/setuptools/_vendor/packaging/__pycache__/_structures.cpython-38.opt-1.pycnu„[µü¤PK¨¶N]dRÁÎÈ
È
Q÷/(site-packages/setuptools/_vendor/packaging/__pycache__/_structures.cpython-38.pycnu„[µü¤PK¨¶N]ø‘ÔÒÒM@;(site-packages/setuptools/_vendor/packaging/__pycache__/_compat.cpython-38.pycnu„[µü¤PK¨¶N]ø‘ÔÒÒS�?(site-packages/setuptools/_vendor/packaging/__pycache__/_compat.cpython-38.opt-1.pycnu„[µü¤PK¨¶N]ÒrjNäC(site-packages/setuptools/_vendor/packaging/__pycache__/__init__.cpython-38.pycnu„[µü¤PK¨¶N]gn݇)‡)S€F(site-packages/setuptools/_vendor/packaging/__pycache__/version.cpython-38.opt-1.pycnu„[µü¤PK©¶N]ŸyøtXŠp(site-packages/setuptools/_vendor/packaging/__pycache__/requirements.cpython-38.opt-1.pycnu„[µü¤PK©¶N]6	ÄÏÏQ/€(site-packages/setuptools/_vendor/packaging/__pycache__/utils.cpython-38.opt-1.pycnu„[µü¤PK©¶N]ŸyøtR‚(site-packages/setuptools/_vendor/packaging/__pycache__/requirements.cpython-38.pycnu„[µü¤PK©¶N]Ó$ʤl"l"S’(site-packages/setuptools/_vendor/packaging/__pycache__/markers.cpython-38.opt-1.pycnu„[µü¤PK©¶N]*µòqÀÀO
µ(site-packages/setuptools/_vendor/packaging/__pycache__/__about__.cpython-38.pycnu„[µü¤PK©¶N]gn݇)‡)ML¸(site-packages/setuptools/_vendor/packaging/__pycache__/version.cpython-38.pycnu„[µü¤PK©¶N]6	ÄÏÏKPâ(site-packages/setuptools/_vendor/packaging/__pycache__/utils.cpython-38.pycnu„[µü¤PK©¶N]ðï*HMHMVšä(site-packages/setuptools/_vendor/packaging/__pycache__/specifiers.cpython-38.opt-1.pycnu„[µü¤PK©¶N]úý¤ˆˆ9h2)site-packages/setuptools/_vendor/packaging/_structures.pynu„[µü¤PK©¶N]æiJã\\5Y8)site-packages/setuptools/_vendor/packaging/_compat.pynu„[µü¤PK©¶N]Åê'¥¥3<)site-packages/setuptools/_vendor/packaging/utils.pynu„[µü¤PK©¶N]‚vÐ�÷÷:">)site-packages/setuptools/_vendor/packaging/requirements.pynu„[µü¤PK©¶N]ïÆ¡$-$-5ƒO)site-packages/setuptools/_vendor/packaging/version.pynu„[µü¤PK©¶N]|EƒŒymym8})site-packages/setuptools/_vendor/packaging/specifiers.pynu„[µü¤PK©¶N]<)XÆÐÐ7íê)site-packages/setuptools/_vendor/packaging/__about__.pynu„[µü¤PK©¶N]ÄHŠ/ / 5$î)site-packages/setuptools/_vendor/packaging/markers.pynu„[µü¤PK©¶N]™XMZ’u’u'¸*site-packages/setuptools/_vendor/six.pynu„[µü¤PKª¶N]‡Që¢ÝÝ&¡„*site-packages/setuptools/lib2to3_ex.pynu„[µü¤PKª¶N]ŽVÐDõõ&ÔŒ*site-packages/setuptools/py34compat.pynu„[µü¤PKª¶N]ŠîÝm*m*&Ž*site-packages/setuptools/pep425tags.pynu„[µü¤PKª¶N]ZÙqƒ››*â¸*site-packages/setuptools/command/upload.pynu„[µü¤PKª¶N]ëÒtää-×Ó*site-packages/setuptools/command/bdist_rpm.pynu„[µü¤PKª¶N]ÊÔ¤tt*Ú*site-packages/setuptools/command/rotate.pynu„[µü¤PKª¶N]›pËÇÝÝ*æâ*site-packages/setuptools/command/setopt.pynu„[µü¤PKª¶N]ÐÍó=øø+÷*site-packages/setuptools/command/develop.pynu„[µü¤PKª¶N]'�„„.p+site-packages/setuptools/command/build_clib.pynu„[µü¤PKª¶N]]‹)Btt6R)+site-packages/setuptools/command/launcher manifest.xmlnu„[µü¤PKª¶N]}s`¿zz.,,+site-packages/setuptools/command/py36compat.pynu„[µü¤PKª¶N]/Ã<�U�U0@+site-packages/setuptools/command/easy_install.pynu„[µü¤PKª¶N]ò—óÆ��/–,site-packages/setuptools/command/upload_docs.pynu„[µü¤PKª¶N]@FBÜ|%|%,ï²,site-packages/setuptools/command/build_py.pynu„[µü¤PKª¶N]œl90	G	G-ÇØ,site-packages/setuptools/command/bdist_egg.pynu„[µü¤PKª¶N]AœRRR,- -site-packages/setuptools/command/__init__.pynu„[µü¤PKª¶N]ý¾Ó­,Û"-site-packages/setuptools/command/register.pynu„[µü¤PKª¶N]…EPåøøEM%-site-packages/setuptools/command/__pycache__/bdist_rpm.cpython-38.pycnu„[µü¤PK«¶N]ðUÞTSSBº,-site-packages/setuptools/command/__pycache__/upload.cpython-38.pycnu„[µü¤PK«¶N]j7ÕØ	Ø	BA-site-packages/setuptools/command/__pycache__/rotate.cpython-38.pycnu„[µü¤PK«¶N]4#n)c	c	RÉK-site-packages/setuptools/command/__pycache__/install_egg_info.cpython-38.opt-1.pycnu„[µü¤PK«¶N]XræÁ!Á!D®U-site-packages/setuptools/command/__pycache__/build_py.cpython-38.pycnu„[µü¤PK«¶N]õÉ€ÃX	X	Gãw-site-packages/setuptools/command/__pycache__/alias.cpython-38.opt-1.pycnu„[µü¤PK«¶N]j7ÕØ	Ø	H²�-site-packages/setuptools/command/__pycache__/rotate.cpython-38.opt-1.pycnu„[µü¤PK«¶N]…EPåøøKŒ-site-packages/setuptools/command/__pycache__/bdist_rpm.cpython-38.opt-1.pycnu„[µü¤PK«¶N]�"
纺Ou“-site-packages/setuptools/command/__pycache__/bdist_wininst.cpython-38.opt-1.pycnu„[µü¤PK«¶N]IGÙ¹¹H®—-site-packages/setuptools/command/__pycache__/setopt.cpython-38.opt-1.pycnu„[µü¤PK¬¶N]ìTýh!!Fß©-site-packages/setuptools/command/__pycache__/test.cpython-38.opt-1.pycnu„[µü¤PK¬¶N]kæÊÉââJpË-site-packages/setuptools/command/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK¬¶N]ÛI–‰&‰&KÌÎ-site-packages/setuptools/command/__pycache__/build_ext.cpython-38.opt-1.pycnu„[µü¤PK­¶N]üIl„eeIÐõ-site-packages/setuptools/command/__pycache__/develop.cpython-38.opt-1.pycnu„[µü¤PK®¶N]Í1q——A®.site-packages/setuptools/command/__pycache__/sdist.cpython-38.pycnu„[µü¤PK®¶N]~àŒhyyD¶*.site-packages/setuptools/command/__pycache__/saveopts.cpython-38.pycnu„[µü¤PK®¶N].¼½?UUJ£..site-packages/setuptools/command/__pycache__/egg_info.cpython-38.opt-1.pycnu„[µü¤PK°¶N]e|¡§&§&E!„.site-packages/setuptools/command/__pycache__/build_ext.cpython-38.pycnu„[µü¤PK±¶N]±
LŒêêM=«.site-packages/setuptools/command/__pycache__/upload_docs.cpython-38.opt-1.pycnu„[µü¤PK±¶N]�"
纺I¤Ã.site-packages/setuptools/command/__pycache__/bdist_wininst.cpython-38.pycnu„[µü¤PK±¶N]Í1q——G×Ç.site-packages/setuptools/command/__pycache__/sdist.cpython-38.opt-1.pycnu„[µü¤PK²¶N]~àŒhyyJåâ.site-packages/setuptools/command/__pycache__/saveopts.cpython-38.opt-1.pycnu„[µü¤PK²¶N]Ä–kÄ…	…	FØæ.site-packages/setuptools/command/__pycache__/build_clib.cpython-38.pycnu„[µü¤PK²¶N]žHHLÓð.site-packages/setuptools/command/__pycache__/py36compat.cpython-38.opt-1.pycnu„[µü¤PK²¶N]Ìçeô——CQ/site-packages/setuptools/command/__pycache__/install.cpython-38.pycnu„[µü¤PK²¶N]4#n)c	c	L[/site-packages/setuptools/command/__pycache__/install_egg_info.cpython-38.pycnu„[µü¤PK²¶N]†
üQQE:/site-packages/setuptools/command/__pycache__/dist_info.cpython-38.pycnu„[µü¤PK²¶N]�$·©ááQ#/site-packages/setuptools/command/__pycache__/install_scripts.cpython-38.opt-1.pycnu„[µü¤PK²¶N]/µXûóóJb,/site-packages/setuptools/command/__pycache__/register.cpython-38.opt-1.pycnu„[µü¤PK²¶N]dM�GÿGÿHÏ//site-packages/setuptools/command/__pycache__/easy_install.cpython-38.pycnu„[µü¤PK²¶N]ŸCÝÿÿNŽ/0site-packages/setuptools/command/__pycache__/easy_install.cpython-38.opt-1.pycnu„[µü¤PK²¶N]üU¡3G&/1site-packages/setuptools/command/__pycache__/install_lib.cpython-38.pycnu„[µü¤PK²¶N]M2Òf7f7K¹?1site-packages/setuptools/command/__pycache__/bdist_egg.cpython-38.opt-1.pycnu„[µü¤PK³¶N]žHHFšw1site-packages/setuptools/command/__pycache__/py36compat.cpython-38.pycnu„[µü¤PK³¶N]XræÁ!Á!JŠ1site-packages/setuptools/command/__pycache__/build_py.cpython-38.opt-1.pycnu„[µü¤PK³¶N]kæÊÉââDM¬1site-packages/setuptools/command/__pycache__/__init__.cpython-38.pycnu„[µü¤PK³¶N]õÉ€ÃX	X	A£¯1site-packages/setuptools/command/__pycache__/alias.cpython-38.pycnu„[µü¤PK³¶N]Ìçeô——Il¹1site-packages/setuptools/command/__pycache__/install.cpython-38.opt-1.pycnu„[µü¤PK³¶N]DѳüüüG|É1site-packages/setuptools/command/__pycache__/upload_docs.cpython-38.pycnu„[µü¤PK³¶N]†
üQQKïá1site-packages/setuptools/command/__pycache__/dist_info.cpython-38.opt-1.pycnu„[µü¤PK³¶N]üIl„eeC»ç1site-packages/setuptools/command/__pycache__/develop.cpython-38.pycnu„[µü¤PK³¶N]M2Òf7f7E“2site-packages/setuptools/command/__pycache__/bdist_egg.cpython-38.pycnu„[µü¤PK³¶N]IGÙ¹¹Bn92site-packages/setuptools/command/__pycache__/setopt.cpython-38.pycnu„[µü¤PK³¶N]ìTýh!!@™K2site-packages/setuptools/command/__pycache__/test.cpython-38.pycnu„[µü¤PK³¶N]ðUÞTSSH$m2site-packages/setuptools/command/__pycache__/upload.cpython-38.opt-1.pycnu„[µü¤PK³¶N].¼½?UUDï�2site-packages/setuptools/command/__pycache__/egg_info.cpython-38.pycnu„[µü¤PK³¶N]ÐeúúMg×2site-packages/setuptools/command/__pycache__/install_lib.cpython-38.opt-1.pycnu„[µü¤PK³¶N]Ä–kÄ…	…	LÞç2site-packages/setuptools/command/__pycache__/build_clib.cpython-38.opt-1.pycnu„[µü¤PK³¶N]/µXûóóDßñ2site-packages/setuptools/command/__pycache__/register.cpython-38.pycnu„[µü¤PK³¶N]�$·©ááKFõ2site-packages/setuptools/command/__pycache__/install_scripts.cpython-38.pycnu„[µü¤PK´¶N] Œu}}1¢þ2site-packages/setuptools/command/bdist_wininst.pynu„[µü¤PK´¶N]F?ñ‡	‡	3€3site-packages/setuptools/command/install_scripts.pynu„[µü¤PK´¶N]Pø#òz	z	)j3site-packages/setuptools/command/alias.pynu„[µü¤PK´¶N]Ý–œÏ‚%‚%(=3site-packages/setuptools/command/test.pynu„[µü¤PK´¶N]1‰ôöâcâc,;3site-packages/setuptools/command/egg_info.pynu„[µü¤PK´¶N]�Ûµ?KK+UŸ3site-packages/setuptools/command/install.pynu„[µü¤PK´¶N]�Ö4’’,û±3site-packages/setuptools/command/saveopts.pynu„[µü¤PK´¶N]\Ҩ四4é´3site-packages/setuptools/command/install_egg_info.pynu„[µü¤PK´¶N]ÿèö‘ÀÀ-è½3site-packages/setuptools/command/dist_info.pynu„[µü¤PK´¶N]°l¢ÜÜ)Â3site-packages/setuptools/command/sdist.pynu„[µü¤PK´¶N]�(ýpÛ2Û2-:ß3site-packages/setuptools/command/build_ext.pynu„[µü¤PK´¶N]ÓŒ*/r4site-packages/setuptools/command/install_lib.pynu„[µü¤PK´¶N]ý[
��#ç!4site-packages/setuptools/depends.pynu„[µü¤PK´¶N]Ó«ÚÚ*Ç74site-packages/setuptools/script (dev).tmplnu„[µü¤PK´¶N]2§ü\Ÿ¶Ÿ¶ û84site-packages/setuptools/msvc.pynu„[µü¤PK´¶N]¬JÚÚ0êï4site-packages/setuptools/_deprecation_warning.pynu„[µü¤PK´¶N]aØ¢22&$ñ4site-packages/setuptools/py33compat.pynu„[µü¤PK´¶N]Ç$l“Ò	Ò	+¬ö4site-packages/setuptools/extern/__init__.pynu„[µü¤PK´¶N]¤™Žt	t	IÙ5site-packages/setuptools/extern/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK´¶N]¤™Žt	t	CÆ
5site-packages/setuptools/extern/__pycache__/__init__.cpython-38.pycnu„[µü¤PK´¶N]ŽÈOkÜÜ ­5site-packages/setuptools/glob.pynu„[µü¤PK´¶N]Ε4Ž-!-!'Ù(5site-packages/setuptools/ssl_support.pynu„[µü¤PKµ¶N]"2§§$]J5site-packages/setuptools/dep_util.pynu„[µü¤PKµ¶N]H±Lb��#XN5site-packages/setuptools/version.pynu„[µü¤PKµ¶N]šBךää);O5site-packages/setuptools/unicode_utils.pynu„[µü¤PKµ¶N]Ƶ²c}%}%&xS5site-packages/setuptools/build_meta.pynu„[µü¤PKµ¶N][Dޝ¯ Ky5site-packages/setuptools/_imp.pynu„[µü¤PKµ¶N]þDÔØØ&J‚5site-packages/setuptools/py27compat.pynu„[µü¤PKµ¶N]žØ��ž�ž)xˆ5site-packages/setuptools/package_index.pynu„[µü¤PK¶¶N]\OºE~~n'6site-packages/easy_install.pynu„[µü¤PK¶¶N]YO™t59(6site-packages/__pycache__/easy_install.cpython-38.pycnu„[µü¤PK¶¶N]YO™t;·)6site-packages/__pycache__/easy_install.cpython-38.opt-1.pycnu„[µü¤PK¶¶N]ªàFönn(;+6site-packages/pip-19.3.1.dist-info/WHEELnu„[µü¤PK¶¶N]Ñô“ÚÅÚÅ),6site-packages/pip-19.3.1.dist-info/RECORDnu„[µü¤PK¶¶N]#Áøñqq34ò6site-packages/pip-19.3.1.dist-info/entry_points.txtnu„[µü¤PK¶¶N]ëLõÔBB.ó6site-packages/pip-19.3.1.dist-info/LICENSE.txtnu„[µü¤PK·¶N]Ç—Â0¨÷6site-packages/pip-19.3.1.dist-info/top_level.txtnu„[µü¤PK·¶N]OÇÜ­­+ø6site-packages/pip-19.3.1.dist-info/METADATAnu„[µü¤PK·¶N]¯#„,7site-packages/pip-19.3.1.dist-info/INSTALLERnu„[µü¤PK·¶N]â´ÀÌhh2t7site-packages/pip/_internal/distributions/wheel.pynu„[µü¤PK·¶N]É>6TÇÇ5>7site-packages/pip/_internal/distributions/__init__.pynu„[µü¤PK·¶N]èá.ÀÀTj7site-packages/pip/_internal/distributions/__pycache__/installed.cpython-38.opt-1.pycnu„[µü¤PK·¶N]èØTTO®7site-packages/pip/_internal/distributions/__pycache__/base.cpython-38.opt-1.pycnu„[µü¤PK·¶N]ÉÞ¬44S�7site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK·¶N]èØTTI87site-packages/pip/_internal/distributions/__pycache__/base.cpython-38.pycnu„[µü¤PK·¶N]ÉÞ¬44M"7site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-38.pycnu„[µü¤PK·¶N]â¹J¶%7site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-38.pycnu„[µü¤PK·¶N]èá.ÀÀN0*7site-packages/pip/_internal/distributions/__pycache__/installed.cpython-38.pycnu„[µü¤PK·¶N]â¹Pn.7site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-38.opt-1.pycnu„[µü¤PK·¶N]Šaœ_6î27site-packages/pip/_internal/distributions/installed.pynu„[µü¤PK·¶N]'­ƒTT1r57site-packages/pip/_internal/distributions/base.pynu„[µü¤PK·¶N]<':7site-packages/pip/_internal/distributions/source/__init__.pynu„[µü¤PK·¶N]öreªªZ“:7site-packages/pip/_internal/distributions/source/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK·¶N]ޜޞ�
�
RÇ;7site-packages/pip/_internal/distributions/source/__pycache__/legacy.cpython-38.pycnu„[µü¤PK·¶N]öreªªTØI7site-packages/pip/_internal/distributions/source/__pycache__/__init__.cpython-38.pycnu„[µü¤PK·¶N]ޜޞ�
�
XK7site-packages/pip/_internal/distributions/source/__pycache__/legacy.cpython-38.opt-1.pycnu„[µü¤PK·¶N]ƒçee:Y7site-packages/pip/_internal/distributions/source/legacy.pynu„[µü¤PK·¶N]ð/ÆRCRC-ìh7site-packages/pip/_internal/legacy_resolve.pynu„[µü¤PK·¶N]�J22/›¬7site-packages/pip/_internal/network/__init__.pynu„[µü¤PK·¶N]7SÐI,­7site-packages/pip/_internal/network/__pycache__/auth.cpython-38.opt-1.pycnu„[µü¤PK·¶N]ü;Ž&&K$È7site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-38.opt-1.pycnu„[µü¤PK·¶N]ÿ8Ml
$
$FÅÎ7site-packages/pip/_internal/network/__pycache__/session.cpython-38.pycnu„[µü¤PK·¶N]Sš›ÔÔMEó7site-packages/pip/_internal/network/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK·¶N]±*‹9¹	¹	D–ô7site-packages/pip/_internal/network/__pycache__/cache.cpython-38.pycnu„[µü¤PK·¶N]óŸ}v	v	JÃþ7site-packages/pip/_internal/network/__pycache__/cache.cpython-38.opt-1.pycnu„[µü¤PK·¶N]Sš›ÔÔG³8site-packages/pip/_internal/network/__pycache__/__init__.cpython-38.pycnu„[µü¤PK·¶N]ÿ8Ml
$
$Lþ	8site-packages/pip/_internal/network/__pycache__/session.cpython-38.opt-1.pycnu„[µü¤PK·¶N]‰Î˼BBC„.8site-packages/pip/_internal/network/__pycache__/auth.cpython-38.pycnu„[µü¤PK·¶N]ü;Ž&&E9J8site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-38.pycnu„[µü¤PK·¶N]ÉJþ¹¹,ÔP8site-packages/pip/_internal/network/cache.pynu„[µü¤PK·¶N]-cÞ==-éY8site-packages/pip/_internal/network/xmlrpc.pynu„[µü¤PK·¶N]t3�o+o++ƒ`8site-packages/pip/_internal/network/auth.pynu„[µü¤PK·¶N]_##Hâ=â=.MŒ8site-packages/pip/_internal/network/session.pynu„[µü¤PK·¶N]Öï&(()�Ê8site-packages/pip/_internal/exceptions.pynu„[µü¤PK·¶N]�}t&&(íò8site-packages/pip/_internal/locations.pynu„[µü¤PK·¶N]¿?äEQEQ'k9site-packages/pip/_internal/download.pynu„[µü¤PK·¶N]|ªH¨H¨$Z9site-packages/pip/_internal/wheel.pynu„[µü¤PK¸¶N]Á6røPP'£:site-packages/pip/_internal/__init__.pynu„[µü¤PK¸¶N]t1�ß:&:&AJ:site-packages/pip/_internal/__pycache__/pep425tags.cpython-38.pycnu„[µü¤PK¸¶N]œÈ3gll@õ):site-packages/pip/_internal/__pycache__/pyproject.cpython-38.pycnu„[µü¤PK¸¶N]›	÷))EÑ6:site-packages/pip/_internal/__pycache__/legacy_resolve.cpython-38.pycnu„[µü¤PK¸¶N]&$>>FJ`:site-packages/pip/_internal/__pycache__/pyproject.cpython-38.opt-1.pycnu„[µü¤PK¹¶N]ÜñÐÐEþl:site-packages/pip/_internal/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK¹¶N]goj]FCn:site-packages/pip/_internal/__pycache__/build_env.cpython-38.opt-1.pycnu„[µü¤PK¹¶N]m"äù%%<Ç‹:site-packages/pip/_internal/__pycache__/cache.cpython-38.pycnu„[µü¤PK¹¶N]ÿó…·,·,?X¨:site-packages/pip/_internal/__pycache__/download.cpython-38.pycnu„[µü¤PKº¶N]ú"q’’J~Õ:site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-38.pycnu„[µü¤PKº¶N][lä:&:&GŠë:site-packages/pip/_internal/__pycache__/pep425tags.cpython-38.opt-1.pycnu„[µü¤PKº¶N]“ Vÿ77F;;site-packages/pip/_internal/__pycache__/collector.cpython-38.opt-1.pycnu„[µü¤PK»¶N]†$cN¦b¦bBÃI;site-packages/pip/_internal/__pycache__/index.cpython-38.opt-1.pycnu„[µü¤PK»¶N]Ö^=2úúBÛ¬;site-packages/pip/_internal/__pycache__/cache.cpython-38.opt-1.pycnu„[µü¤PK»¶N]ùcYé•)•)DGÉ;site-packages/pip/_internal/__pycache__/configuration.cpython-38.pycnu„[µü¤PK»¶N]Ø
4_\(\(KPó;site-packages/pip/_internal/__pycache__/legacy_resolve.cpython-38.opt-1.pycnu„[µü¤PK¼¶N]±4Í,,@'<site-packages/pip/_internal/__pycache__/build_env.cpython-38.pycnu„[µü¤PK¼¶N]Hx‚=)=)JÃ9<site-packages/pip/_internal/__pycache__/configuration.cpython-38.opt-1.pycnu„[µü¤PK¼¶N]Žå2gööFzc<site-packages/pip/_internal/__pycache__/locations.cpython-38.opt-1.pycnu„[µü¤PK¼¶N]— ¼uùù;æo<site-packages/pip/_internal/__pycache__/main.cpython-38.pycnu„[µü¤PK¼¶N]�¦
Q™,™,EJu<site-packages/pip/_internal/__pycache__/download.cpython-38.opt-1.pycnu„[µü¤PK¼¶N]ú"q’’PX¢<site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-38.opt-1.pycnu„[µü¤PK¼¶N]ÈJèÂ0Â0Aj¸<site-packages/pip/_internal/__pycache__/exceptions.cpython-38.pycnu„[µü¤PK¼¶N]:†™pp@�é<site-packages/pip/_internal/__pycache__/locations.cpython-38.pycnu„[µü¤PK¼¶N]ÜñÐÐ?}ö<site-packages/pip/_internal/__pycache__/__init__.cpython-38.pycnu„[µü¤PK¼¶N]•´qð¢0¢0G¼÷<site-packages/pip/_internal/__pycache__/exceptions.cpython-38.opt-1.pycnu„[µü¤PK¼¶N]h,7çbçb<Õ(=site-packages/pip/_internal/__pycache__/index.cpython-38.pycnu„[µü¤PK¼¶N]$0éU¨m¨m<(Œ=site-packages/pip/_internal/__pycache__/wheel.cpython-38.pycnu„[µü¤PK¼¶N]— ¼uùùA<ú=site-packages/pip/_internal/__pycache__/main.cpython-38.opt-1.pycnu„[µü¤PK¼¶N]“ Vÿ77@¦ÿ=site-packages/pip/_internal/__pycache__/collector.cpython-38.pycnu„[µü¤PK¼¶N]ôÀ›†½l½lB(7>site-packages/pip/_internal/__pycache__/wheel.cpython-38.opt-1.pycnu„[µü¤PK¼¶N]0;Ïœ³ ³ $W¤>site-packages/pip/_internal/cache.pynu„[µü¤PK¼¶N]p�ß]](^Å>site-packages/pip/_internal/build_env.pynu„[µü¤PK¼¶N]‰]$çöö0ã>site-packages/pip/_internal/utils/deprecation.pynu„[µü¤PK¼¶N]%o8G´´+ið>site-packages/pip/_internal/utils/hashes.pynu„[µü¤PK¼¶N]a�2�

/x?site-packages/pip/_internal/utils/filesystem.pynu„[µü¤PK¼¶N]«‡=Î||+Ý
?site-packages/pip/_internal/utils/models.pynu„[µü¤PK¼¶N]—^‡÷771´?site-packages/pip/_internal/utils/marker_files.pynu„[µü¤PK¼¶N]çšy;;.L?site-packages/pip/_internal/utils/filetypes.pynu„[µü¤PK¼¶N]-å?site-packages/pip/_internal/utils/__init__.pynu„[µü¤PK¼¶N]—´/~êêMB?site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-38.pycnu„[µü¤PK¼¶N]˜[¬ÉÕ
Õ
G©?site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-38.pycnu„[µü¤PK¼¶N]*hФ¤Sõ)?site-packages/pip/_internal/utils/__pycache__/inject_securetransport.cpython-38.pycnu„[µü¤PK¼¶N]ß”žõõK.?site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-38.opt-1.pycnu„[µü¤PK¼¶N]Íhpìë-ë-EŒA?site-packages/pip/_internal/utils/__pycache__/ui.cpython-38.opt-1.pycnu„[µü¤PK¼¶N]
®¾žÇ#Ç#Jìo?site-packages/pip/_internal/utils/__pycache__/logging.cpython-38.opt-1.pycnu„[µü¤PK½¶N]B‡´„„C-”?site-packages/pip/_internal/utils/__pycache__/models.cpython-38.pycnu„[µü¤PK½¶N]ö’N¡0
0
L$œ?site-packages/pip/_internal/utils/__pycache__/packaging.cpython-38.opt-1.pycnu„[µü¤PK½¶N]œù.‹ÞÞGЦ?site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-38.pycnu„[µü¤PK½¶N]œù.‹ÞÞM%½?site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-38.opt-1.pycnu„[µü¤PK½¶N]�aõÑÑB€Ó?site-packages/pip/_internal/utils/__pycache__/glibc.cpython-38.pycnu„[µü¤PK½¶N]
®¾žÇ#Ç#DÃÜ?site-packages/pip/_internal/utils/__pycache__/logging.cpython-38.pycnu„[µü¤PK½¶N]>&k
--Lþ@site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-38.opt-1.pycnu„[µü¤PK½¶N]’T]V[V[A§@site-packages/pip/_internal/utils/__pycache__/misc.cpython-38.pycnu„[µü¤PK½¶N]*hФ¤Ynu@site-packages/pip/_internal/utils/__pycache__/inject_securetransport.cpython-38.opt-1.pycnu„[µü¤PK½¶N]z6:Ù  O›y@site-packages/pip/_internal/utils/__pycache__/marker_files.cpython-38.opt-1.pycnu„[µü¤PK½¶N]QdC››Kº}@site-packages/pip/_internal/utils/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK½¶N]ykÂ,,LÐ~@site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-38.opt-1.pycnu„[µü¤PK½¶N]ЧîòOOEx�@site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-38.pycnu„[µü¤PK½¶N]’T]V[V[G<•@site-packages/pip/_internal/utils/__pycache__/misc.cpython-38.opt-1.pycnu„[µü¤PK½¶N]�aõÑÑH	ñ@site-packages/pip/_internal/utils/__pycache__/glibc.cpython-38.opt-1.pycnu„[µü¤PK½¶N]…
Ò`¹¹ARú@site-packages/pip/_internal/utils/__pycache__/urls.cpython-38.pycnu„[µü¤PK½¶N]8óNXßßE|Asite-packages/pip/_internal/utils/__pycache__/encoding.cpython-38.pycnu„[µü¤PK½¶N]˜[¬ÉÕ
Õ
MÐAsite-packages/pip/_internal/utils/__pycache__/filesystem.cpython-38.opt-1.pycnu„[µü¤PK½¶N]ezû00C"Asite-packages/pip/_internal/utils/__pycache__/hashes.cpython-38.pycnu„[µü¤PK½¶N]p»é§".".?Å!Asite-packages/pip/_internal/utils/__pycache__/ui.cpython-38.pycnu„[µü¤PKÀ¶N]Šó”#

HVPAsite-packages/pip/_internal/utils/__pycache__/deprecation.cpython-38.pycnu„[µü¤PKÀ¶N]ö’N¡0
0
FØ[Asite-packages/pip/_internal/utils/__pycache__/packaging.cpython-38.pycnu„[µü¤PKÀ¶N]y»ˆ§kkD~fAsite-packages/pip/_internal/utils/__pycache__/appdirs.cpython-38.pycnu„[µü¤PKÀ¶N]ezû00I]†Asite-packages/pip/_internal/utils/__pycache__/hashes.cpython-38.opt-1.pycnu„[µü¤PKÀ¶N]PAkË··C—Asite-packages/pip/_internal/utils/__pycache__/compat.cpython-38.pycnu„[µü¤PKÀ¶N]PAkË··I0²Asite-packages/pip/_internal/utils/__pycache__/compat.cpython-38.opt-1.pycnu„[µü¤PKÀ¶N]�gÉ{nnM`ÍAsite-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-38.opt-1.pycnu„[µü¤PKÀ¶N]8óNXßßKKÑAsite-packages/pip/_internal/utils/__pycache__/encoding.cpython-38.opt-1.pycnu„[µü¤PKÀ¶N]z6:Ù  I¥ÖAsite-packages/pip/_internal/utils/__pycache__/marker_files.cpython-38.pycnu„[µü¤PKÁ¶N]uߥVC¾ÚAsite-packages/pip/_internal/utils/__pycache__/typing.cpython-38.pycnu„[µü¤PKÁ¶N]—´/~êêS6àAsite-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-38.opt-1.pycnu„[µü¤PKÁ¶N]uߥVI£åAsite-packages/pip/_internal/utils/__pycache__/typing.cpython-38.opt-1.pycnu„[µü¤PKÁ¶N]�gÉ{nnG!ëAsite-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-38.pycnu„[µü¤PKÁ¶N]>&k
--FïAsite-packages/pip/_internal/utils/__pycache__/unpacking.cpython-38.pycnu„[µü¤PKÁ¶N]QdC››E©Bsite-packages/pip/_internal/utils/__pycache__/__init__.cpython-38.pycnu„[µü¤PKÁ¶N]Šó”#

N¹Bsite-packages/pip/_internal/utils/__pycache__/deprecation.cpython-38.opt-1.pycnu„[µü¤PKÁ¶N]y»ˆ§kkJABsite-packages/pip/_internal/utils/__pycache__/appdirs.cpython-38.opt-1.pycnu„[µü¤PKÁ¶N]”c"­FFG&4Bsite-packages/pip/_internal/utils/__pycache__/urls.cpython-38.opt-1.pycnu„[µü¤PKÁ¶N]ykÂ,,Fã9Bsite-packages/pip/_internal/utils/__pycache__/filetypes.cpython-38.pycnu„[µü¤PKÁ¶N]B‡´„„I…__5Ý3Csite-packages/pip/_internal/utils/setuptools_build.pynu„[µü¤PK¶N]€ðN·Ò%Ò%.¡:Csite-packages/pip/_internal/utils/unpacking.pynu„[µü¤PK¶N]H±Ðûëcëc)Ñ`Csite-packages/pip/_internal/utils/misc.pynu„[µü¤PK¶N]S:ѰÉÉ)ÅCsite-packages/pip/_internal/utils/urls.pynu„[µü¤PK¶N]…e4•é2é2,7ËCsite-packages/pip/_internal/utils/logging.pynu„[µü¤PK¶N]$¸à55&|þCsite-packages/pip/_internal/vcs/git.pynu„[µü¤PK¶N]_îÁQii+Ò3Dsite-packages/pip/_internal/vcs/__init__.pynu„[µü¤PK¶N]šESzÍ#Í#D–6Dsite-packages/pip/_internal/vcs/__pycache__/git.cpython-38.opt-1.pycnu„[µü¤PK¶N]8Ã&¬'!'!E×ZDsite-packages/pip/_internal/vcs/__pycache__/subversion.cpython-38.pycnu„[µü¤PK¶N]8Ã&¬'!'!Ks|Dsite-packages/pip/_internal/vcs/__pycache__/subversion.cpython-38.opt-1.pycnu„[µü¤PK¶N]cî¥ÀÀIžDsite-packages/pip/_internal/vcs/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK¶N].­dˆHHIN Dsite-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-38.pycnu„[µü¤PK¶N]…x$$>äèDsite-packages/pip/_internal/vcs/__pycache__/git.cpython-38.pycnu„[µü¤PK¶N]$XíÙDW
Esite-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-38.pycnu„[µü¤PK¶N].­dˆHHOã Esite-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-38.opt-1.pycnu„[µü¤PK¶N]cî¥ÀÀCiEsite-packages/pip/_internal/vcs/__pycache__/__init__.cpython-38.pycnu„[µü¤PK¶N]IÒ4ø££G²kEsite-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-38.opt-1.pycnu„[µü¤PK¶N]$XíÙJÌzEsite-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-38.opt-1.pycnu„[µü¤PK¶N]IÒ4ø££A^ŽEsite-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-38.pycnu„[µü¤PK¶N]ë…¤!uu)r�Esite-packages/pip/_internal/vcs/bazaar.pynu„[µü¤PK¶N]©qQ‰~S~S1@­Esite-packages/pip/_internal/vcs/versioncontrol.pynu„[µü¤PK¶N]pCöö,Fsite-packages/pip/_internal/vcs/mercurial.pynu„[µü¤PK¶N]ó_«00-qFsite-packages/pip/_internal/vcs/subversion.pynu„[µü¤PK¶N]i6µSE>E>)ÒEFsite-packages/pip/_internal/pep425tags.pynu„[µü¤PK¶N]ÜñÖ`þþ2p„Fsite-packages/pip/_internal/self_outdated_check.pynu„[µü¤PK¶N]æ]ôZZ(УFsite-packages/pip/_internal/pyproject.pynu„[µü¤PK¶N]Ð5×µŠ7Š7,‚½Fsite-packages/pip/_internal/configuration.pynu„[µü¤PK¶N]2hõFsite-packages/pip/_internal/operations/__init__.pynu„[µü¤PK¶N]/ü  PÊõFsite-packages/pip/_internal/operations/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK¶N]O¤f¯HHGêöFsite-packages/pip/_internal/operations/__pycache__/check.cpython-38.pycnu„[µü¤PK¶N]O¤f¯HHM©Gsite-packages/pip/_internal/operations/__pycache__/check.cpython-38.opt-1.pycnu„[µü¤PK¶N].°º!bbNnGsite-packages/pip/_internal/operations/__pycache__/freeze.cpython-38.opt-1.pycnu„[µü¤PKöN]wí€ú33YN+Gsite-packages/pip/_internal/operations/__pycache__/generate_metadata.cpython-38.opt-1.pycnu„[µü¤PKöN]/ü  J
;Gsite-packages/pip/_internal/operations/__pycache__/__init__.cpython-38.pycnu„[µü¤PKöN].°º!bbH$b&b&0½Gsite-packages/pip/_internal/operations/freeze.pynu„[µü¤PKöN]…§{êê/ßãGsite-packages/pip/_internal/operations/check.pynu„[µü¤PKöN]j׿[[;(ùGsite-packages/pip/_internal/operations/generate_metadata.pynu„[µü¤PKöN]Û¬wöœœ/îHsite-packages/pip/_internal/cli/status_codes.pynu„[µü¤PKöN]ûÌð.éHsite-packages/pip/_internal/cli/main_parser.pynu„[µü¤PKöN]Îwê4„„+JHsite-packages/pip/_internal/cli/__init__.pynu„[µü¤PKöN]˜j~õ"õ"G)Hsite-packages/pip/_internal/cli/__pycache__/parser.cpython-38.opt-1.pycnu„[µü¤PKöN]›ÊEììI•4)4),mMsite-packages/pip/_internal/commands/list.pynu„[µü¤PKĶN]•ï_ï_/�–Msite-packages/pip/_internal/commands/install.pynu„[µü¤PKĶN]ÝR‰Záá-ÞöMsite-packages/pip/_internal/commands/check.pynu„[µü¤PKĶN]VÍп::5ýMsite-packages/pip/_internal/commands/configuration.pynu„[µü¤PKĶN]å«Û	B
B
-»Nsite-packages/pip/_internal/commands/debug.pynu„[µü¤PKŶN](ú£���,Z'Nsite-packages/pip/_internal/commands/help.pynu„[µü¤PKŶN]€¶§Bˆˆ,S,Nsite-packages/pip/_internal/commands/show.pynu„[µü¤PKŶN]Ò‰ÙŸŸ27GNsite-packages/pip/_internal/commands/completion.pynu„[µü¤PKŶN]„B§§18SNsite-packages/pip/_internal/commands/uninstall.pynu„[µü¤PKŶN](é³OO#@_Nsite-packages/pip/_internal/main.pynu„[µü¤PKŶN]Ì©Ã[��$âdNsite-packages/pip/_internal/index.pynu„[µü¤PKŶN]JUÿKƒƒ2MõNsite-packages/pip/_internal/models/search_scope.pynu„[µü¤PKŶN]wbw 
 
42Osite-packages/pip/_internal/models/format_control.pynu„[µü¤PKŶN]{É(þ??.¶Osite-packages/pip/_internal/models/__init__.pynu„[µü¤PKŶN]¶}¨ë²²MSOsite-packages/pip/_internal/models/__pycache__/candidate.cpython-38.opt-1.pycnu„[µü¤PKŶN]‘@Î<³³J‚Osite-packages/pip/_internal/models/__pycache__/search_scope.cpython-38.pycnu„[µü¤PKŶN]à¯�ààL¯#Osite-packages/pip/_internal/models/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKŶN]Mw£zzI%Osite-packages/pip/_internal/models/__pycache__/index.cpython-38.opt-1.pycnu„[µü¤PKŶN]ªÉ+0€€Kþ)Osite-packages/pip/_internal/models/__pycache__/target_python.cpython-38.pycnu„[µü¤PKŶN]k-úûýýBù6Osite-packages/pip/_internal/models/__pycache__/link.cpython-38.pycnu„[µü¤PKŶN]| ¼
p	p	RhQOsite-packages/pip/_internal/models/__pycache__/format_control.cpython-38.opt-1.pycnu„[µü¤PKŶN]÷BhŠ<<MZ[Osite-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-38.pycnu„[µü¤PKŶN]| ¼
p	p	LbOsite-packages/pip/_internal/models/__pycache__/format_control.cpython-38.pycnu„[µü¤PKŶN]à¯�ààFÿkOsite-packages/pip/_internal/models/__pycache__/__init__.cpython-38.pycnu„[µü¤PKŶN]‘@Î<³³PUmOsite-packages/pip/_internal/models/__pycache__/search_scope.cpython-38.opt-1.pycnu„[µü¤PKŶN]Mw£zzCˆzOsite-packages/pip/_internal/models/__pycache__/index.cpython-38.pycnu„[µü¤PKŶN]ªÉ+0€€QuOsite-packages/pip/_internal/models/__pycache__/target_python.cpython-38.opt-1.pycnu„[µü¤PKŶN]¶}¨ë²²GvŒOsite-packages/pip/_internal/models/__pycache__/candidate.cpython-38.pycnu„[µü¤PKŶN]ß‚m��HŸ’Osite-packages/pip/_internal/models/__pycache__/link.cpython-38.opt-1.pycnu„[µü¤PKŶN]÷BhŠ<<S¦¬Osite-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-38.opt-1.pycnu„[µü¤PKŶN]Ó]'Øtt5e³Osite-packages/pip/_internal/models/selection_prefs.pynu„[µü¤PKŶN]¾/�týý/>»Osite-packages/pip/_internal/models/candidate.pynu„[µü¤PKŶN]pëìì3šÀOsite-packages/pip/_internal/models/target_python.pynu„[µü¤PKŶN]žP²ÝÌÌ*éÏOsite-packages/pip/_internal/models/link.pynu„[µü¤PKŶN]Fâ+$$+ëOsite-packages/pip/_internal/models/index.pynu„[µü¤PKŶN]s÷@=��.ŽïOsite-packages/pip/_internal/req/req_install.pynu„[µü¤PKŶN]ÊÙú¬£	£	+Psite-packages/pip/_internal/req/__init__.pynu„[µü¤PKŶN]ê[_ß�C�CN‰Psite-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-38.opt-1.pycnu„[µü¤PKŶN]óLG‚¬]¬]F ÍPsite-packages/pip/_internal/req/__pycache__/req_install.cpython-38.pycnu„[µü¤PKŶN]zØ;òDDHB+Qsite-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-38.pycnu„[µü¤PKŶN]cÑ���BÒoQsite-packages/pip/_internal/req/__pycache__/req_set.cpython-38.pycnu„[µü¤PKŶN]øéÝMt(t(Má‡Qsite-packages/pip/_internal/req/__pycache__/constructors.cpython-38.opt-1.pycnu„[µü¤PKŶN]€PAú¤¤IÒ°Qsite-packages/pip/_internal/req/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKŶN]Ì[FI[I[Lï·Qsite-packages/pip/_internal/req/__pycache__/req_install.cpython-38.opt-1.pycnu„[µü¤PKŶN]:Ñ
_À$À$C´Rsite-packages/pip/_internal/req/__pycache__/req_file.cpython-38.pycnu„[µü¤PKŶN]5%yR……Fç8Rsite-packages/pip/_internal/req/__pycache__/req_tracker.cpython-38.pycnu„[µü¤PKŶN]:Ñ
_À$À$IâERsite-packages/pip/_internal/req/__pycache__/req_file.cpython-38.opt-1.pycnu„[µü¤PKŶN]5(…eeLkRsite-packages/pip/_internal/req/__pycache__/req_tracker.cpython-38.opt-1.pycnu„[µü¤PKƶN]€PAú¤¤CüwRsite-packages/pip/_internal/req/__pycache__/__init__.cpython-38.pycnu„[µü¤PKƶN]¿Z±¢ççHRsite-packages/pip/_internal/req/__pycache__/req_set.cpython-38.opt-1.pycnu„[µü¤PKƶN]øéÝMt(t(Gr–Rsite-packages/pip/_internal/req/__pycache__/constructors.cpython-38.pycnu„[µü¤PKƶN]ƒ‚4848/]¿Rsite-packages/pip/_internal/req/constructors.pynu„[µü¤PKƶN]Þ¾Ó&\&\0ð÷Rsite-packages/pip/_internal/req/req_uninstall.pynu„[µü¤PKƶN]pÒÄÄ*vTSsite-packages/pip/_internal/req/req_set.pynu„[µü¤PKƶN]N�Ê{{.”tSsite-packages/pip/_internal/req/req_tracker.pynu„[µü¤PKƶN]PR6�Ö7Ö7+m�Ssite-packages/pip/_internal/req/req_file.pynu„[µü¤PKƶN]½ÀŠž¹Ssite-packages/pip/__init__.pynu„[µü¤PKƶN]³ákx¡¡;ºSsite-packages/pip/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKƶN]-Ð¥Ó¢¢5»Ssite-packages/pip/__pycache__/__main__.cpython-38.pycnu„[µü¤PKƶN]-Ð¥Ó¢¢;½Ssite-packages/pip/__pycache__/__main__.cpython-38.opt-1.pycnu„[µü¤PKƶN]³ákx¡¡5"¿Ssite-packages/pip/__pycache__/__init__.cpython-38.pycnu„[µü¤PKƶN]áÅ
g)g),(ÀSsite-packages/pip/_vendor/pep517/wrappers.pynu„[µü¤PKƶN]/ì°¬öö)ëéSsite-packages/pip/_vendor/pep517/build.pynu„[µü¤PKƶN].RÃÚTT,:÷Ssite-packages/pip/_vendor/pep517/__init__.pynu„[µü¤PKƶN]áM-ž'ž'Jê÷Ssite-packages/pip/_vendor/pep517/__pycache__/wrappers.cpython-38.opt-1.pycnu„[µü¤PKƶN]AײS""J Tsite-packages/pip/_vendor/pep517/__pycache__/envbuild.cpython-38.opt-1.pycnu„[µü¤PKƶN]K«Í˜

Gž1Tsite-packages/pip/_vendor/pep517/__pycache__/build.cpython-38.opt-1.pycnu„[µü¤PKǶN]ë‹pööJ?Tsite-packages/pip/_vendor/pep517/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKǶN]AfÝrddD‹@Tsite-packages/pip/_vendor/pep517/__pycache__/colorlog.cpython-38.pycnu„[µü¤PKǶN]AײS""DcLTsite-packages/pip/_vendor/pep517/__pycache__/envbuild.cpython-38.pycnu„[µü¤PKǶN]Чÿ·Gù]Tsite-packages/pip/_vendor/pep517/__pycache__/_in_process.cpython-38.pycnu„[µü¤PKǶN]AfÝrddJu{Tsite-packages/pip/_vendor/pep517/__pycache__/colorlog.cpython-38.opt-1.pycnu„[µü¤PKǶN]c›äB  AS‡Tsite-packages/pip/_vendor/pep517/__pycache__/check.cpython-38.pycnu„[µü¤PKǶN]ø9¸FdšTsite-packages/pip/_vendor/pep517/__pycache__/meta.cpython-38.opt-1.pycnu„[µü¤PKǶN]+¯1Jà¥Tsite-packages/pip/_vendor/pep517/__pycache__/dirtools.cpython-38.opt-1.pycnu„[µü¤PKǶN]áM-ž'ž'Di«Tsite-packages/pip/_vendor/pep517/__pycache__/wrappers.cpython-38.pycnu„[µü¤PKǶN]c›äB  G{ÓTsite-packages/pip/_vendor/pep517/__pycache__/check.cpython-38.opt-1.pycnu„[µü¤PKǶN]“ûCÔõõB’æTsite-packages/pip/_vendor/pep517/__pycache__/compat.cpython-38.pycnu„[µü¤PKǶN]“ûCÔõõHùêTsite-packages/pip/_vendor/pep517/__pycache__/compat.cpython-38.opt-1.pycnu„[µü¤PKǶN]Чÿ·MfïTsite-packages/pip/_vendor/pep517/__pycache__/_in_process.cpython-38.opt-1.pycnu„[µü¤PKǶN]ø9¸@èUsite-packages/pip/_vendor/pep517/__pycache__/meta.cpython-38.pycnu„[µü¤PKǶN]ë‹pööD^Usite-packages/pip/_vendor/pep517/__pycache__/__init__.cpython-38.pycnu„[µü¤PKǶN]K«Í˜

AÈUsite-packages/pip/_vendor/pep517/__pycache__/build.cpython-38.pycnu„[µü¤PKǶN]+¯1D?'Usite-packages/pip/_vendor/pep517/__pycache__/dirtools.cpython-38.pycnu„[µü¤PKǶN]Ê]*Â,Usite-packages/pip/_vendor/pep517/compat.pynu„[µü¤PKǶN]º‰N==)(0Usite-packages/pip/_vendor/pep517/check.pynu„[µü¤PKǶN]ÓÉ�˜ˆˆ,¾GUsite-packages/pip/_vendor/pep517/envbuild.pynu„[µü¤PKǶN];ϸFii,¢_Usite-packages/pip/_vendor/pep517/dirtools.pynu„[µü¤PKǶN]W9çpp/gdUsite-packages/pip/_vendor/pep517/_in_process.pynu„[µü¤PKǶN]—»éÞŸ	Ÿ	(6ƒUsite-packages/pip/_vendor/pep517/meta.pynu„[µü¤PKǶN]
±VÐ,-�Usite-packages/pip/_vendor/pep517/colorlog.pynu„[µü¤PKǶN]0)­ë,,&‹�Usite-packages/pip/_vendor/pyparsing.pynu„[µü¤PKǶN]·fcͦͦ3
£Ysite-packages/pip/_vendor/pkg_resources/__init__.pynu„[µü¤PKǶN]¹ø1�ȇȇQ=J[site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKǶN]ñmv­ddS†Ò\site-packages/pip/_vendor/pkg_resources/__pycache__/py31compat.cpython-38.opt-1.pycnu„[µü¤PKǶN]¹ø1�ȇȇKmÕ\site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-38.pycnu„[µü¤PKǶN]ñmv­ddM°]^site-packages/pip/_vendor/pkg_resources/__pycache__/py31compat.cpython-38.pycnu„[µü¤PKǶN]a$Ö225‘`^site-packages/pip/_vendor/pkg_resources/py31compat.pynu„[µü¤PKǶN].�‹"ì7ì7&(c^site-packages/pip/_vendor/ipaddress.pynu„[µü¤PKǶN]!{¼
ô&ô&%j›_site-packages/pip/_vendor/retrying.pynu„[µü¤PKǶN]iöá‰c‰c+³Â_site-packages/pip/_vendor/chardet/mbcssm.pynu„[µü¤PKǶN]"Ò?,,2—&`site-packages/pip/_vendor/chardet/langthaimodel.pynu„[µü¤PKȶN]6uMU
U
4S`site-packages/pip/_vendor/chardet/mbcharsetprober.pynu„[µü¤PKȶN]ôAyê4ê4.Ì``site-packages/pip/_vendor/chardet/euckrfreq.pynu„[µü¤PKȶN]àY(=Ã$Ã$5–`site-packages/pip/_vendor/chardet/chardistribution.pynu„[µü¤PKȶN]­Ó¨ÜÜ4<»`site-packages/pip/_vendor/chardet/mbcsgroupprober.pynu„[µü¤PKɶN]µ2Ãd^+^+5|Ã`site-packages/pip/_vendor/chardet/langturkishmodel.pynu„[µü¤PKɶN]þ»¯)�1�13?ï`site-packages/pip/_vendor/chardet/langgreekmodel.pynu„[µü¤PKɶN]~«þ�ÚÚ12!asite-packages/pip/_vendor/chardet/gb2312prober.pynu„[µü¤PKɶN]EÒ×ëPëP/m(asite-packages/pip/_vendor/chardet/gb2312freq.pynu„[µü¤PKɶN]ðÏS-·yasite-packages/pip/_vendor/chardet/__init__.pynu„[µü¤PKɶN]{ø¦¦L+€asite-packages/pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-38.pycnu„[µü¤PKɶN]$¹[z
j
jLMŒasite-packages/pip/_vendor/chardet/__pycache__/euctwfreq.cpython-38.opt-1.pycnu„[µü¤PKɶN]):±é’	’	MÓöasite-packages/pip/_vendor/chardet/__pycache__/sjisprober.cpython-38.opt-1.pycnu„[µü¤PKɶN]gYjïv
v
Jâbsite-packages/pip/_vendor/chardet/__pycache__/charsetprober.cpython-38.pycnu„[µü¤PKɶN]V�TTFFLÒbsite-packages/pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-38.pycnu„[µü¤PKɶN]O€Ð¸ú.ú.F”bsite-packages/pip/_vendor/chardet/__pycache__/euckrfreq.cpython-38.pycnu„[µü¤PKɶN]ðVµ¢¢TCbsite-packages/pip/_vendor/chardet/__pycache__/universaldetector.cpython-38.opt-1.pycnu„[µü¤PKɶN]i'-''S*Zbsite-packages/pip/_vendor/chardet/__pycache__/chardistribution.cpython-38.opt-1.pycnu„[µü¤PKɶN]’³&X \ \UÔrbsite-packages/pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-38.opt-1.pycnu„[µü¤PKɶN]�‘ô3
3
ByÏbsite-packages/pip/_vendor/chardet/__pycache__/enums.cpython-38.pycnu„[µü¤PKɶN]{D$œ$
$
FÚbsite-packages/pip/_vendor/chardet/__pycache__/escprober.cpython-38.pycnu„[µü¤PKɶN]—"|&
&
O¸äbsite-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-38.opt-1.pycnu„[µü¤PKɶN]…M19�V�VJ]òbsite-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-38.pycnu„[µü¤PKɶN]7ë·óµµLfIcsite-packages/pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-38.pycnu„[µü¤PKɶN]V�TTFFR—Rcsite-packages/pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-38.opt-1.pycnu„[µü¤PKɶN]µS²±--K_Wcsite-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKɶN]�\�99U[csite-packages/pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-38.opt-1.pycnu„[µü¤PKɶN]7ë·óµµRÅfcsite-packages/pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-38.opt-1.pycnu„[µü¤PKɶN]¬Z,ƒqƒqTüocsite-packages/pip/_vendor/chardet/__pycache__/langcyrillicmodel.cpython-38.opt-1.pycnu„[µü¤PKɶN]¬Z,ƒqƒqNâcsite-packages/pip/_vendor/chardet/__pycache__/langcyrillicmodel.cpython-38.pycnu„[µü¤PKɶN]×R�bYYOTdsite-packages/pip/_vendor/chardet/__pycache__/gb2312prober.cpython-38.opt-1.pycnu„[µü¤PKɶN]#ÕS\MAMACÜXdsite-packages/pip/_vendor/chardet/__pycache__/mbcssm.cpython-38.pycnu„[µü¤PKɶN]{`Í~J~JMœšdsite-packages/pip/_vendor/chardet/__pycache__/gb2312freq.cpython-38.opt-1.pycnu„[µü¤PKɶN]ÝÓ²N

B—ådsite-packages/pip/_vendor/chardet/__pycache__/escsm.cpython-38.pycnu„[µü¤PKɶN]â~In	n	Hesite-packages/pip/_vendor/chardet/__pycache__/eucjpprober.cpython-38.pycnu„[µü¤PKɶN]ÅÁ¿QQNüesite-packages/pip/_vendor/chardet/__pycache__/euctwprober.cpython-38.opt-1.pycnu„[µü¤PKɶN]Uø¨\\QËesite-packages/pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-38.opt-1.pycnu„[µü¤PKɶN]õèþ¦¦OMnesite-packages/pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-38.pycnu„[µü¤PKɶN]]­¯¸QQNrwesite-packages/pip/_vendor/chardet/__pycache__/euckrprober.cpython-38.opt-1.pycnu„[µü¤PKɶN]È!±gÃ’Ã’CA|esite-packages/pip/_vendor/chardet/__pycache__/jpcntx.cpython-38.pycnu„[µü¤PKɶN]#ÕS\MAMAIwfsite-packages/pip/_vendor/chardet/__pycache__/mbcssm.cpython-38.opt-1.pycnu„[µü¤PKɶN]¿ÞÕVPPH=Qfsite-packages/pip/_vendor/chardet/__pycache__/cp949prober.cpython-38.pycnu„[µü¤PKɶN]â~In	n	NVfsite-packages/pip/_vendor/chardet/__pycache__/eucjpprober.cpython-38.opt-1.pycnu„[µü¤PKɶN]O€Ð¸ú.ú.Lñ_fsite-packages/pip/_vendor/chardet/__pycache__/euckrfreq.cpython-38.opt-1.pycnu„[µü¤PKɶN]È!±gÃ’Ã’Ig�fsite-packages/pip/_vendor/chardet/__pycache__/jpcntx.cpython-38.opt-1.pycnu„[µü¤PKɶN]Uø¨\\K£"gsite-packages/pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-38.pycnu„[µü¤PKɶN]{D$œ$
$
Lgsite-packages/pip/_vendor/chardet/__pycache__/escprober.cpython-38.opt-1.pycnu„[µü¤PKɶN]—"|&
&
I¿‰gsite-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-38.pycnu„[µü¤PKɶN]i'-''M^—gsite-packages/pip/_vendor/chardet/__pycache__/chardistribution.cpython-38.pycnu„[µü¤PKʶN]ÿ�•ØIIG°gsite-packages/pip/_vendor/chardet/__pycache__/big5prober.cpython-38.pycnu„[µü¤PKʶN]â„„Ø>>C´gsite-packages/pip/_vendor/chardet/__pycache__/compat.cpython-38.pycnu„[µü¤PKʶN]×R�bYYIs¶gsite-packages/pip/_vendor/chardet/__pycache__/gb2312prober.cpython-38.pycnu„[µü¤PKʶN]{ø¦¦RE»gsite-packages/pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-38.opt-1.pycnu„[µü¤PKʶN]â„„Ø>>ImÇgsite-packages/pip/_vendor/chardet/__pycache__/compat.cpython-38.opt-1.pycnu„[µü¤PKʶN]˜z9A¦V¦VS$Égsite-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-38.opt-1.pycnu„[µü¤PKʶN]bÁA-ªªIM hsite-packages/pip/_vendor/chardet/__pycache__/hebrewprober.cpython-38.pycnu„[µü¤PKʶN]ñU“££Mp,hsite-packages/pip/_vendor/chardet/__pycache__/utf8prober.cpython-38.opt-1.pycnu„[µü¤PKʶN]gYjïv
v
P�4hsite-packages/pip/_vendor/chardet/__pycache__/charsetprober.cpython-38.opt-1.pycnu„[µü¤PKʶN]ÿ�•ØIIM†Bhsite-packages/pip/_vendor/chardet/__pycache__/big5prober.cpython-38.opt-1.pycnu„[µü¤PKʶN]ñU“££GLGhsite-packages/pip/_vendor/chardet/__pycache__/utf8prober.cpython-38.pycnu„[µü¤PKʶN]’³&X \ \OfOhsite-packages/pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-38.pycnu„[µü¤PKʶN]]­¯¸QQH¬hsite-packages/pip/_vendor/chardet/__pycache__/euckrprober.cpython-38.pycnu„[µü¤PKʶN]µS²±--Eΰhsite-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-38.pycnu„[µü¤PKʶN]…M19�V�VPp´hsite-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-38.opt-1.pycnu„[µü¤PKʶN]bÁA-ªªOisite-packages/pip/_vendor/chardet/__pycache__/hebrewprober.cpython-38.opt-1.pycnu„[µü¤PKʶN]ëÄô’’J¨isite-packages/pip/_vendor/chardet/__pycache__/version.cpython-38.opt-1.pycnu„[µü¤PKʶN]):±é’	’	G´isite-packages/pip/_vendor/chardet/__pycache__/sjisprober.cpython-38.pycnu„[µü¤PKʶN]M}·õ+\+\U½#isite-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-38.opt-1.pycnu„[µü¤PKʶN]$¹[z
j
jFm€isite-packages/pip/_vendor/chardet/__pycache__/euctwfreq.cpython-38.pycnu„[µü¤PKʶN]Ò*™–RVRVJíêisite-packages/pip/_vendor/chardet/__pycache__/jisfreq.cpython-38.opt-1.pycnu„[µü¤PKʶN]l⤓88R¹Ajsite-packages/pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-38.opt-1.pycnu„[µü¤PKʶN]Ò*™–RVRVDsHjsite-packages/pip/_vendor/chardet/__pycache__/jisfreq.cpython-38.pycnu„[µü¤PKʶN]§—jmjjE9Ÿjsite-packages/pip/_vendor/chardet/__pycache__/big5freq.cpython-38.pycnu„[µü¤PKʶN]�‘ô3
3
H´	ksite-packages/pip/_vendor/chardet/__pycache__/enums.cpython-38.opt-1.pycnu„[µü¤PKʶN]ZË
¤V¤VR_ksite-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-38.opt-1.pycnu„[µü¤PKʶN]�\�99O…kksite-packages/pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-38.pycnu„[µü¤PKʶN]ÅÁ¿QQH=wksite-packages/pip/_vendor/chardet/__pycache__/euctwprober.cpython-38.pycnu„[µü¤PKʶN]ëÄô’’D|ksite-packages/pip/_vendor/chardet/__pycache__/version.cpython-38.pycnu„[µü¤PKʶN]õèþ¦¦U~ksite-packages/pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-38.opt-1.pycnu„[µü¤PKʶN]¿ÞÕVPPN7‡ksite-packages/pip/_vendor/chardet/__pycache__/cp949prober.cpython-38.opt-1.pycnu„[µü¤PKʶN]§—jmjjKŒksite-packages/pip/_vendor/chardet/__pycache__/big5freq.cpython-38.opt-1.pycnu„[µü¤PKʶN]M}·õ+\+\O†öksite-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-38.pycnu„[µü¤PKʶN]{`Í~J~JG0Slsite-packages/pip/_vendor/chardet/__pycache__/gb2312freq.cpython-38.pycnu„[µü¤PKʶN]ðVµ¢¢N%žlsite-packages/pip/_vendor/chardet/__pycache__/universaldetector.cpython-38.pycnu„[µü¤PKʶN]ÝÓ²N

HEµlsite-packages/pip/_vendor/chardet/__pycache__/escsm.cpython-38.opt-1.pycnu„[µü¤PKʶN]l⤓88LÊÒlsite-packages/pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-38.pycnu„[µü¤PKʶN]˜z9A¦V¦VM~Ùlsite-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-38.pycnu„[µü¤PKʶN]ZË
¤V¤VL¡0msite-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-38.pycnu„[µü¤PKʶN]ÌÛIÕ…{…{.Á‡msite-packages/pip/_vendor/chardet/euctwfreq.pynu„[µü¤PKʶN]‰Y$ˆËË7¤nsite-packages/pip/_vendor/chardet/charsetgroupprober.pynu„[µü¤PK˶N]D¬É}}*Önsite-packages/pip/_vendor/chardet/enums.pynu„[µü¤PK˶N]
)Ó²661­nsite-packages/pip/_vendor/chardet/hebrewprober.pynu„[µü¤PK˶N]ˆ=nn.Pnsite-packages/pip/_vendor/chardet/escprober.pynu„[µü¤PK˶N]|†åenn+è_nsite-packages/pip/_vendor/chardet/compat.pynu„[µü¤PK˶N]½Bš1??0±dnsite-packages/pip/_vendor/chardet/cp949prober.pynu„[µü¤PK˶N]Ö‘g2¾¾/Plnsite-packages/pip/_vendor/chardet/sjisprober.pynu„[µü¤PK˶N]Â9a±d±d,m{nsite-packages/pip/_vendor/chardet/jisfreq.pynu„[µü¤PK˶N]&—øÔÔ0zànsite-packages/pip/_vendor/chardet/euckrprober.pynu„[µü¤PK˶N] 7ÄÐ¥¥0®çnsite-packages/pip/_vendor/chardet/eucjpprober.pynu„[µü¤PK˶N]ËçgfÝÝ/³önsite-packages/pip/_vendor/chardet/big5prober.pynu„[µü¤PK˶N]uï4ïýnsite-packages/pip/_vendor/chardet/sbcharsetprober.pynu„[µü¤PK˶N]÷&´ŸÖ
Ö
3losite-packages/pip/_vendor/chardet/cli/chardetect.pynu„[µü¤PK˶N]“×21¥osite-packages/pip/_vendor/chardet/cli/__init__.pynu„[µü¤PK˶N]„°AПŸO osite-packages/pip/_vendor/chardet/cli/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK˶N](êï^d
d
K%!osite-packages/pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-38.pycnu„[µü¤PK˶N]„°AПŸI,osite-packages/pip/_vendor/chardet/cli/__pycache__/__init__.cpython-38.pycnu„[µü¤PK˶N](êï^d
d
Q-osite-packages/pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-38.opt-1.pycnu„[µü¤PK˶N]9¿„zz-8osite-packages/pip/_vendor/chardet/big5freq.pynu„[µü¤PK̶N]ŠþO Ú
Ú
4t²osite-packages/pip/_vendor/chardet/sbcsgroupprober.pynu„[µü¤PK̶N]ðhÉÊ'2'27²Àosite-packages/pip/_vendor/chardet/langbulgarianmodel.pynu„[µü¤PK̶N]ÈñV›FF6@óosite-packages/pip/_vendor/chardet/langcyrillicmodel.pynu„[µü¤PK̶N]äìð¤úú1Â9psite-packages/pip/_vendor/chardet/latin1prober.pynu„[µü¤PK̶N]à—aZöö2Opsite-packages/pip/_vendor/chardet/charsetprober.pynu„[µü¤PK̶N]ÃÁU€01017ucpsite-packages/pip/_vendor/chardet/langhungarianmodel.pynu„[µü¤PK̶N]Á
`¢))*•psite-packages/pip/_vendor/chardet/escsm.pynu„[µü¤PK̶N]õ¿¼=Î
Î
/t¾psite-packages/pip/_vendor/chardet/utf8prober.pynu„[µü¤PK̶N]y%j»L»L+¡Épsite-packages/pip/_vendor/chardet/jpcntx.pynu„[µü¤PK̶N]�f­Q,Q,4·qsite-packages/pip/_vendor/chardet/langhebrewmodel.pynu„[µü¤PK̶N]GÇ�×òò,lCqsite-packages/pip/_vendor/chardet/version.pynu„[µü¤PK̶N] A�ÓÓ0ºDqsite-packages/pip/_vendor/chardet/euctwprober.pynu„[µü¤PK̶N]\û7H7íKqsite-packages/pip/_vendor/chardet/codingstatemachine.pynu„[µü¤PK̶N]u€G=Å0Å06ZZqsite-packages/pip/_vendor/chardet/universaldetector.pynu„[µü¤PK̶N](�¢B.…‹qsite-packages/pip/_vendor/idna/package_data.pynu„[µü¤PK̶N]Ì04[ßß*ø‹qsite-packages/pip/_vendor/idna/idnadata.pynu„[µü¤PK̶N]G\›::*,rsite-packages/pip/_vendor/idna/__init__.pynu„[µü¤PK̶N]ÜT””+©,rsite-packages/pip/_vendor/idna/uts46data.pynu„[µü¤PK̶N]üQbŒD¨D¨C˜3usite-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-38.pycnu„[µü¤PK̶N]Â6+1#1#>OÜwsite-packages/pip/_vendor/idna/__pycache__/core.cpython-38.pycnu„[µü¤PK̶N]è`Zø¯¯Fîÿwsite-packages/pip/_vendor/idna/__pycache__/package_data.cpython-38.pycnu„[µü¤PK̶N]õ¨0ÝÝHxsite-packages/pip/_vendor/idna/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK̶N]mî*aSaSBhxsite-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-38.pycnu„[µü¤PK̶N]è`Zø¯¯L;Vxsite-packages/pip/_vendor/idna/__pycache__/package_data.cpython-38.opt-1.pycnu„[µü¤PK̶N]¿ÓXxííCfWxsite-packages/pip/_vendor/idna/__pycache__/intranges.cpython-38.pycnu„[µü¤PK̶N]1Y;;EÆ^xsite-packages/pip/_vendor/idna/__pycache__/codec.cpython-38.opt-1.pycnu„[µü¤PK̶N]Z3½QQ@vjxsite-packages/pip/_vendor/idna/__pycache__/compat.cpython-38.pycnu„[µü¤PK̶N]Z3½QQF7mxsite-packages/pip/_vendor/idna/__pycache__/compat.cpython-38.opt-1.pycnu„[µü¤PK̶N]üQbŒD¨D¨Iþoxsite-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-38.opt-1.pycnu„[µü¤PK̶N]Â6+1#1#D»{site-packages/pip/_vendor/idna/__pycache__/core.cpython-38.opt-1.pycnu„[µü¤PK̶N]õ¨0ÝÝB`<{site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-38.pycnu„[µü¤PK̶N]1Y;;?¯={site-packages/pip/_vendor/idna/__pycache__/codec.cpython-38.pycnu„[µü¤PK̶N]¿ÓXxííIYI{site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-38.opt-1.pycnu„[µü¤PK̶N]mî*aSaSH¿P{site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-38.opt-1.pycnu„[µü¤PK̶N]|�–pèè(˜¤{site-packages/pip/_vendor/idna/compat.pynu„[µü¤PK̶N]óHÔéãã'Ø¥{site-packages/pip/_vendor/idna/codec.pynu„[µü¤PK̶N]·cô²ÕÕ+³{site-packages/pip/_vendor/idna/intranges.pynu„[µü¤PK̶N]—ÙVÕ-Õ-&Bº{site-packages/pip/_vendor/idna/core.pynu„[µü¤PK̶N]ªMUM44-mè{site-packages/pip/_vendor/certifi/__init__.pynu„[µü¤PKͶN] õ‘‘Aþè{site-packages/pip/_vendor/certifi/__pycache__/core.cpython-38.pycnu„[µü¤PKͶN]^2ÈÎÜÜKë{site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKͶN]»ß¿—ßßEWì{site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-38.pycnu„[µü¤PKͶN]»ß¿—ßßK«í{site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-38.opt-1.pycnu„[µü¤PKͶN] õ‘‘Gï{site-packages/pip/_vendor/certifi/__pycache__/core.cpython-38.opt-1.pycnu„[µü¤PKͶN]^2ÈÎÜÜE
ñ{site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-38.pycnu„[µü¤PKͶN]	ïï55-^ò{site-packages/pip/_vendor/certifi/__main__.pynu„[µü¤PKͶN]\øÒø¼¼)ðò{site-packages/pip/_vendor/certifi/core.pynu„[µü¤PKͶN]b�š11%ô{site-packages/pip/_vendor/__init__.pynu„[µü¤PKͶN]xÇgó,‹|site-packages/pip/_vendor/pytoml/__init__.pynu„[µü¤PKͶN]ùÉpÁyyHf|site-packages/pip/_vendor/pytoml/__pycache__/writer.cpython-38.opt-1.pycnu„[µü¤PKͶN]:þÄ)••@W|site-packages/pip/_vendor/pytoml/__pycache__/core.cpython-38.pycnu„[µü¤PKͶN]a ósb'b'H\|site-packages/pip/_vendor/pytoml/__pycache__/parser.cpython-38.opt-1.pycnu„[µü¤PKͶN]÷”-ÃÃF6B|site-packages/pip/_vendor/pytoml/__pycache__/test.cpython-38.opt-1.pycnu„[µü¤PKͶN]ÛoŽ�TTJoG|site-packages/pip/_vendor/pytoml/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKͶN]a ósb'b'B=I|site-packages/pip/_vendor/pytoml/__pycache__/parser.cpython-38.pycnu„[µü¤PKͶN]:þÄ)••Fq|site-packages/pip/_vendor/pytoml/__pycache__/core.cpython-38.opt-1.pycnu„[µü¤PKͶN]ÛoŽ�TTDu|site-packages/pip/_vendor/pytoml/__pycache__/__init__.cpython-38.pycnu„[µü¤PKͶN]ùÉpÁyyBäv|site-packages/pip/_vendor/pytoml/__pycache__/writer.cpython-38.pycnu„[µü¤PKͶN]œ<ü“QQGÏ…|site-packages/pip/_vendor/pytoml/__pycache__/utils.cpython-38.opt-1.pycnu„[µü¤PKͶN]÷”-ÃÃ@—Ž|site-packages/pip/_vendor/pytoml/__pycache__/test.cpython-38.pycnu„[µü¤PKͶN]œ<ü“QQAÊ“|site-packages/pip/_vendor/pytoml/__pycache__/utils.cpython-38.pycnu„[µü¤PKͶN]GH¾¶E(E(*Œœ|site-packages/pip/_vendor/pytoml/parser.pynu„[µü¤PKͶN]­Üýý(+Å|site-packages/pip/_vendor/pytoml/test.pynu„[µü¤PKͶN]Î#p_)
)
*€É|site-packages/pip/_vendor/pytoml/writer.pynu„[µü¤PKͶN]âuÍ��)×|site-packages/pip/_vendor/pytoml/utils.pynu„[µü¤PKͶN]L;ù�ýý(ÝÝ|site-packages/pip/_vendor/pytoml/core.pynu„[µü¤PKͶN]ÜÌéÒÒ/2à|site-packages/pip/_vendor/urllib3/exceptions.pynu„[µü¤PKͶN]/ê]&ˆ	ˆ	-cú|site-packages/pip/_vendor/urllib3/filepost.pynu„[µü¤PKͶN]wÙ®B;B;/H}site-packages/pip/_vendor/urllib3/connection.pynu„[µü¤PKͶN]ĸ;;(*(*1é?}site-packages/pip/_vendor/urllib3/_collections.pynu„[µü¤PKͶN]ëÀó©{
{
-rj}site-packages/pip/_vendor/urllib3/__init__.pynu„[µü¤PKͶN]KC*‚‚,Ju}site-packages/pip/_vendor/urllib3/request.pynu„[µü¤PKͶN] 'vØ]Ø]Q(�}site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-38.opt-1.pycnu„[µü¤PKͶN]dí�0ööJ�ë}site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-38.opt-1.pycnu„[µü¤PKͶN]dí�0ööDñ~site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-38.pycnu„[µü¤PKͶN]!ç%%K[~site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKͶN]”Å‹�)�)Oû ~site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-38.opt-1.pycnu„[µü¤PKͶN]Í7«}®
®
K	K~site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-38.opt-1.pycnu„[µü¤PKͶN]r­oOoOE2V~site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-38.pycnu„[µü¤PKͶN]Õ�ò
££I¦~site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-38.opt-1.pycnu„[µü¤PKͶN]Ì@A2)2)G2Æ~site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-38.pycnu„[µü¤PKͶN]”Å‹�)�)IÛï~site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-38.pycnu„[µü¤PKͶN]Õ�ò
££Cãsite-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-38.pycnu„[µü¤PKͶN]ùgÚ£h2h2Nù9site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-38.opt-1.pycnu„[µü¤PKͶN]r­oOoOKßlsite-packages/pip/_vendor/urllib3/__pycache__/response.cpython-38.opt-1.pycnu„[µü¤PKͶN]`Mƒc,','Gɼsite-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-38.pycnu„[µü¤PKͶN]!ç%%Eläsite-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-38.pycnu„[µü¤PKͶN]`Mƒc,','Mísite-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-38.opt-1.pycnu„[µü¤PKͶN]Ì@A2)2)M¯€site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-38.opt-1.pycnu„[µü¤PKͶN]ùgÚ£h2h2H^>€site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-38.pycnu„[µü¤PKͶN]Í7«}®
®
E>q€site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-38.pycnu„[µü¤PKͶN] 'vØ]Ø]Ka|€site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-38.pycnu„[µü¤PKͶN]ÂôÂ^Ž^Ž3´Ú€site-packages/pip/_vendor/urllib3/connectionpool.pynu„[µü¤PKͶN]&fü[�B�B0ui�site-packages/pip/_vendor/urllib3/poolmanager.pynu„[µü¤PKζN]JQÊé7é7-r¬�site-packages/pip/_vendor/urllib3/util/url.pynu„[µü¤PKζN]åOœ4¸ä�site-packages/pip/_vendor/urllib3/util/connection.pynu„[µü¤PKζN]“Š?þ28÷�site-packages/pip/_vendor/urllib3/util/__init__.pynu„[µü¤PKζN]±°ajíí1¨û�site-packages/pip/_vendor/urllib3/util/request.pynu„[µü¤PKζN]´ˆwŠ]&]&Fö
‚site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-38.pycnu„[µü¤PKζN]‹+ï_FÉ1‚site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-38.pycnu„[µü¤PKζN]Bß5GD>‚site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-38.pycnu„[µü¤PKζN]Bß5M¿B‚site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-38.opt-1.pycnu„[µü¤PKζN]…]
ÙúúO@G‚site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-38.opt-1.pycnu„[µü¤PKζN]…]
ÙúúI¹T‚site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-38.pycnu„[µü¤PKζN]heñ.××P,b‚site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKζN]‹+ï_Lƒf‚site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-38.opt-1.pycnu„[µü¤PKζN]tøÕ¸��Js‚site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-38.pycnu„[µü¤PKζN]ðaÐTTL{‚site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-38.pycnu„[µü¤PKζN]tøÕ¸��P뇂site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-38.opt-1.pycnu„[µü¤PKζN]heñ.××J�‚site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-38.pycnu„[µü¤PKζN]><}™‹"‹"IY”‚site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-38.pycnu„[µü¤PKζN]9Ø7’‘2‘2M]·‚site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-38.opt-1.pycnu„[µü¤PKζN]9Ø7’‘2‘2Gkê‚site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-38.pycnu„[µü¤PKζN]´ˆwŠ]&]&Lsƒsite-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-38.opt-1.pycnu„[µü¤PKζN]ðaÐTTRLDƒsite-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-38.opt-1.pycnu„[µü¤PKζN]Û"¼ê)ê)K"Qƒsite-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-38.opt-1.pycnu„[µü¤PKζN]><}™‹"‹"O‡{ƒsite-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-38.opt-1.pycnu„[µü¤PKζN]Û"¼ê)ê)E‘žƒsite-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-38.pycnu„[µü¤PKζN]•M>MZ»†site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-38.opt-1.pycnu„[µü¤PK϶N]ëZ$££Mɇsite-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-38.pycnu„[µü¤PK϶N]ƒ*(ƒ;;]é	‡site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-38.opt-1.pycnu„[µü¤PK϶N][£dU:U:N±‡site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-38.pycnu„[µü¤PK϶N]H.ú|Ê Ê T„I‡site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-38.opt-1.pycnu„[µü¤PK϶N]ƒ*(ƒ;;WÒj‡site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-38.pycnu„[µü¤PK϶N]H.ú|Ê Ê N”o‡site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-38.pycnu„[µü¤PK϶N]]æV#||2Ü�‡site-packages/pip/_vendor/urllib3/contrib/socks.pynu„[µü¤PK϶N]ºÏ¢ææ<º¬‡site-packages/pip/_vendor/urllib3/contrib/securetransport.pynu„[µü¤PK϶N]ÚAöii5-ˆsite-packages/pip/_vendor/urllib3/contrib/ntlmpool.pynu„[µü¤PK϶N]®1ûºÃÃ?Ú=ˆsite-packages/pip/_vendor/urllib3/contrib/_appengine_environ.pynu„[µü¤PK϶N]â»2,2,6Aˆsite-packages/pip/_vendor/urllib3/contrib/appengine.pynu„[µü¤PK϶N]¬9Œ¬ll6¤mˆsite-packages/pip/_vendor/urllib3/packages/__init__.pynu„[µü¤PK϶N]!eTvnˆsite-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK϶N]ÚPíÄygygOpˆsite-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-38.opt-1.pycnu„[µü¤PK϶N]!eN؈site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-38.pycnu„[µü¤PK϶N]ÚPíÄygygIšÙˆsite-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-38.pycnu„[µü¤PK϶N]Q‹?\\PŒA‰site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.pynu„[µü¤PK϶N]{Ià\°°IhX‰site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.pynu„[µü¤PK϶N]¥ªhig‘[‰site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK϶N]álSoççn.^‰site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__pycache__/_implementation.cpython-38.opt-1.pycnu„[µü¤PK϶N]¥ªhia³k‰site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__pycache__/__init__.cpython-38.pycnu„[µü¤PK϶N]álSoççhJn‰site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__pycache__/_implementation.cpython-38.pycnu„[µü¤PK϶N]@É{‰site-packages/pip/_vendor/urllib3/packages/backports/__init__.pynu„[µü¤PK϶N]~7†ºÖÖ^9|‰site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-38.opt-1.pycnu„[µü¤PK϶N]òÜ®®^��‰site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK϶N]	OGÑþþXÙ‚‰site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-38.pycnu„[µü¤PK϶N]òÜ®®X_ˆ‰site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-38.pycnu„[µü¤PK϶N]òÉŠŠ@•‰‰site-packages/pip/_vendor/urllib3/packages/backports/makefile.pynu„[µü¤PK϶N]²U“1��‰site-packages/pip/_vendor/urllib3/packages/six.pynu„[µü¤PK϶N]ɽú¼l¼l-Šsite-packages/pip/_vendor/urllib3/response.pynu„[µü¤PK϶N]Ú¶ŒÚ‚5‚54!|Šsite-packages/pip/_vendor/cachecontrol/controller.pynu„[µü¤PK϶N]ˆ$N..2²Šsite-packages/pip/_vendor/cachecontrol/__init__.pynu„[µü¤PK϶N]”%m^ææ4—³Šsite-packages/pip/_vendor/cachecontrol/heuristics.pynu„[µü¤PK϶N]3'çuuIáÊsite-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-38.pycnu„[µü¤PK϶N]©äØVßßOÏÆŠsite-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-38.opt-1.pycnu„[µü¤PK϶N]0Šl7P-ÓŠsite-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK϶N]ñÆõm[[S®ÕŠsite-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-38.opt-1.pycnu„[µü¤PK϶N]Úu»eÒÒGŒÞŠsite-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-38.pycnu„[µü¤PK϶N]V–ãZZRÕåŠsite-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-38.opt-1.pycnu„[µü¤PK϶N]3'çuuO±øŠsite-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-38.opt-1.pycnu„[µü¤PK϶N]ñÆõm[[M¥ûŠsite-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-38.pycnu„[µü¤PK϶N]ÿ­o°L}‹site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-38.opt-1.pycnu„[µü¤PK϶N]Úu»eÒÒMý
‹site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-38.opt-1.pycnu„[µü¤PK϶N]Ð
(ÌÐÐHL‹site-packages/pip/_vendor/cachecontrol/__pycache__/compat.cpython-38.pycnu„[µü¤PK϶N]©äØVßßI”‹site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-38.pycnu„[µü¤PK϶N]Ð
(ÌÐÐNì!‹site-packages/pip/_vendor/cachecontrol/__pycache__/compat.cpython-38.opt-1.pycnu„[µü¤PK϶N]0Šl7J:%‹site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-38.pycnu„[µü¤PK϶N]T!ììLµ'‹site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-38.pycnu„[µü¤PK϶N]T!ììRF‹site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-38.opt-1.pycnu„[µü¤PK϶N]EÆ¿ˆssK‹d‹site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-38.pycnu„[µü¤PK϶N]ÿ­o°Fyu‹site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-38.pycnu„[µü¤PK϶N]V–ãZZLó{‹site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-38.pycnu„[µü¤PK϶N]EÆ¿ˆssQÉŽ‹site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-38.opt-1.pycnu„[µü¤PK϶N]¸Q
**3½Ÿ‹site-packages/pip/_vendor/cachecontrol/serialize.pynu„[µü¤PK϶N]¿¸0VV9J»‹site-packages/pip/_vendor/cachecontrol/caches/__init__.pynu„[µü¤PK϶N]µg%CùùT	¼‹site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-38.pycnu„[µü¤PK϶N]ÃEóŸŸY†Â‹site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-38.opt-1.pycnu„[µü¤PK϶N]ožW®Ï‹site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PK϶N]ÃEóŸŸS6Ñ‹site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-38.pycnu„[µü¤PK϶N]ožQXÞ‹site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-38.pycnu„[µü¤PK϶N]µg%CùùZÚß‹site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-38.opt-1.pycnu„[µü¤PK϶N]¨ÇAßXX<]æ‹site-packages/pip/_vendor/cachecontrol/caches/redis_cache.pynu„[µü¤PK϶N]üÎ/É99;!ê‹site-packages/pip/_vendor/cachecontrol/caches/file_cache.pynu„[µü¤PK϶N]Æb¼M%%/Åú‹site-packages/pip/_vendor/cachecontrol/cache.pynu„[µü¤PK϶N]…–d··0Iþ‹site-packages/pip/_vendor/cachecontrol/compat.pynu„[µü¤PK϶N]x�ÿÿ1`Œsite-packages/pip/_vendor/cachecontrol/adapter.pynu„[µü¤PKжN]®¡]ŸŸ1ÀŒsite-packages/pip/_vendor/cachecontrol/wrapper.pynu„[µü¤PKжN]J›y§.ÀŒsite-packages/pip/_vendor/cachecontrol/_cmd.pynu„[µü¤PKжN]óÑþå	å	5-Œsite-packages/pip/_vendor/cachecontrol/filewrapper.pynu„[µü¤PKжN]*-U½Ž½Ž;w'Œsite-packages/pip/_vendor/__pycache__/distro.cpython-38.pycnu„[µü¤PKжN]3ìð­‚<‚<@Ÿ¶Œsite-packages/pip/_vendor/__pycache__/contextlib2.cpython-38.pycnu„[µü¤PKжN]+Vk'A‹A‹>‘óŒsite-packages/pip/_vendor/__pycache__/pyparsing.cpython-38.pycnu„[µü¤PKжN]1EÂŽ‡ü‡üD@�site-packages/pip/_vendor/__pycache__/ipaddress.cpython-38.opt-1.pycnu„[µü¤PKжN]O7èê

C;|‘site-packages/pip/_vendor/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKжN]ãÜßÀxŽxŽA»‡‘site-packages/pip/_vendor/__pycache__/distro.cpython-38.opt-1.pycnu„[µü¤PKжN]öôÇFFC¤’site-packages/pip/_vendor/__pycache__/retrying.cpython-38.opt-1.pycnu„[µü¤PKжN]öôÇFF=]6’site-packages/pip/_vendor/__pycache__/retrying.cpython-38.pycnu„[µü¤PKжN]3ìð­‚<‚<FV’site-packages/pip/_vendor/__pycache__/contextlib2.cpython-38.opt-1.pycnu„[µü¤PKжN]Úœ>*ÕOÕO<“’site-packages/pip/_vendor/__pycache__/appdirs.cpython-38.pycnu„[µü¤PKжN]êèâÒgg>Iã’site-packages/pip/_vendor/__pycache__/six.cpython-38.opt-1.pycnu„[µü¤PKжN]+Vk'A‹A‹DÓJ“site-packages/pip/_vendor/__pycache__/pyparsing.cpython-38.opt-1.pycnu„[µü¤PKжN]O7èê

=ˆÖ–site-packages/pip/_vendor/__pycache__/__init__.cpython-38.pycnu„[µü¤PKжN]êèâÒgg8â–site-packages/pip/_vendor/__pycache__/six.cpython-38.pycnu„[µü¤PKжN]¬Zd¦ýý>†I—site-packages/pip/_vendor/__pycache__/ipaddress.cpython-38.pycnu„[µü¤PKжN]Úœ>*ÕOÕOBG˜site-packages/pip/_vendor/__pycache__/appdirs.cpython-38.opt-1.pycnu„[µü¤PKжN]ß_4ã_ã_$I—˜site-packages/pip/_vendor/appdirs.pynu„[µü¤PKжN]ên©Ëó¨ó¨#€÷˜site-packages/pip/_vendor/distro.pynu„[µü¤PKжN]Jºfv!!2Æ ™site-packages/pip/_vendor/requests/status_codes.pynu„[µü¤PKжN]¹¸lq}}0I±™site-packages/pip/_vendor/requests/exceptions.pynu„[µü¤PKжN]œ9.D,T,T.&¾™site-packages/pip/_vendor/requests/adapters.pynu„[µü¤PKжN]Ó6Š–ã…ã…,°šsite-packages/pip/_vendor/requests/models.pynu„[µü¤PKжN]‚²¢ÏÑÑ+site-packages/pip/_vendor/requests/certs.pynu„[µü¤PKжN]é‹9y¥¥0›šsite-packages/pip/_vendor/requests/structures.pynu„[µü¤PKжN]ß�µãêê. §šsite-packages/pip/_vendor/requests/__init__.pynu„[µü¤PKжN]émAùÒÒLh·šsite-packages/pip/_vendor/requests/__pycache__/packages.cpython-38.opt-1.pycnu„[µü¤PKжN]•ÏÄïÚÚS¶¹šsite-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-38.opt-1.pycnu„[µü¤PKжN]:¼UUI¿šsite-packages/pip/_vendor/requests/__pycache__/certs.cpython-38.opt-1.pycnu„[µü¤PKжN]|œcOáÁšsite-packages/pip/_vendor/requests/__pycache__/__version__.cpython-38.opt-1.pycnu„[µü¤PKжN]émAùÒÒFbÄšsite-packages/pip/_vendor/requests/__pycache__/packages.cpython-38.pycnu„[µü¤PKжN]êÑ9µnInIEªÆšsite-packages/pip/_vendor/requests/__pycache__/cookies.cpython-38.pycnu„[µü¤PKжN]´•ëT]T]D�›site-packages/pip/_vendor/requests/__pycache__/models.cpython-38.pycnu„[µü¤PKжN]Èn£8**HUn›site-packages/pip/_vendor/requests/__pycache__/structures.cpython-38.pycnu„[µü¤PKжN]蛂Me e H÷›site-packages/pip/_vendor/requests/__pycache__/auth.cpython-38.opt-1.pycnu„[µü¤PKжN]ns^®

LÔ ›site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKжN]:¼UUC`®›site-packages/pip/_vendor/requests/__pycache__/certs.cpython-38.pycnu„[µü¤PKжN]bI½GGA(±›site-packages/pip/_vendor/requests/__pycache__/api.cpython-38.pycnu„[µü¤PKжN]xȳf¼¼IàÊ›site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-38.opt-1.pycnu„[µü¤PKжN]îVßê88PÏ›site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-38.opt-1.pycnu„[µü¤PKжN]bI½GGGÍß›site-packages/pip/_vendor/requests/__pycache__/api.cpython-38.opt-1.pycnu„[µü¤PKжN]¯
ì«3B3BF‹ù›site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-38.pycnu„[µü¤PKѶN]êÑ9µnInIK4<œsite-packages/pip/_vendor/requests/__pycache__/cookies.cpython-38.opt-1.pycnu„[µü¤PKѶN]Èn£8**N†œsite-packages/pip/_vendor/requests/__pycache__/structures.cpython-38.opt-1.pycnu„[µü¤PKѶN]kKpö((DÅ—œsite-packages/pip/_vendor/requests/__pycache__/compat.cpython-38.pycnu„[µü¤PKѶN]xȳf¼¼Cažœsite-packages/pip/_vendor/requests/__pycache__/hooks.cpython-38.pycnu„[µü¤PKѶN]kKpö((J�¢œsite-packages/pip/_vendor/requests/__pycache__/compat.cpython-38.opt-1.pycnu„[µü¤PKѶN]Y“p†
†
B2©œsite-packages/pip/_vendor/requests/__pycache__/help.cpython-38.pycnu„[µü¤PKѶN]~BT62L2LL*´œsite-packages/pip/_vendor/requests/__pycache__/sessions.cpython-38.opt-1.pycnu„[µü¤PKѶN]îVßê88JØ�site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-38.pycnu„[µü¤PKѶN]Y“p†
†
HŠ�site-packages/pip/_vendor/requests/__pycache__/help.cpython-38.opt-1.pycnu„[µü¤PKѶN]~BT62L2LFˆ�site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-38.pycnu„[µü¤PKѶN]½LØ/XXH0i�site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-38.pycnu„[µü¤PKѶN]w*H‹
‹
F~�site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-38.pycnu„[µü¤PKѶN]½LØ/XXNŒ�site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-38.opt-1.pycnu„[µü¤PKѶN]u'Qø“V“VI× �site-packages/pip/_vendor/requests/__pycache__/utils.cpython-38.opt-1.pycnu„[µü¤PKѶN]|œcIã÷�site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-38.pycnu„[µü¤PKѶN]蛂Me e B^ú�site-packages/pip/_vendor/requests/__pycache__/auth.cpython-38.pycnu„[µü¤PKѶN]Y²„M5žsite-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-38.pycnu„[µü¤PKѶN]´•ëT]T]J¶ žsite-packages/pip/_vendor/requests/__pycache__/models.cpython-38.opt-1.pycnu„[µü¤PKѶN]u'Qø“V“VC„~žsite-packages/pip/_vendor/requests/__pycache__/utils.cpython-38.pycnu„[µü¤PKѶN]¯
ì«3B3BLŠÕžsite-packages/pip/_vendor/requests/__pycache__/adapters.cpython-38.opt-1.pycnu„[µü¤PKѶN]›_Ó´´19Ÿsite-packages/pip/_vendor/requests/__version__.pynu„[µü¤PKѶN]ˆ©9»HH5NŸsite-packages/pip/_vendor/requests/_internal_utils.pynu„[µü¤PKѶN]±tð••,ûŸsite-packages/pip/_vendor/requests/compat.pynu„[µü¤PKѶN]Jsáõõ+ì&Ÿsite-packages/pip/_vendor/requests/hooks.pynu„[µü¤PKѶN]½':þGþG-<*Ÿsite-packages/pip/_vendor/requests/cookies.pynu„[µü¤PKѶN]üð/‹auau+—rŸsite-packages/pip/_vendor/requests/utils.pynu„[µü¤PKѶN]<Þ�··.SèŸsite-packages/pip/_vendor/requests/packages.pynu„[µü¤PKѶN]6èmgÞ'Þ'*hëŸsite-packages/pip/_vendor/requests/auth.pynu„[µü¤PKѶN]”¿«Õ)  site-packages/pip/_vendor/requests/api.pynu„[µü¤PKѶN]­=Gïú
ú
*x, site-packages/pip/_vendor/requests/help.pynu„[µü¤PKѶN]?æƒØ”r”r.Ì: site-packages/pip/_vendor/requests/sessions.pynu„[µü¤PKѶN]ÚyŒs¯¯,¾­ site-packages/pip/_vendor/html5lib/_utils.pynu„[µü¤PKѶN]$U�©šš2ɽ site-packages/pip/_vendor/html5lib/_trie/datrie.pynu„[µü¤PKѶN]ïÓ¯!!4Å site-packages/pip/_vendor/html5lib/_trie/__init__.pynu„[µü¤PKѶN]�¶Ö±±LJÄ site-packages/pip/_vendor/html5lib/_trie/__pycache__/py.cpython-38.opt-1.pycnu„[µü¤PKѶN]/®•‹……RwÍ site-packages/pip/_vendor/html5lib/_trie/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKѶN]èÿ©ÒÑÑJ~Ï site-packages/pip/_vendor/html5lib/_trie/__pycache__/datrie.cpython-38.pycnu„[µü¤PKѶN]¸fĪ  OÉ× site-packages/pip/_vendor/html5lib/_trie/__pycache__/_base.cpython-38.opt-1.pycnu„[µü¤PKѶN]¸fĪ  IhÞ site-packages/pip/_vendor/html5lib/_trie/__pycache__/_base.cpython-38.pycnu„[µü¤PKѶN]�¶Ö±±Få site-packages/pip/_vendor/html5lib/_trie/__pycache__/py.cpython-38.pycnu„[µü¤PKѶN]/®•‹……L(î site-packages/pip/_vendor/html5lib/_trie/__pycache__/__init__.cpython-38.pycnu„[µü¤PKѶN]èÿ©ÒÑÑP)ð site-packages/pip/_vendor/html5lib/_trie/__pycache__/datrie.cpython-38.opt-1.pycnu„[µü¤PKѶN]ç�õõ1zø site-packages/pip/_vendor/html5lib/_trie/_base.pynu„[µü¤PKѶN]KOnÎïï.Ðü site-packages/pip/_vendor/html5lib/_trie/py.pynu„[µü¤PKѶN]_Önè³Ð³Ð1¡site-packages/pip/_vendor/html5lib/html5parser.pynu„[µü¤PKѶN]7óä((21Õ¢site-packages/pip/_vendor/html5lib/_inputstream.pynu„[µü¤PKѶN]°
"Ž=Ž=0»T£site-packages/pip/_vendor/html5lib/serializer.pynu„[µü¤PKѶN]2¬ÝŠŠ.©’£site-packages/pip/_vendor/html5lib/__init__.pynu„[µü¤PKѶN]�Wôy

M‘—£site-packages/pip/_vendor/html5lib/__pycache__/constants.cpython-38.opt-1.pycnu„[µü¤PKѶN];0„¸5¸5G›¤site-packages/pip/_vendor/html5lib/__pycache__/_ihatexml.cpython-38.pycnu„[µü¤PKѶN]¤½­�U�UJJѤsite-packages/pip/_vendor/html5lib/__pycache__/_inputstream.cpython-38.pycnu„[µü¤PKѶN] ’²tLT'¥site-packages/pip/_vendor/html5lib/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKѶN]À«oϨš¨šNÐ,¥site-packages/pip/_vendor/html5lib/__pycache__/_tokenizer.cpython-38.opt-1.pycnu„[µü¤PKѶN]dn¼ˆê)ê)NöÇ¥site-packages/pip/_vendor/html5lib/__pycache__/serializer.cpython-38.opt-1.pycnu„[µü¤PKѶN]Y£�/ÔSÔSP^ò¥site-packages/pip/_vendor/html5lib/__pycache__/_inputstream.cpython-38.opt-1.pycnu„[µü¤PKѶN]�Wôy

G²F¦site-packages/pip/_vendor/html5lib/__pycache__/constants.cpython-38.pycnu„[µü¤PKÒ¶N].¬ƚƚH6J§site-packages/pip/_vendor/html5lib/__pycache__/_tokenizer.cpython-38.pycnu„[µü¤PKÒ¶N]r7`t°°Jtå§site-packages/pip/_vendor/html5lib/__pycache__/_utils.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N]'åw¯îîDžò§site-packages/pip/_vendor/html5lib/__pycache__/_utils.cpython-38.pycnu„[µü¤PKÒ¶N]¹�7Å£s£sI¨site-packages/pip/_vendor/html5lib/__pycache__/html5parser.cpython-38.pycnu„[µü¤PKÒ¶N] ’²tFt©site-packages/pip/_vendor/html5lib/__pycache__/__init__.cpython-38.pycnu„[µü¤PKÒ¶N]χYp5p5M’y©site-packages/pip/_vendor/html5lib/__pycache__/_ihatexml.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N]�jU	$*$*H¯©site-packages/pip/_vendor/html5lib/__pycache__/serializer.cpython-38.pycnu„[µü¤PKÒ¶N]�-špšpOÚ©site-packages/pip/_vendor/html5lib/__pycache__/html5parser.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N]ž9qZ§§;4K«site-packages/pip/_vendor/html5lib/treeadapters/__init__.pynu„[µü¤PKÒ¶N]@㢇‡YFN«site-packages/pip/_vendor/html5lib/treeadapters/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N]#¡,ssTVR«site-packages/pip/_vendor/html5lib/treeadapters/__pycache__/sax.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N]@㢇‡SMX«site-packages/pip/_vendor/html5lib/treeadapters/__pycache__/__init__.cpython-38.pycnu„[µü¤PKÒ¶N]Ìl%’ååWW\«site-packages/pip/_vendor/html5lib/treeadapters/__pycache__/genshi.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N]E‹a¤¤NÃb«site-packages/pip/_vendor/html5lib/treeadapters/__pycache__/sax.cpython-38.pycnu„[µü¤PKÒ¶N]Ìl%’ååQåh«site-packages/pip/_vendor/html5lib/treeadapters/__pycache__/genshi.cpython-38.pycnu„[µü¤PKÒ¶N]RŒ)³³9Ko«site-packages/pip/_vendor/html5lib/treeadapters/genshi.pynu„[µü¤PKÒ¶N]€i©—ðð6gv«site-packages/pip/_vendor/html5lib/treeadapters/sax.pynu„[µü¤PKÒ¶N]ÄFj$+$+0½}«site-packages/pip/_vendor/html5lib/_tokenizer.pynu„[µü¤PKÒ¶N]@ÁPˆfˆf7A©¬site-packages/pip/_vendor/html5lib/filters/sanitizer.pynu„[µü¤PKÒ¶N]60­site-packages/pip/_vendor/html5lib/filters/__init__.pynu„[µü¤PKÒ¶N]Y±Èâb–­site-packages/pip/_vendor/html5lib/filters/__pycache__/alphabeticalattributes.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N]õÃã·BBP.­site-packages/pip/_vendor/html5lib/filters/__pycache__/base.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N][@!¤¤Tð­site-packages/pip/_vendor/html5lib/filters/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N]=ÙÖb�?�?O­site-packages/pip/_vendor/html5lib/filters/__pycache__/sanitizer.cpython-38.pycnu„[µü¤PKÒ¶N]õÃã·BBJ$[­site-packages/pip/_vendor/html5lib/filters/__pycache__/base.cpython-38.pycnu„[µü¤PKÒ¶N]@áÖ¯&
&
Jà^­site-packages/pip/_vendor/html5lib/filters/__pycache__/lint.cpython-38.pycnu„[µü¤PKÒ¶N]<„çQ§
§
R€i­site-packages/pip/_vendor/html5lib/filters/__pycache__/optionaltags.cpython-38.pycnu„[µü¤PKÒ¶N]<„çQ§
§
X©t­site-packages/pip/_vendor/html5lib/filters/__pycache__/optionaltags.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N]my00_Ø­site-packages/pip/_vendor/html5lib/filters/__pycache__/inject_meta_charset.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N]Z½†44P—‡­site-packages/pip/_vendor/html5lib/filters/__pycache__/whitespace.cpython-38.pycnu„[µü¤PKÒ¶N]¼¦‘nP?P?UK�­site-packages/pip/_vendor/html5lib/filters/__pycache__/sanitizer.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N][@!¤¤N Í­site-packages/pip/_vendor/html5lib/filters/__pycache__/__init__.cpython-38.pycnu„[µü¤PKÒ¶N]my00YBέsite-packages/pip/_vendor/html5lib/filters/__pycache__/inject_meta_charset.cpython-38.pycnu„[µü¤PKÒ¶N]Y±Èâ\ûÕ­site-packages/pip/_vendor/html5lib/filters/__pycache__/alphabeticalattributes.cpython-38.pycnu„[µü¤PKÒ¶N]ƒTS‚EEP�Û­site-packages/pip/_vendor/html5lib/filters/__pycache__/lint.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N]Z½†44VRã­site-packages/pip/_vendor/html5lib/filters/__pycache__/whitespace.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N]óÀ?��Aé­site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.pynu„[µü¤PKÒ¶N]"€ûÄ2þô­site-packages/pip/_vendor/html5lib/filters/base.pynu„[µü¤PKÒ¶N]uš*\)\):~ö­site-packages/pip/_vendor/html5lib/filters/optionaltags.pynu„[µü¤PKÒ¶N]`rÿ¾¾8D ®site-packages/pip/_vendor/html5lib/filters/whitespace.pynu„[µü¤PKÒ¶N]’Ñd ;;2j%®site-packages/pip/_vendor/html5lib/filters/lint.pynu„[µü¤PKÒ¶N]€°——D4®site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.pynu„[µü¤PKÒ¶N]P§±Ý"Ý"68®site-packages/pip/_vendor/html5lib/treebuilders/dom.pynu„[µü¤PKÒ¶N]eÛkL;U[®site-packages/pip/_vendor/html5lib/treebuilders/__init__.pynu„[µü¤PKÒ¶N]Çä�..UÈi®site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/etree_lxml.cpython-38.pycnu„[µü¤PKÒ¶N]—¶Ï—G-G-[M˜®site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/etree_lxml.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N]�ä'Í$Í$NÆ®site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/dom.cpython-38.pycnu„[µü¤PKÒ¶N]�ä'Í$Í$Tjë®site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/dom.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N]£64Ä+Ä+U»¯site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/base.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N]‹ÙÔÐØØY=¯site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N]tÅ™æ2,2,OeJ¯site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/base.cpython-38.pycnu„[µü¤PKÒ¶N]‹ÙÔÐØØSw¯site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/__init__.cpython-38.pycnu„[µü¤PKÒ¶N]óÜøÐ·-·-Vq„¯site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/etree.cpython-38.opt-1.pycnu„[µü¤PKÒ¶N]wý . .P®²¯site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/etree.cpython-38.pycnu„[µü¤PKÒ¶N]¡}—ðÜ1Ü18Ná¯site-packages/pip/_vendor/html5lib/treebuilders/etree.pynu„[µü¤PKÒ¶N]ÄÕ¢¬ó8ó87’°site-packages/pip/_vendor/html5lib/treebuilders/base.pynu„[µü¤PKÒ¶N]Oê·*7*7=ìL°site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.pynu„[µü¤PKÒ¶N]unAAAA/ƒ„°site-packages/pip/_vendor/html5lib/_ihatexml.pynu„[µü¤PKÒ¶N]Ö†ï>F>F/#ưsite-packages/pip/_vendor/html5lib/constants.pynu„[µü¤PKÒ¶N]eŠo©……5À²site-packages/pip/_vendor/html5lib/treewalkers/dom.pynu„[µü¤PKÓ¶N]­fÜRR:ª²site-packages/pip/_vendor/html5lib/treewalkers/__init__.pynu„[µü¤PKÓ¶N]Á´¾¶¶Tf)²site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/etree_lxml.cpython-38.pycnu„[µü¤PKÓ¶N]—-—†žžZ C²site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/etree_lxml.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]Ù_)¢¢MÈ\²site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/dom.cpython-38.pycnu„[µü¤PKÓ¶N]Ù_)¢¢Sçc²site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/dom.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]AÂ99Tk²site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/base.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]¼Xg1XɆ²site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]AÂ99No–²site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/base.cpython-38.pycnu„[µü¤PKÓ¶N]-Û@��R&²²site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/__init__.cpython-38.pycnu„[µü¤PKÓ¶N]“¼@@V)²site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/genshi.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]8YÂx7
7
Uïɲsite-packages/pip/_vendor/html5lib/treewalkers/__pycache__/etree.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]TÖ
o›
›
O«×²site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/etree.cpython-38.pycnu„[µü¤PKÓ¶N]“¼@@PÅå²site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/genshi.cpython-38.pycnu„[µü¤PKÓ¶N]¾Åò-ÆÆ7…í²site-packages/pip/_vendor/html5lib/treewalkers/etree.pynu„[µü¤PKÓ¶N]_m		8²ÿ²site-packages/pip/_vendor/html5lib/treewalkers/genshi.pynu„[µü¤PKÓ¶N]!-ÚB446	³site-packages/pip/_vendor/html5lib/treewalkers/base.pynu„[µü¤PKÓ¶N]–
œG¥¥<¹&³site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.pynu„[µü¤PKÓ¶N]eD22/Ê?³site-packages/pip/_vendor/packaging/__init__.pynu„[µü¤PKÓ¶N]øGW^4*4*I[B³site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]Uù˜Mm³site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]î9ìóMMIœo³site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-38.pycnu„[µü¤PKÓ¶N]»µmã¹¹N$½³site-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]S‚ÜÒ"Ò"F[À³site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-38.pycnu„[µü¤PKÓ¶N]7[½Á
Á
P£ã³site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]7[½Á
Á
Jäî³site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-38.pycnu„[µü¤PKÓ¶N]³±�„ËËFú³site-packages/pip/_vendor/packaging/__pycache__/_compat.cpython-38.pycnu„[µü¤PKÓ¶N]³±�„ËËL`þ³site-packages/pip/_vendor/packaging/__pycache__/_compat.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]Uù˜G§´site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-38.pycnu„[µü¤PKÓ¶N]|´vÚ//L5´site-packages/pip/_vendor/packaging/__pycache__/version.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]¦»Ö†ˆˆQË4´site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]ÓôuÖ””JÔD´site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]¦»Ö†ˆˆKâJ´site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-38.pycnu„[µü¤PKÓ¶N]øGW^4*4*CåZ´site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-38.pycnu„[µü¤PKÓ¶N]<2m"m"LŒ…´site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]»µmã¹¹Hu¨´site-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-38.pycnu„[µü¤PKÓ¶N]|´vÚ//F¦«´site-packages/pip/_vendor/packaging/__pycache__/version.cpython-38.pycnu„[µü¤PKÓ¶N]ÓôuÖ””D6Û´site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-38.pycnu„[µü¤PKÓ¶N]î9ìóMMO>á´site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]k�•ˆˆ2Ì.µsite-packages/pip/_vendor/packaging/_structures.pynu„[µü¤PKÓ¶N]fŠÚãaa.¶4µsite-packages/pip/_vendor/packaging/_compat.pynu„[µü¤PKÓ¶N]a=­�ðð,u8µsite-packages/pip/_vendor/packaging/utils.pynu„[µü¤PKÓ¶N]Ržü\\3Á>µsite-packages/pip/_vendor/packaging/requirements.pynu„[µü¤PKÓ¶N]ñ3rëÊ.Ê..€Qµsite-packages/pip/_vendor/packaging/version.pynu„[µü¤PKÓ¶N]òˆFÓ‚l‚l1¨€µsite-packages/pip/_vendor/packaging/specifiers.pynu„[µü¤PKÓ¶N]Š×Ðèè0‹íµsite-packages/pip/_vendor/packaging/__about__.pynu„[µü¤PKÓ¶N]²è×: : .Óðµsite-packages/pip/_vendor/packaging/markers.pynu„[µü¤PKÓ¶N]óö‡ÿ…2…2+k¶site-packages/pip/_vendor/packaging/tags.pynu„[µü¤PKÓ¶N]¢(Öæ&&-KD¶site-packages/pip/_vendor/colorama/winterm.pynu„[µü¤PKÓ¶N]mJ Óïï.Î]¶site-packages/pip/_vendor/colorama/__init__.pynu„[µü¤PKÓ¶N]ÎÈݵO_¶site-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]º[pxxH¯}¶site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]?Î=ùEŸŠ¶site-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-38.pycnu„[µü¤PKÓ¶N]3´G——L(�¶site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]?Î=ùK;Ÿ¶site-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N])”„„Nʱ¶site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]wGÂ%hhC̸¶site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-38.pycnu„[µü¤PKÓ¶N]ÎÈݵI§È¶site-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-38.pycnu„[µü¤PKÓ¶N])”„„H5ç¶site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-38.pycnu„[µü¤PKÓ¶N]3´G——F1î¶site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-38.pycnu„[µü¤PKÓ¶N]º[pxxB>ð¶site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-38.pycnu„[µü¤PKÓ¶N]wGÂ%hhI(ý¶site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-38.opt-1.pycnu„[µü¤PKÓ¶N]oEr{{0	
·site-packages/pip/_vendor/colorama/initialise.pynu„[µü¤PKÓ¶N]#ðlsÞ(Þ(1ä·site-packages/pip/_vendor/colorama/ansitowin32.pynu„[µü¤PKÔ¶N]>§_Ü	Ü	*#>·site-packages/pip/_vendor/colorama/ansi.pynu„[µü¤PKÔ¶N]+YH·site-packages/pip/_vendor/colorama/win32.pynu„[µü¤PKÔ¶N]/àݺdd-Ð]·site-packages/pip/_vendor/progress/spinner.pynu„[µü¤PKÔ¶N]—̵¸&&)‘c·site-packages/pip/_vendor/progress/bar.pynu„[µü¤PKÔ¶N]BiKùù.o·site-packages/pip/_vendor/progress/__init__.pynu„[µü¤PKÔ¶N]Xð��Eg‚·site-packages/pip/_vendor/progress/__pycache__/counter.cpython-38.pycnu„[µü¤PKÔ¶N]	Á ÍÍLyˆ·site-packages/pip/_vendor/progress/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]ûBTTKž·site-packages/pip/_vendor/progress/__pycache__/spinner.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]Xð��K‘¤·site-packages/pip/_vendor/progress/__pycache__/counter.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]ûBTTE©ª·site-packages/pip/_vendor/progress/__pycache__/spinner.cpython-38.pycnu„[µü¤PKÔ¶N]	Á ÍÍFr°·site-packages/pip/_vendor/progress/__pycache__/__init__.cpython-38.pycnu„[µü¤PKÔ¶N]üîá-
-
AµÆ·site-packages/pip/_vendor/progress/__pycache__/bar.cpython-38.pycnu„[µü¤PKÔ¶N]üîá-
-
GSÑ·site-packages/pip/_vendor/progress/__pycache__/bar.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]xà¹�\\-÷Û·site-packages/pip/_vendor/progress/counter.pynu„[µü¤PKÔ¶N]h¿\ÑÄ~Ä~ °á·site-packages/pip/_vendor/six.pynu„[µü¤PKÔ¶N]g8p§££/Ä`¸site-packages/pip/_vendor/webencodings/tests.pynu„[µü¤PKÔ¶N]xÐqS)S)2Æz¸site-packages/pip/_vendor/webencodings/__init__.pynu„[µü¤PKÔ¶N]£à7CCP{¤¸site-packages/pip/_vendor/webencodings/__pycache__/mklabels.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]F�Å÷iiJ>¬¸site-packages/pip/_vendor/webencodings/__pycache__/mklabels.cpython-38.pycnu„[µü¤PKÔ¶N]òÏ‘·%·%P!´¸site-packages/pip/_vendor/webencodings/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]Ô½­ÂG
G
VXÚ¸site-packages/pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]ÒТYÇÇG%å¸site-packages/pip/_vendor/webencodings/__pycache__/tests.cpython-38.pycnu„[µü¤PKÔ¶N]Ô½­ÂG
G
Pcù¸site-packages/pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-38.pycnu„[µü¤PKÔ¶N]àO¶ØÙÙH*¹site-packages/pip/_vendor/webencodings/__pycache__/labels.cpython-38.pycnu„[µü¤PKÔ¶N]¥(/g	g	M{¹site-packages/pip/_vendor/webencodings/__pycache__/tests.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]ª3äç%ç%J_¹site-packages/pip/_vendor/webencodings/__pycache__/__init__.cpython-38.pycnu„[µü¤PKÔ¶N]àO¶ØÙÙNÀC¹site-packages/pip/_vendor/webencodings/__pycache__/labels.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]Ç­‹##0S¹site-packages/pip/_vendor/webencodings/labels.pynu„[µü¤PKÔ¶N]P12Šv¹site-packages/pip/_vendor/webencodings/mklabels.pynu„[µü¤PKÔ¶N]ÛüÖÓÓ8|¹site-packages/pip/_vendor/webencodings/x_user_defined.pynu„[µü¤PKÔ¶N]òöÀ|BB(@�¹site-packages/pip/_vendor/contextlib2.pynu„[µü¤PKÔ¶N];;�Ó99/«Ï¹site-packages/pip/_vendor/msgpack/exceptions.pynu„[µü¤PKÔ¶N])ݶÕÿÿ-CÔ¹site-packages/pip/_vendor/msgpack/__init__.pynu„[µü¤PKÔ¶N]ý>QÀ~~KŸÚ¹site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]Gz	¶¶E˜â¹site-packages/pip/_vendor/msgpack/__pycache__/_version.cpython-38.pycnu„[µü¤PKÔ¶N]q³ÒÙffKÃã¹site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]Ïá]>GRJºsite-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-38.pycnu„[µü¤PKÔ¶N]F½2Ñ¡f¡fEáQºsite-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-38.pycnu„[µü¤PKÔ¶N]ý>QÀ~~E÷¸ºsite-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-38.pycnu„[µü¤PKÔ¶N]Ïá]>MêÀºsite-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]Gz	¶¶KȺsite-packages/pip/_vendor/msgpack/__pycache__/_version.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]Âw§ÑN’N’-°Éºsite-packages/pip/_vendor/msgpack/fallback.pynu„[µü¤PKÔ¶N]o�-[\»site-packages/pip/_vendor/msgpack/_version.pynu„[µü¤PKÔ¶N]C\Uwøëøë)Ì\»site-packages/pip/_vendor/distlib/util.pynu„[µü¤PKÔ¶N]Ó
_Ê_Ê-I¼site-packages/pip/_vendor/distlib/locators.pynu„[µü¤PKÔ¶N]%Øsaõ�õ�*Ù½site-packages/pip/_vendor/distlib/wheel.pynu„[µü¤PKÔ¶N]8ù^0KK-(²½site-packages/pip/_vendor/distlib/__init__.pynu„[µü¤PKÔ¶N]+‰üZ­g­gKд½site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]w£dðgðgEø¾site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-38.pycnu„[µü¤PKÔ¶N]±4BÌ�•�•E]…¾site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-38.pycnu„[µü¤PKÔ¶N]±#ã×KS¿site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]ºéºÜ*Ü*FÒ¿site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-38.pycnu„[µü¤PKÔ¶N]ÊáÞàmmD$K¿site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-38.pycnu„[µü¤PKÔ¶N]q~�~e'e'K]¿site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]"îxßCßCHå„¿site-packages/pip/_vendor/distlib/__pycache__/index.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]E]
ØW•W•K<É¿site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]›xˆô«}«}C_Àsite-packages/pip/_vendor/distlib/__pycache__/compat.cpython-38.pycnu„[µü¤PKÔ¶N]F�aX„}„}I,ÝÀsite-packages/pip/_vendor/distlib/__pycache__/compat.cpython-38.opt-1.pycnu„[µü¤PKÔ¶N]ZÀÎ=½=½A)[Ásite-packages/pip/_vendor/distlib/__pycache__/util.cpython-38.pycnu„[µü¤PKÔ¶N]±#ã×E×Âsite-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-38.pycnu„[µü¤PKÔ¶N]¯ASÈ)O)OJPÂsite-packages/pip/_vendor/distlib/__pycache__/version.cpython-38.opt-1.pycnu„[µü¤PKÕ¶N]"îxßCßCBólÂsite-packages/pip/_vendor/distlib/__pycache__/index.cpython-38.pycnu„[µü¤PKÕ¶N]Xã~I®c®cBD±Âsite-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-38.pycnu„[µü¤PKÕ¶N]ºéºÜ*Ü*LdÃsite-packages/pip/_vendor/distlib/__pycache__/resources.cpython-38.opt-1.pycnu„[µü¤PKÕ¶N]¾JE**J¼@Ãsite-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-38.opt-1.pycnu„[µü¤PKÕ¶N]¾JE**D8kÃsite-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-38.pycnu„[µü¤PKÕ¶N]ç*ŸzHHJ®•Ãsite-packages/pip/_vendor/distlib/__pycache__/markers.cpython-38.opt-1.pycnu„[µü¤PKÕ¶N]2‡õFT¤T¤Kp§Ãsite-packages/pip/_vendor/distlib/__pycache__/database.cpython-38.opt-1.pycnu„[µü¤PKÕ¶N]D�ÌŽdcdcH?LÄsite-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-38.opt-1.pycnu„[µü¤PKÕ¶N]j´dYkOkOD°Äsite-packages/pip/_vendor/distlib/__pycache__/version.cpython-38.pycnu„[µü¤PKÕ¶N]
u:Õ'Õ'EúÿÄsite-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-38.pycnu„[µü¤PKÕ¶N]2‡õFT¤T¤ED(Åsite-packages/pip/_vendor/distlib/__pycache__/database.cpython-38.pycnu„[µü¤PKÕ¶N]~ÕRǻǻG
ÍÅsite-packages/pip/_vendor/distlib/__pycache__/util.cpython-38.opt-1.pycnu„[µü¤PKÕ¶N]ŽÝ„**.K‰Æsite-packages/pip/_vendor/distlib/resources.pynu„[µü¤PKÕ¶N]fÚÒ鼡¼¡+·³Æsite-packages/pip/_vendor/distlib/compat.pynu„[µü¤PKÕ¶N]ý¹È¢?¢?,ÎUÇsite-packages/pip/_vendor/distlib/scripts.pynu„[µü¤PKÕ¶N]¼pGUÇUÇ-Ì•Çsite-packages/pip/_vendor/distlib/database.pynu„[µü¤PKÕ¶N]öh(,_[_[,~]Èsite-packages/pip/_vendor/distlib/version.pynu„[µü¤PKÕ¶N]”8Ø*�*�-9¹Èsite-packages/pip/_vendor/distlib/metadata.pynu„[µü¤PKÕ¶N]x¦5gÛ9Û9-ÀVÉsite-packages/pip/_vendor/distlib/manifest.pynu„[µü¤PKÕ¶N]Ÿ§.ÌJRJR*ø�Ésite-packages/pip/_vendor/distlib/index.pynu„[µü¤PKÕ¶N]¶·ˆf##,œãÉsite-packages/pip/_vendor/distlib/markers.pynu„[µü¤PKÕ¶N]#ïgü7õÉsite-packages/pip/_vendor/distlib/_backport/__init__.pynu„[µü¤PKÕ¶N]=Íìa¶=¶=V”öÉsite-packages/pip/_vendor/distlib/_backport/__pycache__/sysconfig.cpython-38.opt-1.pycnu„[µü¤PKÕ¶N]ÆâÛ""KÐ4Êsite-packages/pip/_vendor/distlib/_backport/__pycache__/misc.cpython-38.pycnu„[µü¤PKÕ¶N]Ïáß¿¿Um9Êsite-packages/pip/_vendor/distlib/_backport/__pycache__/__init__.cpython-38.opt-1.pycnu„[µü¤PKÕ¶N]üÉ©""Q±;Êsite-packages/pip/_vendor/distlib/_backport/__pycache__/misc.cpython-38.opt-1.pycnu„[µü¤PKÕ¶N]Ê`ò¾ê=ê=PT@Êsite-packages/pip/_vendor/distlib/_backport/__pycache__/sysconfig.cpython-38.pycnu„[µü¤PKÕ¶N]Ïáß¿¿O¾~Êsite-packages/pip/_vendor/distlib/_backport/__pycache__/__init__.cpython-38.pycnu„[µü¤PKÕ¶N]o­9
9
9ü€Êsite-packages/pip/_vendor/distlib/_backport/sysconfig.cfgnu„[µü¤PKÕ¶N]¯Š/eËË3ž‹Êsite-packages/pip/_vendor/distlib/_backport/misc.pynu„[µü¤PKÕ¶N]ò©ßTiTi8Ì�Êsite-packages/pip/_vendor/distlib/_backport/sysconfig.pynu„[µü¤PKÕ¶N]}-<ÂttˆùÊsite-packages/pip/__main__.pynu„[µü¤PKåå*uIüÊ