From a0a55c2ae33c2f9070b558ebcab8edff6173fcd3 Mon Sep 17 00:00:00 2001 From: Yeongdo Park Date: Wed, 30 Sep 2020 12:23:46 -0700 Subject: [PATCH] remove venv and ide file --- .idea/BMS View.iml | 16 - .idea/libraries/R_User_Library.xml | 6 - .idea/misc.xml | 4 - .idea/modules.xml | 8 - .idea/vcs.xml | 6 - venv2/bin/activate | 78 - venv2/bin/activate.csh | 42 - venv2/bin/activate.fish | 101 - venv2/bin/activate.ps1 | 60 - venv2/bin/activate_this.py | 46 - venv2/bin/easy_install | 10 - venv2/bin/easy_install-2.7 | 10 - venv2/bin/pip | 10 - venv2/bin/pip2 | 10 - venv2/bin/pip2.7 | 10 - venv2/bin/python | 1 - venv2/bin/python-config | 78 - venv2/bin/python2 | 1 - venv2/bin/python2.7 | Bin 3691008 -> 0 bytes venv2/bin/wheel | 10 - venv2/lib/python2.7/LICENSE.txt | 1 - venv2/lib/python2.7/UserDict.py | 1 - venv2/lib/python2.7/_abcoll.py | 1 - venv2/lib/python2.7/_weakrefset.py | 1 - venv2/lib/python2.7/abc.py | 1 - venv2/lib/python2.7/codecs.py | 1 - venv2/lib/python2.7/copy_reg.py | 1 - venv2/lib/python2.7/distutils/__init__.py | 134 - venv2/lib/python2.7/distutils/distutils.cfg | 6 - venv2/lib/python2.7/encodings | 1 - venv2/lib/python2.7/fnmatch.py | 1 - venv2/lib/python2.7/genericpath.py | 1 - venv2/lib/python2.7/lib-dynload | 1 - venv2/lib/python2.7/linecache.py | 1 - venv2/lib/python2.7/locale.py | 1 - .../lib/python2.7/no-global-site-packages.txt | 0 venv2/lib/python2.7/ntpath.py | 1 - venv2/lib/python2.7/orig-prefix.txt | 1 - venv2/lib/python2.7/os.py | 1 - venv2/lib/python2.7/posixpath.py | 1 - venv2/lib/python2.7/re.py | 1 - .../python2.7/site-packages/easy_install.py | 5 - .../pip-19.1.1.dist-info/INSTALLER | 1 - .../pip-19.1.1.dist-info/LICENSE.txt | 20 - .../pip-19.1.1.dist-info/METADATA | 75 - .../site-packages/pip-19.1.1.dist-info/RECORD | 618 -- .../site-packages/pip-19.1.1.dist-info/WHEEL | 6 - .../pip-19.1.1.dist-info/entry_points.txt | 5 - .../pip-19.1.1.dist-info/top_level.txt | 1 - .../python2.7/site-packages/pip/__init__.py | 1 - .../python2.7/site-packages/pip/__main__.py | 19 - .../site-packages/pip/_internal/__init__.py | 78 - .../site-packages/pip/_internal/build_env.py | 215 - .../site-packages/pip/_internal/cache.py | 224 - .../pip/_internal/cli/__init__.py | 4 - .../pip/_internal/cli/autocompletion.py | 152 - .../pip/_internal/cli/base_command.py | 340 - .../pip/_internal/cli/cmdoptions.py | 809 -- .../pip/_internal/cli/main_parser.py | 104 - .../site-packages/pip/_internal/cli/parser.py | 261 - .../pip/_internal/cli/status_codes.py | 8 - .../pip/_internal/commands/__init__.py | 79 - .../pip/_internal/commands/check.py | 41 - .../pip/_internal/commands/completion.py | 94 - .../pip/_internal/commands/configuration.py | 253 - .../pip/_internal/commands/download.py | 176 - .../pip/_internal/commands/freeze.py | 96 - .../pip/_internal/commands/hash.py | 57 - .../pip/_internal/commands/help.py | 37 - .../pip/_internal/commands/install.py | 587 -- .../pip/_internal/commands/list.py | 302 - .../pip/_internal/commands/search.py | 135 - .../pip/_internal/commands/show.py | 168 - .../pip/_internal/commands/uninstall.py | 78 - .../pip/_internal/commands/wheel.py | 186 - .../pip/_internal/configuration.py | 384 - .../site-packages/pip/_internal/download.py | 979 -- .../site-packages/pip/_internal/exceptions.py | 274 - .../site-packages/pip/_internal/index.py | 1108 --- .../site-packages/pip/_internal/locations.py | 211 - .../pip/_internal/models/__init__.py | 2 - .../pip/_internal/models/candidate.py | 31 - .../pip/_internal/models/format_control.py | 73 - .../pip/_internal/models/index.py | 31 - .../pip/_internal/models/link.py | 163 - .../pip/_internal/operations/__init__.py | 0 .../pip/_internal/operations/check.py | 155 - .../pip/_internal/operations/freeze.py | 247 - .../pip/_internal/operations/prepare.py | 426 - .../site-packages/pip/_internal/pep425tags.py | 381 - .../site-packages/pip/_internal/pyproject.py | 171 - .../pip/_internal/req/__init__.py | 78 - .../pip/_internal/req/constructors.py | 340 - .../pip/_internal/req/req_file.py | 383 - .../pip/_internal/req/req_install.py | 1028 --- .../pip/_internal/req/req_set.py | 193 - .../pip/_internal/req/req_tracker.py | 96 - .../pip/_internal/req/req_uninstall.py | 633 -- .../site-packages/pip/_internal/resolve.py | 393 - .../pip/_internal/utils/__init__.py | 0 .../pip/_internal/utils/appdirs.py | 268 - .../pip/_internal/utils/compat.py | 264 - .../pip/_internal/utils/deprecation.py | 93 - .../pip/_internal/utils/encoding.py | 39 - .../pip/_internal/utils/filesystem.py | 30 - .../pip/_internal/utils/glibc.py | 93 - .../pip/_internal/utils/hashes.py | 115 - .../pip/_internal/utils/logging.py | 371 - .../site-packages/pip/_internal/utils/misc.py | 1011 -- .../pip/_internal/utils/models.py | 40 - .../pip/_internal/utils/outdated.py | 162 - .../pip/_internal/utils/packaging.py | 85 - .../pip/_internal/utils/setuptools_build.py | 8 - .../pip/_internal/utils/temp_dir.py | 155 - .../pip/_internal/utils/typing.py | 29 - .../site-packages/pip/_internal/utils/ui.py | 424 - .../pip/_internal/vcs/__init__.py | 604 -- .../site-packages/pip/_internal/vcs/bazaar.py | 103 - .../site-packages/pip/_internal/vcs/git.py | 362 - .../pip/_internal/vcs/mercurial.py | 105 - .../pip/_internal/vcs/subversion.py | 234 - .../site-packages/pip/_internal/wheel.py | 1098 --- .../site-packages/pip/_vendor/__init__.py | 109 - .../site-packages/pip/_vendor/appdirs.py | 604 -- .../pip/_vendor/cachecontrol/__init__.py | 11 - .../pip/_vendor/cachecontrol/_cmd.py | 57 - .../pip/_vendor/cachecontrol/adapter.py | 133 - .../pip/_vendor/cachecontrol/cache.py | 39 - .../_vendor/cachecontrol/caches/__init__.py | 2 - .../_vendor/cachecontrol/caches/file_cache.py | 146 - .../cachecontrol/caches/redis_cache.py | 33 - .../pip/_vendor/cachecontrol/compat.py | 29 - .../pip/_vendor/cachecontrol/controller.py | 367 - .../pip/_vendor/cachecontrol/filewrapper.py | 80 - .../pip/_vendor/cachecontrol/heuristics.py | 135 - .../pip/_vendor/cachecontrol/serialize.py | 186 - .../pip/_vendor/cachecontrol/wrapper.py | 29 - .../pip/_vendor/certifi/__init__.py | 3 - .../pip/_vendor/certifi/__main__.py | 2 - .../pip/_vendor/certifi/cacert.pem | 4658 ---------- .../site-packages/pip/_vendor/certifi/core.py | 15 - .../pip/_vendor/chardet/__init__.py | 39 - .../pip/_vendor/chardet/big5freq.py | 386 - .../pip/_vendor/chardet/big5prober.py | 47 - .../pip/_vendor/chardet/chardistribution.py | 233 - .../pip/_vendor/chardet/charsetgroupprober.py | 106 - .../pip/_vendor/chardet/charsetprober.py | 145 - .../pip/_vendor/chardet/cli/__init__.py | 1 - .../pip/_vendor/chardet/cli/chardetect.py | 85 - .../pip/_vendor/chardet/codingstatemachine.py | 88 - .../pip/_vendor/chardet/compat.py | 34 - .../pip/_vendor/chardet/cp949prober.py | 49 - .../pip/_vendor/chardet/enums.py | 76 - .../pip/_vendor/chardet/escprober.py | 101 - .../pip/_vendor/chardet/escsm.py | 246 - .../pip/_vendor/chardet/eucjpprober.py | 92 - .../pip/_vendor/chardet/euckrfreq.py | 195 - .../pip/_vendor/chardet/euckrprober.py | 47 - .../pip/_vendor/chardet/euctwfreq.py | 387 - .../pip/_vendor/chardet/euctwprober.py | 46 - .../pip/_vendor/chardet/gb2312freq.py | 283 - .../pip/_vendor/chardet/gb2312prober.py | 46 - .../pip/_vendor/chardet/hebrewprober.py | 292 - .../pip/_vendor/chardet/jisfreq.py | 325 - .../pip/_vendor/chardet/jpcntx.py | 233 - .../pip/_vendor/chardet/langbulgarianmodel.py | 228 - .../pip/_vendor/chardet/langcyrillicmodel.py | 333 - .../pip/_vendor/chardet/langgreekmodel.py | 225 - .../pip/_vendor/chardet/langhebrewmodel.py | 200 - .../pip/_vendor/chardet/langhungarianmodel.py | 225 - .../pip/_vendor/chardet/langthaimodel.py | 199 - .../pip/_vendor/chardet/langturkishmodel.py | 193 - .../pip/_vendor/chardet/latin1prober.py | 145 - .../pip/_vendor/chardet/mbcharsetprober.py | 91 - .../pip/_vendor/chardet/mbcsgroupprober.py | 54 - .../pip/_vendor/chardet/mbcssm.py | 572 -- .../pip/_vendor/chardet/sbcharsetprober.py | 132 - .../pip/_vendor/chardet/sbcsgroupprober.py | 73 - .../pip/_vendor/chardet/sjisprober.py | 92 - .../pip/_vendor/chardet/universaldetector.py | 286 - .../pip/_vendor/chardet/utf8prober.py | 82 - .../pip/_vendor/chardet/version.py | 9 - .../pip/_vendor/colorama/__init__.py | 6 - .../pip/_vendor/colorama/ansi.py | 102 - .../pip/_vendor/colorama/ansitowin32.py | 257 - .../pip/_vendor/colorama/initialise.py | 80 - .../pip/_vendor/colorama/win32.py | 152 - .../pip/_vendor/colorama/winterm.py | 169 - .../pip/_vendor/distlib/__init__.py | 23 - .../pip/_vendor/distlib/_backport/__init__.py | 6 - .../pip/_vendor/distlib/_backport/misc.py | 41 - .../pip/_vendor/distlib/_backport/shutil.py | 761 -- .../_vendor/distlib/_backport/sysconfig.cfg | 84 - .../_vendor/distlib/_backport/sysconfig.py | 788 -- .../pip/_vendor/distlib/_backport/tarfile.py | 2607 ------ .../pip/_vendor/distlib/compat.py | 1120 --- .../pip/_vendor/distlib/database.py | 1339 --- .../pip/_vendor/distlib/index.py | 516 -- .../pip/_vendor/distlib/locators.py | 1295 --- .../pip/_vendor/distlib/manifest.py | 393 - .../pip/_vendor/distlib/markers.py | 131 - .../pip/_vendor/distlib/metadata.py | 1094 --- .../pip/_vendor/distlib/resources.py | 355 - .../pip/_vendor/distlib/scripts.py | 417 - .../site-packages/pip/_vendor/distlib/t32.exe | Bin 92672 -> 0 bytes .../site-packages/pip/_vendor/distlib/t64.exe | Bin 102400 -> 0 bytes .../site-packages/pip/_vendor/distlib/util.py | 1756 ---- .../pip/_vendor/distlib/version.py | 736 -- .../site-packages/pip/_vendor/distlib/w32.exe | Bin 89088 -> 0 bytes .../site-packages/pip/_vendor/distlib/w64.exe | Bin 99328 -> 0 bytes .../pip/_vendor/distlib/wheel.py | 988 -- .../site-packages/pip/_vendor/distro.py | 1216 --- .../pip/_vendor/html5lib/__init__.py | 35 - .../pip/_vendor/html5lib/_ihatexml.py | 288 - .../pip/_vendor/html5lib/_inputstream.py | 923 -- .../pip/_vendor/html5lib/_tokenizer.py | 1721 ---- .../pip/_vendor/html5lib/_trie/__init__.py | 14 - .../pip/_vendor/html5lib/_trie/_base.py | 37 - .../pip/_vendor/html5lib/_trie/datrie.py | 44 - .../pip/_vendor/html5lib/_trie/py.py | 67 - .../pip/_vendor/html5lib/_utils.py | 124 - .../pip/_vendor/html5lib/constants.py | 2947 ------ .../pip/_vendor/html5lib/filters/__init__.py | 0 .../filters/alphabeticalattributes.py | 29 - .../pip/_vendor/html5lib/filters/base.py | 12 - .../html5lib/filters/inject_meta_charset.py | 73 - .../pip/_vendor/html5lib/filters/lint.py | 93 - .../_vendor/html5lib/filters/optionaltags.py | 207 - .../pip/_vendor/html5lib/filters/sanitizer.py | 896 -- .../_vendor/html5lib/filters/whitespace.py | 38 - .../pip/_vendor/html5lib/html5parser.py | 2791 ------ .../pip/_vendor/html5lib/serializer.py | 409 - .../_vendor/html5lib/treeadapters/__init__.py | 30 - .../_vendor/html5lib/treeadapters/genshi.py | 54 - .../pip/_vendor/html5lib/treeadapters/sax.py | 50 - .../_vendor/html5lib/treebuilders/__init__.py | 88 - .../pip/_vendor/html5lib/treebuilders/base.py | 417 - .../pip/_vendor/html5lib/treebuilders/dom.py | 236 - .../_vendor/html5lib/treebuilders/etree.py | 340 - .../html5lib/treebuilders/etree_lxml.py | 366 - .../_vendor/html5lib/treewalkers/__init__.py | 154 - .../pip/_vendor/html5lib/treewalkers/base.py | 252 - .../pip/_vendor/html5lib/treewalkers/dom.py | 43 - .../pip/_vendor/html5lib/treewalkers/etree.py | 130 - .../html5lib/treewalkers/etree_lxml.py | 213 - .../_vendor/html5lib/treewalkers/genshi.py | 69 - .../pip/_vendor/idna/__init__.py | 2 - .../site-packages/pip/_vendor/idna/codec.py | 118 - .../site-packages/pip/_vendor/idna/compat.py | 12 - .../site-packages/pip/_vendor/idna/core.py | 396 - .../pip/_vendor/idna/idnadata.py | 1979 ---- .../pip/_vendor/idna/intranges.py | 53 - .../pip/_vendor/idna/package_data.py | 2 - .../pip/_vendor/idna/uts46data.py | 8205 ----------------- .../site-packages/pip/_vendor/ipaddress.py | 2419 ----- .../pip/_vendor/lockfile/__init__.py | 347 - .../pip/_vendor/lockfile/linklockfile.py | 73 - .../pip/_vendor/lockfile/mkdirlockfile.py | 84 - .../pip/_vendor/lockfile/pidlockfile.py | 190 - .../pip/_vendor/lockfile/sqlitelockfile.py | 156 - .../pip/_vendor/lockfile/symlinklockfile.py | 70 - .../pip/_vendor/msgpack/__init__.py | 66 - .../pip/_vendor/msgpack/_version.py | 1 - .../pip/_vendor/msgpack/exceptions.py | 41 - .../pip/_vendor/msgpack/fallback.py | 977 -- .../pip/_vendor/packaging/__about__.py | 27 - .../pip/_vendor/packaging/__init__.py | 26 - .../pip/_vendor/packaging/_compat.py | 31 - .../pip/_vendor/packaging/_structures.py | 68 - .../pip/_vendor/packaging/markers.py | 296 - .../pip/_vendor/packaging/requirements.py | 138 - .../pip/_vendor/packaging/specifiers.py | 749 -- .../pip/_vendor/packaging/utils.py | 57 - .../pip/_vendor/packaging/version.py | 420 - .../pip/_vendor/pep517/__init__.py | 4 - .../pip/_vendor/pep517/_in_process.py | 207 - .../site-packages/pip/_vendor/pep517/build.py | 108 - .../site-packages/pip/_vendor/pep517/check.py | 202 - .../pip/_vendor/pep517/colorlog.py | 115 - .../pip/_vendor/pep517/compat.py | 23 - .../pip/_vendor/pep517/envbuild.py | 158 - .../pip/_vendor/pep517/wrappers.py | 163 - .../pip/_vendor/pkg_resources/__init__.py | 3286 ------- .../pip/_vendor/pkg_resources/py31compat.py | 23 - .../pip/_vendor/progress/__init__.py | 177 - .../site-packages/pip/_vendor/progress/bar.py | 91 - .../pip/_vendor/progress/counter.py | 41 - .../pip/_vendor/progress/spinner.py | 43 - .../site-packages/pip/_vendor/pyparsing.py | 6493 ------------- .../pip/_vendor/pytoml/__init__.py | 4 - .../site-packages/pip/_vendor/pytoml/core.py | 13 - .../pip/_vendor/pytoml/parser.py | 341 - .../site-packages/pip/_vendor/pytoml/test.py | 30 - .../site-packages/pip/_vendor/pytoml/utils.py | 67 - .../pip/_vendor/pytoml/writer.py | 106 - .../pip/_vendor/requests/__init__.py | 133 - .../pip/_vendor/requests/__version__.py | 14 - .../pip/_vendor/requests/_internal_utils.py | 42 - .../pip/_vendor/requests/adapters.py | 533 -- .../site-packages/pip/_vendor/requests/api.py | 158 - .../pip/_vendor/requests/auth.py | 305 - .../pip/_vendor/requests/certs.py | 18 - .../pip/_vendor/requests/compat.py | 74 - .../pip/_vendor/requests/cookies.py | 549 -- .../pip/_vendor/requests/exceptions.py | 126 - .../pip/_vendor/requests/help.py | 119 - .../pip/_vendor/requests/hooks.py | 34 - .../pip/_vendor/requests/models.py | 953 -- .../pip/_vendor/requests/packages.py | 16 - .../pip/_vendor/requests/sessions.py | 770 -- .../pip/_vendor/requests/status_codes.py | 120 - .../pip/_vendor/requests/structures.py | 103 - .../pip/_vendor/requests/utils.py | 977 -- .../site-packages/pip/_vendor/retrying.py | 267 - .../site-packages/pip/_vendor/six.py | 952 -- .../pip/_vendor/urllib3/__init__.py | 92 - .../pip/_vendor/urllib3/_collections.py | 329 - .../pip/_vendor/urllib3/connection.py | 391 - .../pip/_vendor/urllib3/connectionpool.py | 896 -- .../pip/_vendor/urllib3/contrib/__init__.py | 0 .../urllib3/contrib/_appengine_environ.py | 30 - .../contrib/_securetransport/__init__.py | 0 .../contrib/_securetransport/bindings.py | 593 -- .../contrib/_securetransport/low_level.py | 346 - .../pip/_vendor/urllib3/contrib/appengine.py | 289 - .../pip/_vendor/urllib3/contrib/ntlmpool.py | 111 - .../pip/_vendor/urllib3/contrib/pyopenssl.py | 466 - .../urllib3/contrib/securetransport.py | 804 -- .../pip/_vendor/urllib3/contrib/socks.py | 192 - .../pip/_vendor/urllib3/exceptions.py | 246 - .../pip/_vendor/urllib3/fields.py | 178 - .../pip/_vendor/urllib3/filepost.py | 98 - .../pip/_vendor/urllib3/packages/__init__.py | 5 - .../urllib3/packages/backports/__init__.py | 0 .../urllib3/packages/backports/makefile.py | 53 - .../pip/_vendor/urllib3/packages/six.py | 868 -- .../packages/ssl_match_hostname/__init__.py | 19 - .../ssl_match_hostname/_implementation.py | 156 - .../pip/_vendor/urllib3/poolmanager.py | 450 - .../pip/_vendor/urllib3/request.py | 150 - .../pip/_vendor/urllib3/response.py | 705 -- .../pip/_vendor/urllib3/util/__init__.py | 54 - .../pip/_vendor/urllib3/util/connection.py | 134 - .../pip/_vendor/urllib3/util/queue.py | 21 - .../pip/_vendor/urllib3/util/request.py | 118 - .../pip/_vendor/urllib3/util/response.py | 87 - .../pip/_vendor/urllib3/util/retry.py | 411 - .../pip/_vendor/urllib3/util/ssl_.py | 381 - .../pip/_vendor/urllib3/util/timeout.py | 242 - .../pip/_vendor/urllib3/util/url.py | 230 - .../pip/_vendor/urllib3/util/wait.py | 150 - .../pip/_vendor/webencodings/__init__.py | 342 - .../pip/_vendor/webencodings/labels.py | 231 - .../pip/_vendor/webencodings/mklabels.py | 59 - .../pip/_vendor/webencodings/tests.py | 153 - .../_vendor/webencodings/x_user_defined.py | 325 - .../site-packages/pkg_resources/__init__.py | 3286 ------- .../pkg_resources/_vendor/__init__.py | 0 .../pkg_resources/_vendor/appdirs.py | 608 -- .../_vendor/packaging/__about__.py | 21 - .../_vendor/packaging/__init__.py | 14 - .../_vendor/packaging/_compat.py | 30 - .../_vendor/packaging/_structures.py | 68 - .../_vendor/packaging/markers.py | 301 - .../_vendor/packaging/requirements.py | 127 - .../_vendor/packaging/specifiers.py | 774 -- .../pkg_resources/_vendor/packaging/utils.py | 14 - .../_vendor/packaging/version.py | 393 - .../pkg_resources/_vendor/pyparsing.py | 5742 ------------ .../pkg_resources/_vendor/six.py | 868 -- .../pkg_resources/extern/__init__.py | 73 - .../site-packages/pkg_resources/py31compat.py | 23 - .../setuptools-41.0.1.dist-info/INSTALLER | 1 - .../setuptools-41.0.1.dist-info/LICENSE | 19 - .../setuptools-41.0.1.dist-info/METADATA | 77 - .../setuptools-41.0.1.dist-info/RECORD | 186 - .../setuptools-41.0.1.dist-info/WHEEL | 6 - .../dependency_links.txt | 2 - .../entry_points.txt | 65 - .../setuptools-41.0.1.dist-info/top_level.txt | 3 - .../setuptools-41.0.1.dist-info/zip-safe | 1 - .../site-packages/setuptools/__init__.py | 228 - .../setuptools/_deprecation_warning.py | 7 - .../setuptools/_vendor/__init__.py | 0 .../setuptools/_vendor/packaging/__about__.py | 21 - .../setuptools/_vendor/packaging/__init__.py | 14 - .../setuptools/_vendor/packaging/_compat.py | 30 - .../_vendor/packaging/_structures.py | 68 - .../setuptools/_vendor/packaging/markers.py | 301 - .../_vendor/packaging/requirements.py | 127 - .../_vendor/packaging/specifiers.py | 774 -- .../setuptools/_vendor/packaging/utils.py | 14 - .../setuptools/_vendor/packaging/version.py | 393 - .../setuptools/_vendor/pyparsing.py | 5742 ------------ .../site-packages/setuptools/_vendor/six.py | 868 -- .../site-packages/setuptools/archive_util.py | 173 - .../site-packages/setuptools/build_meta.py | 254 - .../site-packages/setuptools/cli-32.exe | Bin 65536 -> 0 bytes .../site-packages/setuptools/cli-64.exe | Bin 74752 -> 0 bytes .../site-packages/setuptools/cli.exe | Bin 65536 -> 0 bytes .../setuptools/command/__init__.py | 18 - .../site-packages/setuptools/command/alias.py | 80 - .../setuptools/command/bdist_egg.py | 502 - .../setuptools/command/bdist_rpm.py | 43 - .../setuptools/command/bdist_wininst.py | 21 - .../setuptools/command/build_clib.py | 98 - .../setuptools/command/build_ext.py | 321 - .../setuptools/command/build_py.py | 270 - .../setuptools/command/develop.py | 221 - .../setuptools/command/dist_info.py | 36 - .../setuptools/command/easy_install.py | 2342 ----- .../setuptools/command/egg_info.py | 717 -- .../setuptools/command/install.py | 125 - .../setuptools/command/install_egg_info.py | 62 - .../setuptools/command/install_lib.py | 121 - .../setuptools/command/install_scripts.py | 65 - .../setuptools/command/launcher manifest.xml | 15 - .../setuptools/command/py36compat.py | 136 - .../setuptools/command/register.py | 18 - .../setuptools/command/rotate.py | 66 - .../setuptools/command/saveopts.py | 22 - .../site-packages/setuptools/command/sdist.py | 221 - .../setuptools/command/setopt.py | 149 - .../site-packages/setuptools/command/test.py | 271 - .../setuptools/command/upload.py | 196 - .../setuptools/command/upload_docs.py | 206 - .../site-packages/setuptools/config.py | 656 -- .../site-packages/setuptools/dep_util.py | 23 - .../site-packages/setuptools/depends.py | 186 - .../site-packages/setuptools/dist.py | 1278 --- .../site-packages/setuptools/extension.py | 57 - .../setuptools/extern/__init__.py | 73 - .../site-packages/setuptools/glibc.py | 86 - .../site-packages/setuptools/glob.py | 174 - .../site-packages/setuptools/gui-32.exe | Bin 65536 -> 0 bytes .../site-packages/setuptools/gui-64.exe | Bin 75264 -> 0 bytes .../site-packages/setuptools/gui.exe | Bin 65536 -> 0 bytes .../site-packages/setuptools/launch.py | 35 - .../site-packages/setuptools/lib2to3_ex.py | 62 - .../site-packages/setuptools/monkey.py | 179 - .../site-packages/setuptools/msvc.py | 1301 --- .../site-packages/setuptools/namespaces.py | 107 - .../site-packages/setuptools/package_index.py | 1136 --- .../site-packages/setuptools/pep425tags.py | 319 - .../site-packages/setuptools/py27compat.py | 28 - .../site-packages/setuptools/py31compat.py | 32 - .../site-packages/setuptools/py33compat.py | 55 - .../site-packages/setuptools/sandbox.py | 491 - .../setuptools/script (dev).tmpl | 6 - .../site-packages/setuptools/script.tmpl | 3 - .../site-packages/setuptools/site-patch.py | 74 - .../site-packages/setuptools/ssl_support.py | 260 - .../site-packages/setuptools/unicode_utils.py | 44 - .../site-packages/setuptools/version.py | 6 - .../site-packages/setuptools/wheel.py | 211 - .../setuptools/windows_support.py | 29 - .../wheel-0.33.4.dist-info/INSTALLER | 1 - .../wheel-0.33.4.dist-info/LICENSE.txt | 22 - .../wheel-0.33.4.dist-info/METADATA | 60 - .../wheel-0.33.4.dist-info/RECORD | 32 - .../wheel-0.33.4.dist-info/WHEEL | 6 - .../wheel-0.33.4.dist-info/entry_points.txt | 6 - .../wheel-0.33.4.dist-info/top_level.txt | 1 - .../python2.7/site-packages/wheel/__init__.py | 2 - .../python2.7/site-packages/wheel/__main__.py | 19 - .../site-packages/wheel/bdist_wheel.py | 372 - .../site-packages/wheel/cli/__init__.py | 88 - .../site-packages/wheel/cli/convert.py | 269 - .../python2.7/site-packages/wheel/cli/pack.py | 58 - .../site-packages/wheel/cli/unpack.py | 25 - .../python2.7/site-packages/wheel/metadata.py | 141 - .../site-packages/wheel/pep425tags.py | 185 - .../python2.7/site-packages/wheel/pkginfo.py | 43 - .../lib/python2.7/site-packages/wheel/util.py | 46 - .../site-packages/wheel/wheelfile.py | 169 - venv2/lib/python2.7/site.py | 851 -- venv2/lib/python2.7/sre.py | 1 - venv2/lib/python2.7/sre_compile.py | 1 - venv2/lib/python2.7/sre_constants.py | 1 - venv2/lib/python2.7/sre_parse.py | 1 - venv2/lib/python2.7/stat.py | 1 - venv2/lib/python2.7/types.py | 1 - venv2/lib/python2.7/warnings.py | 1 - venv2/local/bin | 1 - venv2/local/lib | 1 - 485 files changed, 145094 deletions(-) delete mode 100644 .idea/BMS View.iml delete mode 100644 .idea/libraries/R_User_Library.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml delete mode 100644 venv2/bin/activate delete mode 100644 venv2/bin/activate.csh delete mode 100644 venv2/bin/activate.fish delete mode 100644 venv2/bin/activate.ps1 delete mode 100644 venv2/bin/activate_this.py delete mode 100755 venv2/bin/easy_install delete mode 100755 venv2/bin/easy_install-2.7 delete mode 100755 venv2/bin/pip delete mode 100755 venv2/bin/pip2 delete mode 100755 venv2/bin/pip2.7 delete mode 120000 venv2/bin/python delete mode 100755 venv2/bin/python-config delete mode 120000 venv2/bin/python2 delete mode 100755 venv2/bin/python2.7 delete mode 100755 venv2/bin/wheel delete mode 120000 venv2/lib/python2.7/LICENSE.txt delete mode 120000 venv2/lib/python2.7/UserDict.py delete mode 120000 venv2/lib/python2.7/_abcoll.py delete mode 120000 venv2/lib/python2.7/_weakrefset.py delete mode 120000 venv2/lib/python2.7/abc.py delete mode 120000 venv2/lib/python2.7/codecs.py delete mode 120000 venv2/lib/python2.7/copy_reg.py delete mode 100644 venv2/lib/python2.7/distutils/__init__.py delete mode 100644 venv2/lib/python2.7/distutils/distutils.cfg delete mode 120000 venv2/lib/python2.7/encodings delete mode 120000 venv2/lib/python2.7/fnmatch.py delete mode 120000 venv2/lib/python2.7/genericpath.py delete mode 120000 venv2/lib/python2.7/lib-dynload delete mode 120000 venv2/lib/python2.7/linecache.py delete mode 120000 venv2/lib/python2.7/locale.py delete mode 100644 venv2/lib/python2.7/no-global-site-packages.txt delete mode 120000 venv2/lib/python2.7/ntpath.py delete mode 100644 venv2/lib/python2.7/orig-prefix.txt delete mode 120000 venv2/lib/python2.7/os.py delete mode 120000 venv2/lib/python2.7/posixpath.py delete mode 120000 venv2/lib/python2.7/re.py delete mode 100644 venv2/lib/python2.7/site-packages/easy_install.py delete mode 100644 venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/INSTALLER delete mode 100644 venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/LICENSE.txt delete mode 100644 venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/METADATA delete mode 100644 venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/RECORD delete mode 100644 venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/WHEEL delete mode 100644 venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/entry_points.txt delete mode 100644 venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/top_level.txt delete mode 100644 venv2/lib/python2.7/site-packages/pip/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/__main__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/build_env.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/cache.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/cli/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/cli/autocompletion.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/cli/base_command.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/cli/cmdoptions.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/cli/main_parser.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/cli/parser.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/cli/status_codes.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/commands/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/commands/check.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/commands/completion.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/commands/configuration.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/commands/download.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/commands/freeze.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/commands/hash.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/commands/help.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/commands/install.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/commands/list.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/commands/search.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/commands/show.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/commands/uninstall.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/commands/wheel.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/configuration.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/download.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/exceptions.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/index.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/locations.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/models/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/models/candidate.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/models/format_control.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/models/index.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/models/link.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/operations/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/operations/check.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/operations/freeze.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/operations/prepare.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/pep425tags.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/pyproject.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/req/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/req/constructors.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/req/req_file.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/req/req_install.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/req/req_set.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/req/req_tracker.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/req/req_uninstall.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/resolve.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/utils/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/utils/appdirs.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/utils/compat.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/utils/deprecation.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/utils/encoding.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/utils/filesystem.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/utils/glibc.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/utils/hashes.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/utils/logging.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/utils/misc.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/utils/models.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/utils/outdated.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/utils/packaging.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/utils/setuptools_build.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/utils/temp_dir.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/utils/typing.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/utils/ui.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/vcs/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/vcs/bazaar.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/vcs/git.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/vcs/mercurial.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/vcs/subversion.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_internal/wheel.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/appdirs.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/_cmd.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/adapter.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/cache.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/caches/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/compat.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/controller.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/filewrapper.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/heuristics.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/serialize.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/wrapper.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/certifi/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/certifi/__main__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/certifi/cacert.pem delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/certifi/core.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/big5freq.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/big5prober.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/chardistribution.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/charsetgroupprober.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/charsetprober.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/cli/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/cli/chardetect.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/codingstatemachine.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/compat.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/cp949prober.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/enums.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/escprober.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/escsm.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/eucjpprober.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/euckrfreq.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/euckrprober.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/euctwfreq.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/euctwprober.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/gb2312freq.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/gb2312prober.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/hebrewprober.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/jisfreq.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/jpcntx.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langbulgarianmodel.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langcyrillicmodel.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langgreekmodel.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langhebrewmodel.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langhungarianmodel.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langthaimodel.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langturkishmodel.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/latin1prober.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/mbcharsetprober.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/mbcsgroupprober.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/mbcssm.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/sbcharsetprober.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/sbcsgroupprober.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/sjisprober.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/universaldetector.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/utf8prober.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/chardet/version.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/colorama/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/colorama/ansi.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/colorama/ansitowin32.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/colorama/initialise.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/colorama/win32.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/colorama/winterm.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/misc.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/shutil.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/sysconfig.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/tarfile.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/compat.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/database.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/index.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/locators.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/manifest.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/markers.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/metadata.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/resources.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/scripts.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/t32.exe delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/t64.exe delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/util.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/version.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/w32.exe delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/w64.exe delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distlib/wheel.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/distro.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_ihatexml.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_inputstream.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_tokenizer.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_trie/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_trie/_base.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_trie/datrie.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_trie/py.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_utils.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/constants.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/base.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/lint.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/optionaltags.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/sanitizer.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/whitespace.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/html5parser.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/serializer.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treeadapters/genshi.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treeadapters/sax.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/base.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/dom.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/etree.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/base.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/dom.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/etree.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/genshi.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/idna/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/idna/codec.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/idna/compat.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/idna/core.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/idna/idnadata.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/idna/intranges.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/idna/package_data.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/idna/uts46data.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/ipaddress.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/linklockfile.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/mkdirlockfile.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/pidlockfile.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/sqlitelockfile.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/symlinklockfile.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/msgpack/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/msgpack/_version.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/msgpack/exceptions.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/msgpack/fallback.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/packaging/__about__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/packaging/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/packaging/_compat.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/packaging/_structures.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/packaging/markers.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/packaging/requirements.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/packaging/specifiers.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/packaging/utils.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/packaging/version.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/pep517/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/pep517/_in_process.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/pep517/build.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/pep517/check.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/pep517/colorlog.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/pep517/compat.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/pep517/envbuild.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/pep517/wrappers.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/pkg_resources/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/pkg_resources/py31compat.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/progress/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/progress/bar.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/progress/counter.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/progress/spinner.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/pyparsing.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/core.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/parser.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/test.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/utils.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/writer.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/requests/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/requests/__version__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/requests/_internal_utils.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/requests/adapters.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/requests/api.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/requests/auth.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/requests/certs.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/requests/compat.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/requests/cookies.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/requests/exceptions.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/requests/help.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/requests/hooks.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/requests/models.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/requests/packages.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/requests/sessions.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/requests/status_codes.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/requests/structures.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/requests/utils.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/retrying.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/six.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/_collections.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/connection.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/connectionpool.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/appengine.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/securetransport.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/socks.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/exceptions.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/fields.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/filepost.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/six.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/poolmanager.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/request.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/response.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/connection.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/queue.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/request.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/response.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/retry.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/ssl_.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/timeout.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/url.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/wait.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/labels.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/mklabels.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/tests.py delete mode 100644 venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/x_user_defined.py delete mode 100644 venv2/lib/python2.7/site-packages/pkg_resources/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pkg_resources/_vendor/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.py delete mode 100644 venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/__about__.py delete mode 100644 venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_compat.py delete mode 100644 venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.py delete mode 100644 venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.py delete mode 100644 venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.py delete mode 100644 venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.py delete mode 100644 venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/utils.py delete mode 100644 venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.py delete mode 100644 venv2/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.py delete mode 100644 venv2/lib/python2.7/site-packages/pkg_resources/_vendor/six.py delete mode 100644 venv2/lib/python2.7/site-packages/pkg_resources/extern/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/pkg_resources/py31compat.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/INSTALLER delete mode 100644 venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/LICENSE delete mode 100644 venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/METADATA delete mode 100644 venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/RECORD delete mode 100644 venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/WHEEL delete mode 100644 venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/dependency_links.txt delete mode 100644 venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/entry_points.txt delete mode 100644 venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/top_level.txt delete mode 100644 venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/zip-safe delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/_deprecation_warning.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/_vendor/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/__about__.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/_compat.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/_structures.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/markers.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/requirements.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/specifiers.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/utils.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/version.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/_vendor/pyparsing.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/_vendor/six.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/archive_util.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/build_meta.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/cli-32.exe delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/cli-64.exe delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/cli.exe delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/alias.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/bdist_egg.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/bdist_rpm.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/bdist_wininst.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/build_clib.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/build_ext.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/build_py.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/develop.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/dist_info.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/easy_install.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/egg_info.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/install.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/install_egg_info.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/install_lib.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/install_scripts.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/launcher manifest.xml delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/py36compat.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/register.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/rotate.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/saveopts.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/sdist.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/setopt.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/test.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/upload.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/command/upload_docs.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/config.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/dep_util.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/depends.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/dist.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/extension.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/extern/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/glibc.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/glob.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/gui-32.exe delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/gui-64.exe delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/gui.exe delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/launch.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/lib2to3_ex.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/monkey.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/msvc.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/namespaces.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/package_index.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/pep425tags.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/py27compat.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/py31compat.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/py33compat.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/sandbox.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/script (dev).tmpl delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/script.tmpl delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/site-patch.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/ssl_support.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/unicode_utils.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/version.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/wheel.py delete mode 100644 venv2/lib/python2.7/site-packages/setuptools/windows_support.py delete mode 100644 venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/INSTALLER delete mode 100644 venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/LICENSE.txt delete mode 100644 venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/METADATA delete mode 100644 venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/RECORD delete mode 100644 venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/WHEEL delete mode 100644 venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/entry_points.txt delete mode 100644 venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/top_level.txt delete mode 100644 venv2/lib/python2.7/site-packages/wheel/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/wheel/__main__.py delete mode 100644 venv2/lib/python2.7/site-packages/wheel/bdist_wheel.py delete mode 100644 venv2/lib/python2.7/site-packages/wheel/cli/__init__.py delete mode 100644 venv2/lib/python2.7/site-packages/wheel/cli/convert.py delete mode 100644 venv2/lib/python2.7/site-packages/wheel/cli/pack.py delete mode 100644 venv2/lib/python2.7/site-packages/wheel/cli/unpack.py delete mode 100644 venv2/lib/python2.7/site-packages/wheel/metadata.py delete mode 100644 venv2/lib/python2.7/site-packages/wheel/pep425tags.py delete mode 100644 venv2/lib/python2.7/site-packages/wheel/pkginfo.py delete mode 100644 venv2/lib/python2.7/site-packages/wheel/util.py delete mode 100644 venv2/lib/python2.7/site-packages/wheel/wheelfile.py delete mode 100644 venv2/lib/python2.7/site.py delete mode 120000 venv2/lib/python2.7/sre.py delete mode 120000 venv2/lib/python2.7/sre_compile.py delete mode 120000 venv2/lib/python2.7/sre_constants.py delete mode 120000 venv2/lib/python2.7/sre_parse.py delete mode 120000 venv2/lib/python2.7/stat.py delete mode 120000 venv2/lib/python2.7/types.py delete mode 120000 venv2/lib/python2.7/warnings.py delete mode 120000 venv2/local/bin delete mode 120000 venv2/local/lib diff --git a/.idea/BMS View.iml b/.idea/BMS View.iml deleted file mode 100644 index e7ea071..0000000 --- a/.idea/BMS View.iml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/libraries/R_User_Library.xml b/.idea/libraries/R_User_Library.xml deleted file mode 100644 index 71f5ff7..0000000 --- a/.idea/libraries/R_User_Library.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 030e88f..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 4ece769..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/venv2/bin/activate b/venv2/bin/activate deleted file mode 100644 index 960f35c..0000000 --- a/venv2/bin/activate +++ /dev/null @@ -1,78 +0,0 @@ -# This file must be used with "source bin/activate" *from bash* -# you cannot run it directly - -deactivate () { - unset -f pydoc >/dev/null 2>&1 - - # reset old environment variables - # ! [ -z ${VAR+_} ] returns true if VAR is declared at all - if ! [ -z "${_OLD_VIRTUAL_PATH+_}" ] ; then - PATH="$_OLD_VIRTUAL_PATH" - export PATH - unset _OLD_VIRTUAL_PATH - fi - if ! [ -z "${_OLD_VIRTUAL_PYTHONHOME+_}" ] ; then - PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME" - export PYTHONHOME - unset _OLD_VIRTUAL_PYTHONHOME - fi - - # This should detect bash and zsh, which have a hash command that must - # be called to get it to forget past commands. Without forgetting - # past commands the $PATH changes we made may not be respected - if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then - hash -r 2>/dev/null - fi - - if ! [ -z "${_OLD_VIRTUAL_PS1+_}" ] ; then - PS1="$_OLD_VIRTUAL_PS1" - export PS1 - unset _OLD_VIRTUAL_PS1 - fi - - unset VIRTUAL_ENV - if [ ! "${1-}" = "nondestructive" ] ; then - # Self destruct! - unset -f deactivate - fi -} - -# unset irrelevant variables -deactivate nondestructive - -VIRTUAL_ENV="/home/sean/Downloads/BMS-View/venv2" -export VIRTUAL_ENV - -_OLD_VIRTUAL_PATH="$PATH" -PATH="$VIRTUAL_ENV/bin:$PATH" -export PATH - -# unset PYTHONHOME if set -if ! [ -z "${PYTHONHOME+_}" ] ; then - _OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME" - unset PYTHONHOME -fi - -if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then - _OLD_VIRTUAL_PS1="${PS1-}" - if [ "x" != x ] ; then - PS1="${PS1-}" - else - PS1="(`basename \"$VIRTUAL_ENV\"`) ${PS1-}" - fi - export PS1 -fi - -# Make sure to unalias pydoc if it's already there -alias pydoc 2>/dev/null >/dev/null && unalias pydoc || true - -pydoc () { - python -m pydoc "$@" -} - -# This should detect bash and zsh, which have a hash command that must -# be called to get it to forget past commands. Without forgetting -# past commands the $PATH changes we made may not be respected -if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then - hash -r 2>/dev/null -fi diff --git a/venv2/bin/activate.csh b/venv2/bin/activate.csh deleted file mode 100644 index 36276a9..0000000 --- a/venv2/bin/activate.csh +++ /dev/null @@ -1,42 +0,0 @@ -# This file must be used with "source bin/activate.csh" *from csh*. -# You cannot run it directly. -# Created by Davide Di Blasi . - -set newline='\ -' - -alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH:q" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT:q" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate && unalias pydoc' - -# Unset irrelevant variables. -deactivate nondestructive - -setenv VIRTUAL_ENV "/home/sean/Downloads/BMS-View/venv2" - -set _OLD_VIRTUAL_PATH="$PATH:q" -setenv PATH "$VIRTUAL_ENV:q/bin:$PATH:q" - - - -if ("" != "") then - set env_name = "" -else - set env_name = "$VIRTUAL_ENV:t:q" -endif - -# Could be in a non-interactive environment, -# in which case, $prompt is undefined and we wouldn't -# care about the prompt anyway. -if ( $?prompt ) then - set _OLD_VIRTUAL_PROMPT="$prompt:q" -if ( "$prompt:q" =~ *"$newline:q"* ) then - : -else - set prompt = "[$env_name:q] $prompt:q" -endif -endif - -unset env_name - -alias pydoc python -m pydoc - -rehash diff --git a/venv2/bin/activate.fish b/venv2/bin/activate.fish deleted file mode 100644 index 4b2bc39..0000000 --- a/venv2/bin/activate.fish +++ /dev/null @@ -1,101 +0,0 @@ -# This file must be used using `source bin/activate.fish` *within a running fish ( http://fishshell.com ) session*. -# Do not run it directly. - -function _bashify_path -d "Converts a fish path to something bash can recognize" - set fishy_path $argv - set bashy_path $fishy_path[1] - for path_part in $fishy_path[2..-1] - set bashy_path "$bashy_path:$path_part" - end - echo $bashy_path -end - -function _fishify_path -d "Converts a bash path to something fish can recognize" - echo $argv | tr ':' '\n' -end - -function deactivate -d 'Exit virtualenv mode and return to the normal environment.' - # reset old environment variables - if test -n "$_OLD_VIRTUAL_PATH" - # https://github.com/fish-shell/fish-shell/issues/436 altered PATH handling - if test (echo $FISH_VERSION | tr "." "\n")[1] -lt 3 - set -gx PATH (_fishify_path $_OLD_VIRTUAL_PATH) - else - set -gx PATH $_OLD_VIRTUAL_PATH - end - set -e _OLD_VIRTUAL_PATH - end - - if test -n "$_OLD_VIRTUAL_PYTHONHOME" - set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME - set -e _OLD_VIRTUAL_PYTHONHOME - end - - if test -n "$_OLD_FISH_PROMPT_OVERRIDE" - # Set an empty local `$fish_function_path` to allow the removal of `fish_prompt` using `functions -e`. - set -l fish_function_path - - # Erase virtualenv's `fish_prompt` and restore the original. - functions -e fish_prompt - functions -c _old_fish_prompt fish_prompt - functions -e _old_fish_prompt - set -e _OLD_FISH_PROMPT_OVERRIDE - end - - set -e VIRTUAL_ENV - - if test "$argv[1]" != 'nondestructive' - # Self-destruct! - functions -e pydoc - functions -e deactivate - functions -e _bashify_path - functions -e _fishify_path - end -end - -# Unset irrelevant variables. -deactivate nondestructive - -set -gx VIRTUAL_ENV "/home/sean/Downloads/BMS-View/venv2" - -# https://github.com/fish-shell/fish-shell/issues/436 altered PATH handling -if test (echo $FISH_VERSION | tr "." "\n")[1] -lt 3 - set -gx _OLD_VIRTUAL_PATH (_bashify_path $PATH) -else - set -gx _OLD_VIRTUAL_PATH $PATH -end -set -gx PATH "$VIRTUAL_ENV/bin" $PATH - -# Unset `$PYTHONHOME` if set. -if set -q PYTHONHOME - set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME - set -e PYTHONHOME -end - -function pydoc - python -m pydoc $argv -end - -if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" - # Copy the current `fish_prompt` function as `_old_fish_prompt`. - functions -c fish_prompt _old_fish_prompt - - function fish_prompt - # Save the current $status, for fish_prompts that display it. - set -l old_status $status - - # Prompt override provided? - # If not, just prepend the environment name. - if test -n "" - printf '%s%s' "" (set_color normal) - else - printf '%s(%s) ' (set_color normal) (basename "$VIRTUAL_ENV") - end - - # Restore the original $status - echo "exit $old_status" | source - _old_fish_prompt - end - - set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" -end diff --git a/venv2/bin/activate.ps1 b/venv2/bin/activate.ps1 deleted file mode 100644 index 6d8ae2a..0000000 --- a/venv2/bin/activate.ps1 +++ /dev/null @@ -1,60 +0,0 @@ -# This file must be dot sourced from PoSh; you cannot run it directly. Do this: . ./activate.ps1 - -$script:THIS_PATH = $myinvocation.mycommand.path -$script:BASE_DIR = split-path (resolve-path "$THIS_PATH/..") -Parent - -function global:deactivate([switch] $NonDestructive) -{ - if (test-path variable:_OLD_VIRTUAL_PATH) - { - $env:PATH = $variable:_OLD_VIRTUAL_PATH - remove-variable "_OLD_VIRTUAL_PATH" -scope global - } - - if (test-path function:_old_virtual_prompt) - { - $function:prompt = $function:_old_virtual_prompt - remove-item function:\_old_virtual_prompt - } - - if ($env:VIRTUAL_ENV) - { - $old_env = split-path $env:VIRTUAL_ENV -leaf - remove-item env:VIRTUAL_ENV -erroraction silentlycontinue - } - - if (!$NonDestructive) - { - # Self destruct! - remove-item function:deactivate - remove-item function:pydoc - } -} - -function global:pydoc -{ - python -m pydoc $args -} - -# unset irrelevant variables -deactivate -nondestructive - -$VIRTUAL_ENV = $BASE_DIR -$env:VIRTUAL_ENV = $VIRTUAL_ENV - -$global:_OLD_VIRTUAL_PATH = $env:PATH -$env:PATH = "$env:VIRTUAL_ENV/bin:" + $env:PATH -if (!$env:VIRTUAL_ENV_DISABLE_PROMPT) -{ - function global:_old_virtual_prompt - { - "" - } - $function:_old_virtual_prompt = $function:prompt - function global:prompt - { - # Add a prefix to the current prompt, but don't discard it. - write-host "($( split-path $env:VIRTUAL_ENV -leaf )) " -nonewline - & $function:_old_virtual_prompt - } -} diff --git a/venv2/bin/activate_this.py b/venv2/bin/activate_this.py deleted file mode 100644 index 59b5d72..0000000 --- a/venv2/bin/activate_this.py +++ /dev/null @@ -1,46 +0,0 @@ -"""Activate virtualenv for current interpreter: - -Use exec(open(this_file).read(), {'__file__': this_file}). - -This can be used when you must use an existing Python interpreter, not the virtualenv bin/python. -""" -import os -import site -import sys - -try: - __file__ -except NameError: - raise AssertionError("You must use exec(open(this_file).read(), {'__file__': this_file}))") - -# prepend bin to PATH (this file is inside the bin directory) -bin_dir = os.path.dirname(os.path.abspath(__file__)) -os.environ["PATH"] = os.pathsep.join([bin_dir] + os.environ.get("PATH", "").split(os.pathsep)) - -base = os.path.dirname(bin_dir) - -# virtual env is right above bin directory -os.environ["VIRTUAL_ENV"] = base - -# add the virtual environments site-package to the host python import mechanism -IS_PYPY = hasattr(sys, "pypy_version_info") -IS_JYTHON = sys.platform.startswith("java") -if IS_JYTHON: - site_packages = os.path.join(base, "Lib", "site-packages") -elif IS_PYPY: - site_packages = os.path.join(base, "site-packages") -else: - IS_WIN = sys.platform == "win32" - if IS_WIN: - site_packages = os.path.join(base, "Lib", "site-packages") - else: - site_packages = os.path.join(base, "lib", "python{}".format(sys.version[:3]), "site-packages") - -prev = set(sys.path) -site.addsitedir(site_packages) -sys.real_prefix = sys.prefix -sys.prefix = base - -# Move the added items to the front of the path, in place -new = list(sys.path) -sys.path[:] = [i for i in new if i not in prev] + [i for i in new if i in prev] diff --git a/venv2/bin/easy_install b/venv2/bin/easy_install deleted file mode 100755 index 139a8c9..0000000 --- a/venv2/bin/easy_install +++ /dev/null @@ -1,10 +0,0 @@ -#!/home/sean/Downloads/BMS-View/venv2/bin/python2.7 -# -*- coding: utf-8 -*- -import re -import sys - -from setuptools.command.easy_install import main - -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/venv2/bin/easy_install-2.7 b/venv2/bin/easy_install-2.7 deleted file mode 100755 index 139a8c9..0000000 --- a/venv2/bin/easy_install-2.7 +++ /dev/null @@ -1,10 +0,0 @@ -#!/home/sean/Downloads/BMS-View/venv2/bin/python2.7 -# -*- coding: utf-8 -*- -import re -import sys - -from setuptools.command.easy_install import main - -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/venv2/bin/pip b/venv2/bin/pip deleted file mode 100755 index 979b5e0..0000000 --- a/venv2/bin/pip +++ /dev/null @@ -1,10 +0,0 @@ -#!/home/sean/Downloads/BMS-View/venv2/bin/python2.7 -# -*- coding: utf-8 -*- -import re -import sys - -from pip._internal import main - -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/venv2/bin/pip2 b/venv2/bin/pip2 deleted file mode 100755 index 979b5e0..0000000 --- a/venv2/bin/pip2 +++ /dev/null @@ -1,10 +0,0 @@ -#!/home/sean/Downloads/BMS-View/venv2/bin/python2.7 -# -*- coding: utf-8 -*- -import re -import sys - -from pip._internal import main - -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/venv2/bin/pip2.7 b/venv2/bin/pip2.7 deleted file mode 100755 index 979b5e0..0000000 --- a/venv2/bin/pip2.7 +++ /dev/null @@ -1,10 +0,0 @@ -#!/home/sean/Downloads/BMS-View/venv2/bin/python2.7 -# -*- coding: utf-8 -*- -import re -import sys - -from pip._internal import main - -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/venv2/bin/python b/venv2/bin/python deleted file mode 120000 index 8f7a3c1..0000000 --- a/venv2/bin/python +++ /dev/null @@ -1 +0,0 @@ -python2.7 \ No newline at end of file diff --git a/venv2/bin/python-config b/venv2/bin/python-config deleted file mode 100755 index 3e01499..0000000 --- a/venv2/bin/python-config +++ /dev/null @@ -1,78 +0,0 @@ -#!/home/sean/Downloads/BMS-View/venv2/bin/python - -import sys -import getopt -import sysconfig - -valid_opts = ['prefix', 'exec-prefix', 'includes', 'libs', 'cflags', - 'ldflags', 'help'] - -if sys.version_info >= (3, 2): - valid_opts.insert(-1, 'extension-suffix') - valid_opts.append('abiflags') -if sys.version_info >= (3, 3): - valid_opts.append('configdir') - - -def exit_with_usage(code=1): - sys.stderr.write("Usage: {0} [{1}]\n".format( - sys.argv[0], '|'.join('--'+opt for opt in valid_opts))) - sys.exit(code) - -try: - opts, args = getopt.getopt(sys.argv[1:], '', valid_opts) -except getopt.error: - exit_with_usage() - -if not opts: - exit_with_usage() - -pyver = sysconfig.get_config_var('VERSION') -getvar = sysconfig.get_config_var - -opt_flags = [flag for (flag, val) in opts] - -if '--help' in opt_flags: - exit_with_usage(code=0) - -for opt in opt_flags: - if opt == '--prefix': - print(sysconfig.get_config_var('prefix')) - - elif opt == '--exec-prefix': - print(sysconfig.get_config_var('exec_prefix')) - - elif opt in ('--includes', '--cflags'): - flags = ['-I' + sysconfig.get_path('include'), - '-I' + sysconfig.get_path('platinclude')] - if opt == '--cflags': - flags.extend(getvar('CFLAGS').split()) - print(' '.join(flags)) - - elif opt in ('--libs', '--ldflags'): - abiflags = getattr(sys, 'abiflags', '') - libs = ['-lpython' + pyver + abiflags] - libs += getvar('LIBS').split() - libs += getvar('SYSLIBS').split() - # add the prefix/lib/pythonX.Y/config dir, but only if there is no - # shared library in prefix/lib/. - if opt == '--ldflags': - if not getvar('Py_ENABLE_SHARED'): - libs.insert(0, '-L' + getvar('LIBPL')) - if not getvar('PYTHONFRAMEWORK'): - libs.extend(getvar('LINKFORSHARED').split()) - print(' '.join(libs)) - - elif opt == '--extension-suffix': - ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') - if ext_suffix is None: - ext_suffix = sysconfig.get_config_var('SO') - print(ext_suffix) - - elif opt == '--abiflags': - if not getattr(sys, 'abiflags', None): - exit_with_usage() - print(sys.abiflags) - - elif opt == '--configdir': - print(sysconfig.get_config_var('LIBPL')) diff --git a/venv2/bin/python2 b/venv2/bin/python2 deleted file mode 120000 index 8f7a3c1..0000000 --- a/venv2/bin/python2 +++ /dev/null @@ -1 +0,0 @@ -python2.7 \ No newline at end of file diff --git a/venv2/bin/python2.7 b/venv2/bin/python2.7 deleted file mode 100755 index f0691d4ee883da52afa53a3c0a130a87452cb640..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3691008 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

B78%kS5IM!b;N7;r+GHXvRH{i5h@6e$Dz+XGCB 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
    Bg!`p%`c<7$jM{kf~rB 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 z zzWZ0q#FcPRMrqCM8KqVA;p_b?=3pfq)TXrNt~T5fA0CA-*zh#Iv@NR{*0#Lr{qR7( zj3HX^pv%Lc8*+t>M#Nhgqlaa0eK@^!BASmk|2A&PNTE zKj1$fP7g)PQ*=g|gIkHc%f~95Ze%wCd)o!QAdknoL8_)SSg~{h6x4>tSTQEQ&reC8 zNqV12UPGO5mRQLe=71`$nrZRDhDHuBq$hOdI(zhFLl?szaw0uCJ}X&5;;ramlbxgN zBlZc+yVi6(D`oR{cv2|f!xVzNd=8m%Nm%qpd{onfljYG3*eE}vZ@9y52rfF}60X~6 zK+wl|te&Y9mblO2;r{joisHlTQ;@FRzHM8XN4jVGMyqQ?ZA0fOtJd z;omab;yhNR$GYqE%pqM_9Qi?|#0RD8Bu%vlywz*HRo9rx0FtdNhTidL`&r#j&>st1 zJjfjf1P_-4ix5H{psWgR$cn6QO1#UJ&)NPJcjXc4))#J*K#5nIUex~%*uBLqweZoG zxZkVNyezh+ug2~fPD!`$K3=?3&5N$L2t^mEB42U;+b8?0=jkg(qI(AL;GTO67Hypu z;^K^3y5|il>hn zjT+BwcD@I@S+EQ@-}fFY%Y#)2#4aX*g_9hCzz-ru-|#G8$8&Pz|3G?=K+R$fF;W0YN-k< zJlKUEY=&UoU>13>&K~Rv!FX0>=Xfyb2h{QYf_a0|*@JEMU_Au$2F2&W-t}N9f~Dk| zGWUP%PQv3J?7u$>#tZdr^V&z3#zAc(CPy@vJhR@?a9l z)Q7NO-b(m`2Rp@sjW_kV`R04Dqac>@4QK_s)q`#GV7Y>M<2liTt@dE)f_ZHTda$QG zn7zNHEth(*m4%us?e+6VHG$ zckct%&V?=YV2Y)s`ZfyI-i6KaU^6|~tAcfKVbeU=I1l!aV15@i#)B1mu(^V@abcHv zuroZ^WWn0HFvWw>xTJZoGQoT3;WuGDZaS!eJWTN7q-EJ-QmGj3U-nUd(DGQ^k9z)*2#rE;lT!au!Vwkbz#5v zU?`1DeK!bph6|hP!KB?*TP(qPy0Du)SOVM5cfJhlH2~QXlHYoQX74Ytnn@xX^yW${H4h5{%#1LBfAj{k|BJ;q$dj1u~*?P zykln*Ooi+0XD%epn2G#YHJwk)M$JI}`m1{>&n6Q)^3XKSxg!E3B{Tc+IxdtUX;p$+ z+<;K z4-`8sBWA=3I)|^9uDO^oSpmZ?tzY;IIWsw=s-mZC3dQ<#!}+mtL=XA+#}XpaCYHK#8@sXNrAa0n=)9_Tlb!HzKPNbIZuIg#41!@2?uB z7Du<75CDMqOX{LKe_;|d&!45#@r=-PH~dm~AY**t&QnwD=iWCH5gv^Ibv1n{t(iH= z?)r#=Sj{fdbf`<3#fjv&;HLH|lbl`eYEoJ*<|?M_*`UgEOHeY-ohg z#Hh6!GHK#k{8mZKNgfTX=IEb<<(GA-pD7~G6fqlYD9zUWx;kW-`|b^@Pbz87(`x*w z*`)rOj#xw~(241#Z&HVJAe=13goDd3r%QtG!for{0;xRuBU(M6CRg z!Zj)1zhno%P#SAP@7ew(kJBz0RtUX{Ys5CZK6F+x)6V&$4zJ7F=;MC*F1QRzJZD6j z9t4oq1H?9$Z)8$l5ZBp?qVN6j&eX%1Y=$PYzFIOHo=h9~#s$YY!(x5*D$1=DTddXd zEdMb+U8XTAF8TIxg?7uMH}bvA6c8(H8fA+t#k;=Tlc=uscISKr9CXjGo~Mq)tZb>I zGp#pT4@9UJCks~jmmHyQ$$_AO48$f1HrIdomwl@VX*Cf4qjs8sm~p~D_|;z)9t}^9 zf)BsMZFc5Y}+ z%GIf1;zqTDCcbxJcd#UoNwg{YVnXwR3gaD#_ZY*SLjDeq-Le<-|K&8^p$-+7oc1@S zvAW0zlNiB5;HeNZ*fKl#&uV7ERFIq*7e)JP?p+jBa7uS(iiM&}QTWh)DUjarW_h5l z-&mHVR{FMbSN4MM)xZ8kvJm=MCbEI-DWxthFZszG_KR(4+~|_0X2M<4IFE9La}JJp zX7Rb}fWR_fRWLr_UfX{^qo*~X4@K|!m+ZxO<{Wp;{(tD@EqJHGjH_-1GU1CI;KA6C zOq8O8k#sa9hECX%lQ|#};pvL;a)qH0+T-XC3my+JE&qPJq&V-RKBq~9Eu5EQAH42o z+AnnX3{JZG*ZJ)(h~^;ul<23welFI}1^VfwpW*tsNk85BA^r?JK&0s;|KeIkgyppw zrh(8cQ_|nCd>fm#M~*M>FFp@Yw4MkboyHLSa7B*-{F*?*>|bmiI?rj+KgfCt5ZEo= z^Xt*=QU?214Ct)nkzJ|WbhyprO6u!O`dV6I%Krz+{VUQ7OzQ2~{&%+gqKf5<=qADa z7T>Ha`)ShA3-R8F{#a)d4{gT+jI=-C`+*iN-503a-nQJgekcu2#m6)~l-6^_Uvg56 zvMW$OxD#fPOF^P&1D3)pd+-@)^4iQ2FGw8gCVSPT>4q`v%!>fFuYbBMV_A`-*ZS{Y zRb9)OqP6(mtoVymjG#%oP9qtDRcl*n79yAN5Sr81w1xd_p^~ z`Jh05^^N2tj0*wS7;$qE`Zxa9dR#TN4nJh7xxcpEYIT2BvZk4&H$yaiq&q|nn+3lT zcyf5oWL+|4*-S|8+pt;@KnSZpFcVVpSP^)H2t z-h5je%&|a30*Mo6;Pa;Kzqk*3Y{4dTlY(^83h)#!to<4n8xspW!~gZEOaZIiuncgk z^RIA~;FmDu+GQcHS3;hX7mqE3LHU4bV^3U|628%j4KbWt%}GjLJlOKb+ww$-DIJEz zdT{)H4rYU<46tF=Ow_yEJLJ0h@E%@0zJy=0%ucGvt#Q(HuxOYhT@uNJbrdVH%Y?}#(=C23R{OK-He{LCxxM1GFj z>hi7Fow-KM8`K2+Krq|n#(uGij?G{Q?(rA}4Z%RZnj!F4eMi#__rX=?D1|rum-HZ1 zO_Ltfx@A&lI{SGwaZBycB85nEU0GgNqFC2OskyiWJujE;V0`9&!j;~}7t0M`YDJg# zhkje}3fqd_nrp@9ZM34nTu#ug#F6tcOoTO7{DB$ZEq880kGNe-j7#|zYtf!s4RbWU z(EJ%Y&5Dj4$pM-ER?*(d7lZ2tOBup6jL+n->!BXWY3TXu_Eg>yHP#8!0d^8I3E?yB z4s^)nx2gqkwtmN${c8BZCg(<8?LIsuwzY5s;7F#`V1yKq#usK&YH6hm3y(G>zCR(p7z@HkQ}E7;%knVjg=}hg?rQD(7M!AKe#|sq zGwuuD=1u$~BnZW>Bsv+PboOf?i^hSAJJlwZB!q3#DzPw}-_&{XVBNPk)BYzIyM3gh z>eoD}Z?Vy0rD$v5>cAvLD|ar)JKS2hK;FRW0Dj)(;%5!H>|sk<@H5*Ch{Xt-yA9Ps z;?4@KP<{L2gB; zAVxp!JTZ(YyTQT_6?3hy+uJ69xfLt6FZljYQ-X8K+!ukr(wuyI(mMx0cb7{J(+Cbx z&UJQ#6Y_0S*zun=?ku3HQW6i3mK`Dx|5{&SJ=I*lo}@MPevMsh-?1=tC*q7;u+{5V}1;`$h{iexLC- z{D~FgdWPBV9IO_;uf11u;I87Y`9SzB=D?6icMjgwN9N$~uW1exa_fG5k-nmJglX{K zLt`V|bDzV9$B#ftGb$ehlhb9EyGjTg?|KcM8}xMIB&R#^?_000pbYxwbfj1+b38hN%iza5Xp&ZcQbN0SNZCsTpnOWBu z`>S%aB9j5q;p7W9ufQx-|LP$LTU7_N4iUCM+I{x#pE$0M)#F7<5Lv5zW;M@2j2xaT z!yaphQ-DF=;gIhO?i};qa}p^R4s6dU02BpGE9U@%4Vx=`AK>WUHaycJJe={*(_#IE zmtlNcr$jOej^j5qtUJQebYlfKg`LlDM)(wd+i-lHbodhZOr}4yeyMJG3D5PCP?MWB z{F@L*$xzr;6n!}J`oO{gdF{jFlCaAa3^}zu_Qkx^a6m6<<|QqBiC#D}4J18$o?bG{ zOGdc6UfP(KHsOwXX=`5ERz9d=Ib%XR#coz~x(0i826o8>SJ{Vuh2RrelPeOi+N+(* z*ICAi4NSo8Z!BueAEz>B~)G>i9ZCvYTY<6 zCMWSoGyWJp3XuhDIkT98i-u%YPGrpySdY7YN3le8iHqiXf?4p~F%mwF#8sQ2UM>?N z640!#1Qb0H)B=+{Lz8rnC(}NA0ZY)d-DldauooDam$t%Xr5`H|DazFb0(%ygukB2w zXbg$+orN5imC0<{&tBl}re~-eLJpZ5n|)v7j^d9jl_Kh0hED$$=#WPiNLJBnvqHu# zUHPq$`F>%3u}b7M>=vf zxG1yck)!kxDd=^3LRB#j5G7yuMt)Pnef%rh44|wRl4YIal{J8(bcA65B^7!lA!xNB zQY^{mC6m|haI5As86=qVM3z)93#~S74J9+Y=VdT${fZGXZQbl4zS?@X2&?lgKg(75 zN`c}-eEt>LAc!eUmYpC9ud3Ot3tL7)Q`kMqLC2GIZzQ=Hry$9LaVwR&!#9vLe64@Q zNP?Qp;0v94CYkO`HyxwgK0H9_h^0Iujke7k;SJZkWYYTWV!;C}%Q{A^dN>o=3P*_5 z9_+Qg0`I&f|0ZG3M|d!IN)GuK=Y#hxvv2kKSp3Tp1!v|;`}ig8?4=h=$KVF9oX=bYL5LYI-9T^WIrRfi{eBJ;^DnH>o|Ep*i#Cd^DL)SLXPz)UujR8~{yK z=J0%F49_Nm1)hvgZO-*rGMD|0$(82jN;A1ElWPze(%ix5z=w9>+e|gDnGBiu&4@BTi?f6-h68Ifg4%lV6Gu2gs@ofl2k4TURW$c`MC+Uf zVcSAekfzIt7V%~%TC3DYgM{kxZ3+3l8%>1e>a~0{{&*b4u`4Oo?&p>L0ub4B;)Qz_s|nle2iv<% z_yZ85y|evJ;sQ|gwV1tx*g@FM_Y>2u2|ts zqzuIuOEM0{N9;#39?O?z$@nEn#sqq^L0m%klyV4iX)gGFaLG*kE4$A&Yr?}u^0 z>xE2k_$#^zi|N$Aaln(egl(U~$9{O|%oOpaOxmD8`;;+uM3*6HyZqE-qHe-XV5eJW z-}$QepWYCo_Xw-3OO{|ls4Hq4j;Iy-3!kq*XW8~pcTm~LwmNkF7c<(kXygK8PIbmj zXuki)un&r8wAv&>*@UL)*N_PD8K?vc3l?&z-nq|v`vOS2(Ijk}wAP+tthG<;BcuW` zpfL6#ym`Fjdc!*pw2yqwm2G&jZ8!07%*FHS=ATS4cjVGT=M-#Np1y0Of5o^S{uOte z=6`L$sZ;B?F66Z)Tl92-HKozHAp2nJ$uRO;Y}|IuM{KCg%t}+rkki!>+pX9gwiRW$ ztsApXzM1%IGU2||YUskGR!Sn^1c96QCDI;>B zuky3zE1N!8F0o?e%b-xauxOTKlKyr(IxLyQ^fwSa%+1Duh~x9uyv59x-~8pR6k8VE z5LkIebz)RmbUmJhfx5$I5bB2;#sdvDp4)Xt+6L+xGs-Y7P5G#-S6u)RAfDA3=_`b| zF*KGQ<1XU)ZA$CcrG>eV`IABMbl>WCWW}vAANlMg zHnu_-+3Q^iY0+*&$l@78PsbrN-t*u;yGv9u<_-N|sX2q@%T{g-i!xHlT-I^o1ro3^ zAu<9_{vBE9ho@axNKO&1DX3^0?j6Evl)7Azw5{@7`+?a)DCH_LWp@E=FMmtEw@M?6 zNW#QbMR`@&NAz*ZyPj?J6qSU@G1n+C%}rwR@BNOGdf-)cj6p!X+JDivDf?4W79B|` zg+-})Yb)jF=2I!z!j1TRCXt z8$SBuMn$IMzkxL>qaZ9irXBhA=3$4MCS1kYMvbFcn9gV_bt?4JRzH8{XF2-7hih^e zSE*{NUf>v9&lBbY*^jj|q#KdWchnr#eMO2>WqACImr`??8b%()nanog_8H=ACS_fE zo?e2{jrMbAx$OT$s~xShRYoaEct!@1LIJ7kIFH@Ic_4d>HLclkx$d`xWv zyj_1Q&tQCQHJ7EwGF#lT%(gpq|6!os;itJi>S`v~Twlie?Mg|xDk*ufrbl|`6w^0q8wv_2y;o46WPw~5JrV}7VH! zhs(JNC^o#`M3JG0a_OIeaRr^}Ug9kp+dugk$3s!U*d3X=-LwzSEgVuSe}>3zOp@OH z3*Ujqz+ijCq!u;VTVJ9Ax7o?< z_e0`jTp_}!7eLv5y7sHTL{wE#0g_{TWSwJzDA;2~2IvmByF@TRjb8U1_VQQW!diF^ ztPjPwPcegQ?_x6zlKsVv)8!h3h(5wrpK|J5~13KogM&aJSG_ z-J7jC6r0W}*cNCSOX%@6)`=G>7)>(nNn8s4p3k0nK8mMBKdVPri^N)ZHFM&GaD7dQ zbBw1!JnLum=<-vcw^H;yss*d$q;klfD zJjg+p7xETTmXGG|QuCK?VOMlUGeLwy=9(#R`zQ+6h<9So~?G(;e49O|>(T}J= zfm2-h3i=mal%#*lpN9VRJ%RqAr(=QCFMOUV@#t7X7q4>GeaTgxu0K_h9_B-$9{U+) zk>SiCts#uiV~C;sOiz~rK1yc0_gP7z-$MPy@vVC6>>g$_uzUT65shc0s_n3>AcnC^ z#k+3&7hjAvF9t`n*M8|vxrE@lCY!~9n?*OZPkq#?1IuBWh{#=^xXEj;kw-knLxd~a zv{hV03niFim@Yxxo_J7?a19s6qJsLT=w#E*R+UK}3S1fFTHCQf&Sb(_e&}xIa=Uv) zV`5~M@B-OCsvr1563DHvKzsaE=P)#y@v1Z)LdAvE%n6nSlIQ}|>VN5h$Rmob(-uAG z&S$$5@nc@Ul<;5}{4Kl@YdL&rK`n8UxJZe}((Gm*K510g_Tk4EaibFtQjFSwTD)2K z2wbz8==k~E7F=2D1W0f~hYUHbx=;B)10zA42p9jo{r`^NJK2y*jJ(pkx_51&fz441 zH~>45PO|HrW2zj(7Sf8ZXGckH5Hrmzgktw-76MJ%gE07&b(BePc#iI~#Ux%a^TGW# ztTGN{Ho2nZF))_xI~2PuGZ_1OEwd7eCPGDr2-OywZYIOqbsk9(NsB#ik`x^ZZ?|Ii zlj=IRiUR~ zdD!SoAd~qCoLnzMtwf#gK7|fF-t(Yw zYJfLQ$MVk3y2fsThA^n`p6>zWo+^LUC#2=%WJdZKr=yX&FypNWR2(mPU<=+7)3fC_ zz>LxCIk^;)&T-4Z`Oz_5qQi5dGkf?Wi^#406xSJ7I9x6ybi2Z#FUwr=S}pT|bRN;q z;1P0-{3eZ>Q~_0&>mmAuoetTi?KL-1qQ7c9zbFN6d*@8HVqq=4a!sKlVWvAa>_hpz zt~6f*h=RZ(St|uWr0)fMAQnqGZdwFFgs6lk85IQTD#*uVbnAe)uX{gi!L(dLb8M!% zcuDDV(BE~X`%x@WJ659^+c9*3C8c&S%8K#_qgT-0-HG6iJLFZFi5F-}S9)mA zC~r{%jZhQU4K`i&dN$qkEW=Z-Oo6EHsa%+dm;sCRy!dSf1y1B;)(jZZb@g7xESk}S z&zK+(Qqvgult|xHKKK$(B>7*lmsQRtD%0$2*MkUSY~(aiDs&IvFe@XqX?xPrHOij$ zvUE=2^VzHHtKH|*G3mL6^5Nea1LVOwMerY>JQ*S3)e*Ex&Um6b)<9$Jhz*3IKYe?< z6uW&}iL;3sK|b- zJ4;}WL1G%C1@MpQ$px?m7#mYf5A`sfQTaG?qs=&WzbW?y>*6k^qRK2ptj8$Th*0x|i_vA97=Lh2DO_9da{fnPe!H81vuF zBNV$lGf=-sdoCB|>S^?RkYHJ@nEXlr034b>cUokP$en!1EPL>0};)2`%o zroTP(p+il9s{#`=Gv&%_+TWhC-%t&hfb6jTy6u0@Zfn}l?BtMG&P(}$MV$3l7y9u9 zN|YK_OTYX_F1tu!RXfz+Q=^K zGT80Xh)Q!oW2o2OfRF2ZxhF2%yAk)V=qCrPCw0Z*l507b`r2tzG3QneUYV|0XpINU z>sO^$4rS$U#z4@mtfq7Qs?;!H_BIdUM&Q$rPbC21X~z>QTI4+nLd~zGsd7wE(PpHI zb&7rw?LeT4%Z`;r%ZiUVbC?Xpt;h>3YGihq&db4WO*q$V9dW-5Fkgrt7+7@F{c=8E zC$M+Wl1CZgar@L0NQSx+6zOD^}v)3T;Fu z^C;`;gH=XdXikr6GUw(Ec)cCvnt3_!yqPjqLVs@q7Hg1V59xN0$XLm_qNusIOTF`+ zy=Ovl%BGM+Y;X~+6MvB(cvGWW9vjKUZ%0xqFGax2N7Q?kB}$}sX4Cj)>*iw4L6})( zlAa(=pKVXVZIC_RxelZ!GZvrIR4Sl<1ENEh{l|3ZH^f)6kJPyxxNA%4oW_gFByblkqP|+;(aCZv-BlELw@GtuKsDC4<|e6fc-fp3GT&d_jt>Q!a5Ru@GKYH1WBsyr+b( zXUs0bW5-3X9OZNoO!mR%=F5Aw6@v9#c&G)zrZ?u`@?YG+Uu^=f7R{vP8^L%hHZj}T zq=$G(e>G+6!)i*#TVHwYctrbhtngLdomo`i%+RLT>^~tc9Pv3q$eRrN!m+Hb$eeyG z)9EIgv4tQTFE0f_n!eTih+mp0p!i*63OJ<6ro+Qcj?(ewxOpWk{YJJ-e#B(8PQm#w=q=Z>+Q1D z_1J50xs-2`Xs!4d+B$~&5V4O^}RBahd|UpOMMYf1iMWTWb3=O+@l$Ji+2ph;pxOa@P)7B zH#Izz-?Z?h{K|buZcK`t&?el@ie8dxwyS}u>jE{l)PC&XoZcK=9isfyzN z$pFshZ+E3NiHg?W{!R;if{ut5@#%;aryDM;@ZLYQh!s{0XQnYoEyIvnh9kA~f+3Le zZBk@F3&CUzWhatqvW26&nlGX!6`(?9MeN0e43oKCu%nslj0c3H@s6|p(w(~ovk6wi z2(9*&MRK)TFky~?oW(BO$WE(BbBd}~ThSo3k znBN}E7t&aEs=xXqJ#u`R|>+5Eo)sqSP&XvEQJ>k;8PGnW;_TyMwa$?o{ewvAJ78!K4;j ziXx*Jw4z<|j7dQ!xKL-vM3l`s`Ys_`_h?2MR>?H2dLZPEF#;KW?(APSOH&^2n)vFB zltGIIJohmp;9qu~Fr&ERZ*N6ftG zV-U^QZVfeD1#al7DFB`kG<%QlA7kuS9#QY3b)gxqD$X1%jeF_V1qfqNas1gIDi?1HR+F&Z<2=( zT-)0Hg8ff!*NxIsXpevX-{N&;@)(@kOk1j-;GCB;8j$+)Hf>CCej?zVE8kZ{KXd-e zcAebsLeWi5M-(v0cXyus)gy4taBkqImGI{6pU=uwB!)gNX62$u{0ttxJx=?(8ts84 zG%Q|NqXaruwi>3@jN;&2_8gpMQ7y5x1S8w=TArE7Rmin%Wkvt?M@A?So6T?8PJH39{HBJ>`ArM|ir-&s zHf(tLZ);17+L8BA*9}OCI_^Vebg%o+FZzS~kj?JK)9~nk%s@2ZKIN1ZeddpR#mGkO zcts{LVO2(aY))C6==!8&Ys`{Cs_ z-fDr;9p1@S1D2m1aIrjz;qiG8Bty?3NKO8w2PoSkNN*5a-6cqEO`B%R>>ucK2qVO8 zhAdUxtiy?P19uTNH1)&z3hWC;=2+@>)6)+-5zD_=&^~(&Z z(EWE5%_@P+%|!2afxA7S2K2Tk=a{%xx3}9wBmzwv>1AhnY3PFpg_8w&plN2HdwrqP z=QOaGip-ZwlV5t7FUf(+HJ@7suJ(J*pa0TMD{E1^x9G&2HL6t0w_zY4v=PK*;I&czTX?v=o{iXr}4TKbZ`5zzq85 zrcdwaQ@rHRGO#LM*eMS!lcAdf?UP?Y1c~+FXtCIY*%a+OwT_0yJ3iE`n1!^LDN zK3!S1*;9Tzh?Up918AwzAw4(k;T!f_+>h5!ouRr1d8M` zjm89HFLHADrj;X|YabV^prL$BY**y!3wDH3o6qZ>0TI_cThC^N)5c1n0%i z@|#+ji{a|poOdqZMZN$2awHl2N_xn)=L{{?(p)^=uq0A?nn!%8X8R^O=L2lTZ*tdz zq3uC6#%M@~=CtxR4~#?pD5!NK?q8Waan)xWhge-pKxFqc2_u$-k&*VTJzP_1x)u=j zB}*2aQ0%2=XeYNEbDuj8h;mspt%7R;7KtEmT)rz?5jU^%lJ2igWnCFR9Q*QnW%^%Z z8u(9PDeS9d=a)3{)jcHinAk*peMf}aF0ti7AT|j$0k?7krFB+pRA%zXIL>rMz$P&d z%9&|T>%(w)vd=(rwAzA}W8s9=-q-ZNc8WI|f!gpKWgE$v@xR;vd8={+DK5GGdcAzb zOAwVG5hPGQ*d60wAc9#ApZV@OF?=ZM1bR+R2tCC-9^?z?xop0Qa*tpsUa;1xbZCwu zbb0pfcwc7++j49Yv~CWxs(Ko*P%#!D{}Qo2Zg`FM_=cKxkK(=;c(lq6L9}js*(K){ z&f~YTpK8x8wBQ^Y39tppU4u7O_L49U$vZP#(kX6X`5#!=X5pSH>f=QZQi30BB>=T?mc{Y1+>(!OOEI;`Sz%4veZWA4H> z37KC)^A8aIok@?W^%hhBIDF(MIKm@} zxQ8LqrS>)Z*3b|nak{yr-@cu79tb(Y0o& z;wG_ZRg0g_y?`Vz8js^GotQiDoHbk70qZSj*c9N{ixEI?7R?2z#@HHP;&KF{>o|PD zSG8`bR9p&1;A$?=N;WY1K@L(PNkO*jnF9?$HWy6IHv-al9DIF)YUZY3Y`a1+s_ATX z4@#-PAY)v3M)h;jc$eUW0bkySMW4@WZzjktIVQ5LS^0vkl^_tAj2?3Rz5p_q>Tyms zdsuU)m(+oP!v06iG=Zw7+nS_ods|2R#la9bwRK7B`L!7L)pcZmC$*7$wOYe(;*ngy zBSlrW%`V&NZnp*-4p5oF z1|eq!*brz|WWBbk1sy5}fEd_uiIPzkJGmluRnE|8m**AO#5i$v#=%M$fD@ZR{J)Xa zy)@hL8GK;!xM%r%;Y4=w7Ko+=+$SW?DA)3RY(*PG98TcObOr4HGR>0)Ek9KBWvTx! zYlFnJ|4UtI=0`+VQ`sUC-|2yqQp>uF=ZYpYSL5aBW$qw0clvzIjaARsQ$}K00GR6- zls9WsXK_rx?qJa#|B}9D6os3`@DZ)g-F#u0C@RZVP?=c`K_C9@?}dud2>O@B%vWZ+ z!nZ1f3=!|EHbMUyKGzvGwvHVCve)YP#$1orq+)NK+lkA6X64x*j*!6v6Rh(x3&QSu z3tntG${_DKE@Xh^O>)PmaO4ShB^wUdtcjh(Xzv5rU3R&8Kh;Vvz}H;`Tjew7+)jQc zr&SlnlIgd7|IztvF-l)xz&8 z1JVhOd&SK()bRs7dfI$O(2URFBFxEoA$-}ioKP7cclQNKoGEA#Tf{E=vVn$8SL-P6@F`{x~a}>PIa#R(`BZt@H|p*bc%rfs_DGu6zAC+ z-4y;R#djkWmP)ZFq4>;vW2=H@{>n|x%NPI`uhrFzb)tq;h(@-qw(a4Pc zUaKcEkWFr}p5zrURu4sY5PoR5Sz4h6vJ_cF|HV7FEiy_(2PX4u_jUpwM10Cl+s2#sI`wZtnzE-L>sOzV=huLGp^u~Ndb_*YEN zlNb|A8B||3&6gVX+xKgY$Fc{-vYx9M4k9R)8&)=*3Y>{2@FjVqoJGoP`!^jU!BcM1>E~9U7#Lh%cC$%3kffnl_Rv_5=gMj(o=eiS@B)>1UNDxf5@(pY z4Sg|nzg#o?JW{2HuTmTHy?TFZ3N!R2rg~qbUg+r08R3fpZ^PH73?V#t?>w*S-;w$x zdkxgXt@`C5HCOjWYJU&Q@1Dv}TL~Hrs3wun)9#TR){#!-{DuWpTkwAJaLx}JP+_RS zkL3CSgA1qC$;OA<(jD($qFgmgqMnfgtN%`;a2FnUFNy&<319hyYs-92312@dR-)ug zazn;H<`ZRgQCZM{xhh3Wm!Y-F+uh6iTjibS=KZ?X8rmL~JM;s$xYdEBk{ zBIOMzZ*+@Qw?5rHh<)&Fs-|b)zPm#9*>9(5g}AgvOQhV;84hEK7uv1#Qnxl#YscZp zD@f8;ZQ#Jx*x6>|eGyN7@<`(4qmCZ%n0VNEoxIMg{IpuT!sjtkQFxJkN+V`bv2}&= zP&>dOtS!rHn`^J+Vq2m14pTqT7qxB(^F6maD{bO2S>3V6cNAr&JM4DEWMrip9f8#g zrB$PK=5gy`t{k))4*TCx;n5>B&+@Icdi`X-{-ar%33q*sE02E6md!no=o13?P{m7T z<#KW|`kC=_MV(S6s$^f>kz8ukXj&!dKi+luB0@$?SsUwdH}{gJE|^<}>m%2a*ZUIo zXB*fSRwBzQMixFeJ0i7hpbzJiwM%(;99&7Dp>a%kbbmqZXv!IUH`4F6}ud3#ru{0nl{lz0y9O{WTLI<+VqLEYv?QP zo+?Sx&Cx}?41cB<_CnpZ zfM?dC-Hqro{!gQJGskBCzztBsgP-2q+cXkwVEc^Iu~HBNmTJ2`LOGTk>^$FDu2KhqX1J_@4j`{9KU(ogN)qO`irR7W&FlohHLS#$4#cBb0@h|a~{%BwZH zomuZ&>#Fi}$+-T>b8LoePAA!0i`XatDVhFByeXAW8|}e6uYpq}(|rDus`A#8KoR&j z$niZz+o>JJ>UDkdV;O3@d&;5@-*9yo#y=NQQ5u>;ehWdNA8`syi$Vk=>}8H-(=`_J zmX^08Vgd7!>g|7R74dZg+RUa*Ptw1pK^=2ds-uKQO zH`wz|ZBdK$YbmE2<+z%$E8PayboR>O`r(>Z<%s*#L=;j^vOV_e&F%T9U$Q;*d{lcr z;IGTG7EQ{TUn(BUYZJxDQ89sBkW|$Dxuv8kN^)BiHZ8jIU1y=7h=0g8XixC#Ds@g3 zS6Dq6fIF@XUT=KM++pMRI_a;-o2&s0|0g+s#6@$}Bxg1^wwKrG(^U|?yJ;?HwrGu3 zMkun{S{b(vakJKtT)Z(Ira4b}`C45iNhtg^;Em|xc!@8Ah2A}Yw_(8cEJ~uir z@q?DEFz&mBmrKN1PkrLdTJ0HuD@7AJR{QWrX?Fcia%KJJxf@85E7KxH|3&%U`9Ztm z9H|OX6`8S;R1`1V0ok_mjN6X3ErHh>FdUkEP2@#p#oknKV^R;l5!WkZD*NSXFRk*B)Wa??Kv&Oo zE)6PxD(snmW2?cCJyiQ^1+nNn-(GwgUQj`?D;hB;q@wS;;yB(7I;iz?<)(`1|J{P@ zK9_?A$i1GLXQk?6-wZ|fC#P~X7V6W zY4`1?I_{o2%l>N>1A)$eOX6b-hY;7-IG4MPK?f&=4yboa{zYw4A1pl;qUGGkTLp1_ zD`H)aIw8KevV;`J3;k6QGxArWHodkb9+Z3nU8%!tQvRx&&43;KfRWQkJCX#12dGovyg^12>vSSpg^!~_MLf{$(I1}*+E|l`YL%;w zat6rvf%7qwNB5qb?oK~jbI*1Qc*dV@iW?y7$RFiD?`#*T(SGXcJKVEc@J!JI$X<(f zuh%d^0dlPk5(f^GRD|1G{DhyoYAwlN^$2cf7NL^FMcga8%*pgLcb7}rK&bOW57A# zLQ!G&O4bqaOU@HJ3Mt!*k3GePz@+Ftd=V>r-`kg!a8W5im!e-LYSCWY3IDk|mAj7o zRh>x6eS>%TtESOto+fbEkKP8}(iXw{)XK-5H7ise?p4@}v?6ot3RPKI5pEKbj zv_iZysZkmu!-ge;HfKvYx5q&;(;W90@1ixDxmKhB>x`Fot!ax+We!cF)_BR9g`J^& zYwYoPqG}>s;e|R3(-94Q`Y;H3bvJ4bMK3{ABgA(6a%}Z*uey`oxledzWMVwgv{bOg zThZ=#0DzrN(Z4hteJ{Kn%!{s~vxQLlf?A^V8S!f9XM}GYMMCv9Go{jOaJlwN8aM*I znP#oE>&`aB)*wg+3e<7hc4)6}4(6m(qIkN2TGJwEibt8M`it4K<`t561pm)U1|w)y8wVgY{L+>FYY6XCP7 z$iTw#!{23h7@VO&)ZooT*Y}~NjqoX&>n?{0Jn0x##so!Uh-)vBE@8 z;#sW4bK6wRH0ZD}14<%S(T}`3OucV84+0~8lRDIi&zc?G3%rJXTKqb!;p|hSyqSLz z!Rxq3ivv*#R~IYIQM|g21LhcFux|%A7%Q^(-1m!kbpaG8gxaEEZ&f1IaJuHrP9T&; zsHMp6X*x`kYb3qqrHL}+!1G#i>__YDc~e~hcC=6yyo9r7apmd_>%wjP)p9q7QLx#J zz{^}SG_?FCIEjUD`pf8xOiRpu&ntt4D)&hRgONeSR1Pa#kYA6=lii@Bg~n6H!F6_Se^G;XGD6mg6I(te7(F79z2S9DV<|G--bJ8j@J==%wS2(#&LkuPgFq_K1rf zmA9Rj*O~1Ub`E%pG#Fh+$(i~^*v zpZ$w}$F48$*`txhll;|FU@XdFL$YG?Gs}h3x}+);JzNI)>*ZL)AzKn4eTD9-ZS?sU zYYCLaF6XRAo$vB^-cmxRpn|=OB;`<5-tc3n;Em%Po&8nkl9~$$gB;U|>_l0=(KNlc zC${3IW|v(Ai%-4P9|A&g=8vpa8ur^@-?dLquudH}^TC&Ay zx|PFT=7CP5^z;)e4!fZ6GLWUUH6VZ!Sp`OEdU*F+B7)z%B6ZHe0?%KNnCs=p$=oHq z2G_TrHBpiEjGlkRyp*z{2K09fD$$I&6QR)``Gw?Cnmn+va7nET@Wv0B!j6f0e{Bjr4#z4+@ zGfiq!&Mm@K7rUUg1|-Kf|BCXq0q(=AI@N`6WdO}P#B9-}%s>&LITZ|$F10g|tp-xj z&UEQ}7t-E9>I`ITd()*4Tu284c^Zhi)WLM=B^Q)sKssLoXl$10(gQB2BZD`y(!Zjz zW0|_M!2Q}uU#}(cq)z4BQBXC_{p{Cgi*ESKxaqHIwEH!i(q~=dUvX=88E4PCImLW7 z`f~q@{$`%e=R*)8Lb}QyTKr3(WhWxU3G97oO6>A3R^%{5{4DYZ2;|Y(U%d*x-1$z% z@c67Q?t=P^HxqB*DVgbuexCU>y`GL+y5H-c)RE6g(`fJ7wto~1w=+9<)7UV?|*1fUWL*0>4UD#1#VpmGkm z!6txDyFm6d`tJg-0SH0?yw?S`6L7u@3;+bD_T6#1a|_T`Q?Oj3rm|Iy0RW5b4(bq- zFZ``3P!~dkpjk;W(c50!*CSqjBSGD&C?)>IzabrhN|tJ9_AiPwLJqS?1|?b(1&MufOK;JYE}=?kAkfg z@mrQ2gDuP&9`CZIB0d>v$G(y1GIcp3Yh|$^tLo%$m6L^&LNx0?G2AIbi?jY*xs|Z$ zSU-OZU)Y?moP@#XfyAbvv8%hbq%I=$-xCOnKRf#{WfQ%^T+@tO1VJ;o4>#zuVQ;e7 zwgxj?X_bAY1EiDN>?`^(WbnGi&|Limqfj2ZI-cSvl6Ek<$N2-JX7*d>O<*nK$4&2j zYIW9>L;YR%t!rzpeqaBS|LQtU_ivopL1+B;r?pF&=@Yw{aqCpWE?&vOYlRYfC(1@i z@U#|xLhq1~3EO3)NBgdq4GUOZ_agihQUwlt&CWN!{s&AFt*_s5uxVlcYvG;3xk0Y? zFm6>Zl0lI>qTeLd8qU%S4>T>D?Yp+}KgzXy6~SZ{&P{K+wsM319>2Cyvc+?MY|C8l zvVVWRiMUm@U6sTOm-jx&e7?*3e5?EUsU?O1x2JfYQ{2xb2xTfHnk-seK^ z^GojM^SsZeyPr*bBPRmP#K&^uyqj%zD|l#(kcaH+6|_;DL9M>YkL)!)aF_+!ji=JH zdW&~?)`}14Z53@U_20LakgWm#eRXAcgj5L}j5K!g-}4teMSoxtxAK1z=o*ZCyZ^u- z|841~P4(ZleyV>O%+=%%c($kdZ(haU9aH_+k>TbIgSZd-;eNb*%Tws#Y<}||=I54& zbGcL%qP)3sg|WsHV0-6&%Xh$vXZ;hSi-jtvN)gojD|&O=ZxaWHbcVy-hURdO@UY|2 zJJaPVw{!=~fHg6OyM!nFToxUrBP{-j z7DsJ5M(@PS>izj$RYphhUqX-Px8=IyPSLCSvk93fWGmVlRkZl_EEv};J9P9|Q({NK zCUW)YTo&!|doJaL7JOE@H}Qe7pTRHMiyr|MJQXBze1^UA7FhP!o8uW^Y3u+-;%A;v!*T@Gn;$c(GB6^=H__FT*@sT25+U<%USOTX3i~Qee5Dj&p}4gl)!1o# zA^0yh+$Yjatjvg=qj;AGIH4m>oGKe#1zu144Yw^Q@%qvhGOrESN~tc*Rl7X zWJXarHHz51nQW@T{`0bVe^YuRs;#`9oG;OK`}a2??#1qt7q!l65iOWVFBe;} z$Yj1Sc$Fu)w%1m{lyv5x(xCv81kX0b@%fT>6@pgP`2G=GO?sb)_^diZoDq_DVPdhd z*AX4wh|#~MRYr`?WQJlRvRH&wKkA!A=nwR;AQK7t3G?3r( z4mzDBClPDPi2fX;3H9Rq?-yd$bo<&7f(7q$Yy?^Im!sJWJab`7RBzEO_diL&k$H(oSE+zk*CGorZ|1ZNum5Fo0z0izO zv+syDv55xtUCURk0iv=_URa`2RZ)FJLN*r9<^OB^(Mw;zOe|p=tMtQY&8Hlh;5`1O z9AHvf$1B6TY?cZ`Z`S52=c0CaE5!>>yPTwHsigK-hyQgtS&>TzO$Ix|1M1EF z5)?AbH1ipw5*BkMComIO#9sO+D=yym(y?#}MRxd{`bc zzXIOXLFrgRv02jyMm5b}wfR}2!W~kgx!h_ z%F$IKuhh!u?fe@439s&W-zis^KB0Z(gKK#)G5#HkX13rT`m!cz$wt}NAN$EAi6clL ztx!C}e<{Iq;(f2iAHj;{BnHNY;|noHsv}e>sS2>~`kz!?Ocu|IH?fO*3F-c4ga*d1 zw~e5Y)im>B=Cbnj3C%{l)x=XW_O(Ob_cY2n&0o^G_UiQpNntO}S#dQkahSEK`UdnJ zyIypipB&W@8*Jf!)MTG^RZDv|n#$)`SWEwGh#-fsjjFY1m%r*x^JOMTg0I*u=4H$@ z`@6SYN0_QX`VuWi%QMGH^)J1qIX{Zokn&G(^UpB(E8P6E?Z=b(<@QAWT;)&mFFoDM zZwzN9zh%C>vXI#~Mf5lC_to%jPfC`ebKI1I+tC~=orr^aHNnx6tvJOkWqGm`F*igw zlh9&gbe@E2LTwPkn6%^3R7?X%J+)s54vz?SS;Kb%EG8fYUXrj=kfN3 zZ<%2UUpOpUwkO+oH5E^{<_$MRf#`RxK;!-NjRqx4t`wdOw8zgEm#wL<9{M!;<{&>w ze@FN3k+I(BF8dp7zIYKY__7H)mo&Q4#PpuvI}Z?>C(hV+xLIy`UuT`3Qwm~J`q2J>J#avi|noE<{9NDiqZjqT0$ds zI+gG7j9phTUal`Bx*>VG{0pjPEHYfeB2DuH=C(|BiM+G|_lWkV=gWRcyuv5ZF^I3tCSXOt{f zXw8$_aWUv7C>WYM^$j`-(+kG=SIo_8XT>k+Tu|#@aZ6r%xWlr%4*a4l<@bubjx~C_ zI~G#LM#nOCRGulVef42YT_3=<{DbX3oF@8_(c$JZQ|va~C_bZc+L&YtGEv5cfE zI-jtPTr(%h+-09J9VSGmaUL-7cGwxslRR7wfi4qQpUBRari`Y+@Ajj?;jZ>bx2^x= z)s%9O9M-yww;|>%$)P_z$j~0UvZ@2HdB=%2xLosi5|| zqMVK-Z*oa(qz+Ak?{53CZS?gNeLWLdm;qVkBg0`;9(D*{0co4w56i8j5e~%~VM4q$r+(;>L?ogqCg~;q zVzACB&8GqucnS-s?)Hhsz(v?W#^wKq=a^74+kU=_>poVf(KBWSa}vz;1YAs!hVSfYmF?SBYczBFNKdI&RZHG^H$WS}6K{sMqJAUZ0>Rq3~hK9^GIE|CMx=g2w%g;w4P%vwv#O z0yn;97rBkB`4*t|<$h`sn0nM-HB{p#*DRfDviy;^*&sC$UB@vIu18h#)~g%!2#kmM z3bjnF8MGF^IyuNyZ#JcwfqLS5&f%}Ch;b*48K|k$t@CQ{)3xS-DkZ%;P-3~019kKH z8mM#C6K|l*0r}Pgb)4j(*rVP+;al1GS5nip zkAr(f-}{dVYY;`v^>tv6ac@MoQRhgn?&1FLD^pXrJVKWmIe#Qa(mu<6XOGqVshxfe z9sP_KzJDFG0xR(kFU!N#9CGkiWeY4iuuE0O3x6I7UjwpM8cZL+%iW`9!S z3G3d&)rsTPh8Z)PsciES5;&mJY_&JSfbC!HGGWiE$XH43cc-P;y^ljp;)VC~tkzxq zGrXubFLx`Mr@b-kxLjJ19gq!l=Ij6A>`lOJxV_i z)QfpI9o{J7*91CaU(K_$-e_623~&5fc9=!9<|UWyY8ETPrtxsiOCO{2eh#{VP@~_@ z-Z9I8q#APZ(N$Z(rTxeiq74UlP3KD2Mo-Tige-5;bCio$9Jox|u*~_4`})NX5Z-;> z<~hT}3q7ps0fb&rbPrBf5AHB*UNmSuxyGwE;6I7ENtfL?j2*+(I^zlLUan6(WQ)Vt z5;=?|)(%YeG%x6M3%f{8s&kCOWQ#n*c*oT;D6RoPLIpR@L9l%NuvTptUB04JtvO_3 zxGY~W(&iF?z);tMv@7)CPA;@I_iW|tAH-Qkho!j6pOKG@^!zjld|di2H9`>haw}FM zo4vH*2P_?Lq-tw_%iUu<`=;<;>OJ3%e^xPLA3_H=_@*oh$8Ur`IT&0%C#{3*>oR0a z(0%i1p2*d7o_B68`$wDs67(NDDNpSq^T4B+cWQMhxwlx^doSV49M#srKHznA>_Awg$_sYg|h)Yf9yJ7W*3huENfp#mOz+ zn%gYaZ$}CS4jQ~@X@388X!e+Ml>KCl z4Yv%yK~w|ZzIFB>on+QX3N8})w8jyQ_V#WbZ1`1N!#>W^m>A1z^c9b0U|uqCmskFb zhNn{$j1$UOkrUqcE^;jzZv3;#mMKc|}bU#%`1w8o%_kjBu~7eT`*mS||7$K0?lCpw7kF+NeqH$b|aTR99pv}+-b*vPb0pn_bGuP zm?RY{(JtiRU2oi>(3;KRPJ0Ku6Y&N9Ly7kICL*`JsejwS*7^a$H}55|7J7? zea~W~S+Xu1@898~0oR=a9U0*Ut}iI^ESY1mDMKtx86c#FAdyUxO{eUF)^vngMyuldL0J4q&qTgP zD4#WR8f|0|WW@f?o;jZ1*}j;>?y0m6GcP5L2&!$;I?k*Ny(Wf`|7Q7Lm0b9u0a;yT zV6}*q`GiNBN2QJk8&&pM?Kj+)3Ax%x>0jZ_aMl7!W~Y9~drZGa_%sW_LPlo7Q^{6z z!+TKYb1Db)^2MyTB-~b&u^!_y0|Rb8hv|Po=l(ZYB;G1eak<-*xyxTp&c~-CQ#rFOJ^iVcj3%0TRT)>K1J!9`<+Nd*+;Y)4f1Z007c$M zPaC%}u`5vwK#1FqVkvygugg^_%@5jrk$WW85%?cZCTZ-6yp)iJc9nD*v>(2C`bwzt)@Z^4ThYRhDrbB0!hh18k<^OD&i8#~8d!weURJ;{y>>aUL`P>0qqy6=|jQujb8cwy04-aoy)GwI+sJ6md;URTVrJ7G# zk=2xeK{vb9r3}PbRq9D}?c>I#;UtpVJcpVGTXXlez$5LiyxVNGd7rg6v)${9Gudmc z#RI?AMwdD&chnp0R8s!u8*S53Z?uVywl8570i94 zb*i-;9Ku?RU5vVjQTA-02*{zWKBWjt{2!S%cA56R;5)=6E=|2mU3u|7=c~kom!r)fC6-uwvv zxQ$OUtvyXeM5Ul?RmnHO`d3zHs!+fr@cxrCvJ(cK*Y(U9Q4`*jQU4W1bsdD=`6_3m zbBzL(GE7Z$s>AN9YSX{hJc8rG$&CN*F_e*pMZ+9^;|?5BbdSAaLgkf((TbqaIB}`T z@1kfQez%Lx;=4F{3g7Lcllkr&EqIg3bDu0nEn#o;noxOQUt#S|f8Ca%=p|wIfz*(q z7lmq?0**pX$h{I#cJ2-lbH~k}?Z?QpJUdWW2!h z;D#5?x@Irpx0DnczP7(V@Z)`!-?8)PFJ#26f7Y1lm!JfD2*m!L*2au*q}_|uP|fCO zyfIw|>E++EyeP^g_^R2==)cYO$cc5!z6@hnVYhW(b})?ezRXigi6i`DLvQ}(SAx`$ zI1$s<0s;4G%={CV;n*EQsHm4Z#IlKv9kQa4qPxG|{#kw*)5`MeIl zKfu!i2SRDFMgG^R#yoC8y(YAw4Zz~>-8kGue1L^kgyt ze27tA#OQ(;M!%t9)=wzRtcraT@C7#|YWUq|xWEtRDG?zxJw8D1{sPIr^sJCNt!w!- z^Rn|!^k`c?Ua|5bz{=S($jzSzB>S7!q|GzGW+zzk>F1Jn8c)I0 z1AjWuoOnsU%dc2 zF;dN}4^XWQ>Wl4CTboFv=uFd(2${qL{?Vv0%D3C|h79zGtP@Oo3q4}i(-kkVC z)7dyr_Ni&3@ZE-SM^zt?m80&Dn%DBGa0)DSkx4PPFt`j>-^sLGhc87f8=<9R8I@gj-VioJ&UX=(o)+BIZ}1Y~)NXN~4O(*HtF zb-A#MxE@>OKcnGq6h!SkV=mkJIFSQgZzAZHXV33i2td;%UZc6FxNquci48hizYLOj zmfv|iaT*NuyC?Z&Ot*@1_;7n;$AyUTSo4Es%%zgeFXsB(qr15@R}jpP{=oYG$vkA7 zRmD^qpO?6f9?6{m_icz!Ejsh@3Le?V-i$>nqh4LZ`>s`eNmxzmZ)o)KprJ?RE&wI? z>jqrui|ytnGx{Az49|dw;;yKX$~6o!QaSI9dHB*vi62i>8_;Z>u0bRzAwVcT^(c#a zUP@S%qM$?c(7?fi;38|9Gmk+cL2LS~^_^q^N$7uv;zO!^4+eUkZX_hW#+M~xNbT|B%s&}vai~RZ^%{Ez;+&TR7w|WxK?`DT3(4h{;a}w?X^VHqZ{)pF)_O#H z(1zRRj8nh=p2IB*%zbmW8!7!S$I(Gb}RBXqRtOL*6KR*A$49qLt@HOea1`Yo*-+w_n+RQ38j5OS{p~12jr8wgw%-2w%f`a8v zW-Qp7aSFBwsAexQ2gZgSv*F=*n;DC!dNA+~Cx0e2jQlj%>mw0T^E$+ZKa3#v{{UPD zu#)>)0qb0<09fNcX$7ncNs?iKfXde>cj=M%=<2kzNe3q<@hF(9^ir0=nTeDod~?6leJV(JTl;a#qpkZfU2tfD;kcaw2J>8S z=Y19$#*z!KQY46Nq75_A@*dsugq+KiAn#~9ymgXqn|=Rvs^%$bw;qu`Z!iotSdM=@ z9G$BQ4OYwPTrrx;xH2-WFbg>W#U~u0iks{1>UlbQ@;BjkL36ll>&*UU{9C-2KpJT< zk(q63@Ru_J3(04tM(_lg>IO(=uLrVxc5<;2J`*D;)xr;X$vsEIbK)238VFlG)|w`+ zJ4zq^f8Fncds_GVBG>Hqw2xZ%djv_X`;82l{T^cWn{#ZibWY+gy80B+3=ca5zqQ~^ zd{u0I8^LCTYVju1C&2NRfTMarD{x%Na8m2Le_IQ1Tz#(vjtj^Ia}}{uf20X53O@0} z<$Vt4qS1Mhv1i=jEo!YO=cXW_#%wifV8enz8vw!I4zre{TVNyhjpkZ&WzT8h%=LN! zOu@+9&$WXOF+Ed1@d-cijacb>a9Owv@j+bV+0oIYBOxL(R3j!7X4C#;mvUo{HzI0t~A~S#}p6H&nd63_}2Kl7W&2q)JNlRs) zM$0DL+Pjohovr*0yQh8C;}nI?G{b2=;CW0w^^JMOZU)^BM3g=-Z<0)>1lx~`mKM9s_@9ZYdLdV&g>PGc`JXo?Dr;(wi zuYCU5Uu9%0+Yv4yHX;g^Tf2r!)&`rlWzRmKSQmJG;R>%`)K0I2BE1~bA!}j4eTF+#-|UUHJB*E1 z1)CCGgC+XYLCrON?;FGamuKHha|V^5=>ve?#*0FaoO#Df4N&oWN*|;-#B^x`2FQEa zi9}>{;f~-DXc6VTO4^9OSPVVORgdfcFp(onJoCEQ8(HyLns-KBxYK87*4J;$46RB; z`ZbR43_SPiye8tnppWJ;WsP40&ZwiRDup`H)Mvyo$_%dB8tnIQ9p#7i%U>6EuPF{X zqroL#64#4@;Z7fgKFb>0P7qShhk z&aSZ)N)HHzLG(n>{B6OlCC7zwM&uT3|tSCFC|185U{9XBJnc4vOBqRL_!~ME1jyMYn1$6PsoK!8sQ0Za8ZB#mKSojNfdOPH-HjuY9+^>3H zxL^L7uroi8GHvU<(^BufG-Ppy6P0_DEK>w))tyG<$^OA9N)oEqeZPbw29A-wP2o4+s z?$sUxdna{lQXn04=4Vhg)M=M`H-{(@>=)e0-mk;8k6|X#tJE^v_x^9QHL)?wgRlEy zBPegVK~LOStaB4PGkcQ`F9_x*sgVRrR)jl!fx{vA*!oSGXq0!fr_%sMzx*WU-5^Nk zVYL@7`9P#h(`KIlcG-?#$xids3TYSud4)?>1e-i`W0%G+$`n)AiXubqz@0*BYe8rQ zzZwWKaj3>hr>SmKbTBp7miuxW?Ekjuf4 zZwW&VRfA$q^^Q$64=`lKW+#Oq!%prbdO`yxjUf}CLi}0$I92!&@?!<`PB{LA4gts! zrJ+@S{b%Lvs!G2E&6R331 zxdxU{2r>mk2Eqg^t%xzyFMp*FV=z9Vc)kKbSX7Nn$>LuN`@v2?*)D?y>EMynaJ~z= zw{tBVPgGxqV-X-T;?Zgir#aI$V21RFc6k^>3cD8<28r_=rhS92gWzi|gBovJK?smJ zsEZ;hfNlTRJ~ZuAA58gjaPW`&uwxM#Z0Rl42b5_OnErB5;P)vM`Cn#a>kI9vAByh` zy2ry>woHZEv>aLmV!2;fFw!soyRdWdzEIga1j95~aGu42|FT#RUU+e+J_!~~f(3E( zRR1+taEZZ!JU@d4d1yY@j>sVFmn;_CnZ|<19KeDMEYz=%xp4Mcu^=ahGib2juAuvp z#e(14d2#=?0huxTEW9i*Sn&U6y&&4vCQx|`eN3!Kga6VEg8#UMkAf^N*${!ETY+oL z2D>FM8LZ?i5V~XLb_rU>ZW_`lF`e7zm&IUU^<&`p|FSxo zW$aXdotsRUN=UF|kJ*mYiS5)BbXJ%{1}dJT?GE+J;*iZz@x(9~BlCo5Z7aOSZ<2~Z zFT()gmA}joAJFG#x9Z(`zD!QhJlV;+b)Hg$8;X-?1%`@(^$Aqn-)nu&3_BkrZlduv zcMyz7p*Px*<0;-KysIF=ZC5gczmaf*le+Ue_jo-xX4USJ=#m(Y)Q_v1_t{=E=JG!OPzhB+|Q6Sg2jok_Yv8?gvV)|F#<4JgZnJ z;n*(UOzm^L;4M>0-;$jgg)R*}$bn6{cP)YkIF16oUQ+HQuSmYujTjyYJfX*#?f@%| z-!m;OjrVJ?crG$!2`y$;v~<)!ST-|-=hVEQ>>+(HZ7i)iAo!9do>9Wbgij*094h*a zGkU2JgG|?RVRGw?1r-mT=4BTj(T+8)zEiyL#N4V<=DK`vC5U*_B94S7w%{%;(U{gpo5J1bGvoF>^!-%zjp;j*`V^Q6fn zKq(5gzjJ{1xr7DOjZQZ8qBj%14da24V`g0|O~JmA%#G?O?2N4R#m>|a%SVoziRYJ* z<21Q=6^`I|wpc#+Hkwt3E^*@yFY`G<7FZRvRs&E`b-pfxD-+{@ebbjSa!m3; zIN4(+CFly2fngN**fHWS;zP|T#1 zz+%KcB0&PXzPulX%O*_o-B)LdPzSnha5ZB=D!OfEH@h(IodXmnB6D*j^IPv#$r7~I z%Lk945=$|GsZXek9*bP0W>~MBe77p?PCjt!%6b0ztKjo7Z7^=S(&y_z@hVAG7ngu6vn*= z2O9+Q(4yq?NA<7ny{W1!;MTdcd)i-PVb#$JjA#G3$X+1m@Cr_%{aN{-Dm0#IhBmn} z*lU@QtqMr~y(CLRF`KHLseL1{8we@cV?g2)0}|0y$=A$zub-uJBfV4RJWkffH#jJm8Rd#G#Ku+h)~G7D0+Pt%!Gt^RuEbC(Oo?l@((AUzy&-p z`_S3CG%$_rGI)$tc9M4z7Onl{0p198WKh#QRjt=%kI`3q3OnZipm#?vv*nF9E5jW* z4$1tOX z2b)Zghn;LmM|ypXcZB2U!*J)#v22L z#)WFbIk;y?KF=2c#v!!rYyw|z*^ncD@-}eIALm=7eWFVI52XD!8u7Y5Bm;+~-Z2{? zB1CgYz`xwA4!18@%3HKq!c2^M7kj5sSU7RppTLPat|QGj)_dVf7LKvofiIqKwZj^p zq#fQ|qEnC74=`ZpF9HOkXO*mO{y<0I6K zy9H+kZCuq@`viZrIoIBGYq4DAfJ6xhvd?HpEWbQ)&2&~Zo;^)9aR7QMM-97~l^0qc zq2_!`;oqH=llbrlC;+3+-|9g^F<{3;vKppvS5JdjKwyzcH7CVAB42VvAwmKlT z?ae$13H~0Zs-mJpeb%DtH#m>{@ibh-w_axNEW~5@i~*c=C{@KT?jITv4`;Lsm%TUR z=RlN!0<9fNj}=EsPsxauS%k7A(T}Fl@ccYDyZPe9T*&eK3#tBwjviYS@5zL=uPqhzZR-gts@B)?4Sqna~pLP$*e8C=CA_Lr%G!ENN|5ruY2&8Uga3Iu zUG7CNIR=qg!M>}H(h^R{Q@Cc#=8a9bwZfF^y^&uinvA_sme;bJ=xMz8d$6Yn_}Dr_ z5Q^JsQM)i66B2KcarFF0Lu{w~y(oaiW=Ai(7Y1xvjnwh;`*HDEjr;VxlnzG%}>uD<-pJSEbM@XnJl9XUt z8U7_H!xJD9W%w~D!&esJ(*2c4%Ef!c8H0=W+fay~ZxrI=3#1H>i66@F-Xef8rPHELvucG@`j`&^5;Wnz`RF7+dAUzd(fSO0BaBVy3Y=zIq6 z&S{`+P>5jcQ4+%L)B&K9AgvD|hb-m3MwuCGJx zP<|b81RL^1io*(cK^+CSX>NEG=S&v`onZs;B^$&TuQH`m^mBnx{gS?IsF1~PW)$(} zJ8iZ04aGHco@(f~zP^q@XL|45XU5|#`&2#1{j~GxLe;T!1ms?xcc6kNc};JLx1Qql z&zh>{$@Hh1C2S2#v@x{|n?}R~*k!R~;MyHlIw9S=94mUj_eY`k^!uq*iZKYgN)hL) zNH6?AzZY@d^;XPnU8Pqi{b-e*{qpEl+DaQ{m3{_vnoyE5NoSRiZ@}rmNR4Hc2B%gj z_L&Z@)$|F`bjh~F3R3VDY?x+t``;PGG{{YhfW$zV7m~y*wP_199J5~-NNo2`GK1Oc z{b^0IIWa}hDDl%L`~s?CwG?Ir*ti>fH?PEhpd#L(|K!PHk&P8Oax-O9)En6;W^5!` z!x%Muh4dx-G|WIx*3iu+=`}xxMDHxsP7gG(n*u4DK!{E~630v5sOl(T#}082-ix*1 zG{JkmrU7zOAe0?m<2w)(pf%KX+lGykRzTx{+cn|R$)D!220Of4)Itg?4mFJ|Co1rq zGo(0Ulm{EnAQg(FmN-S_a^yY)m~L-$8uzIwT`Vb*gzj1O_1^R|TjL}AMP=-$&S8R9 zt!XBSjJk2WX#l^X6}eeac?9#;E|y&N(f(6;~m_veBq(&K20j3;J9tKPRPY zKBdC!$`;e_n30CXOJBGVWawUiak5Np_ZU!>;P0Ly>rm=g%}8x~fnJuVGu+s_6qJq# zVX*r$O13O|f)#j~r~zZ}i-a2@D_;vj`^e+7h~%(_@wOsBrMAes4RKoQV(~r=04~y^ zXKkVsdtTdw5F|&~fq&3{AuKE>C#R*&?DDyq@*wDgdKyEG$D4j}O6VnF0u;nET}1vC ztSW^3jhDU?>?k${HJJOO#zWXug5E`mQT(BQYtNFBp?xUsf0wo<%p%D_fr99uZ`d5Y zD=Y;to=C6V!{YsWdyOWFxxJ?z)Szi< zX#B1sgJmatMpb75<}VY_2kx!qW&Og=zBE`W00gvWV_#}28gPzLjSBgyj(BIktGe>l z;%n$aw!c1B#{e?Dd*)a?I#W0Z!%!z-5opN045VG|{Znd9!lBE&$0+Krf8NwH_lXsh zwI3SK2XzCC24|Z4hJV08LY#%L?>UKtK>&;>rR9?{WrM-{F4(lcT`==Icq#8uN~JaS zubQ~M+05Lqm3zEf(|F$d;XN>xxj)V9HxUt2x%v=l7QAts1QFjB8KJs4bwXTLke$Y0 z-tewAd{K_+N@!fFryaCOz--2D6SBPFyIbw4v65xU)|9(3yUhvOr9|D9vM++*Y9Y3E zD8opob=yfYJ)ab_#oqi0+QsxeIhkH`=<-t0hYYnAy*yMuEibe75|CqU#2j53K@`_A z7h~=JJavyg!1z8UExos6%&z941EbSxw4N3RUt^K=->l>k5njo=J>L&z!ZFF#5(jT- zopo&`ZXee%H}CVC?3fD^XHW?Gr@TfeC(rtmX^@eoS9~vifL~`3?UE!8De-T+)OPK^ z62GV2RulnwnhGzsNByCh+px`a43cmM-6m9o2>|3JA01fsvCSK_$L^%@l#LFzHr>H- zhI@OJibRgq!XfN)!Nin}LqWGel%y-W5{;^ps42*Se+T;Qlo2WUBlz2s0 z+>&5bAlEA>L5XAsCHq^nP(jQ!Wg;JsK|&rM@mYLpqHR;Kd5D`hiZ!5-%h^*7>kSa`x)D%LlT`x%-kX!gU1Rb;o;0KxLI?r z0*Tl*En9W-iWKJjg|giqe+Y?OpSBaq{SkdStn>o&Mu=xfUInKV;jxrg!M&}of{9Wf zO~Uta;{|(Sk!oirdeI*EUC4YP1QRW7@n(Uh>-S-`eJq(g3nHZAU(h@o;%w=fp$GzK zg5_oP^sc*4il0l0f6R{<`7n(R;Lfh??A=l+4s6K)-FHaMko_P+`pEyv1*XTX-Yu)- zZ7Mp(w-E0)bq9vbI;ZYH)r^4+tD^(z4xA=$vV+z6vSV~*m3G_D!x|2yaUzHe@vB<| zRmmso4qSiN$8`s8oS9vB;MUrAQ&h@i^w*LN)01VMEc%kg^8t1*Lq)A#}zKo0!@qEM>{nu2LVe@_)g+t|2 zXzm8SBJLD!RyrHPs+-X4?m}7I8jHbO834i|$>N$nPV1PTWC-8w205}mT?R?uXs^{L zm`KFE8gHTXb4p6-L4{AkDD-Vb#^45` zOZ`nqWdyfB<8|IzU6rA)7(#dkbGthRx#EuKD|c%#ys%SZ*3KiuvgZze%uMc@4H0*= zhYyRLU^fW*6R^zN5OPO&L1%al$r~6Zt(BPduDJ;YaP9(9>i3uU=1r$dTqZdtMa1FU zwMIqY<8b^MXi&YNETJr}QJYypoWnh!kr|&R1L>SnM{Fs*e?{DIv+?2GaI+~TFC@oN zir`A^u}y%qK{2LX#0|VpsYTJ>$j~Hul0q+;+^dOZ)Qo$Rbt_~ckheiSpann;f;&M2Yh@ob?apMu*rd6pJ2|nQs4sVTk-3M=Oik%`DIIXL zuQ~aY4FBwX&1!GnwX_#@3r3O_c1pv_;zc6hWS8+7aYk{-O7A%=vFy$$PIH8NT12YD z;&*Mr|KaL=_&>b+2aa~>m6QxYU!>RDaxjU@Qt1qTUJRGh?;#Y8-jF7jXfU*(i zxF4-T8-zGt3_{^9jcJ)dHsZI98It>I3$n>%bA)URw9560|F& zO)&<&@$81#LO8=M!Wl&~EeIz{aPL_gB4Cy@vLR$z#I^V*;*4xTHVo~B%XM`doD;i` zjZbX7{wRiw_(0D3#0fHR5$Vt7=tSe5`~h*D3S7rX$q+|$mfw9?XDw9!=9B!%Ae6k{ z`Il0n$Hw-|@~MR!@4lhD=ZJ%|$8HhX94!IfUq6DNa*>Ynsu+7oh~J&bG={evyNFZ9 zks;|KFYNe#eC(bxHAZpl|SBsog3EH zNEn|e2XwTSLuDF6{L~dXJ_EnDs!NgQ=}c@Fqvq4thKeIUNX2m}n5zFb!c` z!&^G#6W^FpGr0uJqEF4iSjy%+VitqjT+JTySDEXmLIuf6Yk{+nc5437pq6-uF>x=r zJr&@?sPL$jth=>Kd>OHW7V;0wkA+vTAdvbWGIjchRTeLOikbw)bI6sc1On-CpDx0Q_NDN|2)A+NE{|n=D^l1PZpTARzgD#}0EV-L!`Q|y) za3^GiYc@+>b_KtxP+w{I1^ec&J8~@AxVq zF37fp-1^Wm-$;8Z&+l7!B;*VI;3c+L9TQF3Pt!Ka9Rx5T?)I(<$ERbyPOrmh1;-e@ zd;04R_rcjHO&Rau#w=C`nMN^4xm3%4#6w3Qqwdb)Tcbazzq2s&_-%XF)-NRj2x>73 zzPZQy!~2H_2efc)mv@bT6xwVckx!k^w`9~T5 zx38MUTXd}e-gs&El^w+16txIkwKw3A>kw1G{^w{e5hp=VBBN6WW#%8{{fFSMHWIqV zAt2AgN6V-qBJ@3^NGu>|DN69k-1~1*Vh|kir721SX-S1%F{4?M3RsB*HHg@zD_jTE z4dsN(bMIKwEhBnL#Jyj;>fieo|JFeqkHZ(nY}uGsLLc$NcmOhn(W_?YLNJO0k|`N6 zWS{9=d-2H}WBhzOTa94U3*IZ{+=?lTaaNlPAOG32=~yy=cP+Gl#Blr^NRcV3o}YZV)uVUBl@#}A__+8L;j=PdN) zZnd)Ho7Fha6Tm>}3bcg9upiT8Wo)yQ7cc$$u{L?vBAYzkCU-`xs?wjQk}GZU5<*WY zd1)%S7s=kfNkXxj5E3w^z0^BysRWls6Xe9nWJ;>GRb2|JZ$U< z1T%Ax7xDU^+*r5&tlIAST&P19?Dd5olfaPEyXP27SuZZxBX<}LWQwz>s2g~Sb;Zpo z;dzBu$BCqjP29hhamFjQy@JrYYQI#$vPY3&ZuwWvhevw?6{uq${=$rm1PJa}oKMM81QP-yTy#x{GlgF?bAka#Av;KNMPB7wE_N*Q$ zVdprjUVEFqr+E)Yq)eiypy-FkvJ#pe*&k zNNAQ5K|}Hm1b(NYF3;riIT^ltCzIxj-J&k+BaZdAsKCtT4GH-=3RD>N)-M^;s(i^H z@{b*i@~DRm;*+2#FYeiWy2MSRl>$TbtAReUif<^ipG+dp_OV z5`8d;I$P^tucLcQIDOiXMZ+NOlaq-NMjCeXQq;HqO(>GOgJ zOENe23f!I6>q6l&$&6NEOeO|zPTvFcZu!w)o8Cb!%e*4fyEser9)aJ5OfgSNaLp~x z(t4=saG9>UUA|bRsr_-7Wd|%7u6J;Zs9+6Tccmb1`WTUGbJ;lEwU9oBf+Z|4M4IL{nys)naJjeoYz8g9*E|v%2nR*h7DU{L9VcwDkY*}dUx-+E zBLG+W)sXP#mtJ{$s{>*mbEM$_rEpPm2(#vq}lirZIS81$( z!wzp=JB`(_`rJ7>n#k^J8RrheDkx34wfP}qhR<&{%$VZyY1T6bD>dS9ZeoesCrSk- z4QKOj;zG`)FJ>G+#tT*;phk%@Xq}(B5#E0WSQyYVoFua!baXVXZBH@(Aw#gqfj&u zaP~wTuViJw*~lT>d8SrIY#dM|vFcu!J<<&c$`>-VKDNi=hXA{e=lvKFK zY*HicnZ`+0Z8xG2RsX;#iI+YD%D@D%r*~U7#6UlqGqKE*Pqm@PMtVd0fvq4AIjkvr z1lW|l`SQmSyd3(c3iH9;*_2`f90|b;J8_8 z`Mih?EAn+2se8jHpyBQKZso(}2_u0ca1MmuzjkLML@m!IPVN>`eaGQ*uZz1=Fh=8M`ftihj4AG2`l2W#d;dPiyzOv($7NBePL<@2 zIUqVDp8d~P6p21}84kAfxFpV2LC(Hx$Gqyltu%Pd))zHUWX*`Q6z18J#fH)_#DhMJ zj)^`DrO{%bQ{)ZWZQPH~6jA~UN$0e@;_;Q}FAP*jQPjx$(*58{-@H<@v0@i^g6pPx zU`j@N?LyRVmD$^ABNs94%CU>RS3OblvPU^a^!~>qQYpJ&cQc(N z-_bwI+5kW+KmOW4ZMC&Rafft=j&~;(J+k+p-&qCK(71doYQZY<$lfD!Ur(X`(ioOon3V@eE1GPv%zF)y1p(A zJ)y0E2T+Cyy74yEL47Hb?dzgv5V=2=sJiWoGWJ!l#?<-)81i=BOK-a|3_>vg=&d~+?~46<`~0JgG0 zAkI%N>H5!zBfqXriy_eu+-?h9fq!bS$Sj>3Tq>8C#jt#2w)ge(EQC8!lr(&X@ms?k zftV>J%rqteV}tI?5|=e^PV*=JOF92mWB@LKJ&czo|B(Zl5cvcs6`2vS_eDl1fMXp2 z!T|5@cctY5f4@R|LQEHLTozIMD{kpEKr55OW6sah4&_k7>IgzmC`SJ%vHykd zMGU0*yOjPjI8-acrsj^R?;!^>owcCgg40(+xA)&^5J7`R#bObx0@snh;YWSNlNX*W zW~7lH%d_Y6gOOx-zwfh)pR<*xW*ExLAv2W1w(RSC_{+SHi;$rczuEKs_WNebl=93; zJg$$5GQ2x~|9!K!`9;HCj?O$K10ZU}D6+?EwFhL+$JAH6e1V43(1YQK|Kp}v?;ZCy zs}UGdqFcK6EI}|QzL4L-9P7OwUQRZ@sk^{?`)Tc`C9aPrKkOh|ko?e?N`#$pND>Q5 zRkH3`m0a(K!OsQ=j1=-8T6Y#G$J-$_|+PveG1I^w;7izv2 z3A$3sZrR7|;Z$R8@tMz_nmuEH$BG+&XinZoPbl@L!o2?WsQpTmGlw=Q)<5%grf))d zR%ER$vcb)~yPsmR7~=v#!hk472U<3c7=6&adxKWCJp0x~GE>^DG$Hvf_~7A+n%SDa$hJ#0EaUo0 zgd`C?Yq^@(9Cp6;I36k*61+pQIyX;|kPq4;i7|4rNg}S;%QR=WoRF+0$jnPVoj#A; zS=o)HtgO+WdD@H$Z5DS>j$)W2{}N^^^d1_=S+Y>M)bpMZ9LmIbA<6Jdu}12FC?q}t zS}P_UkhILJyUFNy6r#M*a{j@e@dCk<0B;w#YZzq#Y6y#>EX(oH!p%K9R|kz~Rjxw| zQ>e7qn>jXxMPp~sqj%x;dT-Ds6q(TQ3EG~Z6?N9PqTt`PD-E`=Sx{N5SHsx$s}p&23yp_R>_2vU6+LK-n}+o;Er)G=}ryKs222K_1jw z)-nN&h|rqHXI{f2jg}BL=wQ_%n|DwW%6DDnaOX{@sz zd@nI92mSp`mM}6v40_nBcnaALZo+l^(I+drC`Yn(5Wr7HVJv=+mIiybLj=q;L{~ib z$_ps$`o}dtS;yR=ui!I?uVb!mXRpPA@zOy=Uj}bjR>*KcEvV7^%Vc{JOVv1!VZg;b zT1JB+pI7m>)Z=RMwIH6r4a1v$h80p}8g1<5=fn6VM-W%< zHdq#?RlYejrp^>p@TL+dOAqLJCSh}9&C^d#{6~x4mLAdG5@60ZPw$V2wu-~?tg&c? zHAV0*hDJsd2V{5fwvUen^pW+TGgaJ&sATMzyb3gD3m0jY!#06tP}V9FBP98eVi?7*m&FhL4_$3(7zDg|`z^d##L}XCWA@8buzl3G^f8~W*rHiaMgIX% zucU=#w2*w=7CX%hN{)X!@kN38{C^*~BX`6p85~do)Q>b^e*dS$1#MtZ!XUo^gPPs- zPVh@J1d>^EtZhgbY|+0(KKc+|Z_|0zHn02< z>RoR0?nvkLw|NzR%FFO7Y~HAJUZKtViP}8H=ADzyI|TVce^qaE&G52q-cQqc8*JX? z&(dGw3p4kvr=;c})dlLse$TqRYx9<+^PaYOOFtv;Wt;cAbl!b7@3o!eJ!JD{rt_q# zN}DezuhSodYb*maM(J+pD3ybR`R%`zm3?8lnhE_CFRi1RuI%?KMfqeGrn65lt(MlN zvR|^<-xZ}MauBsHfb^HC?E7u@+v)7jm2F9o`PE>GX7B8EW+k3Xmw1&D#u2+$U~^`s zbDmUP2K@N33^-n~{Zr;u@_W7oSoJ1TbWGRBB|=>9{Tfff!xb&qNB|Y?>Q+oBZa)R zDv$AspQ^xfw!pjT0&={Jj=~rEjZd8IhPm*5{;gf_{pLC?_?OL%r*d;rx$A7MV{@NK zsVED2?XAb#RMNeF%C|k7ql)Se6MG)_68`!qO(% zY8(!%_x{t@Ap2GJIdcHnmTZWZKC(^zhnl@BUV`mdVD3%=JbIDk&KNU6n@(vuL4yOL-+A7m(HC(n;)BcRaQ8v*V zOp53o9Qo_6e<93dQL0Y4bgI)&BT8r?CsOwz@sPCym=n$A z$H^~AKU#0#M(peD{cEe^@O#yAydZ0|uFy*ntTnu+a_ds>tHebq3c0u90REG^kk+n; zKz(X=QAV(7OBR6|E1-y=B4c}Mry|dVkXttEawX@bl6|q~%<7G77bM*G1@ZlNH(>;GRoT1#g#0p4HOjDJz_k0b*_(hxT ze%$6P3WPBxk{Ig%%S!&mRFn^$VEl^A?~!;x!W6wo>TQ8h248O7u608N(3^FVnl@zO9+|;^P0^IY z{MX42p&ZTR&>@3vODrR^WF3l~MNo9bD2{L3#rBo0_ucoLsyUx(*@w9|=j4ot4`j8r z)mpWe&v9ED-5qf+Gzv>ww8T>F{&sJ+LtbYJ2XZ-7O_QxvsPQ{w0wMo9da8hrC;*{7D1wTY7+Nc@k|AL?l0zhphN5h2gRr^JZQ<)V*s}8R*o*d=iR*zj z?0I$?Lmp?hRUFc)1?xB9LUT5>6wcu}+!GJxWbob~itr*g4|TS9KYtttxpUR)N+{3Prw4medsseC&7gUOHd zB>%lo=BHujoq!YRnabxipuyx{R!sg!#QDQNYQVXyIF+9r9UpM7>P_C4q0Dt*XI;R# zs&^`{Lo^(4Yx|P7CzQ$4*{*<7+c%ZhF^Yq-=0R@Yjs6UKSupdHK@Q)FM9HrC&)#)i$pbKunccVymwBZd_rg9 z(Jc?Ozca^Q-%NDK59uLNvmQ|2>N_Q4sM~wJOy?U8GqRu?$r$Q%CT|Aqe=$5h@QHLd z#c)~k~z@ZEY8f=RZV48Qzz1>ti4%T%#fk zurL(Aqi|@v|2*@ItT=r2Qko3Mhjl0N565j-&v1NfvD9e+*O9$J>wVQOk_)7i!FW~o z;qgE{@)<=gAss=6g7nre&vK_8l9i3DwE~zb2HfgHT<3y^NG4jx)mb><4miO>ctkD= zmopsSJ!jK%z#ZE?;PTW=0ro$fxiXX~pU(jV*r}3*zIzH-Us^2+xMPqby_KV8!@FHzzudLC|KT)`XAFd z-D+RoJ%S$E>djGB-@(jP)X2B}GpoFG(E(GgVvPB$XMYM5GDapS=moOvw8rGCY@}?( zlzzm$&+@zeLjm^$CY2=^4rhK6%v^!!!Wm>%3I`&SK52t9onyin@RcFZ@y)ph1kNMM z%+7xInnP0ic~OIOZpn|-aFP4#4*+L-tH3|l7v!Fjv1(w?p>947l=FKIcY3b!H9Sf2 zkn?TGJkJL1UYncAmi6px9ZL;TAIi6pk(HbtIcfUJpAN1a^Drae; zKOl}gipT(9-yoAtV_${sZRNM|oJ=0uYL{fP^zl8`C4Js)`yj9i+K}A zY>7Pjg{ympvX`2oA`~m>sLQH1&fj_Jnm=p9O3lj@3-3J*y%Kq z*iY;3j2!T!H`erQg^^FH(;7mf#HS&B(NlgtZ^K}ucx|4y@ey84YG&{xmetdsuuCWn zF?b*a)ogVD0nu&*(<_x7Z6UUZZLq4Z{u|RdXeqROkwveeUY^0Q zk<5Jtvxb_yc6dFA8O++y2xb*NwU`y=BPa2c9lsGGuh|$M#K6~R#Qp7vo3^*d@j-l` z8DsziT4b8H*c()upWkqKh{0ML&eriGw&Y#FN{X zvg9={QoQ366;F56B&~DJ%zSrBp%C*lenx6;I zgw2nH?FAJ|6&#R8<~hE5er-zX;+fXw;@ST{E*@^PRlu9Bn}B=1u845vexkQ`PG1o% zR}{C|G}|Z_&$RT#qvGkJ+(xOJuV~7w|2LOT@su$%)#lRK&*XIJ97#`UTFa$#R_mp6 ze(R;P@4s9+M&4@f8~o$>=19{QFA_6z{O(oUHqq+?&h`1=<^e65vi_^V&Hnmnx+!!O z>7oz->Y^aVS;J$bSqMDhyKg3#6#N>%d7JZDqy|P}akyq@2oK(P+iv9_s+_O=IFZ3C z_=UP3X6Sy%t#Uq3&Ia=*uI5145@7f`m8hTb0};Be|DhI{ysFiZ7^?r4SepZTX4EcA z;M;&iGBxte)lDbSoal@w6xa2)4a)QYn}6-uGkL_R+PP9p6Qy3g(}Pt*}P>u^zq zf6dqa_+Y9fQ26SFKxCjf?!>tubVB=3(}DKRflwyGs{U)4e@1Bb0ima<=ULSB91U@0 z=LjDq{sfk{U8t{AyC9I>DFm{uJ-1r@$0Aw$3kE3CxmSfOn7^P@0iKjrC%Xv|r_c+ok_#w52 zE-H!32qRZ3kTLH*Lu=zjo?Z76JqFYmt7n zYueI|r`Im9udfzSVfGgOsq_Wj;^jH{dYc;a&8I`%?vU&dT@TPi*gbZ* zlfNE>g=y7b!=;K%n7f_4Ds0U4Hu^EwPF#0~*yyUexlCa~6%C}ODnA189?!bRU%&Ze zU&9e9xwQoF{m#6dV9%Tt=(RT-pV58IW@o?OImfNSLhiFQUZiZF@1ECa(eHMnbR<3^ zD-s`>wPvHUzY{TS+xy*)DzpMDW(rNsvZZn;m7}&g?esf?A$^8qnQ~Jm`H{`oGMy>Y zxupzeen^fjGn_J=O_`B-E%{KOL#T00p2{qqd`6X9P7z|-VD+^)%fDs|__xzOKQyi1 z9el_XngmN0(AKqM7h|U}=YUg_AFjEcOXv`nQ1L)f7p4DccS^pH(N1;b&;uyv3P@zRFH{Bb`(zn)vU7iLkGlpq+2NQqF> z!S;S$$ zz3jhkC7a}Ty0+cQInq~8B>4wm`D4gA5H4Fb>4z$3Q`_?pa3hmW$qq@u!mL z9gA_iWEeTYn(jS8DBkJ;KS+rMpDl#pSmxE}L|EZyF-4`mauM~)y7xqUSA(VvRlSAO zG1@@_1F7ZA=e@d^PEdzqq`QsZW@&_7>`lHA*$){wPuo^YCxeUSS9`wSs6JSau=wKW zqp`bFQ5c$4`0qNlxn#9}OyWG4n6!Nf8vnFsL{U;tjQ4r8CsMnz9ko4n`6iCc^YzN_ ziRD3-{$cGHSIRpQ_N$AK{PM8)u|$7STrXNuxb}2j6{}9LT3XUmtsS8PfBU(NeHG~} zzsc7t3%9{RmoQ`a*2U8p_;|f{yKU}l*tyM17(=}D^e+%7qXOU2lkWt~XnYOVmr3}x zVo#)B+vmGgcT(sGArZ)-7fOpaIo ztVP-JR+l&I!beOChTLGaA5T+3{8)_%Ew3CyRc@^2+Ng{!XPS8BLV6%rl*iq>zTgWv z*-~4|7wZfvQKv!U2jy;(c{}!wf^M2v9c?n|w67&r z4`90H>ESYcAxOU4=n2H8i8OF;N6IQGiSxdpR=F4@Pz019T^VKV@nSOu{ASMt|e>qvt9P4%5`_1Nj*Dqm& zI2~`*r@PFz@U4=Swn2ZjX^wh7Pq+1gX$wt;#ohz0ZEdL&t}sN1|FU4so?y*tS>|X! zPzLVAd@Bv)Eolvb@gxJRKa7O)1BU62kc1QY4Gy!Ae|EQ-P>+8jGvE$6O29e92srBx zBj0?`WREyXzB$6kH|q~)MW+Yc(MO3k3BPB0&5m9jaIZN^vU!b>Y}Oy{5FLy_R#f`t zQ0C{zMgq=_Mz9GF7A=N3L$3K^8@c9-$TgQ*x#nd?u35Hr*5~s%NK)YXsg}0YaItJ+ z=b2r@HSbbkuyf^og??12^ONgP{blRL^$+?ioX|6xT@rT6m?{t!6%&>P& zgi^eD4Ln#RZhv10Za?Dm-j{r&&Fy6G3;b8I5l~9EEiBCNo*f4W2rSN{0fB`qq0A#R z2<*t4dI1^FnE}--A6&#D^LsGwc$XFOp5}=E``!!g6BG>=p7%AZFV&&EbLSD*#SOlg zr=L9T3n4Bayc1fUlj*}9>4vbeR~w8=9?qpN0*V>e-S2}o3=kP) z&xrh}FbzS4=>hcsV5s-TyM{ZP#f&mR53S|(bs02M@E*( zkV2Ab1Z~DiDPQHj`__?xf8uGO`bC8d2g3c9z#BVaS4JqXn! z*G9Jw3_T#Tb_m*MEc=)uS%bILxo^k3e_ILfY3up56sJ5)$dP(Izw(14{ zeAR4vly@rI8l*sr4nMm4#*LtHtlCzVXYK=70yAFe^@rT?cfp|FoLfa|fhE2yJL*lFXMdvIZB_95F!0HEM4_$t#1$EU&k=8VM) z_UG$R|B{Qb^a5o&?8$Peg77)4h`lOqA>b9i0f7$(%G_sPodcoxYD|~3RovJ{f(gRv z-Xp#9)N=og)YNjXGu>7J(MI+5dX?8XeOMo5gM+@gaeXyy$bxTf&(hzl5xEn`;0Dny z{Tv3SrLXVfWop@-+>nac)n-2cE`w}_ZNT1-rJtns;-&eEezf#K_c-v?25FuHqFzu@ zTswrM!)EW{`$Ia31j1=q*g1cu)CjlxSFBNpM?Q0GTd0SW zuldnax&O3x)g=tZt(ZrPXqhych8yJ#F&rPili+Fca~^aCz(VqtbqU_ghvLr3 zZl!40&Ayc`SfCsE6OLPVk@%2IEl}7&VstGo-?ccG6h-1Uu{cAYjNsZ_E5!;upcNvN zD=T!jRw&}!)Vf0VYK2%cR_GE|XwZOA*@4;@T31LeGz&I$LA}D6z?sNCqxmFOM{c*; z>r7~a6I%?Ewilqzz_*^acjMvaM1NKahRCMndtWQ9fHd#;%3aNgWL{6g=%_c^kH$A{H`v(z_N@1t0?aH&iGpxIm6RVob2%-P(f zJP5MrEJ}dOZHeDg!eoC)HafjwAMW|<54Ve6PO0K_sTt`~FC0~>eYBtdbzmL0drQ?H z@9GCsM%j-2=9>00m+3VdmN@`-(N#ypkH2NLhzQ47qj@_@p@@_KM_&{Jr z-rF~%Ci{_^l*3ZZHgOxFEW$yMy87_rMldMamU+vtVac*jlRVWZvf*@pOr^7}L@1O-cooZuR_@=fZ7$4p4|Do+o zz@w_pKmG&~2ngPwq7e~;#!6h17Ag@U8AxCTW&j0TKr4!(6&I8lM79KHqFl!TYPD+J zYujHJtJW$-t4P=aD$3@9E8@bv3Uc9`vXQ3|r>)L297|7AuOnCmGGr&$BRQxeNX_1vBRP+N zl>J$^v#bulUy!cR%4iL?IC`kq=#)N8cMPGnlAPk5^^&bTRP^3cBYo z1Qx?9C?%nHH3s8x+30=)P=>Y6{QE9T3^dwh=6Y2qf$x27H5#eubROQ8Q_uus*{M1S z4OKB51^X?$;P31TxGGop><`TC&e?LMl%HzP15ebCV~vnCaj&Y;Y9&tn;B8N*MU-4K zb>REeG9Q=e!iq74k##;8+$U6AeL|$s2NBl2BGNtbrVswn_=;KMBma_mXfb9##a>%e zOIm50s}a7+5gRxVcWWHs(h^5-*7hPZ!ec@LI^1Ayol!gX*uPHYnpuUS_c| zqhXB-xI*gr5iThh zNAY);3K{W%U0vi}K^-mY!)2dCWki{|MVFiIVVKH9$is#4Tb}ok(c!d*l|dnMhzt@G z9=tdVWoNj!;;eBF_Sv<&m`=Xvxx6^qp|+AM$pfSX?Ea7fD;a8^HOkUhzaOk&7Fi@! zns1Q&=S1uF{O31fh2LdRF{V)BKRa*S1|=wwb8?j@Z@4VO&_0bZ8J`MbSCkn~XwFlA z^8EQP?PZu^s6D}v>bxYV;K03ze%=KRowNE@6GIqoFCY8-osayUdCdQqOq!ZAr{+t(@Z^Mejv+-a+9-vVzt$)ad)+~w4oi3qgTM5y=wnN>#~pJ zJMirdELq~zQ}RyBQ7t&pJSQEzKuo@3rLB@u7Hkm|$38d zOpxQ%JP3KX8cS%NmAy*e#?oQ6m z)4Z#FAyqqfmZXhpfq8bDb2>d?Pr-S7lrNG;?4o+c8&K;W9yBtD7Ggx_Ws5$xIWgH9 zwX6^;vXauy)mw}wDx+j5#U1JDdcp`4uXP^?#V3~G=(ev}4UsYdv6DTg3S^Nft#KWF zocVND!M=Obw7V|YxJ4>NnT97I=jy6JTg>^rScTQ*tkNLl^4n2JJKNdVKj=u$FVK?Y>@N%&ezbNgQq zM1*TCY!h1&L8HIxn#DjczT4zz#F@Y(^5nd8wUC(!&s01qiOTyo;bT4J<=BBU<*oT! zk0LX8NHBzmPt=+#m(c037~#*L zQbC-QPMy(X6?DjRpmw}Tm8%9uP=6V3h}@#>HNPu_^+@L~Hs0hydj>jlB6M1?LZ0agoQKciD0d4s;bdNjMQ@1Frwd-Al!Dv2>+p*soqazYd{@g)4^+os_Z5)Nqn za#3HzQM7mXBm=T{xG$3;dDG7PpR7r#86!KQ(RuDw^;ct3e`WG1R=NiPVXQYO>-PuISb{;v%nd5 z4f`)%xsgxog*EzNcb!;qdtu}Zf5kNgkyG(C?zan_du}v!{7X5^Iqeo+r>(mmbNA#s zne$(ly0kYq3|KF&2$U{I^{0G&sQg=>_2|-I=|@+3w>I~_JoM(ca^-#( zc?X)IsEv*X$xIO;j)zB8${niK1*cqj!c+c>tZG zdk9mHQ*wKcaoq>!zcF$*$-}W{-O1hi{C7!5J$iHM%ci%pVq#xX zf=m;w3pQDgKonf?ah3JR%BsFUM2>MH=L0EnJF^T2b`8m$k%i#TGDE2LSw?hXfBYh+ z=i4UU$H!a_r{f?F#76fYSiptO%_sQ}(<)t{ixsvZ?HQ@Qn`9MVZUXFA03gj9hJ|Og8NOey+0O8Pj`% ziHs{TkG`6JqIZn_f(o7EPJzCe$&U7y$fcb3uTG{a*d(>Pg!s$JKy%xk(}&v&(}oMt}u_tfh4nPaM(%z=I8 z&whV0vN~k6_>D&qInnvsOB8SLOX`VJ51H?y7UQ2PSg|==&}=-ey-+c$ApCuL0gI`+ zMwirIQ@N4If%KAVbwb?(Pz$z>C5zAKMAPs;9y>WFd4Cp!8Y*JWc8Rv75m+Ua1b=Kv z_(H1`ufbMnuw=YdI=W=CRr*9p9ht1sKb9;ozt5LEV}4&LdCB~~QL=NSLWvkt4 z=>2A9M?AmI;ZRpsMzdLoteY0E<&cbc?TXEW*1cL;qSKHjdwvISD~626Pb)AA%Ki)_ zHddvD$}rOGk(-Ge#uQ9OvepBR3>`)1!gB)hXBq*Izz40B6!-!2YQfhi*3Ed{o$3S8 zfQ-bL5X^yK;>uh^f^CN1j@-k@IQd%pP+(FLR+_Q&jLN0#s3?8)-0 zTFLV9yn-9e%!EfyL+r1~4pgj~iO$z*Yrgy=n`v+pJb8MxuBA<^0|0lY$mZ-uaqqx7 zhyO~Wi9R=&v$n7E>QWO4LTbNRn~n3P`F_Xd_l||~9mWyG5JbL9WTH=W9CRICci zZWCt8irhejQ~L~FEOvUdjBZA5;t*EDd~fFe8yyic2P;-s4=4nBl7L{1PS+#af3j?B zv|_c?jBZlx%1AqvO}^iJW|-Sn)_^(xB=6D0{1a|TOKf5e`uyMQV()O7Hm)K$<_o#y zJz3~s{BzWKLz+vyIGz!fE3RIQPtK2Lo9IKox?N}l&K3fe8Wk}fr0BJUfRq7$X5H6~ zWb_ulW!Bh$QUbhktnRFyDDZH11xvsJvvU25Vwdzeyi1&+E zFbi0L)5W)usR%CTQ#2z&S!t{i%uS06>rm|U_NzVTSC^?NqkY%*g?v+Sk@M@TU|1wN zpZ*u|?kk+3G5K9;rQek`gPXy+C3-5~u!&Q@_?M?_03eDsPdzPG zahSm48t1i#ShGjjL(`Bfe+;)Qkw1_8e(!8VUke?FefW2+yy*-)giJY_-fy=suEwe& zZ@%y|SyimZ#;RWWac)801xwbuBK9Mzxb0c`FzzXPTLq+Tt$%H(hk>RPu?bMd{-q|- z#?WOWj(yn@&huzXm=#?Tndz2+^Rnhb_}LGNi~XCPr1u8v@}+YjegZtbJkOepxq9VT zZ4U*P5SxTS{`O_hThBq`tw+v5ol~@c(ndL6St<^OZ$af12z!R=GaOMP>GA}8k*M^E z0op(ubt!Y4bfchG=4C1~2b4~u2g+??trlEd4r!QjbrQ&T^$#UKkmI8GNQasxVReO5w~lDA>BJp(WyUy zvNsgX{F>b}`K7GgBQ7^N4H&ZLol#~=(`qLtYhN@vUp5JA8Vfj#XJ5P5 z>OD?8lZr@@HP5fN)`NP2(0o}lya2z09}C=Rv`nN~-~W%OKsd}I1vgW-5$Qq-7N*;Q zI@r>RBy@(%2aV5Ju8w5OG7LQi!kheQF&#WI3LE%7Uygw;{`YmBtUva65fj}n|1RJG zjBdqd@GdsBCVy%7X7_*Elg6K|&T4VHUsO4^>Arhq>d$ujA0=>yIMPFy1SLZjO-H;D zix>xm?P>w;(2 z1%TDv+k0>{8WM*H+KexKM*->^+k+n1x&Z#2s2pAA$C=v|sv;P_d8E~4pr6^f=#ygn zJ1u7hbt;W)nE}S(ym^XoQ0k?7biwf&gJC?C=&9K%rzKEM5mAZF3}gs}Ec`Be!H?1| zL-694WYFAA!xk64G$1lj0=i z$}MtG+7_Vl^7WZEAxy=54#N}GgKb*)KCHm~Yv>jEYoHcwAN>Iczcay$(B14F>lT5}ZeuE76q#aE#JL;Gy zV8@6Qas26h|73p}TgVNr6|t807w<04%p<~*#OK6`0Pl%7_QP-uI<5#rU;=ck zzjqqN)A#V?j~bI8OrX5wlBrdc^ErDi%)q(mD1TDGhj2^M#t$45GHS(h`6Drh>@% zTqcWhF!6xw4PtZ_3xNRq{klGRlk~6ts0HoUb zZ=Qc29qh2-*;_lE@mIk)@}{|pyqetYT_vE|>fA7`nVr1`$o+1ssGQyuqLbuX$icV96trGnYqPY?wxPN##{&sW_M>eFo} zv?6&7j6ocEtT0^$Q6istdF^#ljsfx#ccIIckx&^yWNk4Wah5Y8&s|yMVoswozw41x zz9Yl;sInej(e$~o499Ok$|*2<+uRN3%={ z$)w~-c;6Sbk*$P*z=*?cN2GI5H`bv2qgyD@#j%U#fI|+|2n;B~)y>}(NZ6Z;8RSI8 zE{A~*fTsXr_IQJG=h~l;iu;`XL%mVgcO+|aPMVuWD@Kun2HiiXHX~G;b-XudD>jNJ z^{Kx(YbEp{*7s?C8*4mSOWCI(G9*h-!mjcifyNr9j!=a<3%#mhs=y5OP4`5e)BNGi z?>Fh@-Sy^m#oSmx*$YOs%SpD+;9p}8mi9TnQ9Sf_AX$r;>YyDfsiTFU{XofFeqmZx zS*5Wwck+RfXGpV3A4+p4pD^4>aWBOmv`U{hq^VWK(kqU#_Ei zLa>8mf6yNN!HZ*#jdmcE=;ZkNmBT(%t^Isdb+Mk}sKSeAoe$$dF?K@nmnBv*6jl{! zz#zC1PDSQqQS@_ShMrRsqtpk-0jjITA1E@6j{LvD=%`;k`(na&j0P2 z3@aAoou^q=?C0Lo)r9BZDTsSE>YN1Kwx@n|?NU?se2Ufen{`(=YvJ*s37r;%avOZ9 zud)c>i3=z*3TEk)TnyUY@}Ykzr$({$kyWU3F~32OWSP~)FrJAWhkpQT?u886iZyoO z*w+q#eKu^C?swN$9u(K+#OnCaBA;x%?V&|A z{W@CnA0(HF^3H1bQjmf@AisTvwy98%UE1~(c@Mc{s_z{-o&#P6H;HQ@MP-Gv6pSHwvlLZ&Y<+QfF01`(P%mw!0Qp zR`ox6z`XmS8x?WheU0R-0uvWBFWoPsbgZd*TvKHa>BRz}-zlGVzQwGWnO!Y%H6A@W zIeD4voB4z~a}zx3mAN$)d#!orQbe&3>-fTqVln!W6S+(GI>RW84beo)$6frT=6&Sd zRK^szFQQ2wh>!Cd<&Mr4d*@Sk5EVl5Icx6|0GgxIih24ngnUb!`WI9RAdoFEjKuU_eBg`6dxi!>X{hyBIaQz*Bz)Sy< zOWR*|@OYMEnSKUzCqJs2iO5O*!Kf#?iqj5KdUvki8>*isKc&yhDX!bgD@oW!7p2Pq z>p89f1tG_OK9_vuRx(}fP1*%&{0#mW{O-G)`}h*iVk*P_%@EK}EijBs6E{Z80rnS! zvty^Fexo%2ohJT%=RJIlNZ$4|Y*3+8;C1wVaqAI7d;MBjd4J)rC`E|+Hjs3@No{nd z-2;c!5Q|83iRDeQA^z7;OZ}3?j3Z?Qb^%re@kzZTOna#_IpmqWUixgv2)KVwD0U_{ zHl^%A-2u|My;b#uUH*pefYDR+BK7^ZMu^=jfemong;axa(H1t8q$n42i4o$07e}r3 zfi$5T`OMI+=L#1UJ9ixmv~uwsXy^S*DZQKEBrI)K1_nJj;Iq_h(&2T$!6P)2DrnQni zb1BLq_7#$(ytgU%w@ksOR4~|FkhlYJDjum4_DM7t zS?L~21@39;Q%3*A@HaCW)_~cK;%~k<7XBvA$j^Ll9G=H-gn2%?=!3F|)gg&qZa+8haJCdujmY4HK++uL`s7suC9#8WnP9eMa63=dCENQt< zd!;GL2Rox;=RV`aHMYH@7FtHBJN1;ve>!?{PGgP7c!0YqwjZ}f6{6eIPW8Vo2u!8m z@>Q(83&otBOQe>&#NFDF{hMac^Rej*oV!ll9I$^VU!81Y9|$zK?Gksl3q%i`cGnN! z++IZf3N$VSkW)jfg`ElpCW0N-1~zO7^rX7y-n+9mm$qrgo9YAB*>XQHt;&tk1}=}HJQ2Z9Z7Q%{m!hK# zPc5X!MR|d*oN^lyICX#N7eZy;MRkHnrw)7ugKR+;h9Ti0Vx8g8jb+JG1Xmp@1mj{p zm>bVPN;1Q@`{93N5cE!GU5cN_d?hS;$t`| zTgMT}E1iv>D^Y$hjgTc@-7{^9UpSSO*EKiIbPjn`q3m?<$$ubO%>90>_}IXToMmlYtUF`%xii$>VN4g2L_BW4^&Bq|3v1^9Pw zRi{MaMkLzkOrEFmns|GecWpi(N{gv03*u)$bg{ctDT&HYdr;BZan7Gq!CUxA{kaBm|Vh}Zc6YXj=#>TY!QuA^auyZK)|+$?S?;=IZKf%hbK zCizbK0~Z7nM(U6bHS8a9mNE~LrR7tP(?*f747v*s&rHAzZJQ^6cz|lHC73Ln2(+-5 z1ACxh+Urw3n}K0m_Uq@2aoK6k+Jk#iU|hV8cm0#TCHi!FP=dvaoR!a_?yw`d#Q4+k zh_A2OsrHfZuP#S5;}i2%Tjq+M&D#D8BoUswjIVARLJFWSU{vLd$WJ0}&l&mCqa^Rc zwe{lBlJ`{z4d9YmyRf3B$eRDGCQzYO;14?m*m^gUTRJFh#)zBhVb_!LwXe8Y?R18b%Tq?H zKUXb_^fV+PBM@ttRVr|gGY#ioknXD6hIe;;-uL*sGV(DA9ln_F`M^i|sk;e7&T-~_ zzt7P3FObz*NNRa1y15o2;N09Q+#x&1eg{T?huPu}rlr0o{+IeLPS^_8dgQDLow zvChhG)AeNa=cfOq{Lvj=f6k>m1H<`Z<*9@=u@>%y-T#}zk}9Y(EfyX4^BRI*#SulJ zMBW@HA1tC#U?!|>*;j@CS}!=gKn2@!TEDusO--S3N!#P=a; zb-XVw=8yb`t*t5lwDjnP&Grwz4Ni53C7p9}b`8MW0q%v@-Fb?A09SB)Nmh6G#NT19 zR&_thxBOjJ6CZmx`K8cUD$?;SNj2RetZ8}5>$erF)(Xq3(Bfm%*3#0W_75Aj&3W5v zV2c`3GAJ!ktB!W$fEBgOASwwfjqB<<_9$NzUJ zCsk>qv~P3JfZ-}4>UaPiZ`Mdcc>H31#(hWq-(kH$w|_TMc)`MCYGQjzU-(+E$|(N`6WUxV1-P=PgnZ>}hxBrG!|36}i>#mG>?jNoNn zA-^tVUy56Od5(AOH3U;^4)9?3)I=6B*1a{midw568)Q2NP7p`sK3mF zVb??RV_3lr|K!90lCL4=!IUyTSHt?V8HX?R+bU*H++K={a54F-mi#1z3$_$C_3 zIsf5*@!)v)-$lu;&G#w)xmjsp`_!gP3> zRsW$@F@CQZV849d2rcGsNee-{&-p567c8l`uee`+)9M~M791~O=gtRtK`*n4CgrJR zc)WX;U@37O*#m7QT{NS|Vo0LI0M5Sx_Jtw)ZgU{Teo30oFek()Y`s=y%08g8zWOf^ zvQnK0N54k)WkdGJ>HrrrvWMuZH?sTHX^9eT6mQ0sg({MS@gU8YdeB?FY@kp>u{VVD zq3I0g)BxAn=NsP9+@46X|Ekt3m5YadEV2=(C#m-8lWtubFzXnZQAb69&Ml zU(0D}#IVhwfVsY!SmQpc)Cb=M2D}|8bRVRaENo4Gf#(u2+rJSX(9^_yghzKHe?$*z z+W*o!nQ||uC?41fL-8x|ra6}XqY8a;M3d-UYi{L<{^eq21nf%+YuM5uf+hI4ZP(b> z6xQ^+<^(JDJ4WS;9%6h3HsT|S4e5LoCR%4_=& zN{ry*1-U&KsHrw(`U|@35r{Ztlm+*MQv_?E$6cMql>XEr-q$cvM~!#)3ii|E~2h`4l%Y0MxW zHoHnv85+@PG#hA=fK=PrA3d6j0vyd0<%Vzb@Q$>IIp{k0p|%t2@QjTvIQSSg(09%w z=XhXpQECU6rdkL~?3pj9UHGd7&&k8H-~BD6)BXzNtl(v))hK_v$FrHZPhNpnNJioA z^78cx+S8ck%UKRw=iRP(v#0lRC-MMx`}-6_`F5XB01l_x3TO52_NLrdC<_UGWCeor z#vz8y7O?MPb@qh`TritDE5G8KTdZ2ZeRP?-UHD3&GZ5(cx#22^i7(bdf)N2)Z6MKz z4;jz#L!Z^Vk4+1pVrBNGH3eW|tXYUbVSDlDlB&~i$?Y-UmM?S%c4kEYhUbyPrh zo*p;6-pXfwEiL%=x$Z3UrE`@!_(#nSHvNJzUE?PQ?V-$u0nP}%R62Jg7o%y*&*Ge% zJaE|n0It|s+81wcjqO$wBEu7-Gpe_eSlmBtO4od zlXy`2H-(e)-II^(NV&uLleI;~-;r#b`_4502>5i3AQp3shW!Kl<;(n~XytwBJlrp> z54DNnTnkXl7{&Q966A&Lc}#qNHtLfiy!?sbyI?%`;h{ev|MvT=-!=Gi2?pZAwc%x1 zO~EEBwu_vUZEM~8oyypsAZY2JSQ%Cq3uE-$u#bdGc3E96-^FX2@XvX@5|>ZcZ05CX z_zWD-$ehHtNL(4d<&_7-%j%MMp+EY4VX$IpgxIH>{L!xt2TF0__)d6m0KdKQnNJqj zGap5(XnnX34u;wej$f517;IlP7r{1-_QXYQn}PAs4;KuyM=wC4F{UukgkPGGY$>B* z4}QJ1(BJgAagygH0q}QSl%AazG!K})+rarL_&ej6dlo5sQvGgp27%NkilEDdR3YG38*j zI$W&|v++~mdr_>yz19qzj#s}*di6`BgKc9s>#TzS#;N;$Rj=A%n(<{MU*w0J2AW!? zM6Fn{-li1MFcMStwQk9Z6`60QwI6@l+F=lSy0yKnTie2ybZdKl+M1jXrN_1Vr>*_X ze518!(#me_5WSqoH&(ZZ)rBSGc^i#<@7|>%iTvN;i9;q+R=s>urLCphUOc-6hyHs% zU{%Iu_~{<_jhx-;=x_zG|Fs9CgZ%$)5B!M|-X1WA`2YWV;1@sL1E>EldjRWi?SWea zrnfARsT9m40d8hj7{GNv0OZO7<~HGt0CR3DU~U^;qAdr&9n!WFu!UbpFa5#ROCSDS zdf5TnY;d+>(_4USfA+Eqq<>|;8IW#j4P?47rCZw9x+NIirj!9`z_xX3omyJk`_tB> z6p{w%J*`{&kT2=hcK@`s*G(x}Gho}&n!xrczQx0UZMYTK$~9eDUhLiHB~$n?fF2hT zJn8QC-1LFz-UHD3K*_4-zuCtzO zheBJgRd~kee0K+V$~b@Bo#(^&{!|9CGphZSgFt0OpQ@BAqM4o0|NXhD^>_n2zriGR zxifOlZh}~2_3%HOv27b9D1zgKYFqesByI?Qkz9nmeOk+J&h}@h05ektpnLOE)bI7j zC)Y(YOS+@i>D*e9lu=@L^)1;E&iiWLVlt|)4V3Lv;jb)cW@=C1ryWz0b9`)qS_C?!7h>r44vi z6Pq8Jrfd^mz21l@D%SnA#CXlpg!gj3`xVZhu~!#oRawnJxp|+C!dqbAmVPcpi~7rH z%b&nlA$k;Dm0aqUWU_4W^$dVWR*+-GxU>zH;I83gh?7^R9Y^-g|0LWj^LOoRSbtXa z`@T{X;kLs5Sh{6*%DMG?hyZ(KBQ=de1O^)ri zI*mh-InZ5`I%bySa-K$Kl-fcS+ljEJ&e~t1KH@9_d2(ZXh9Bh zm$Tct3epo$Id6D-11jhBfPHMm#jbFMd3vbH#WI_;8-Cm&A4uD*2L!^^w#%e;E~FH{ z`B&T~j#SeofM*qlbwxw%kKUZKUb=kdI7iP?i^f8Fsn2?Rd9_vZwOdI|Q4zb!lr@N;!dad64jm7KIUsW7+qS1rtiSHqfg0AZt_K!msQU_!@ZFj zta@nx(BAbL$^~amIF%vXyOjQVeE`;0xMH(w0#EG4jpPeTEf}Mn_koeOk1|TDlFt}* z)nj_GZtPC8C7qHckCQc<3PoxrDwAiyIe&7ywDd|ZriGYp zSy7}-PMCDN>;8X$66A5yv*lF4>7utbL$G;Rz$s?4QxR85bF7Xrz3lV4N+lL~UNil> z{C56dNFl0@-!4n$h3u;0K-4KB4p(H4tQG|~m_B1p$}w~5j^(C#KUdPOcT+5A- z!dkcs`+&|buBFR~uHF8Y7QS`72;ti|AA9#v(Zb`+BFr$0Fc{`50@ek8p&9Yw>bMuZ z%Z*?Dy8Q7vC2Jexh9{=|*m_byNamNh%X!kzQuDNY{5X-)QY-VcwvQoMMvsA}IjY91 zdo6Vb;wHh=8~IBXvCjOHSeIkP9yW6|r7%F}2<*_1gv;m-2;}YwYD<3--J0uPchFz@ zzDM}o$DBtS%c|ziEE&Tc1a1xq3^JG)+%{+hR;qk3_Y*{)frkBUf~B8$l;30(TUs`E zbjfIQWxkE~klhfpm-ri;0Z3g3pr97WUE+&w&JCZfrf2#bsNpSO&B^~^ec5VRJzWiL#2m;8W<&mB{&PCr@y3Rz+NA)H>i^; zP3)F*U)LRM?&=N-CWe+#>=JX!>}(obAF|g5=&IKsp(K_{ylWa<3gN}h_=<8hiLo?@ zT9;|?E3Q8Ze(IIfAOl1r%3Z3-S$7~D#Um~FH4mY4Lpi$@%%wHE}iW9Adrk9574I!I}`Z_mIdI&yd z%10C?pH;n<-mo$u^cX2jEd;Y{t8=T+Zv|GV{b7l`F072d;Q&jzwmN~pnB}RlYL;qY zg2BYV{xCZtrzD4Eff$qTo6CMoVauz2zaOyQVZQ+w0PkgSqNKC_^=gz_Y(xc9KIH>T9WfXYMJ@P{<;v4v0 zSzU4|b+Pi|y!h?4Eh^=jAT3(G0(+3}l5(@ur<0G6a6V&KApax>fENrQ%mUY+=H(sf z)tUF-b>cWlb(VSgMo=gGpO@)&&|c+R#MI`fPW-DAqF5QL$!M0?y_hGB_sDsS5E8~4 z;V=Z9-nK7haNu{geb)Ta?=hw?^)s0OvtBGjjVq@$;)n5lG<`sd^kCNaYWI&V-$$7~ z)<2*1eUKaDd#1Jlt{2c&mI{f11KpdlzWLm-S#MQtP;Yo;0TRMRLU3(z5SGUOS*Dqi zY%d^ANaEDI>vY77lo$9!p9|VxR}=5&>|Cz%#w|8kyw)yu55n-s^rX_=Zr&SRCUkYR{cLIXvlL$*4CQe$k`<> z)VzDazShE-C4?Zlr6iT8l_w!<-c$NqvE8>=!Uo^#W%~Qt<@^mJD_Qv4RJyb9Yzg9+*2UMdZE>4y?@if2S?`0C^~Kv^ig? zmkl9VI-5?sOtvFG&32?Y+tpdw4*xXU;pS{Ql`^#*`f0X9&DpH1YzKdu?O<~@2P~7R z?Z8j79ca$hkd!0LO;TQjYe?=`b>rA$tMvqLuje)KVH7l z-K_>OhE(pYzQtxndagj3yhCj}-(pRT{X4UlSbwh2gG z#^XV$GWqNul7-QgWlTcp+f{Qh^IU?o_NW+IJy%xM9qllCOLXPsSzjYt?AHE~w20+P zv~csUWd*r&cETa8oSm#3l)4V4&C!*Ej+WKUWJiZPV@z;;$ti*8w%nSzr%UwMmpCIO z!HN$f$0Ylv`49F{xIei*YvEY1`t01f*Q8>fMqEh=`s&t>vC@)~VChQdU+*baCRKoI z{jH7kvyQ(7>R&JoVud0B9_4_@%8>q^9>P<6bo+8CYnDew8!mU(lbX?2(!2YUcj6;~ zEiZSAz28<#7k=ue%Z8^5^0|ZgV~~(*Q61)J9w86$1dRiBKZ8Rq&~T)!(VZ72hwH7R zbw|*X_ug}OPkt|Kd7it0qfC=u5U$aW_~l2f`d8f@Db`_{*1+&4c?oKD-30l0fkfj) zeX&1uc3mT?aD^+rCzW*1k$o)!rW{TP*zd}2gnm5So>^J9Cz%8GC+^AoLQjp9qWzFr zdsAak*>ule-bz`J?|73oKBQ0Hq0?+Q-jGJXB|U~W#3FF_D{^N440+(UR}u%Hq9NQ( zu`~kFi*jZchANhZj|tiz;<3hUm%~Y3(S);zv3zEwBvaL_2d zed!G26Y7PP#xPToTuOWT)X!oTnWZB5w3?87&T|KVCET<9h% zb~(w;&#{a&Dhnd^YDgI?ujgD5KXNW)Ofa_c-+HZG&WsZr=gZxQ)%DjWN~ui0?|r_Jn5kEWs@iSlUj-}j!bS!S3h3Wqqm5K8e(-s zPdT+coyU(upXwyJE6pA`LI8Dp*4RK=<_u#O2}RXmomsW zq6bd3=3m44uKU8g!94iwRRMbqkrsz1uJ4`af771p{R3$X@Hg%7=MsPPU|z5kxzq-) zi4FeTPyO5np>x&{cQw$kv&Wg>x&hVpL7$z6PdV_;yg1GJ;-m6v;F6-k+~I?2I~ibr zbH4VnZX0M{)mxnPHsJ|1@o@!cD8qIOcG%=24qAiTL)J0WX}>+#p4qz-`Pzp2`3w>x zp4GpLY?sT@hRvw@;255JGWow%{vr0cugC%@greJrS!;@1ES4uGCQ_s`pB^f9;Lau0 z_L}Io?Q7b0dR~zX5fxk&%ai6dj$-k_ZnJxVkFLKC6`(nFg;=o+ZG5K43)tLydGjs<&B5P7iJMm&{TB``*;F41ls0g`2oagmtZiSq z&nJ&;4JOWgk_E}ZqS*gfC^s2sIyy9wSFfa+c>lIFx-zfx!K%kjVZ*n94Lh4yubFvy zzMd{~F?-VB`1M7Hi9OXL#HBdY;a#8Y*7W=;uwi?(P2|P;^|J%WS&9G!1?jug1-EZwQ!_`RirpYDr((|%Cf?$4nWmB*T}bXpHB-F%&lS&Pqkp$Y!WFmHnU z{=fv^|FjMo<3J&!qMxb_pr#b-?Cd}$vNTt?VFxVW=2ft#t6CK1M|5qU?gNVD#S};TXoAZc%0*vA@uCFy8`An*mh>DhG2TBZ7(Ea;2FwJdxMYy$zBgtHTo) zpi|)HkeHzt)PKi-?fLoBcB%hgih792-Hf}DN7^V*byVIa{2XsabMkdIcuw*m-+v_G z2KBBO0xnsc!6jH3loZzFeioXro&93X`xk_Od+b&)iU3*xDWWrswiJ2-E2uda9 zPA|QX`X)ge6p(HVBy~Y2e<#u>9I@(m(V~&<5A@QR$i%qAR{h5&o%+uvJ(!qrXkc_E znvYifTjm2}Qe<)@x(A~(A5psWZ4GDT0K@br1|5jbyie)I0h;jgSENfeOhtILh)g%E zkatbyVNG7zM57+F$Yh+dkBt8&<0WQOK4&sc`Y}55MbawG5a*kWllGEPiD=$1?&-=H zO?GCCq@7^qXrh;vYtq8oqhOI-_Yx9)|Iz%rHbe3K=Qusi<}r{9zlE5m)%L0(2;vmb z6)npi!49j;c4>e@#@6fgKy)Xh8R3vWa=#b1q){hstJpgTJiZ!X$b#SB<&gz#rXViQm|)bvM#nIBq;X|%Ou8p? zR4X=C1=z^BcdHT@Hj&-#{iM77`NRDCMnk|FrqkEq0%_;Z*}j00%fm&PM0I#?KtM+d zN!2AprQgDPcfC8$Hh3Z#d7BhrSjC;CyO=q}0`}jMMbu$0(LZJ7tDQ^b+6U~|*DL}1 z>MN52qlWnX&*)L8^dCIn{LrY7)yv6&$77NeakCzlfr~GdLiNQ`>rPa5{JcG)FK6-l zQfWrJ(~7N7hB?bM7~^s!V_)0cB_oJ*-sskiJ(C%f zm$JYO`vFZURJ(E4B;SfzUk!c6bQu*^_G|b&(_=}dB*41tGyKzZYUy#iuUW3F9>cKf zC#?DX78rJ!{p1^MI9E8JW9PuSLs}-g0~yi-Yy++uv8 zrUfL4hi!j|Yb2E+syJDeWwmGG@2Vq=h>)7a%I^kG`eDDhC}~{_eX^HyPadZRW=x zU*u&=g+u=6qI5O^vuBJ$Hrd!`)%LSYZQ;qyH5ubC)E(n>={6&u?7PR@m#o;|O!1dh zvk}Mro_B6}gsq901B>VzKrFgqHD+n)yUc8y?)e_pvfDC*$XCg45WO&Vw?ya#6JdY+ z=3)sp8V;b{_P!)!){E17fjcf}ABb+=AIx2ue4PBwlb`Qo&Wt%_71u7101@Ki_ZUSt zt@{<5ccj36o^!j@W)vCk9AnVml*tHXcSw&h_crtxjpLHxWX|xH(TBkMhD6A4nYj$( zgTuM}d9KgYT0fMG&TA`W7BtR;rZMh+vH*4g7*O6@z~mPo$D+z2$bgGJ%7l@)PgFFy15L>_2(i0#u))veN3_E|F%uq|LyJ{ znz!bPFNLubN;2&NH<<8mmN41y89Z^Zf}-LAmz;R1SSTEl_B?F7;f3Pe5G`*G#3uoG zH#tF^#~34{p>&Y#?&SY;+aZwsJ6MTl;%(<{gEG! zAL048MIOQ3GHuey*e+w0xmU+;2eYm-nwkclR|M=;{?ZkJ^0k4|Rfg2NgZ_hq19p>f zK>GrdW|?R`@$d^LRD@qV!Gif`j6na@rA29Zl1dquVCXCxD*R0=5yf}?`Bj)L*jw>vi=O;itNt9_)IF;O1EPi&T%)q~EIF!S z6|?-fWzG|{D^Jeq*}5;%J&R9a=pUQD8A0Q%Tns#oWv_d-QOC2F8Beq5uReuMDTg~7 zV?{tmqB$v0qR5YrlXb-qe3YOTT(Q)uUqDU1G-TOwEFhY72<>`A+Kgi|_9a$qjCv#M z&8<$!d$OnSF#nCzV3hh#N6%ME5of6l%oyT$l#l_(0Mo>81ia~qd--$jO5VhsdSI-X zIJ{Pr1uH(c>f4jso40`dnIW~M>?k-xN&aWxY%`NlU^ign6q|W0Uy?PGS=a-53JE>N z1Rv6J4a)SKx9E-H{^M1vW%X~RFTq52kvciJu`VK)Gc*xA1-(j#(D7qwDDFFqLMl?O z^?{~6_Ta-_v_jof;&<=&H*D$Q@9>eR*8P0;*$wvK{UPhccYQCwcM7hHJO*#gZGkoS*R2@{OidKJMj@yG2S8myW(A~D$WbvPNm!bw@SCSsx&`5 z*!MaBnG-18R=y)X^RLeTQhD_Yjvw2LmKFjP+aeoU&u0i$NTK~v&|Ynh6nj;$oGr-a zgYhw!StdAM>;!+}rj+;=az5u=)B(B}N&>(FZGZo%IIZI_dl*vaX*f6oYWgm->iHFbKy|60A9kpGiy_-yX_hs7aN_(!}n&~|>x812EWcI6JuGXJz zDifkhRGxi>HrVZ)o;ASpe$2S|=u15;=!b;Nqspu)HS-y?*Z9RXvmG;=Mj$lrkx$?$ z!}Kw;S&qZ(C6Tj50-RJ6AN@RuV@N`6;5RI)zhXuBSlwRd{+dDoc5$JztbO*huU0Om z1B(v?w5T;O6IFfRk5p;OH3hLhbBAZY7~11LO*38x?8%T_`z-r0zOmUoOfz3^E_5x~ zt8$DHhOzZfO_qHPACs?hi8Scg7=Y7LOf#@qwd%!nNN!;kj>7(jFPMBjwU##-PC&?; zb#hOkW*=w5?bMX|02JWv*VB5pLG7;J#9isH{7Ije&%pI5E3 zdU;=HE$Ya`4dF4UNGe8s^c^d{gXtxW+MRQ9j7r}QUawb{UaPzhaOl?Xwie~Wb-S%! zZB$Se@o~`2+ipDq=kEfSs4RWKmRB)4a(|#4_nI6g^c!kp3;>@RuXQkLWW7sFFG##< z7p415{}JxaeTO~ML37-Tm_Uv6g=wC}?hYYTMhjuZbUFVfaHxo; zcPQ+B#y7Y|t4+u5okB_XP0~qP&wso_{AzjfNvpoIs!Zf}8fK_Kd!jDEeVro{jNkgV zTh4Ps|KaCV-uOhzG4*{0#ELyYD`cozET`*vP=sk#z-kQvZHH|CN;Ax`IuGx4fMWxK zBT(@kswrmIap^%WUf&foO|X{ko4VyVjcyC=^Oz}F`OU{z-+Po!Fi{2FHx1Q9k<#`} z$anIHL@(Ni;NuWMw^0Oc??0=#3N@}|vvZi?B5m@n5VtpMzcypHRe+HMF|FH#;@wL^ z_MieM`h;{%J!VGoBaPs^Y4?iwK4`BL4QKIc?)qhJJxK!dR zEQm2>=1PpSutCc1`66D9zF@N#S!f0VLz30g)Pq=-3oSW{c=7R;G2LS(`@BEar^j@j zc^|`=&LxR?>}u;%W+>@#nem__yxFQZ`b~+-af3u!)|j9coPzQ8LA!~0{74C2kNg~R0P>PyH}v?>|*rlJwm;k>4yh6&wfDvpvwgf09;0u)BOkK-H-U_ zF5nL$8MiMf!oL~+_?hhm?z@dGCUXv5!-2keLG?5~n=gYf8vQY3Olyay8EJJ~?PzV^ z94YniGEB>=n8QuZoUk`(k0>co`G*gfw5vaFnY8V6#oIcGX`9(O>?3?cdfR9k+o(j7 zjbBDz%M1nMZ3ywf4EdQMKg(Saj2}m2cc{^;3w-;c>O`Iun@r82_zi_b$)4Q_Ua;{j z8n8xe7kR?kJ0JEHV0!MAMw6LwMh2UkNSYMLZ}^eEUBG@=5t)KH8qKBB03!&>-U?W9 z8oxp5SbrSbtc`Zk5C}jbYyX9~$Gzk@R#s{v=EA=-qH^f|ABzL1#fI!~6IqE5TJa-} zJ%GmK*MiLOBgtpD$=!dCq@X`UutePDp?ng*ohg6JP0o{@z1!>)EGNnPNCu3Zd(+AF zO7>Rc>nz}Qgq`6~zz;;$HtsC=wxV0fXl1mtsc zDnnmhkb>V;x%Q%yb3C2#M4w=_(bcAf*Pl!)X&e0+<(QYCNa~00M>fG>sHq#wHX@I>R;dkuGh(W__mL`JRn|Otz7*$rSmKsH>5K?l zcwC($Khh}aKgwT!{L}+egla*@qO1LJLOxFc+kQf-u?ikfO0&?Zt943M^QBn`D$#SKFytI79K9( zT)c9UoI7_vZ2I;;niQ_i$qi|Gyx*w-dIq7t9$h&}mIUU17Q;t@m~{mh$(Kw=6h0@@ z8K$bfgsIB(O5=r|zW<5l(FE-om@=ZISxTqf-qf=oz{#9Ab83Rg;BXGa@AhlT>!nTQ z*?!+e2jz-75Pg?@Fk3;K7EzE<7KU<{PwNn>*lf+e!)z*+3*O{sgx~tq={*i+mbepH zw7T#ujU9MgSX_SguKBhF8(ykP?eQ6uZG2id7n=;}amUs%ZcRTcKdi{t==;B03*r&b z0i5Eo9#^v--CQ~CY}KJ0ubmIS`2l>0Kb1j6?rM!i^opm6!R?8;a7wN{Lh5o4Iz^tD z*{Qz)>c+i}j`{oL|K?cnTMw+&QOFHKA_rZV#d`yNZj<5k(dovK#oRSy^07C@~?gs&xVF;4cZdfhGEC*MawH{~4ru;FjJdvqbfH8mz_ z-l3x#y78zJ|EIwuD}^G$m-y{nO?m|WXEMhjB1{@lo*8(3du_FfL4}bnVAOv-CX6}= z4E;yig5AnFv=4Omy7TKb8rU*-HjM&q)BAw%GOEN~KWNA3`jT; z2Un(5VX}oL=mG;LEQPs*ey)c_LQnjw#UTiKHU6fffr^#Z{Bx){XuY`4zu5bn8W2bf z&-M3w50h)ICi)828Ts25^0ipC#fRZ$Y&-`RiYE1jfUV~cL?y@?v8FoSJ^)ig{FixS z4LH104cDU6MC&#jrUvb=;a0Q>pei%bn%s~xBGLN{G)u+8$dhX(>=oLFCt$9S8?NDR z8#y({jQJe?=7oFkH$U8kzwJD!wABSQ=VgWe4}O9bd&0f5rf`8NldL1eIFEy#;r~ng zU&8;j{KsH?&@ReEK9=c8bj#sT#oJ+=v0s{t)`rm<7-Hu=-UjfFgH+oy>n&V> z2NM0C(0!uxbAQF>%qw0YPcWP{e{Rw_jm*gp*xBx{sZY(7r!t&7_YbJA0mqO34tG%% zHx@*Wm)SC+1NR2TPdk)?4rpO5Bzk?71UQfy>pC*LZ7w6}d9kF!_^ez2+4r zWlB*TEvx<|Cgf+<2AqB#pGQk5f9YP?-=qKk4EVrj)vfMZ*8m#ee){K3~6)u`f0{4Zpz?EB3MF`#hb1G&{f<`*-F^nELH^ z)VwitXbwsK7t%Z%&*z>+vXY)R%_m->OCZvMhx2oM`(hMS%fc}7vV!M zs*krc<~nWGW~HIUkd~$c=J9saW323Eageqwn)D4*`fcwRs19M!GE~^1Z4i zy(-H*`&8qhmC^rrW;Xmk`;4dm@PG<5@6RR!|3F8P6?>2`&dv9<%<7#L3wTXy3upMf%^IAB>nIbtNRe}rsggNfKGKL~)6?ir<6M9A?UetmVyf-0 zs$oomLeFg{R%LOsI*0D-WzEV7yj1bxpJMv5KhK&s9y&HYJTL0@j~+PPx_324RCWAB zZ26Y^qK8P(B>}r)MWY8E8O`_pQi!pAvrDVvWxnXq^Q?Q{rHW|ZGpyL@j0+3y2zIt) zjrJ|Wp9D#w_=-K}(l!eHGH~Lq{fQ|2N4;=2X1=txa{X=OOCkFcgf`)mebIjBqWVQG zzUW2g<99uiA;?J(J(6e5AHlZ>E{=Y|d5KG#t4eSJKT|fo`UwrcdPgdHaEevG zN)Izj&ZUJZg^2H<7I^IiaXO4ItZYd%Rf*RlbK}B)nB+lo|G`@b?_v-9kp~He%Yu5F zr#I0Y^*j&*B~-dSn!4DE-N9=#^(!kT^9(4xy~{*&d1!glDv?Dnconl1W{aS+96Jn4pcn;VX~k z0h}v{9D@A7MHR6jH~Llk@OaTuVLyM{g!}QgZI}o|2lB!_`I|4KdZ1mnz10OyS7YJ- z^B;f3{xHrNPOIiNtg<`ntS&>KcZNK}f9RbdOZX4HGh{RWcab~tv1pFycZUNw@Q;mQ zkStNVVB%M}%j)!CsN!oYQAJ`XcNufqW{BPC_e5*967uwq1_XItHpUa0toeTy`TEXE zojb|b2n3wAv-Hc(a%FicRJzw`L==$$mgmWt1uRREi-E zzLkq2n7?6banO3M$%^)*H~q_Hi(QErMtKRKVpF9F1nx4$Xy zRIu^GCwbf&pPqtM-$Swy}7J0F^(rmX3euW2;LUH-NcGQ3-OQP$f`R#L} zTWcE};*a+ERT(mlg`L_oeAPbpfVHsyv5Y>?-?sAn)QLGb%iTBR*fx>eW!AzWoih3q z#$Mqvf3$Mxq+*~c_A1MT1macRIQN`WPiuB^`?HLb+ttsbbqM}vg>_;YUZL?mZM^)_ zrD;FcjqD<40Slq+HH$i(JPGFwZ+cKeawx|oUuL0 zXyoo*UIml($uvi=hR`Q9o>3y``vSj4}0#Um}wF^ebr5v;$hx9apwVs(M@GDi(3 z_hv1ATA%Z%p`r$Ew4{9&-9Fj5aR@6S$l0Rai`k;_*^T5A>DFf@3g^y)r%0dl96~0y zf&zJ7iT%x#t9<{&?m5oEd()LYVdjQY+n<=$%Ls@>*l=3llcM-FNn-Z=3E_e#l8G*# zEHZbQx$GordpT`i(7gl)>ldAa%~Z2~dRn|%$W+Kv5Z#6(Gx97?O%-JdI(*qDs7`*> z&D#z#?@T*!hX^z;FsE@0;BPys*kAFH6@8Axx&as$8=-$<2%Ph!*1ZoawKkVz&#}yq zHYWLEliY@6Nzna?A#F|aSthwH$)#R$o=KKUQ(bKy$;Wxg`6gLhg}T~&k`FNtRMO5Q zZ!yX3NdCr4Zf}y`G0E*oUgISrE2e|5nB)SIjjmr}2rPY)pESuGNPgPO-O(gVb)l}d zBgu2U7*i1FHLz3(Z|uB8M#+UVKFB zC0?RN2XqW?q-WmpYR1p{`a-t2;hPTH2{2>uR;EmwHKB)~S`=k`C~a zw4_td_LkG!@xA4odQx4jmhxmT7fZR;x~C6EyuW3<^Ov?7@3aACtPFEnzOQ1}%nSV! z_BnSW^)#*>H75`OpHV*fHn?s{PjgJi;KBJh1-sN3S+`3I)uk(g6W-&{?Np6=ROzsy zd$t_fV^B{P8}zi5)R7oPQ!*$X5~Mo~9id*OaBnY}>r9FyFkWB4w5!9Hl1dS~7A zjvd1{@e2Gmu-?;w{VRC|_8X>-uA2_r59JlOZBif?4S&wBRgE;&mB@U7SLUr z{4xtgkMU1{!(I8U)jdbJxybqZoHROJvP5EvG6rNUC^*_d($bQ2uJ{a|S0;w}WU~3~ zNg&*hbqa7*%&L82CccH#m&5ta3ty-tNcIDw<{0``{-v|;l*a6$(-w2Dy(wUS!%6GR z?dl=chgfEh>n`?uT=!!b>+_U42SQT&S=Yi$SP?NzLA<5g0{HPxoTYxohxHnsxTQ1U zU)ETOhZq@RkYZyGIE8}2T=do8^Y3$}I@=%$CKUzyO)9qLy=^i|%h8@x?6Y?m68A?E z1BSu$(lb1obHTtKLQ<~{sF@rY97h+TU$mln``GJ zE_IB=8%6jRf%t8($R2)19WpUT;zQN@Fhj+8aZ?IEJ?EPU8WTxr@}=ZaKSLE52Vi}e zcQly9SPUg*<+@{dfTDl+RD&w6Tqjh~&-t!uFP&Ap(KX_uM((3bzRHv~1alk3;dgxMWfCy3Xj!HBtYSi17v{Hi_B_f)E1ZL_)qaxw~4WI~71Ti2gC!0x~=`cXm`uJGd z+G<#Bb@{S*{ zP@i_XRAiWBtoV)NRU{!LIIBXto2;`1E^G~*V9jNIc$D?RzOd9P-`4C5s~ z5726Z{^aJo(}W~-TC(acI|C9OYmhq%xoytg?#WA5XjjSFsZ(!hzCr%(I8!-k(pXGR zuVeZgdoTI7JSWvowlt(pP4xWr!`c)JVrGyhsCB@H$v$h*C`!rdW*?n$!2gon@7ZBq zhSGZ?y9!KylmEr`kJH|&wg0h1bzRBU?#4M<>8xlzVs~Tqlz|n|=_gV!Zo0y`d15hG z$>hc_a2vIFdT)%Tvj%z3_L{c4u}kgh9|E-CnMUmYn-e*m2Z;I159kpg;Wj7OuPIp6ByyfxO+heJ!&&Bi zz51;&cO;=(R-MG5&|oXJ?G0Z2$zb3=BbW$e2Ue%Ni0x+)T-SiPaTg2R!9j99jz+cz zaGaJ1bPX(R#=f|VMhQd3*yi0Al+O0R(j*^Ah*(S%$XU8A$BS$fcNrqKh);qT+p+Wu zUY7!Qd3O&iO?CGoi`o%clhs>_%A60Kd2yNNl6fwn?Wjy1u4&Kw(AtTX@nK819aejz z%k*$BQku^6@Y*VuVNWvbSv%Mv9Dz&T_RNl`?dvk~$jGZ@*`vl_-(}a|x3n$Yn&+kp zOosSey>-eC8I4f8)>Mzjv~-P7t}MI%>k2OI8MyYif~@3i&p~-+<<7Jt&eq)8pQVf0PtlM zQG0$`nom0+SXz}gGv74Q@owvb$emye5`h<%2UiZwW6(g`I5fSA>yusE6^gpt_M&4e z*`(;#aCK(_6aOcN>S!Z7%x;L&UCMYwlqZCaYqidy5{_TBz-xV;qIR~L`OE;1JfXhR z!hF5H86VeX7UtblIn27+7v`%CgN6A)4AH(G*Sb12>zRMG9xp~#-E<5RGuG<7LP-;i zRNA0f5weS`(J!|Hak?=beYLD^fARS4wrj2ypZ~^6ipI(g2bu34C%yi*fLk2dkLz5Z z4*6kr#K;ZYUul5vFIq6AZsw(rUXl~uLxZ7g3Rq{NE~&B-W{jSSPp~6zL5fsdC4~a_ zf2e%Hfm3M0Q^%)%PyUkK{6P$VJ!2UMNyFg!T~J{8by_4>LPO^ff6OFH|1m{Pt2gQ2a_YNr!9TyO3{7&yy-yt-a2YViF`_QEjZY) z36u2Pl;A+}JWIs{FuD(hN;3%rp-1wK|CZ&6)0=-z#&*31mn&fx*L=P<;cuBjv#Z7C zkPCMmYi9y@FxKt8c5 z+lQ8C6@%SK>;`zX!zH@!jL7J;bmGY7Z?{**JLYfAV{}C&rqeX}KVW;P3N znVD?Syd5XMGPKCEY|}TYb>yJgaQ(?DI#b*FJ;ax3-FKV8g^AYhL}WtUW_`vC&lZvf|W8 z>9Z4kt6UaEmc?$}(aJ+6D4iHm_hmu(oL0~@p|xK8%`8R^*ksG;G_=cgb$p`a zC-P~7g=76JtH{8QHK~bLvfGG3KjB9WL=(743*%K&cD6NR(JuYH8=pB}?S^QXdt8>h z>a7D(oW?|L&MGDUT^WeE<3zty`fB{ol5_u4dv%VwY{jbsh%1wK0ybSGWYtW8ZA!T^ z*}y6&LyJoR+i}H}$>&e%XiqI$l|ntf4Q0!d$Qf`mR(5gZ>)m*i8EfRi-6WYNbyw2> z$Xrd|PGWF_k(j(pYC9aeIc*R^MMYdSL-bEh-2ecOQDyDTH$hqqlb>z?%HL=1fqTA`2V`xE+%dMW`r;ngDziQGta}C8J zdZ?7^kv04^|97Bmb@QJNs*wEZaDxSh4AO@M`?~?y**`PFVei1iD;%GSEMvjU1rM5M z6)g|-TOZ`wflv`f@5q+q;~Ue0eH!(FoglB|e8JMxca2r^93PvLHe9|h?#1Ps-cQfZ z)#T>&=MI6am~v;u*6IT`tV%OvNqNPP&OYF?;4Fgriw#%A#6JBYV+D!*fXWqE~p>9u? z+LN#i4#=e&7k6&vWEzfa@p$tQQUI?zmG~eU_Ui)N+phgMnA-$95bE6L42p5LfDD^( zJ0pzH+RfqIhJzCr5(_(=N|_Gp91`=Xbc&UD#{X`rv1OL-ka+l~1);<}T|#R=!sAP< zNq%^+E5U2ennAJhddwZeFBK3N%3Y1e3w+YL(2CfrvGNxcv#a)yYpl&m75gYm664{Qtt}|^L3svZ!^g@N zEd7RAp|uwBkrQ4o7tpRaV#=nGD|45Y%V}^bT^p)zi4Ts~{)Uy=Rb4VkcP?D4acHc3 z0mZxSKQNd@iOQ~%}DEbPe*S{!P+=woY8| zE2@~~cF}GA*89RB-NLr8T-Ri*KZ!>wm;p3*qiE;v!@J4(d)SulUqF(D+KFc7*YmVf z3L*ad-aO(*G9eDcj`E`Gx@AFa-3D+e!+?GL*4Q2_)H+}f@?FkRg1Kz$zJ^6+sP!ua z=9PO-HE}kxp}Yt)&Sji(TpioNO-m<*a~p91=>6mX2^v@Rqln@vu8ZS-Tyd2aF~(Jw z8CUu7DFwkXM+e-z&wFY+ijRN}ChzTFuEQwHFA4^A?e#!#%o=PJ8^T4)V(W!+?`NW@ zL9uflkX3x2xCj?WaD!W^q{Gm`q4gB!oI1l8v-@8m)sYgHTx1YI`ZuWw5gz203?(>bJ$+EGtiRh3 zWL>9{+tI)5yH|H3xeiuf!JXPVU*Pu_}))?F?pez{1<2)bZH}T>$vul*0r*% z^dft#19aEbEAEYDtvn>aw_R(e^4qPpir<{tAMlHn94~`HLa3 zVJ>{A0%O2+ls25Z?35124 zoFNWURwkw#u+kAY5=WcT553jfj*5rkBa6A?$gAJV!X$mPmSbUgm9ck1 zOZQ#GMtQhjQ@Cg|B5CFk@P0iS!D(1Ly;>WVK{`5Pk_*MSqiQ53PMd;Dzqu$B+gRCe zW2k5&+PIlV4UONJ=p~1Jw%b~$`;0LL z=;2}9WaFP+3+l@O$*N_xTzE$Z|5Y>G8F?w)O^^Ox(p$$;d!(59GyAxXE0Gf?{=65b z(Goqs*SnBY)dOOs$-*Pe`o8|rgOvr8+d6`&K1Gy(HgulZde$ z$i7v<*iuM3_Eve(YbFmlfbKn&_9NB6;iNl?x?)UJp17>-UP{q+(VfSY$JT!v$@_`+ zi4c=B4=d*+b!>HN4ahvDr`NviLA-r2ynQ&l-5(tBw#4f^9q>(=iBlqH!Z+QK>{wap z-g2Adlo!2fSf{swb-^CYXT-*0zU`s4TZhDI9s8tCA{90VYNyvtuV>Yrn6|H$OK;m! z4#!hU?xcJzsuhnPl-R4iy)ji;<>)rP~YE4b7%IIL_UyF8O zS4(GIg&bh)amZ8OwOgbyOa39Lg^{)p7jB1`N`^6B9BhulYCjK^vhgPyAkjs%{4W|D z*#!v3F3C&%8L%d9YfNrSj%PC}gn*X+H{+l)_ zW&RE+ao#OaqFG+JbaItff0Ge#$)aE(+8e0xOquj0a*FG;5YVA6S?h5)CXZ`ehVklj z*C_9X@)7^pZ2ex(^rP?0>rcw+_d2c^Jtc6#wJ10CX9Y@0;Y4sk119k%ZDS}t0<9-{ zqWAca2d8lS589bF8x%Q{X7<3MEztH(X3_UwgtEnBvoB0%*KwjFv%;J8XKb-J{K_8n zhso=@Y30NsoQb(t|2@l#rl>g+`2z_?H!x;R z4&`r4&MlTx0=LW`q|9PlGd=#v`Dz=t)W4V@a{{Lxuj#@BQ$>ItWDZrKRkrN0w8-XL zCfc&j=Gt6u!!hWvx>H67t#**inr@BJRCa@9WZfUrT`GmE7k!R4)g{nn-r|+58&aoA zDkSpHxQa_u;%9|)Qmi)loH#Dk-GT=GdNm5Q!?RRONHJ%01y$3W*G^BW%MvGkFiVFQ zM!*F<6^Cna;ixXWwsX`jm^c22aa0)`HSmmU;iwI#8$;c)3gdvc2b}EHzYSJ!z@4PC zLT?=BO|8_6T;}L}5*uz5d7?mxfg8)|f^Kip1ruk`1<-k2HB~h?6{$gbJCdKYJ%TNh zZA*xWHTDY07be?z1W4s@P5HHJOEa84Tv`!Y*Ur;T86Qqm|sBNgJ*3xe^SPlxDi zB9%9McNNaPS3^&+{MQuJaSM(P*xSC1tc}o*qkp*Yq^uvuyEO#0y^}HQ&gkDc0rK-K zo!~mhPgb4oc8Fg41Di4rOvm4L;`AlgsD;PSGUoWgoc6rJVq}9@jjiL;uOK!Qx8$Vs zL8)6#gX9t=!>&|?E@VSAXk)?;>DcD~wA*=-(Ix4v$S@gk=X=9I-NZXzH}V7%Bev7m zPXgg$l5nhtZsfVPkU@_9(M=sU@`Phe=EO(@`=|NPOfKo0zNKzp@!-NN+lPZR$pGua zlYt2H<)3MbjhpG?C5JoEwau4cF}QmWF=|f+yoEPmmRPrxJhWNogYj(k%w^pu+rTeY zLXvmw*Cs{IGNEz?;ML~N{%fy9-PV6MKK00_2-eHk82+>Fe=>6Hx21VkS|60?IdPoE z*ZgZp-xPg`wK-h#Imy*edh?xE(W`AWh0eA0;NOeQ2A*nlK!6N9&g$^N)&167J2JK4 z0LC>TP}=D+qvki2KJMvC_MhIvY%w?)ie8(FlRGbIg*r1MraQ^U=VTP>G3AE>iUsJJ zT9y@ExTi?FmB0HdwN49^3UHj0>;-$F0#S9IaD{;KK;BwLJ*_CmozcZ0!@_W577#jc)AEaT_ zmI9jj$geUf9waJl`pouh`g8(TFqF`aw|;y7v`_N284b#RYvtZ=3 z0@&>JU(Tjr$v-{U4vqW;%s^v>Mjpk3;j*zmaYF-{*~Un_mQ&e%W=17*=lce1O&(Dmw+vyBwAFvv-cYLr;nQu~AC8ucyJ zdFt;#>`Zn0Av^3{f?V7^Wo7DeQa8I=bH4C2HE(WAO$X>^KEa|7k{{xcA#(!tFD^ta zH||+zTEe&nm^MbH^s?*7)ya&y8trZMf)3v^`4LJ?$WE@gPTSyauW1|+U1LpuwxhAO z{toZ`w3lliU4*rFxa>;t8B=%_wRcVR>_}asWaTL7tJ#XH_#EGG=!fC&BP%nS)>HlcDe$YL+cEL8P-)vZVJBkt< zmT!~sO5*P9r@MR(VTMXLtKx;-1XcTd}^j|`YP7Cq~EoaJro zg4F%n;jFpk-8g1PL=ru7a*n4d`UPUe@%%u3VU~9Gt4Jyi!?+i=5E(c zk?(r+AnPT~2P$K4HUHX#=>0<&Qnr-GyZQB-w5w3&{bEIiN-j-Yw}pG!!hN!F_SLN* zG$s|!ejk7Txl^k+#mH&ny<@zeUQ#ZpRoNwQ@7~Y5qJ019KnLgw!27-cX9!TYq8otU zV2(WX=$9VlkvL~D!0hbZ<)!PV?tr1C9`EKS@0}!J8}a9h97X+)Q~YpZSRc$_dijCI zE?KNw>UR&;G7h&goAp9>B(5n4wQi_P9FDKy1-@vR-t1agv^`YUkb7yOcbCf2ja-Rc zS-Q8(duT;j4@_0=LjZ>oQxAm6?NLRL?c{+Yyq~s`=FWgOk)cHoyKZG`_SkZ7V&B2v z?~%2$LP7mmZjbdQZW!y0#tLe5o1kGo2;RBbq}|!PtyOyK^s{BGH+g+muknlb`I@+zuXSBrAO-%Ex5+JCDEk5T z%I!0aYu{H5uJdtNN(o4N?*{_lvPoZJN5YweYU6>KGx?4F6nZw zsJAcR2g>AQ0e5z>plpljvg)tE-2zkkjtql(Z_m*3vRn_!(27F_md&OU&;7D{mh!iP z?I7Jvr=R9Pqt$#jtC%gj_@S8P-o6tX_ZWVS3f=Ol6}Q4`q*o}+dez?WCa%+)>M&ZZ zsybNL((pSwiv1bk6L;}bqYPShkI=nN&ri*IeJX%%R<7jrp5?Vx-8-?F&f8@jYrvh^0Qc?`=6m}2 z3>s16jD8OqY9}i)N|WISnWVglEn~fwk}76+0z|v7YTJq0Qs9MExvAUi3 z;kC=g_bC643XD{M0D- zmJ{y*k7oOaHTg#*Jb7)70!|-I044g&8sVKBl}02!(P+m?uD%(q%Cvk+3LiVft^g;l zQ31sUHEYNjK27(~fzOmdi?z^~Lj06+e*yQZaay)eUO3d4QzYa#{J>TvwwteAidVzi zUSsNAf`4f(Yfa3T=wbAFl``GXCIAQ(<p}D)){pgk6TGZFWv#Qm(k?j z9m+(4q((nQM>pVZ_O{7p1571mRVAt>Z(ooH@PfsraAZJ7vO17L94wYMmv!~<0(da6W;~g za{6=n@>=>X(i1?*A9lb3H<4x3CV~-k9jp)MSjJ~@m)2^7HdWkOprv{Y2qDjeQR8o;TDjMoh2Y@)Xa_)wvZ+*2l3Ei z$Y|>vHI^~6FG<6Ac<*cc&UI$ot0nK6Js8J34+0G#cOvQlZ3 zO^+mCjCMWkgy_GQ5MpTviTdb=F-MfxnVRyS_-Cf|R7MjJ>)m9c0Ax*C94Sv;FUh-C zgEmA$5x*4HjW!LkUPVfXgh>T?Y~4YIyM?|sGlihoV&+ZxXDd^B^mXnXS0#$)rLboY{PTGXhcHRT(|jL`_g`oV~b*j86fR7Nw7 zGNLHMmfn_O{+B#EXsvr^TI(Q`e@AKXrpAApOZ*E;qd=Ycn$Lr%%;;2|t+tbNfxuwP z-KwEPevN)0cPLMy2q}~%J&27=P2g#+QDYO1Egb_9fsPkMDiSE^v8bKWOk`PML}_qF znmYSlh>0#lZWLv7W;r=Avj*c>ByKyaFXKDI>Tn(WeiX$rVbw`QIZ^bG;#&QwjEXVJ zsKyDUy9jiB4%}L3jZ(6atL4ONE!$1`k9|bZOrCUZ@QH3HIoFVGwz=OrWz-}&QV5g| zWkzR`XJ6lwx2k$J>zlmxDDbF$(XD=!Vr&!nZ9U#%d}`w6oui1{K2C!oNx*D_7N-$3 z&|Bvrd6eb9mpq-5u<^>|ycJW-?jqJmdON8jVP<(j3TdgMoQ()*H*b`cL&U*21*(X{ z1c*_Hahtj|GyJ6!bAlryEa<4tBNFYZhHu%`K}7#@HUs}m%s+0k^~85NdFgSklT{Pz zWQHrFSV|xga$``*BSMob__5Rg3`%{14S7w;0x@lE*%D{qM%4D}mBG z>9J_2a7bY7F`dVven2w>y8akPI|!)bwUDt!5p#7Oi>j6Lx5lC`3p&e(V>-(RkpI7q zMI`ZWB?QAth9YdXY>nAY5z5(71SI7~pAL#>7Y#-c?eZZrL9xn<@Jv1!vmZQ1VdUyW z5g9@A~PR>8_196jv9vgJNH9etf?S#O9nI1X0wQ^I*1}+zJ9knli4oeaZ2$R$$ z`E!r8j%@ju+O;gxkAy|bYZS+Q?$w+9yyi8&BEi*koY(leID9kz(kbw)*+9SV5lz{Y z)s`1;3wiZ%{JeV{0eU6Juk`Z~Fh^PhBDh5g*?W6m0Ztx>4P}%RmexBh@7o|x8q87chc?%Qe&PZB+(?sX zKq~}4z1nZJC8N6eK&w!$^Q-khg=yL$r)OvhMFXbd|i&1alD)3eieStq;(dq5i!NME*L}aH|^t4~?QXTa* zZ8IL-j-|@k38nKkNsl6@O*tQJQdckZXA2v|w-j8f6z2Go+Eeg04SWtng^_|+^q^lw z7`ZR;%Y@|JypoJB@R@7mT*|6OwaRlC5kHF;uPEZrMkxi>0(()^VhdQ{7dp(R{q09u zqI3MsyeP^dLWsi24`qF$U+67f=wIr99M`qhYY^_@r~Ml&mBn-Xx6+ZDcm|h#+Jg&< z7x*6-R>YqO7Un!Xg1NgCX)9pD7y7e+SLSXMzPEUZKaWpu@q_+v+R;~dizEI4OJ#xo zl)$-|`Fz@g;vMdjM8tnNjT_EIGX;@MvV@NS%IDKo>rgJn!k_kV1=z2QP9nH6H`M`M zr)+;@>2twQ2KRl{;Ua@#5$T}e+!Y~899!rwqGiLeIlgw^)ldrzQsEu>2pfuR>fS{v zI9>XvJ)idH+w(zxHcv{&J!t%1=ZIsvhztUT1|Ijzgg}yP59+}tjUI=a;tOsN{Z+X% z(j81FEMTND$pvUEPt(m3zZ#g@yV9Od`w5;PNBm*~MEqab^FjY57x1)SXfL$yNM2NT znstsp!3EFp^IY%(e};Qm=s(GeQp|EFkNex%iK4N{W`Vz1yHX^gMrktmn`)N^Ue&~J zWP<6Me^{`jm{vqm!*Sy(M-Ht75&uhqttk5xC-)mDiq8f9;mRJ;I+154g4&Gz9c$LS zaPIP8u8~t;P=Gydw9y&2+=<>=zdD@zI`m|eG*H+i6!xpyan&(p0@8!w+)cq;u3x2$ zF-H@@+@1DGhCsu)&B53LMz`!a&`)9f11an{+f4;yR=T;&8JCJ?MX7arUeK zvn*F~nPUZ8;vbeS7`rl18Pt;JFy{CRcnRkwjf#kHf`c#c7g~(XMiuJxCHl^73g^B_ z0q6KX>=Yc#-4M=wAMgTyz(L?WP>yoU^qLIh_{1FEJvIbmkxZ{G$@JRY^QrZ9##uKy z3Mh9%veq$b7)JFbcJoz>MO0ZW;poh@37pHoqX0EtHNTJ*b!Ml+0c%OsC?6nAo=&2j zh=DRdI8^l0nZ%VqHBf>dM}XMN0!9qc)Iz`5o^$9BeLqc~>G>dM0{Rjb;_?zvy zz;CkW<9>slP*O+{Xy&W!8S!iE`Jn$Zo<>pBvNkPv?-ndqdN`_9t!95DjinS)q-b5V ziWk_C8kDO6K-(yY$dj0~t;q0eK(L`m_0J>%+Co3KQ=ZrP#lRx|-z`rQ;m7exqPOBH zh_r&aCc%r+aWnvEw8^zGpcJSL2_Q16NUm#yia91`%y8%_JvhDL9vj^QtK$y2&wvR} zBlibAYQ46|DoIB@%8T`_13(DwWr07*LKgbfJSpxu>Pl$Gnr58BXsf88gdLN)4X=$UTGC(`I@{FMfTHkx=*d%w#Q zcA{AH1@R*OW*0Bwf6j|FF2ap)Ml))!9H#q|U^PH)D1%Kzj@#4d5=GCErPZ+&ph&P- zWnfMK@#STT1M6fN9>78iXAGf?-Fa8L9GgZ|mcFlAejkV%{%=iF;dyBs1_+_K$&a;h zwG+*fbHk+9>qekiWKsTqMz}A7vIKTH{u!wNkjJ<0VMwa2eI!+1hGG8 zk@4svYfNhTs5Qhwf4)8E__OW#v_Hw75Bk+SiLu15G5`}ldoJ*c?TOHL2oXQey*%w_ z@uF(L9b%XvLZt17+jD_GmS=`ajL(+%Qvs350>6QyUW@~3(-piLRsA%BFA}P<(l@!V zh5kCjf8Pmi1n)!ODr-1jSs=QNa==mvJ~iz9Y3v35A6&MK9|{0py}ZkinnZ&+ghRY( z{D_~=w+P@_o>l{8qz+kONV7-{<-OIh5@A`nV-wfdwQTYdEcObe<}7I7QI%} zAi29p^?*kn<*8bho2XK@c&}q098%o9|cbptj z6VTO@(!s8BkhHp{It}bh%Hp8;f*UQXX@>D-oc&pe(g6a*8E-EKU<|v~LZ0?N;VH4H z^6cc@C~SfM3nHZF{-7`PyYa1V|2+5Oc1%4O4)wHZ{9QHy#50Jz?89!jyn-uXV zLCHeMaFdXk8c>}Dej!0d9FJK{=GBrC5&u+!GrAO8T-B3l!h`;QXYkK5d@H&2eYFxt ze!0X=iKM9(z_6z9Owk>)8xa%+W9bRIl}J-Mx3&|$O}iFmI67>q304f?4D+iXhHEwp zYr59!kNb;UOWLpm0X)j5x0s2ax0un98nPsG7&MZ~KO2JL{0J)#+IF_EMK(M+m*u## z+VE+bDhplcm)UcUUu;hnZuWf8&*Nz%ktM+5ZdxtR@h>yzVq^|ZVbtjoeXm*2D8oZ0 z*-ZH345t_~b;i3LJZcM9Nt9A9K430U=yneOc1FEdNmAC$g6D1*vRb8yPl^`t8@`4A zbMV8G)E_go?Xw!9artI`h<5Lm`Sb@$n~6(N(wJ`S4a%)aJ~}VK zOgr{ZfeLAbq_F)7$M=d6w(vfJ_IZS*bxIHSq%ygjf`Fm0~d^#(0BW z54X(&zI1Eo(!j?)#~Is9d|j|Ny~eLK-Fgl1yXehE^MYcTkaa|EvTbk_M9$`>W~K7p zuY9(HGP$)28N(2QLJi7Vc^uepfwtFbF(4ABI0g@enA=3w);zea!bPQqZuWpnnC-Kb zyp3ORX?L!@yH98crxlW80jEBsyM(O-!; z4EQKO39{evEQ>yKUj{y(Z?u~S5RXgz`xTR#(o<^6vgnMNO19Nfn5{rdR?@AGukvWc z6bqWfhk&&_qZPLrtXc?S=bH?(a*RQ%9CV>S+@KS#F=&~CF7SsMbmV0QE#^Z-?$5I< zIwfepLIW=Giwrp9A_L~}L0%F6c)dg`&NXP3p+@|}ct$Jw8f-g`aI94O^b)N^;?QE7 z9dx0;#h?>TFldv5q9HWsNcNW`5BQ)NCazS`-qwdB4XlIqP|93=w%V@tHZ@`!Kcm~M z`>dJM&8q}DMHHqH7BOjXz3#P0wk+C@idKn@=NuaBfr54$KlY30KFnk zB`@Y58NG;REsMT54wlVt&*xL%`*}tyW(ak*L!IN-8ER#%fRh}M z38n!j+#+DL11|7yGT_M30#@;^ejUz}&b(T%GJ`GghZ<}K3&tgWG4EEQ{(6a43}x%9 zr0{@h($cqpr;K5QSV%av`%1+uviFvfJ^NjYHiDer>^@osew=6*c7Yn-m+XW~vJp65z2$7dT8Uf;I52E`=Uj2A)6> z*mY}_&=)mf6BO~zUNJ3JF$6TJ$26$4te^uk{AYDABi4+G8$tj>L&t_>FaB*W zD|Jx$RgW}d!916^;$@g;V*dWOL~{GYXA{5nikO2liPB_x5zQT~pKFZrp#Lae^uiqf zw|a>t>eKM~4!+R8-{2FbE9z_qT;SIkaO52VPU2mRQOgrrs1dB%U`za)3^rqwU{$hw_Y8Tq;np!<*yxH@wOr0v0;pLZ5qpM4AHy%;R0Oy=Jcn3lcqE z05+sc8h{Ye_c@-<_>BEQ;7N*)jr$z>5+72&oPB2Qj-h=_KoVu;_= zjxtN0++^_Ufm7QbD&qD-6mf~ak0+FWs$d)sbG6-~muSUt0^+C>#E8$0iPV-k=YxI& zuk>RRdF3BUn(b^Yf?9KkbaS-e|u4%17t;s*k5&v8`C{Z5X%Cbt@Q zmDIRr-_blfbJ^v5M=MS_h{-M#4vB46BJkCZ_%^;W3g2ST$?IgoIJwCT8EweuA*^U+ zfnqj+1M))u1HD8icmg(9M8`gxuy;O~eR_hwz<=8!x^d@Q>@!jZs-4-V=l_-LbNiD2 zKiTJhKkR5I+LXWP1(AWKY7_J4X-UFp;|7{@9IMdotS9DVScOkX$=@3I#kvfqSnp`6 zrk7~N-RjoahRafdXSCvWfhIY;Iex9-RgM#|+5s2(HyLok4FXm<-~xZR0Y?rOu#9(c zz)+rWK&4>C23z9yH`t7F!3udd4k*$~v|@mOd4|Xuf@ieiEP=8d-W>lh!>cS3aCs1^#{HTfwv?>35Hcxl=ME{47+$*b^R9l@ z<)~-g?v%gHs#yNF^nK7J$gG7#8Qz#C^i>J*Dj`!aLMZ^dS$E}l&qRTNfq zvNIZQ6GyZw7+_I@WnfBGLYTLy@8v2PMZp5-X3D*~Ng6s|NSY4bZ`hT0DdubkTi@|0bBUlsfR-6y?60PVdx?i|G zP0Np^UveJdMd%G+saNeNP`!ZZ^9@H4Z(yy^od)axGqINZF#^y%tq=}sEwM+H;Y@y) z2$M091#+Pv5TKR?kg|~?>H)L(cw6~FS9HHK%}t-DidJ-U{G~zD&Ssfz%nsQcFeQ+w zxVD?(K(BkH;xk1VDh5)Qva4mq|0WGvDOwt~XxuBkm`g+CXv&9`)K_y*N2+^N`epo} ztS~jiroM}wu_my*wr3a>tVT7X7_$cHlI9-iHQIG^lv#QM)>#x+CX;rGtUU=@b-7D| zkoQ~?7F+5&TEz_J%-(RX2@<3b3=ab#A)Fq<*k1{2f#Alqt}3k72Bi5KsVL!_S%B^9 z`=_OZP+~hL^08NRhPVrxlOnY5MmdR}86Pe5AJwNOE5GH1E=?OaGIP8a4Ap3}V$E02 zQnStAF7WTy7ny#_5@ni#X9EyB)$xRWCki&nU`za3gUuK#ST*lPzc=Y6S}{^&w~xiS z=&^;T*SHs*!$QBxB1in;JZY_WkD;Ej>2LWsS}{xrWiF*T{!mM)@?rstd8ZDa$PQ(p z-`~Z3$E+?lFv<<01~nUmSg0T>;0#uZEQyh&3d!SLH94LqH7SPXFvp~a-s!5~EDOe# z#)4;jUohSMZk5`nmuSUF0&eDAQfmv(Xhpt2O%894|AFCE9xh-5@6;`2C4O5URPr?n zi=w$D|08EO+>)~){ZjHaFOEIo{AGf|lYe)>tsSc9W7Ko9*lfx9l?#Lv0g0Px#NV&# z)A5y^kJ1TOlr$=P|3L|Cu#y^Ll$0ss_YkImZoj6G5C4~1ni&nfv!7Z@V5U{f z#;?|{Hin~NPiJ(16r@J=_BsuxH~PT8h;C-;Cgh}zly>qv(HY)V3QVru1VBSRNosn4 z^f36QzPlHxgg38){qz6)qTZ!*srgb9U5E?iIz?w!8NG^;->+gO0Z^>)DT@CsPiDch z0khu00-Mrs0GSB$4FlCWPfBOPkb*MBx|7cX+l4b*VZ_*-ZLCn|KKFhGKiozUU!l1B zgg433Ld`A&v!G@t!yEs3wBjbA38mTvX}+?Q#L&JQVDwTJSl6i*w$)k%(3obpUZNAO zP}DL9LK3dfVP>+@=y` z>*6&o6NNEYLdrHmFk@quNn44iy}hdxppoEpQLbiZ+P@mF6BeW1GO)L)=f_VPO@Owq zsix`5k_t{J@KACqybw}6{fdy2D#C&f8huqK0{ z9yZvFLj`N#-HP+JUZNG;{ISui|2|%N<;Sn?qwPW5#a4LF9~Q@5-*I=qd5rC$KNAK*&ieOkA& zxGXyJKlHYFk-7R3G7pF&+h~;P3922^%JuA21iA? zawa0o?%%=0cZSQTtHO`^7vZ0|@Gc5J=3C*<#RhzKWu~avvDHgc$5|_=vKQQ+-B$E< z-O}Rd5xTwgC-2FvMw}*&KW*M5!d($-G&Md*&r6oa8UintC}fvbU5MB?Ga>KwV>TMHGa(J-OabHxN0NblntAT%tziGq#5NNxBYp+3$%hRRJz( ztJ_b6$BBS*%NNw6L^xm(KrRQlBD<~ilZv9f<*|3EZy>f-y@Mz3oVxvErrw6XWg_hF zh;RlGwp0`~m&ZPI&9na{>oqQy!hg%V0s8FT{qo*1wWK_@M-FrpcU^gGuT`p6mD*h{ z@4|Q@UPh&k4AiydPR$9#wl%*+8nc)9Pf*&dDdBccsq!tA==u1{J&^O~mGMAvh+DDh zFGth`+I}wf492mXB~I|(SLAT#ARmQqroP1gZsU-)zRgeKBw0>L^UC90QxQ5Plo-?& zXdKiQ#{I|4k3+W{XbmT73c$KF(d~?IY@ziQel~N1iQaj^nCrE0>GFX0z|wH(o`Cnz z@`@fCYmW%gq*xam;oW!S5_L5emz3t>L~mTHVI#Ue%~00-FRHZyFB(U^WE}N>#y_7V zX8l|K5qG%Yf5|-0iI-bHav1-fe+Y+7#X#R>oD54jUjED_^)DIdImw9(gZ#f_p+pE4 z3d=3-yT(Fu4q~566Vtt<`73Jg)TeMr)X4=)>Mo)MGH$)NGNK$OeD#|G_@(LBFgP*& zN7=vv&hgopZK>tYgWcAY`YT=tJMIgG^e$re4+mn$x18+!#XVY&zqr~{)BfUu>HDAt zzT4fryiL=EQ1~Jg*^)PVfKVpaL#;j4T|ag1HF5=2i{T8eb?`D+a zNQO&sUuePduT{*w%yq9!<0hVrKS4Q0wYw);bQ7@ofOGf!J+LtCH0wxZ5W^ubKFQ3@ z=uU5@InKIK-m|vZJwKtkZhp3R3}Cwe@ZG2Il!N<83gFc*xLO4qO!N=sl~R5*Uoy~@ znLEI^BT)bf_`$h~D1UE}{}KqtRg^dFQIs;5W!Xgrx_cS7dY2_%s==Gw!*a$GT?GCV zylmmKY+Lf7v0vdhaN0TH_$_(;HdV%N$_tl%GX2ng4O~Jb=cLQIERpks4q`sI&co&0LxqZ1aU!T?Te?vubWSl|4Cd9Wo2Kx+_`|PuSvUryljMeGyg?! zf{Evx3&=^#2y*@+NbKuiEDzu1u}~p5q2nz7tqvEET#A~yn$|w3f@;aVy7p}MeSe~z z@LGPTGLRF!S(ej~9?roT&US|gQ1?16mxlPd33y{TwsOal!PeEm?2W+zm*jc%-3{Xq zs`U2}j2S}un_j}PK{)+AkD&*C_Ut~nl~*aTSJWmQ%!xlQ%EL&{HEi)&c<61bJpqS{ zuiS+f$(?^Ue$Zt%X}6rqq3S|f9`EZ)EYWlG!h)>KRYx~&q>;JOdEX32UwefT=YC)F zzc{$Cd5QBMY4?qDRd$hSmS9Q0$sUckE%{PUU1s2%(B9#K-nmn*YqupIvmocX zcC-un=5`N~Sec9}2ywtXk89WnGY5#r7*hUUdf^o{QS!EM7dRrPYXOqqq;ODxVh8FA5d|yUB;wu``xzn6y=BDqeopQLzNv^28 z_-oF;*(`xosd#PbNo z4Xwj1<>SYRbGm~YHVWac#&E1L`8;u&UrYNJrF;w;=_`1BVuW?!T6}0>xTpb#q0>&| zmf-0p1F~ksGXpSr+Ye^GncR};XS$3~@TUDVXsF>wB zf@nj;&dTJi#K}_%3=j;TqtAS(0n@Ahp`yoou1}qu z6&^6EzgPdlFc1>?6~{@6UNIusyTypN{wm;fM~*e+;7LIVMa0pB&y}HbHtgwsD_Un) zTBa7nhsulNtby&Wt8btN^hr1)G~c7SNTuzH5fpe@iSxy4pWIPIFE9~U-dOG*F*}HB z<|E7@ZnWI@+O87*T~DOWp!B+H^_>op9=IyD+Ii3n#rCY7GwBfAy z3`9UBKGlB#i3W7=cXoieBMXY`Rl2eFz8SznvDZT^yO(}lfJ@C$p{3t&@L+F`Ko4fK zwVX?;h~RMXQSfM<>dL=MB&m(6>06Qc2wn0d&#&TW5>W@V!$DDSwq7B{PzP8fD! zZ@M}iEq=5}Ct9n9ttrq1w|N;=SUf{j_z6>+VBL(oY;W$1GL5gB!NhIu{d$dU<7%27 z$&+d{UUcJXA=vbyYn{hieC6W2dhMvMbmakp6|&n!X+m7Z^7S48u%aC zaO`@SBrM)`$(U|`4sioO+h+2=&6;owYc}O{xSuS!VOLxHaLcE@mZoF;6IuTnvZc;} z*a}tKe5?|CkH!9o4sdmLxW5}j>&u<(*@3#-XrsCd{H!U{Qd|NEC*SH<%dP9Emrkan z^75QN=#B2y*r8<6i95KcfPw_;UTtGSV##S*!c7sK8$UIZq|`qb8|9|1RmwDl3cBJi z*%b7!rF%}U8(+ZvJrn~Mt?|oQw!Wd@!)z=DKUxc?sdFrp(9uH)tnwbZ-$)DY$`S#y{A_yT%fWLm}h zq3QQ9@pQ)H`H^5+6Gp>opU(6qs%e#sVB~(H7%C9pGXP#>tr3Xz&)j1q0KDj%Y0M+8 z*xl}P_jzD+23+*$p9|1#T*75wOS3CtmlRYCIMkcBP{A==WPYAZvT6@oF9+1k=HZts z>F%V$a_*ZhencMZQ@>!=LFM}1t;)Bsn&Km@Br8<%(2NZzB2wN*sEhSdt(WAUkK_p)gMHoI>P1eV*jjH^g`xQBpcpw! zsYhf4#F^)J5)i7vdzadsj?Du!lc~Z*Gz}QxMiYg-M3}%M9C$(+{71k6oU8`!-Je8Q z)gEiBSM-Z?sYqtUZjDD%p3LOAxb$0jj#auKUZApcsE?3vFEimjR`b#Lz_UML=;Mm_vq!p#wG&VySlBV6yYP6ety+^m z-Qb2x7pLS*;;1l}-XjmO%wA01&D7X2hE7V}hX?x1jg@~yXocvy;;bp|F12LQuN2Br zT8nk5P7t$-XClh<3YYDkE)Fz^7kO9%Q0&fvN?NqoxO{|UpxlV7eRn5EK8goy#a4E8 z7vZ~o2vH34N6MIsw}bJYJVCE(xdkQNMXmMP&5N8Q)`+!A2Qs1pkLY&MtC5XB)ydUY z%O$@2GVkf?-KXh$l?gK1<))S0k&2qQjSJv`ce+3BDpC>=jl1l5OmP?sc~y9I^3WgA zV@z40j>zN2<2a|Sj9;d^M*iYTa*?W8iqP>QIbu z>2CXa#ZtHTAJgF}e9aY^L5`XBwrijvvaK%{v<}DPoy1Zw&P8<7;NbdS6RInhs!$x( z9;w?+TuT(9SSQHxo_T^J;VDO_g~Am`DAnkAl}-$%MRWahNe#ZL?Q5H;mai&XP%mac zb=Cfyn|~DdbW+b$`micD|jokEK3W5a)5tyVpZSQ@KSPtll? zCd3;$S@C}V4JrNkVoEol?_WuY`zr?YZMj`RM^O=z+u5{aUM2IN5#GF6m1LU8pZTV) zdOGpq(Z^8L&oA~~>ec1q_&LkD(=!Rmg03IkRHhXH zuhFZxqfKgb*;7ZGylKUmWrENR?p-hGpoPkFI?;l1{+^Ll$$cLM!YbMXlj!Bhp9dKrK_1fb4`5m_6D~OE+S6yonv<*uQTaHrnJ{6QS##1 z-zv>FVKPAq6o}o)ZNvMnSWQ!0u~6JJ(Bbp|qjdA{S?X}bZ?a1|yK{giZz4Nl{vjRn zA!23(ba%pa!L7Tg8y}M&mPCQ!)B7nuSb=*B)vUy2!kAoI>Kv3#xR`G4I## z&YfRg*jagwpjrWn^oB#+&SoR^$+O&I;kQNXex zVutp)&+TdOUjSza|G*SQ^rN} zfo0N+bxu>{xs41%i91UueQBJ%>$gvG#$kF94i;0R<~bimq;z%w;@Y1&B!se9%XbrOB@0#H8%dz0Cj7 zq1|^9K**pUxJ=cOf6nW;G-SQ9Pn7vw=|Q!^F}(k8dtR@0#|U=-B!bz-@sESZ93U9K zz`qNoJdn+V2&%4#ZGZk}_RZ6Bb(fHD1H^=2^?JkS{1_ z^)$LXI?Nwa9=*=LF~}gASxc3p-Wa9Dl?{99%O8@l%H`IL2B!9brTb4#g{fbfts=il zPYZ*|6RN}?MkRCKLX3prLRKLq;XiaoF5ZQvSUX0)fR@yR^TB}Kf4#v;)R|m)kRiKr z1?kR*$caoOG(BU^y|rBU*h@RgpS#sj{u^*wC^4fgS$V(awvKL}1!(OWDrH;f3z|le zYy~%*cp^8d(s_!cSyps5(K4j{Y~N1oLV061LISDl!Pwy)iJC!NX}FNG<`P3XrVDo= z4ViFs^ZUKpZ;d>XWxaeeKgnyS>r!-A!lB@VkeEzmV>Bg2OYL})q*%=VIMJ&pli0Kq zGUZt?`a4`h%;e`+d_g;(7O1<`M}(?Tw7dy&Q_eE(?#yC-RK61N-jJR8N_|HA^$69m zZ6Uqg!E1w_KkvLYkdYrdSDdDg4=>P7ne{&e5{%u}X+bblyrOxH8h3Xx{2)EZXZwO+ z?lvTPs;dohcl6l((5Pz_U-Tw4-70-J_W%Sdwf;2utzh85Dr zbr44)|5u#;f{tEC#wTC?d}~|kO@t$jmAty2@kp#zgU~XXR0Psv_66s`kTJ+NwVp*- zM&@7DvA|xr1#rg{<@{STW7-|)v?{+8s+RZ|L5teR#+`Uhj(GE8onl+qNeW|DjW)d! zR_3+}nGb|xm074D28)*6pc&W1@4o@0f`Y2)!tsfPc3ac!6&VQoDIck=#U%HL=ph-z zM?vzQZRtq|$>n8v(Nl<`{g5%hnNo;nj}S;3F`>E@eug}0x=(-5o26g_a=F~^lOZlI z`k|5^GmHrU?bfGVC@ZB`2+Gi2VRa|kQ{W#742|I`pM&Sg^E<`)@`i)s#9k8r+@=iU zCC9zv#`wa1Ym)i*cQF1OH4Ed-e{IdE36$GZps1k2r7*u&Kbs^{7b&p~YROV+oEoCx z&*@ISZ0_h<>zsSHi?XJ%=DROVfR*w4M1bJ|IZJOA0ct;^zL-9&v<->Q1UO=?5n%6= zi~#TFm{{_{Pa(jtDEk_6O@;N7ub)Bs`GctLZTjb?JeqNxASFJSgMuVl5a9Nq@`=*S>Dz2T~5QPQX@jbe<%`YB#w3c)Lrp&f#|3zxn$c0zW1ksT^s>D5Q|9b>|a`ga2Fb@v2W zuDnA-X2|63KAm*xUi2X)JO+0b&=y80X}aisR`+JkPfC^9av0=2`%+Lsz&mnCLGsRv-MTx{DwUt6Vd3}; zZSDlxt}1T+Pp&m)I>W~m#m)7ppOaHcvuN9|$lUj)tpZqdz!dFF*_LpBEjbElS<^t+ z+9Uboc6H4P^`9+qA~&c%D0cWD)p{q2YfoQR7U+rC=>D6MjC~U#!`Qm^ownoE>hYX# zlhOL=w@aAaP#BI^=Y>k&@#>MW)SJyi2r6=jKAvZ8p}$$d_&o)|qEwLEp61?Tsoc>g zoValyWA2R47WCpDfANeD{RaP0EIyf)*>jX z)uWRw6tlfpviXZpY+E>S&bgJPpH01*?wdA@K}ST}Yk1mVU=uA8j@^OMpHjsJ=cV(X ze!gu>?p5A>I^{j1n=-}LEBG*~o!Vcf6u**jJ-hk$ zEVPSyPeJov2xWzNUc&a2zu_pR7MjsTJ8fHNq2k7rC1l9my3M~#%^>woy(4+he&1T% zm;KA*ccSV+uks)2SI8hft4}D_l5BhfQ7Bd(BRB)OCJBxXdL)Z3>re*`ws_l;^(l?x zPJ9#rbC)fi8G}yK&_jWSW8-L}Wz0N6nhJzt)!d|sWes)flk76wbdJ#t#!%s`+8Jg~ zkjM$042PEvVwq^UX{-+3`?aQ?-n{Ol%0wvdcAJq(jhn}G@<{8X%*Gm{l;&QwHO7oy zWVu)mO%#_unkCL-X;v(cZSU0omX=Knm<#;ozoq{RC1z&7bRzjG$4SW}yCDbJ647j` zRr?}XjjjnME^lj|osxj~4!;?rp*G}-=H!hPC>zznyTF`s0dkFDdp~JEU&N1z9V&8! zW_(AaWtFX~?FQn5OA6mp#pL~$s#{zaJW8U>+Pls=)CtVzGHJr{Ri_;!FlU0wrf=n# z1C^!wW_<6*@!C&O%fhxd5g?t=hslRAja5;vuvA~kZeFJj6J>85;sjCsF>q)`R(^Eq zK^dGykoI!iNGT5ht{>{pf|)~H=ZmP)w#{jL(y(4_r}gO9$TtetQK%+lohww=bfI1X z5~_P88xEcIZl+wrUAd+VroO`{jw>3nIeWL;eDz}E$u4y-k)7}!$0zGJRd*xPH(SRw zrY;AHl07l-=u9G}zi%HR0>sx{YN67tvo<@vOTITh+bshdQ%4iM?jA__+)Udvo^nvz zWD`Ff?Xiw%|BzJwj46h)KK)^$Sab%KG$p7r8VOHlJ!5n8-#hF%hB}$~l)~e8!fz{6 zf9$d&bKk0HFnQifbX$Bd{mdMs!4NO*qZ`bRw7Vz|Q!~ma#BPp!VK!Z+TN&#Yfyu?% zDCS?Ca#c8fEpy0CwTFbTe5t(-UUl<|t1P)Y%1l9frhVKqNtQ+!7M;oBD&|1d$=?mt zBEs%Oy|yy`h%8gtKMv_K%*QAIYXGg?XV8CfY!vZzmbwC<+tR+c%n9@(ud>rcj6$qmYW z<=|=_93t4(z%Wu4Tv->@H-Ef7?A|bk7+l5wIQ|QhrvxNj2N&BA`D-iSJ!MFd2kaI3 z3h{3_gpne43u}a%dYD1P#RO^*^Ef1+-X9?3c+QGdGKi=yrWkq3%d5X$0f`cMndU;o z73|t*8sCH2iDpVMRy^J@ym?1nF-=S}tdYXdARWdL5i9c*G)43{tVFIzs6c!8qwO6Gd}AdQk6#pu z&nyU)e(2SIPO@R_h0KVq9DxTJ(t0-(_G_ptT3eaD8k*N)tH1Y~hHy4!LPJ@oZt~`y zDOBKvm_uY^BXNndp77?~Bk>o34nKz1y}4(I%xCWz!ey_t9DKjh6l4%Mr6fS;#_)taa&m&L9zOv-J zgj@MOD*-hXDD#Qgdxm-u`PJhsM6*&qmG_;aO?4cbBUIhVnYr(I_MRVkk@E$Zr}KBj z>O(B%%Zl|9ou*n2SFC)HlzzPzIZbUbugu~9#EYD(w#&qyJ*7r*Pfh1|yy9-;$BnDzK~jcUPL(ZQ<) zBifiA{4epxdy(1n&#Ymz?af}qBQ9^_y!yK#0HrZ5?#Ql8X|(avDNitGpjHLbDDf)=kmPT?9RHr^`V!t9a@8ATyxj%4RG{$j(Q`EKw+8&xs_BNv(Nemgn zd2<_RF)5r7%#+%Zr*QRpW}ROu9Mkb06m_~HSk$2hMg8pSj^)J&bwm6i4T*Mh_~*$d zXg!-#LjGQ)>qTkWpK_SlzB1Zj_G;X+oC;OOFM(|X1(l@%_GTBN-e+$fmJ1YCCPu@% zqw+3|UC@+zlRYKPFT8o5(n?6uG6n*+h4)gev&+P-r@k*4g8LNUqFLDYMC+EK{brYR}_3l)^$10Eo zzRft?vc{TUJ0{8V-m%F*Qa|BZoM`d7C_+Rk1a zdc2&`3mWt0E^_jDm=`(RkmhVO^-wjp1FA`>SsEl7z7*14E>d|?Xu``yZ&SPt+Q)Qj}h#>!hFbmBdCN|d6A1rnzzfm`o;8Y>ic}A<)b&}D@O})ul^Cj+DpANtyRBPDIHHr z%+w@mX%=bn>b7=CP71hk^%qJjKPtgr(!%OA0WmQ%;Agb0igkp5Z}L+azYVUhbkn-a z=!DAnmGH0btFILQzGnRUm|ra1otm2jhO@)26A zL;8F(FfDz&NOoqB4qLLF$K4oQkUHOJL2IHdVos-Dum8>YnFQ)X+F&?!0Bl7)$FLw# zl?Dj7mmdKyJl@swdjfvS4}xkO*1FYNug#rFS%R3Wgkm$tA#4wbWTP(&OOv@%%Us+q z*aS)aDV^Y!3mtHsfDc-NmyqCa5`5L0+t(7b2_*^kdd;}#HcK!)Ebc$vl~TL#sbLmh zb8i#Dscq>I?TPO@q)9?LGoAAtKXkxr1w1|toO!kb4iPZNGP=Dml(-B1NpA~@{sYpI zNKc)cAz@mb^Brjd=&6Wr@T1nMN)ziI>CvA}1LLKx#-9lIJAk3OnfdtluqesvBL3L*t%ZDVD(Qga*UNlqN2V`WqXgfsznVVT!e6zfM4+= z9Z_LgL%?YIjt#;a6aeQGrp_Uq)RRO`t>CAfbI(4*Nr`5*AX0w@oB1sA@;2lpq;sNC zp)8$dj=MB|<9=qF|Ma4DmZ&Ux4;r;^71&1Yw@O|8-GE=bqhr(#{_CheQv{28)j?5r zeZ?@NHXjeT^Ju?Ky6C**GYk+Ksqz@#q%xp$XnJGADTj5^f15CVgDRSwkA2)O)*pm{ zGupD>tJh+Uw%;MJ)Pi(b?S*C`5P5)L>ye11GZXQTTBY<(1odSE(P_wqp-dkxWj1gr z(+7V~YAyx?GIWz}>+<5}#fdX-oW(1ojLqpe7y;LQ&sx-os<>|7H(0{s;yKl+TzwKRU#k_rjS4aD60zU z3=ZPpf|3ZzR!kzjUIWayZ=<7*I^%+lBZ>>QfD}|@6GRwg5%FHaCJ1HE`+d&6X^Ox3 zzkIa0_uR9e=RD`x&l*^4>|Js`_y{7xc8WnJToBX->K61YosMO5*VFxOq`g8d=oov>0PBg9&%Y@V(jzYTQCLmoOyMX% zWLMRW>cL7P;8l4q=f$Tl^}E*v-Cqh{s;csOmT2*zd=lMqX;a15I~6DYA$x+H3sb9- zYnmOHBL5EPDG@0g^bW8Fm3W1SA_q&ioHMxdJk1eS2z9E-O`gJ1zM~ zFI6_Ye)m^$0>t}Cn!Xls#wj&Z+N9dpDFOXbMpba~sG4P>71mBY2dNo{`FN4^-zvTY6UGLOK>h$d zuK|x$oZ1$4K(2FZz_Ze?1$X!pJ$5k&HH!E`8Z)<-JKC1T(zJfDb z52GGwnggp&oAt8lsc_Yjn72?)vD$w~qA{_`A8lZm_ve>=b3-yWEk7OVAAL|{q^gAw}a z7cW%9w96NmuXnT$uVTAw^6O^)Joc`%fn@Dqy3xsBwnijuTklbD5I&`1ncwr(^t^z6 zaY@GAcPNZR*D~yNFzK1Hlyjxtom>xnh_6;tQvA(&cQFglRu>=yo&ir(R zO}(!MOGM6veVF_Kg=p^l69>RKk#^n@yj2{$X_WOIq}dI&jJ#qs@9hU1OwCd9K= zYmT#Md^I{cYHSDSi2_TG?`gl*{|xP{@tb>K1uD^Q|#`rPj6NGbkD5i!^b5(8-ll2z7DQ(Y{=gQwso|3ZQ`pBg z(p_y{ennl)kt}WIBD-+G$?n5d&HU4;$Pb2WhHs>^NO%>>NvaNF=|!KGGS@-^r5&Z( zkkO2G-65JB=>_CrgRF-f$mT_t@4)tDs;tf}st$PEnyW#t*YQ^Kpquo*k`7-RJ=!9I zSNS3L{UI}ZxlE4jgm|;lw%O}4R>G)emi%l^KL_?be8P{M4GLQ>_(&hmi2Lb<)YjyO zZ#I6Pt}ODQl~0k(3fj{BX>Q5%`nct`5P$22=#i}OhuXXWS^oMh`To``qDQhL zuWR#$wcw7B0)Ol88f9&2!jFH#fsC=?PsRS$o01PJT$sS6dt<(h%WidAPd?IYz;fP- zH(A@9;zC!Go1%CREC1Mzci{dYQvGh?KLM+YosbAAN(C62%n{6|>kkR}6T2I!RRB99 z?3boskAUq{X_NE(lLCAad*M>pZLvr>4J~yVASx+{sr1MV$lHveE;)6(k`2Be9#9k| z%Ixp&EWl?%^$XD$KMf8dn5cZ~KSi`zxZ97AKQ@pw@B*jiU^+Xv0P~%ota>XKEiSD)0pASWk=V}jalGntj)JL$87=Bq; zhg~jNh$qv+8~v%3$JC;q@Q&$dc$_zS)Eyqi->h(7{E z*Q}4E72?^{Z?GS(_Ud&!^&^8K3i5lB)RsR6ca!_bkb)GI^HXx1b4L{n5#LPxuoP zHX{lUVmZe@Fif(tszw{{})J#kY4?%Ub(*ZnScwMah4Z`jRVoE_b=$K zX|rp|BTD2Sg*so$5?)2_fKe(2;j$HD^JSfpVrj8<3aZCD0(jaT$x?~hDGP)okAhi5 zN+!AEy#;1OKbWWtoBJTh0|ejsRg3?s>XV5eUWXPFk1&SAum_tm6R^b)d*=m>$(vD# znjw8Sp-`^f%#i4OF$7!qoND8F70rcZuFz(m#{j$p^Qh*^B{}D02gx$t#q5s0Qz z;RiyA;aLNWk!y10NPb?ae9sY281?n00mhJ{tkml8LjlT0wo7hWUc;gauM5?VDbqmS z*t;T&rHd*IfntT3{|`TBwV>oNAf!w2zRX7&-!Un<{^)V6+n*31NVNUr-6EHFMvs5W z{SDge8cFQl^BS+%QcmC{VDvzVKN-LG!rk6z_CMW<-u)+EyoMd2C=lhgF$V2Q48^ee zaW#SATn0a@v&^7P;%=@4od{NlyQBqUEbc#}Sj_!ed?pD%fGp;S{P2Z-V?3+oXCbT9 zLI(5-4j0yTEZ}?(3t6>U8VebvunpnDY9lTy=8YoupM5P2daWe5m|4{_@A`j3 z=rdWzBdpMT@^ij#W*u3f@v3=Qp&6hT$;LuTHnC}9i8jj;X|Vv=WSO+sjbsZ%ce0Sj zQsMC-+>ltw;32Xt3qK=tSNMEBvyyziZh+z2%u2EcCd>9@1|nNk5tj2%dO2A|Sx&W* z^fI%Qsv}AnliB~qc-HSI>vtzCJABU3cZysydc0^apYrbOUOBy&EMI>z1dNLba5I+W z%l9s zrOniy&5kF|V`2I~I+H_G#ys~5p$Sl z-&z~lz-f35=_{<`N*xqa-LN+>dUn#RAt!5ZgkOR_zhf)(xq(#zyp~^^yB1HeHm&^8 zUk;h6d^(n>^h<_#9j6&WMaC3NAd%$wfdR^wlO_<|4DB}|w;~lRBie#GcHBGu&%xs* zQb2UeA#e0BN6&4D%c>JMq&}0Qr&|9q(2(6tI-EXwe4gc6w3lRJ!`}_safgTUH!EDt z-xlF3`TM)Ghx4!WGj;Zu(Jyj&bLp1-kgM;uAIkL|_Cr309Z&uB9=TpUX+IVCJZrV+ z*UYSLCPKN12(q0XY|;W>B2>&H2hyn0M0I&0)Ghi&6$zMp_sEwj_#c4j!L}ijXYGBT zTMtu9P#_Qd!=DD!Q$pJVO-l6D z{58=B7gh+gfSzn5w@INlZ|W(#rEQsQ0ft-qagi&0f!D#}85A@D6l90F1C9^Eu(AXW z3K~WAf`TG5UlcD>;Zr>GrTpbpVnYDErwQNOE$V(iVFf*&&b98 z3aw1XAP$RykNJaz;IMMRx*WDjJ-kLrh=r;!KpX(HU$M;k1eg^dA4huv+|M($&WOPS zX7Ej!BZUz_^^7z*zsO~Iq#q|w%PPLD;G4qvs)RC+0wY{E6UoQ7+mt(GJU~gS@=~D` zDr;^N*S6sWLP1teCRYF@*|-L=x|7qkRI+Zkj82QKx-8g>|8f@0>c^I3h|M}0Ro|L* zw6}D0j^s=99CJs3%iPi@Lov3XZYahsSf?sxBs>t4k}7gR%g+Ci?da*B8}3fGM()D~ z6LvZFh3MLrC^YgF-51GC@j}wnT)sdG2&VP{e$i0M@QiWA4(%ypi6PsziWv*OT~IwV zQ`y_V{98`UfYIIj$HU^!$68rk>9KV>Ij!fZ#@fK2W*BXb@W>8P%tEr7npJjcDmBQw zVh>PIcjF>zo;0?=l{9Vq1wYZK=C|+(J4Own+n~sWhCpGbNpVG(o8Gk|5zt~oWXi?y zK;&Vi)fIIJBosl8LEsB_iVeNZhFz?dW(fwk%<$p8Eot6-`zOM+DX8oyUl9PF%pp1U zsY)_AR9`F71>qLNVshUC7G5SX#gN6SPKzmHLKw@QwlU~wREY)QDMa20mz<(3LRlJI zjPe|#zgh_w8kljch97PA4tc@kJBU~~V-3E9+Bv8@2b8_ytOaDUEd=NA!Lil*@LOde zhy)0x@gz%VQIQ7zEWT{EJ^Nq^2`E(3c?UddyOJhns_iPldUR=fl2Kp>)zH3^Ee%tb zWQ@^UUUriG`Zhk<#vbu&0b83xLgRu>ep2RFapKLm z`FmB*9d3TTys*ZgjV0z`d>a&CDqs)DC!~nlydecVwAeMg@N^-{Y@TY4@KDYJMng6ZNlbuOm_!&BUm;l;q|JAX z0iTzuj23@6DWb&>77pPPzgcye)2A4djws9(%q`p|>~G^3qJUP!U%;%iAbL^*X%Q9O|xIM7{#WmZs1Gg0FCD7|=qJ19m;A2ha@b4HiIb+zm=F--7^zAS8mlMo%@&0HqfnIW zALAZ4!KwLKk;!Uh!eM)&FOsgJCAb-G4~mTtMg44!QHOIhCh-5XVt=$1lBh|=NVU6( z{~Ys$hlL-Cus@P2PHYjS_LmXpJDkvL=KD`juYGV=tFbw7jyNOP&>X%4`nPQI1FD~x z_uDd3DIpSmk#tnpFWq>FoT`wam_aM?<%yoZaV+t@iJm9Cp4hkQjTm-TPPI7vqB~3F z$WT_d1#)EMGDn z-?Yd+Au)h^OzobI?_dX1anRI0JftvNfh^b{6(^Ndqr)9vxLk~G#xO8DbVWV_XUL00 z$FN;;?K~;D$nG*oD()kzkUI2Jw3Ep$5K|ki2URNi;k1<7Qg-LY1jaeJz`SQarz1i8 zK2pjx379yF6iZCioA8yghg~PiyXDH(*k0J^&JoHyR}^UaKZJ=lS_X~wLC;DpRx50f zXzPqqMVH5Bo^%5PL{tVZ6VMw2Wet=3B1WBlXQWC zo389>jW%B8iHyAqz%$}RNM9P%Z!5{~W0brcShHD~M<5Xzi7Y&}pH(yZWe3)53AJA8 z^?V&^9ZdL-OEpY4vrCxGl`2cFU8kMVhw3u6l`*S4EinF4dGh{Gp0Cq+koVN8Jo&%N z6CuX2|A=BH5W^)ixE zh&>Q2Tc%18joTgc0K(I8xS(K2dlOLubE1|6Gh|;$X&)o|Wp=nvD#nMm0FXm8nf(MU zxO#hnt&Sn#VTFvmr^G|EG_c0>)@*hMwCXj%1jnT3=(J@@=_;YOc!*pH-CgjREZ_td zaEX8pQZ^RQx|$r#){L;|iKmfY5Ombdp$6mmk-eNaXqD~tKNDy?9AG!kzPOaLS)02` ztxh1(<8pKUhnZ7q+l7LN#uor#;vkaV%;Ix7%S-JtVR$6{SCq({I1rry9mlNW0fjb1 zI53leiir@Y1)*?=AlkUY4oGxe;5W_?BwvP?bE8?^SL))tJ(LQMz_W1b<>~0w%2kNq zM4_@HA^kfxb)f#2Eb*dpA2sheS2Q^e7D6+{awDG<@yKiu-3D5S4tp1~(`b!j@If8# ztsi8CO2w8ukqei|X;}~|JI>O)ElWbY%Fm^v`Q~ZVZEc6Sk|9?0OXR)i*YTm2g)bL^ znl5>b4v%^|)P_UyRwdN7-!I@04gfi=?Df=MS*k@Vgp1*GLD0RyDv_6j|Cj4-WHu4!T`F`6`SQI+gs@_#s&8Giww)?Y0d-N6H!%8AY&|+d{tIj5&FzeJyHG(|*;QC$xVfxV0YG0D?a&S!- zXix{2R%=M2s2pdzSQRZknRiaDpuWuNt?IMSRylt%LO?5L=Mfys>Vi6W31|{fI`3Mh z+qRaiy^@kb*tUB=gQ`5|3)=x9!bY>f%a~NarbsaDU~_h#*{jIj6F`>_Oa&qe7+3U9 z^!SL7wkn%hq;fDs@EInZyF-F9cKY=ngxDwuxeqBuCH6d3%7&($YBm_6FoWQa#;JIO z)&$FznD_U#`zk>|;?{X!SbeAU40fb4ly26$JYk-HJCm=1FI4Ob0LD5z(olMIB@wIW zw>l!sM+a;^4z0Ym-EkiNJYVkD+s#cX=^20m!<+bOO-T+KH30w`FYs`GX!Yl{R- zY>RvbdZ(fdRwaU(161rk;$kS{6M+vxf%yzE9hYQB;8Pzb19^GmSx zQ6h)8B&)v+8A2VHa?$iH9OcjYwKw-u;Gmr6zl9RnmviR)#%ZQ7FX#DH$HEmL|Cs^K zsWp2-I7ZcMcL%lVC8Ep@cn(bcin;YSER>_zuT?L!Bu=25Fo%MP9v@aLGqNA?da`G0 zF{~|tFiGd~lUSCF*64awP4soC8Ql&264a9|8851kd!Nd7(_M+#JwgKDt8gOHg#H@Fmtc)DV^U z+Ua=NA91;g{L6#06}A>jyV*0OK7GG`+(9(F$176iu%#TkGzVu2I=)FhqbB$xbBF6) z+wWV5kEDIUxPQgS>qm;-1;5aeYkQGJ?xT}^?UNX(XAT) zjcMp}WMl+Kwmc7C3)@Q@T$#l0fMdSen~%%gElN0+;g_4_p@U=p|Myc|QD?8gJ*sO^ zr-HB1iwSM_dYh*EDc)MgBNS4x*d%D*i1hR1`zf0H7~PRM7a@5HY&Ej{|SNaWMwIfw@5WBNd|CvxP#!x7jx zU)0ps2NO`c#PpZz90>1wRfy}6YL4Jw*OeN18n4AR@)XnyMe54^1`-tpu}7f_Ch`)% z0Fg%xXe1j@P;QI-+ZJ)etE6dE{mh~mNZTUhBdYI<3z|eqDu_n2-Gsc1v#nSu=n=Q5 zI99P8>{NW}*yzZz^zp@{f~{r$D$xo@_i@rBI)U#v+?_DHC$w4r;d}BY&O2>ES75y7 zUDHI~)=pXfguA1c-v5$V9CZA)zvwIwl3mW`^P7qB;?fg7i(+`C8a+qd!CE9LpL|H- z379XwBMJghzQiXLiU>1;^l6WnrJ|a#+~5xaA*DThIP11}5-TXcsuxrs>nzeJ&nhj}K}s7v7mrmPn+n#c zsG|pF3;L!aI-B#e1zd8rh6Rj(%{+Rcq@fMw?v`mt3O^}OlzbIvZ8FoK$0N=b^X!3Dp3rjoga_MsbX|I9=JS2lU0mzP>20b$4nBav4@<&*VT#9TD8rdb) zwZ+y(5T>P5t#u`TZ2MPndR3CvRgvz5uTTV~!c*@oYU*EqII(;ft3(9;xJtm!tfGEU z^0|(+F85vZ{Ooo$4fof`G*oOfj}x6gxk*Ve@%&C-@=~!e`BmEAZ@Bk!>8F?!uOnuM z!1T}%Gys0!qb;!ceo?)lzF3nbt8zZJL`3o47`{UJc4_lkz`O2-Z?k%^OXLvjF+O~+ zG9+7(8eEJm_1VhFAGDWTjOb0FKe^#Wfx5Qf3P5q|WI*w@JR20tfx$rm6iCL^=H9y$ z@D*tbPGe|W$Ecy5t%hcnFfa)v|F-;j10iJY!I^K;JZly@OF$8ln9x}H0d&ON;S|sY zuBY46I{On32$IFF4_i0*L$m*>G>m08Wt9$+oSSOTwEFxX;B8N}Ht<5%0=+`riq%CS zIqe!(m?zr96brf0BySXXw=Kc6g^n_nV`bk9Br0G=*OR9-fQ!sM^OdNZgCdW0^`w_A z?XVw+9#4g*i$zL4% zIo}^$o|-Re^T0(+Kt)~smKFgn6mxd?KiT6MDuL@|JYOW2)72~K5gv#LuIbT2=~0><$k>;&#gN?^ zbHu))aUpZ)4&Px*aBC##pQO0LRj~2-X5Uln+A%aQV9}eD90bIYbH`9Iu~dP`ij&ZF zl?vMoU4pWbV`(vxVZ^oGk(3#GD^^b7-qLcGE6fS-Svg>UQr)~m0xq-OFF|^Q`UvQI z%ma*1Amnwjm?O}`l79}*uE<$zh3`hIt#D{68>jyr`-LhT4m>as$E&6MWHkO4@HYFE zGtl%lhJ$8gs(467uC=W<@zZ%G4I z?=v!5ysQ75qpJ8=RT2J-POJtO|872-=#f^FY&13e*Q%7YKs^y{Ea51uRN8!qV}LxSRM>ac{04%qRnbyb!0{6tN<=V7RtktKd*f)&4BRjzuj zEZ8kC3915PgkMgBY)+IFEW|8qMS;6k-C9CKc+9zD_NS5`HiL*XzpZwqQaYvYkAl-Z zoe7Li57N!!!jJ3UYO$pks_6bWHO1m&69f&n!bI=^ zSX|&cSr1?<+NX7(_fsW~+7zCYqJ57!-~%TV&*J2gAg&rg!gTnXIFx|!Cd0@bfH8qq zt^342?VA{rzI>CIYty*-tOTJs>)o?a>^0C@?hBTQ|Kc=XU!%ipuedr1TXGI1Y{y12}I*so> zeKproR_kko{Sl^Uk1$0Y+K*{yIWmG_SDtW1zYuSKNz2|aOJ~9uWy1>%OYu z${}r~vhiZCO1eR;v?obS_qtXk z5(bC}OhL?9LIk>j)xbBT`=I=(D5{ue&o|+-Boa(W-^6vgZ;j^4rBR`!=|Dtjk zTN87cH|I~cx9#2o0sJDQ6cIZO0vn;m~kEl2}Pw}CbvZ%Y^tD+UMSC=v_LRfW(qBl^~thK{8h8u(>A<-v^kBzV$vAi^ud^gHS)fj>3=I_=s?Zlz3(-a9&zR-*q_frIexl!iX zuH>CU{MhUS0^6(PDB!%g@8E9$#~}>oJIndOl~S?;_n22dVMmvHiJeL+(OD(6gjCyh z?yscFsZ-CG6b7`<1{*O>LYR&H3HKM+)>V-h#{XmgBJ?#t36a6=rHj4Vyv2>{(>qpp zr$yETY7_fgdpr=_C%Fv@(ttEl)@Oakax(;;gM?}}CEXZU6*TV6H(x%mw`mWq;6pHR z7i|CJs*vY^_UIFmQ{4UZ9m->{QlLV)u%%sxZ%}pNNTy;-1rycq!F}_&TRNHEJ?g&7 zrodN7_6S)~Ck+`Fa>HTJvvukywEO|&gEV#VN+dVay9dg?t=QOXyUhXB{QwgI7MdUp zHu!!JxKR*_KZ_)xRpau|$hv?&^kgmwko|Q|dcBXy6!i*XMiB5E)E*ryB?;&$5_>si zB{3G|A*k>5m+gH6g4Z74a1i~?7_{8E?@++=<220W2NomaAbP;}h{e7?WZpE|hWjGB zFIgDymn0cP^VyRyrw%8eR((T(Oi5g?*!7xPu^7i~%sK zuudhf)m925dVblrz03Ob++*S&DVnVvK$~sKXeRF#tN}9rP13}fNS8o-DT%#@0Sk_f z4%WB{oN?14FDS3_`deGshF`3~Em*hQUM%>^%zq9_!#Qk!mR+VUNWH7XMgws2uR`i6 z|A#R=uu-V06;+wvJuAeBedujb1^pNpk1w%9%}}shXhb1jj;YPN$&7e21mtGY@S#J@ zQ{zYsmP)RK9~y9n=+wCDr02$Qv@`c^IU(d?%r8zd0uxRy9er~OWkq&)igSik@qQB$ zJ?98H*?q1`#mB3tQ+QyEc4^;y?b$li92x((!RC$wClnLV8atyCZLu@Tk~QOcQS2CO zmyRRSU1JbPvq3HvlSp$-_!f)?mPPm>7O(|os7_qZ!uN{^m#vDZ9rVQKTyrqdECelm zpeiG;xXpxn*%`%y^b*Mq0`7QbkgK>^Rfq^ow^v2ldsE8OG%e6BweLUyr6+$?O*qaK z$@k%`dRz*+7s=W>n;sMJXqxw7v~B&l)8Xdy$9xpvuEF9pMmgm7@q>OXfassl2T)Ds zTcM-U?bs*M?T;Yyqar$w+B*VJqf}U|U zog;l#Lul&pk)Yk<3Y8P#tB{-Kw{z*0Dw3hSY<$k74Y$tD7)r{CE{+s%+&E`C+311j1P#-E^P#@rMsyTIH8i_{H-${d~9Ow1?fExhdz&$XM zbTB-^E4dCxQpYzXX*KQ~cwNMHlZ3^CQS`Q5_A;L|zD9xtUvuF z=xTwNDZu$U30?9^SH-%%bq_Z}R&0Z^ahZFE?@w8sQ9As7Ds#s&mHS?^r*bo`{6D60 zhkUZ9aubjCEGlk8rt&^yOL(~E((!;XLzV!MlB-<=U&!MTEk1`5e3CRM`GO)ZvRS`?ON_|Lb@!32ur|0uQL53KW5SYK23sXxi)`~=P zM8AVz@2y}_hb_K}!KCr`->F}`q-GsppcNQ}nf|i%Z@44Zr}2d_XXpU0?N7jAXB(&3 zN&(MEF|s-p(UDk;mkOn#Y+_S`(7DS)Sf62sabJNs;;02z$n=G<4J)>;W)$?X3w<0j2Z*z-WMx(O zAef}QKWFr3wSqk*&J6cqV&S1QKP-vd2%;1};*TRHZMRB3TP^e>Rat-GoqADmAW~Fl zgQW&Ie&VCq-H-G$(ebt|XEP~ZSQ`*z(V4q=wZ_{WdqAFVv!7p(=MnbvKjm3=0{K6X z=Llt`{}MNmv@%KigI!;xJP);>z49EepF{H8lV@jn=RhW@gIvtOSr*1Bx-2k)RVck} zyE%QEQ8?Lzkt*_M$e^5bE&eLKvqn*o9S;sf$Cseg3uY!2+c`Qqb~eTIHCma_7b1Td zI@oM5l^j)z6-yC)k$J&ylDQjmVj7z>Y)_*iYZr1j8h;d(|0eTzPrzL~0WgviC`M&# z-q5VX7fmI`IVHZzl-Qs;I5oef7YwCvI--AGu9{O+tVlY*0yJ0U6rPnSTw@n5Fn4Uq zbZ}Txb4&hUcW`8;#5Hya>Q{t$6G^UoC4>v2ZPncz0CgCBc#GxKd zlkkyUqTC$PtVCT?i9b3emSjpq>=ND7B;3RclW_ajnMsHWqpc?4DyOiXDSVb)xXS$b z$IK*L*VNppPKn`}66@uoG1YIr->gKZrV_hh7i3*KXG%ONAGHNj2bpsS@1I7*JKLvc zVVP58U-zb280-|e&K%XO$o!@v&pJgu&lJgbid=7YX;$RnrXmxZB9CT@d@Ud8*kH4< zHq)`eO+^McMQ+Fxsdb7BF&8&0QruLei&Nx+Oc9?`WT^Ra42uQ#8D!s3nlob)LI9@O+?*>*TW?f-LOySMAj?$S)y`! zEpj+dBaRSMX#RoA*M(BJffo^Ksvtp+<{srZsvIggIjeiBJdsb4y#Kok1fnt2_U2q( zhZr6W#|sHj%?X1ola3bTuP32978{=uQV*5ufjy$$nJN5!&_kb-P*7sRk}@Y>Cbp!u#M%@buRI^& zmB8=~W>3NjGRE3|P}XAqUECCyY&~5N#--H9y$^bWm^9AHBUflN7h|`5{exDn-ZfM5 zQ$ft5sI{isCFl{BK*28YMvvX2#pXi9@H7cwFQ0iDp~Y%=!mHiX6$8-nIS9Im2L8$s_9c}RM?|I?;A?_`*{Y4QqmjP0^%kqCEnsTn|A3|-G^ZASo(FY{U!v%&(gGL`pF)xI zMx&<1gjQT=FE`T0HnAE_2&!F{5cR) zYkidv*~Fn$>)cV*G6hcrw;33{!|x_=B5wj2Tiek9H}N$7p!~|>yaq;p6?E5&8>V}? z4T}ZzOL%+&+WGXWEzyrMHQz8bxx}Xa3*+|ctE&Ye2s#JRbHSuk@QMwz518y=9(YkOxP1%f z({1T*Vl2G2uqi^Kb8nrGmkvINa4htf2S+yYkx2E5+`uCni0aiW2g{bTkCM+|ZU80PmJ z(Pn)|Roc9fJqhG9_(e?I&YZX{nk=p*A&CsL?cd&O<+4s-ug>$#BA)k&?Yd3eKOoDv zCGTYYNJX8}xZ(7isO(q-mQ(^Mkwwio+qP+VSLQ=RQ6dZSH)D6?mT@B1aTBH-+1Cp& zMnxI3$l-x+q@a1zjUvgj@!c3z6Z$wY>Z3>}RRoPrWC=E6P^u!ALD7geB-5RneD@^% zGYYC1JJ(B*`0B`oW|mX&jKwPLB)90yc_jX|Rj8!BA6+9Q^>y=a;}?R)+`2>IgV-mZ9$JRvE?fb>c`a$NH+`SOlp`#}s#KP1} zD#7zXKu>~)b&m#+zM&K}I&(ws6UK+YFLeSVYpUSgoC&U80qN2_z=xZCsc)MEL_&(4i&f z&(Hsw^4{nr{G+{ckE@m1nTwZ-zJ={TpT?uGpM(hZh#WM-eA)u;6NO(gHyk~Z@{aJ{ zppMzNSVyDJV_7$`tkwY89K6!&t>utX zIwi<8UpR6kbtB%Apv`jynViGGWL zuK-Do7G|Q5nGi9AT(!w?{I1Ao0e2u0PV%p`B|H0xzltPYl+iUzxE(Ozes)P^$+=2w zcL8lkbd8=qtf6*US1Ad=B`b>6$B#a+p#hOz5#Oyd`HIB!J^Slw^%doi>5`Afz;A?H z=*0QTiJ-VxXX8yN>4Xbxwg6zFXmLa?FzFt!wTIhs5oF)ZLNxPvC z+em`wGtH-%C8Ym3vuEVEG((L@;lmjz7Zlj^zUGn*mdbE9875CBrt7FNnD21j#teoZ zG)6$f6umbUH%Gmww|vq`X%Ks9E^X&N8t^72@#HC@o8X=kozz6kZ3m$a)q2LYnE4o2 zAezKn?lSabE9}cED6lh30pm1(^g$Nl3u^)c!zW43kwno-z9k#Dq%~(Pq~JVEF#232PjP`Sv%2bmjcj-_t2zP(Az4XT{uq)ESV*Xv5ZF%D?!Vsvsvi6{_n zR1G)jI~;-i=ykTfK*=GRD})=e3FO2<-J(t>b%9h8*Cx?}u#yrGAo)E_ z-QJPu6s5+hIo_f8%{U?%zwHMOSm%pF*US*>AzCv?cz^ev5B=8BrLWcEI;m_mETHw@ z6b?}KT8&X5z96*S;VEOPwLQzm__Ry8$zbx?(c@WMPnF17-4&LEM(Ls7RDkyLqXo^3g`HtmLzpAnzz5BD>7ieSGxx(B7Fd1$R;ias6iVKo)al#`;abI7HOB> zS<>xe8Jkyo?hBt*y`y3oW6~b4M}i%Bh}I8XafT~dL(9{r2-mgAY#@3xmJl!U?bvDd zR9iU$gT~!R5S<8FHEyooOjN%4p!D_t%Li#Xi-M$GCH0V&4U>2u+*4zr0{@prKs|Ba zU;**Su~vLv?c~ZfWHyJY7V*r^*_C2(MuP-z6T|-7L}WUWS<9>s0f{Im_gpbFD7wiA z@ON3I0V_>u(1_n6sEg&xwa2NW>Z$Q&p(798P6T--?th#8P;PNN2)x|h;T$GxBUO`biGo^<*qIt?Nnqm^>7jL}ALDr;pO zN?3+$`6EidcW{!m;b&3PD9e){NQ;B*7C)30i={=VDq75QS`5-+@>N^Dh63N;0I2|U zH;D5PlPWu>nQ5&na;a$7^`m0$3ORN?i<0$#EXv-QE| zJB;Ah4R#c8+?_y$O=>t!ZWe8~x#Lk=4-}#SK^0)X6ejT9dv5u)qbodCl%f8NdWV<| zgUBcpExNXIc{J~MSKJ%YXtO0rN{@j|&Qvs}>{=01iBh($Y9Wn`Sjx1@fxB0KK^@SR z5s^3fb2{DvLBi|2il-G55g<)0Hf}@*-;Wso0ne&wry6;Wg^)$yA!vK?CoT5p33udX z1_ubFu*;az#%C1H32CpazYpo_vPg~}yPXSf@|S%hu9l;$iSLOw>S~n3(>C|%Uig?? zs<+Ucgk@WoM08R#latDiw`1gMJ5tCYXnMcLntHy^=uk_wD<_=kbjH`c!($O*;$oEe zqjV{02^Dak?0tPVX6BB+CI}ZRQSnYt?1g~=QTLqrdpd&szXC9oYm8_cBpk;PP9DE; zRWLCI3zZAurkMcyI#QA5h}U%OPgyLToLT7gIGPp`4M3~?Qt3g(F}D$+*cabR|$UgQyE9&ds4}+m?b{bAOpG(f}{aEPzb{at&cGzioTC6R5hq9Cy z&R6n5qG#J_Ia+M6orcHf*>)NVlfHHuUZ1DhX|1%_%XWQ*S`3=kW&408PiwLVz`O9T zT5PszejyIu3nRNwW+V&J@WD$n2?F|SiEEE8>OxzpwM!_*gh8A}W@|08Wenu_$7*=Qaa>A6tq*xU%R^fA zk7Qu#gsx`ikiq^KOiVh)c@fflo5;XCiVdqVFt2%rqpAj#Av=7(T!N=c(=fQqe}pD{ z-O+&sHQ)EtkrN(l4D4Ws)*$@GVY{$=X&Ls|F)r{_o$XbcFuN0YzlO?IG__LCe11KB zL$lc!GY1KtpmhB2>j-zTTLvCVzl9(qyJsDG9sTcG9lV&M# zKj_>+5F1W7Gc|#X>6y~#zU{f+igrbq=gia_bS6DhGwm4w~dxDisGWy_cmPxrZJQC<5F8Mg<@^Hy+ou<}j9wq*Tle#eT_+jSpt<2-!GmlSZ9##AcB1E9XD=;tpr;tJ-A_|`;`r5=q z0@t!CP7}9eiVfk>KBD>@-3c1~n&`BWBnF8%TA173keU`*KQOLlD8aU8ti6CT5HjI& zg8CvS>Jiq~=AO@}0SjWWxN~Dw2P2AUT}Jq)?A-(U8e(^dzvMS!+)A8?p@UTn0Sxb= z*RX+NB{cxFM3@{e)S~h{3KG0|j!I>q{qp??g5Va|nF8#$Dokx?q8g7qK%$6a#`^UE z-Nasim=`$Ph4g+^1k(Va_PzysxSt0{z{qVl~DZoqoy~R7!vZF7Lz2QTauJ zM3zhLM8_i&Ajb3tNLlOvv8{&ShFsp(ACsm|580%wiaCK)5TgKWcF#Q`lf{F&#@@3* zn|)l3L`oaamxxZP$J;`-`9+4mAs{L!~b z@w@lS-5?$$K#zW1-Szq5mG>|2hcZ|Pp-G94__>% zRoV}^IqF0xE&e(jgAgPbMk=}mTC>TRUu19S^BJXb%VntpdMkXFIq1C66{#dPGQUc| z5$0YzE{HP{GFqAvzZy$=C4Y%0gu`2nnD4YR6;Ju<$FH9@G=kNG42 zdIb%-?O8p&O~}1E=vfocf*btCrzJJ2Qv7)E8P2^@rhU>vKeMUQ0U;TcvThF=ErLe3 z06r)|BfDfkqHumlALX)E(hp=`<~*)Uqp%E@Q9cZuGQHQGr4tSxqMy}v&v!ww_% z%~?{35fBq)n?i9)dlp4}z+AZ4d~@Ai&c-y@p=?aTfs z!Yktcieu^uSiyCvHDYA5IJq@F9>oL+6+f$yLEswWzX+9s{+(7kl>}?*9lyKp#O9i0 zv)!f&Ol1GUZPYJCgCgR{he!oSG{xie8#6yr1C_`&akW4DvT_59hk8Hxu4}LFsc#|% zx_*q&ik`l(ld!0FEDP;1?<07bR{JtVPsTR^y)IC{Ih%Ml#KXIum;#9DMN))93CDhG z%7lK2AuW+kIiHrRPlK}H?52zuz^CGX@n<+vE__;Te`+D0ddes6D(Fpx3~i15DO*0B z=Laxo5&YE>v3iG=s<8N>Di+bRYU+>vJL;FWg>%mNX;J$t?P-{EkZBm@*VW*gqf9^^ zJAF1n(8v-Wry!Ol^;`3U6$||{_PrmvDJP)KUE{A<74Xz+35|Tozc-tJF>_S;E~Ha9 zi#n1EntcWz`^C_+vwTnV<}!t>JoethY#Q*5aIx?_(w^4klY={O5@ut|E%dj|o$y}$RpBSfyK^i^u3zi~B= zf&qQ0O2CmjSXPhHq5UzG4WeSe{&|+j4((f3fB8)|1@eYLA%fqaOu%}-4F%modPHd><6>hfGgwfuj7eE-4&N&iW=}>rU1TOo&)`01BCP!u z(hpd2ae=cQNMm8gC*Fj_=)EBvbe@5^$P+vRa>IEbkatoffw>lmQC`r~w}8O*YRJ>s z*5aNy5LNiFT&|SS;=TBQM1xaSawKxD@8p!djyYLHFp22ZFj}kktB*sSif?QV`+}dm z!w_w)mIzbF1wtIx_@Hqm@+xLOAilbWlKmnQs-ePPsZgXt?g(>Vx%^Ku24t~?(g~*c zE$+~>MX_yEw<`PJ?&SDcdP0sz$RV40E$`|&7*--bvk(w9jpoC1ZNXW)JJ2tjZ3_p9 znK8Sw7(8T`aMLIRx!avw9QlduuzqBbiGkmbS; z+^X_zlRAJ*@<`m-X`Jy0G}E+A{B1Z`A-2W>3F@BUVty%b&v?HCT~s*i8uA2}k&`Sdy`NE$*wVDt9>&er6+M2b7QdH%1@sL8C|rr~iXMi;4_ z3c^EuiMv*Y^dGSsZ>`OIj&=Y1GJt7;)E2;^!tRfkLQa1Yp_S3YWUV2CeyGfRrtyRr zfj?SA(du!#+IZc|lW5RI5G=fy*u9JuWYNw1A4R#(DcWpz+pB3gq9z6=+U?J2Hf z%o{HH>Ui8uqwzZLXEcQQd%&bSSz7Hpdge98W(N`@i8+E!q>U@?V4f0@PogKT&}Pa_#enO*A+%hh^FH*u52v13HQU^kJVwU;TfYp@&8eG;=Z-jXL7yL*1g{7 z!t&_$<67)qfZuzt0c10=HG-i;hvPC&(XGYYQt5}<3u>V)#F31zhRaV?(}MTGUZq@zhG_G7m{c50qeF!nYBm-Q_dmBX$6i@KJW zhr1{)q;?kjmFfwUAOB+-OZcH8Xy0~jM1XS99zhF&BxWoY?9=SHLGPo18-t!ICP-q) zMvqT`Boi?jCqR0QydM`c9~G+=M8v@!R&pPwt=hqwEDwlJ_MSBaX$B!)b6rTL$l+j~ zNEt}_jWYxVH-?MMc9=7Ih5lpO5i`PC1%Z(QD-I9a#0y#z<&8jkAmXA=f5Ywz?T_Ft zDJL*hY+XwZxwI!>C}K~}14MvJKn3#1c&=kSuv#Vz3%wFT^w4f*qGu|VPZWTwnH4=& zB9?8K71%>mO6-c&4Y3jtt;)Y(!p>sNVrY0cmX!BTOzC=C@S=+`rs+`W z|8LjjxXi!HK?D4DQ;v!4mHPo5?Ix@to$98}l`?5SueWy63j*4R*VE^_z=GNWZ%K8G zf!s|7pEH@(J2V_Ueuoyjjb??_mG;aL+d&6XV+h5(9BR+8?*h#=hJHy9s6)3vKoO3l zs*FyEQ$KbItvD3fAal}8Xe{P#kj$7uGD0~MK1%_+45)rjFXbcj6%bJsgVPAo0B6go z?XcVdx9O(?A6|9(vki{5Z7*mBu$eC_$wnJ5XV{2p-C9ruAc$nGYEVVpb$)%781vjp zO*d?02KR9LBi19#;RvyC9OSJLlIKb)2`1iB;3bR7$_^>1s;HA{1}&H*kOfWnK4o$D zk;mFovOqtKN1};v53Lq^TYyy4AmlN}XJBJQW z)E?f%dgArH=>!`%QMvcO647R43EVcOBKywWuU3JG_F~_A5U3CY205}(t^y@C2={#| z;f=BrkPTGIZEn=iqeQM23+Yo?*bu#Pkk|?y;WMshZ#$4SG^v2Mz_>>LR86N90!^X{ z1DI8`N!r9CeUe z?HRS4TEH=16al7Avzvk9^bzNx+jgGIk@G1}C$D~LAaQ-RfNZYSfmE!9sUC>G;Ci_b z4`U7l0bGJ7ZC0_=&{2ZVg|3Rtun$nqS!T4de;IOwm)(=LgDG^wB%am8hH{ z)a(0$Mj?yJ;m0atzPTOMr;uV;(S7C$lHq6k`J<7 z)@eNJCfUfvHO!QkO_u9LTEu0DUcI~57=J937)O8Uv{#>yZ8b7pJ|erY+}2a-WvAPk zCnj@+T(eh7xz5P#}nsD%m!Ayc8wVFLE$8WZU$zXg|EhWzpkhku8eGY{-ru zoc@zUeJMNPuRj5|zuRq&dQ6F773?mczs^=zM^!S_7;XG$w*CTdJi!bgXEYrDl5gbW zAdCG)p3`K#(Cq+(qVpAbZ_VUtc)>sr6~U6RTH-+l5j@Q=+eg*QK$6?;2_gSsFd@AdWl->kbXV{165gjwv+jKO2BzO zD3vBEXRgZu#I7;FDni`$lbqit9npHP zMPeJMKa>SSebXq66JMdc^)dCQ$@TD)1~Eq$v0@An#FcH8OO_i=**Jtr3VxG-;AU) zr_++MY6Z~hTM-E0UzDQ{ZtE?uGp3DiP?$oxDs;8EtdJSl!Y6A5_yf`C8v`VM1s5M< zL&naMFFX07A=o{qD#tt}<^OHs+9GP&hxneGW zF*;=5BHXlpK;|={vzetz5pSUUpl<+$uo}R@0Dd)RsZ%t$$eKdC&BQm&><5&UGLjld zRN{oPrA_aBX+cOBNmhe-?>LDvfEoO@X(99RkED;|u;iT3S@meyfSb}a<+Pnh?eG}d8NU^u}&LV(XMXH$cy)7DPE|^x7kXgRK<|L3o zxQOahTU|S(D3x4lE}bXdYxzdrzr3{}S8`Uf0nJhFEWcW)KvbZ?rm!ZUa3l-d|2m3k z6am6F0*8r9jtvl!7@3)1AQ2bbbeSzK_#<^V(N+9T(lC|ui&^k`I>u0>izQ;jW*uMy ziv;L{=Nm-|tHsJFBbzxqR19?5{eWCoNxF#7A$)b@6lE*KH@RFV(Q#@pBe9JS9`kgA$z#pf4jK7a9 zz#QTR)bk{OFCriTj?F>O!tjBBgh_*`TjVzXHZaR20^)gSf09qb9rg0hNL{yxnMrh2 zJS!OkTIfKg2i7Sd+GgYT4rh|bFBFG~R5Lf9QuB%t8C^`B5H3WVu$B2W;dVsx>n5lS z6A^YaHN5s|HiSdUJU(1XsX%A(k(_wu$ol|7F=a_qj(tjbX*GaE%T}Io7M8Lb_s9uE0M`puU1owxoO`{LyF9a>j@Md)Bd>JM z_)MIbDPwg-Mf7M3k;>SS*t*bw*rIw5M&G0#uww->P&O^0(zKX_=0#Zf+8-oXVcWq6 z&fxs+Q9>Uck!lG>9mA(0Wu7%xT>Wg8yN(1gJm1FsEBV^&l>$tViSe)5#v!r5v}X{8 z`A2Cx(fRmq;4!&t*ZERRpav!ZB=nQ|;)Y#ChGTYynoJ8h?~_^+m7@wl&)M~2B1 z*drQ5SrDS#%@u0c65n;C98?@m<~hIaRi^|3C5WkoTC5WV1lyuQ7+X-W%kMd^J-U~< zP?Dn{+9dr)3_l6bK&hZ5ZSH99Iz zI79*x0*hM+syWLg^f08ATs~h|BGKX6*l~vDsL9$W*B=VKdJz-UJTA$NOrfG~#5}Eo z-)NQLqcIXVteQ$mUGVO)Y?*K9TwbNFc2X8?8sU_hG1x5XwEbteEU^;_8hI$^d=?(U z#NP)3@Iv2Fpj>7|ll}4hH0fy(6jb&KgvbX+}>wMbMxaXApyrWM#m1`L>C z4IvrD#KkQSiMDyPs9{l2_8tlh zQRf685t(4Vb@x7HJMgp+YK8>ZI9=#dj=CKT=yc5RnJvEodu>A%wn^fW=1mQTDOE23 zn{`Zv06O^F-_w{E^DbJIJz%xxBR6fA&>5LeaRc0A{^zrU_N=j+#UXzbkg|tL1wh7# zE&E1QR&K*IbLk^AK>e?>cUrowRwODX3Sf&P!6w@wWW{TX#rX`G0>e$sS11aSWo(Xw zPjCzt<1bO#s{Khghm8n8S#FvWq7CT@yJ@4+%ZB?9go^W9Er%F}*xJ4}B0^wpEas+7 zq$oWv`S>R|lcF|}uTa^v%E+ zmy;(tR+lR7Y*}Ad+zCqBM~-xl1|)V-fpm7<)Rjm=MPq@ zO^8ZmQz;rwd=Ngt&p|@8By#TB%bYq2PT640*2mLqrTRiu-DH+qlIhLNPtoGA=7QU| z5H--u&lW;hVl-v+iORGbCF+cwE2YCCZxHIQO3<1=Ru{fXTy6%5%f_u@Og>&Kd%mQG zoLbqd%HTjNd#mIn_5L5l(P?F$melcXK6YK^e5#bLA>=J)_5J#GU`vb^{E1kJ;4%fj zNRE6Z+2!h$r8OV#m^lZ8Iu=hQEZ_E+{lgL_jqQsWDj^T)yhpw%;?9C6*+$FJyqva2{iZ`k0@1$eh{eN2}QlDS9NS# z)nWnw=H67X%tl+O&B}xVrSn$BG^*itEy1-8kg0uw$|!E{T3AZ%kd~I*OQ}b zW9C>l^*!Dk0ImKfzl-wEh6?i%r9@;}^UR00*>QQUk_tx?-Z?QS6+O~Ro7qzmMBAEZ zyYR?4fP>GCwifsmY~{DfU)1s$c*xZMxKqCZAZg?ex7vW#lA;hsxg1M*=BMviDJ48= z6nvS;`Fa=lGhMIfPer|t9jpEI9p`ICU#iGtV|q7p^sNFfII#9SpN4VdT7oQN*7+xC zN2xDO-}_;|-VM?gvH)n&-`ltUT=GBd+yA!8j-~exh1@wRvFG`p_U(8Yj09ePZ{Pk+ zoByYM`vkki-`lretXh2FUseyARP*5|Z&8X3EHK6E3r(Fs{9oT?CcB-7Dvq3d75oQy zSw|*dGLX^#v;Mezb^cawiCVLCB^itAibTaZOV`*+#EB#h`I`5ycn2KrKh6Ak zu9a$#a`av*OfKcO=Tk4Wbe*I?haVDyjYQiI-XP+XXt0&d#yW1G?HInO=|bJ2CzEgu zSPB8!98YG$HR5%n#V(VBP}q2L?Hww}Rc(<<5se#K_<=#=k{*jXf=H&66l1Yk{<@V? z#Jc_q0mnsZSPaKudgx_348sqgcU7a`vkAS0yhY`XT`}Q7X?sbizN0HSx7mKM4Y2g( z4m$@O#?F-nb5rZoMp{7~(Qe(f*%lADsu_biuzmXuA^lG(hG^Hh3hu=yW?$A>=xlz&zn+c>v$RTm5nt+VxKXf00-ych5YGzw)SCPqT|l}l9yYGe4G~rW9sV|aGyf$!=+?6 zM_iTjtKF-l$hjOP6q~zHn>VnNHg{ODkAx1&Q;p99i@o(*bG3QX&!d_=uY0MAF6XV^ zk}vhnYZhQA%Q6z>=Pgn2kDD>Cqldar?CmvN@|!QOXH3NOZ}m-qqh7r|>DPGOuH+j8+KetNNN$WS z?7<^-Q2x13s%ZO}#-pg=^jTYWre-XZ1oiziuiI_ijvzN(pgl3N)AmVXDX`YI6cD23 zI^#+%5{e!=MVq;uT99C=+df|4IXHR=vY0${4SkKmhX|WM(6ng-eV&ceJ0g9ak!p7# zSJT{~qPMEul-MBB1+ER1R_5+ibjm z9Ht%Nl5DmDMlkCYsRy$L076@u66)>dTjYF~?gL19093AL9roJN^}G^9huN5i^WslT zIMbh)dgjOIkzMA(w=6{K+hGyJ3A70Zm|f0MTX-g&_^`Gm2izvJvD&`o=Wmp&rqvVN zpyj^*V!3!X2qjL=ffv}sK+&DsArQGjm*5i|i`~tUfqf_ik}sk4&%(PWk#ov%;sSF( zClkEOoZ2NeLs7Y`@QtV=84Er0<|rUaGijtk63*9heuKa*w*E0 z$buyVj9SVMGweut)ZHK=PKAd#A~fY0RO8iK%8_%4^p#H|lk)zFYsR4E@y|k5!;GUzi|E+8<;)v=VuR~mS2#&aj*&ct?p87@d z9zo%1j6CWq=F}Wq4s?uI;K(d!geu=vKiF(OX*Z7^}ny>7A5W~TIesJPU zi2;7VLC=Z;3VMFg;)7YbpmA4j$n&!nKTX!L34Y1{y_}2UWkr z>;mvwyc=)Yhm+4la9XI%n{f7+dK7#g5>Kt-IO!qMhmsyS+p8}gQ(w=g!)CF3nm4$Z z?B{CprWS$SL&f|VdMfy}?)ZrMGNHbt3QoW9&`f zqpHq7?hGUl6udz}q5`HGH4#v#phSpfB#{}I5h$Wm>e9x#;es;5B0|uakzB_CTE(T- zrHid?wQiNVOV|RU2qK_G*;KgKVOMq`@Ar4^OcvVr|Gs`chCBD3{XFM6&;ImAEz@xL zlpO!qJp(I!%bh=+%EqNScl{4QM+DnZP1}#(a=+*idCTu~-aFNkPU5^v>3;9i09n$a zy<;B&V!B_Q!{|NIb0xq1O{VPArflc=U+Dg91!uV;{YSNRxA`9VCOy9eJZGhLBZy6l z!SlLEPejv2WWyl|0R)la3>HQ!l}wYYs5_^24J4mZ)C73k#JcFFM*Nxq+JR}wSB}GQ zo8Tcx1U8xUH)T8TTaw=F|3K_%`mJW&&rV)ll$_W#<6)k+{?I8o#NyrmpZ)9iZ*Zrd z0@z>K9Qi3b5zFvziizep3wddeDTUD!l2g0(n9>y_Ftw=16p#Q0Uu#4+xJSg=;~6Oa z;O0s~l9`}5bs5aguE5x%?PKqj#d$f2uxRVJL%1-p*!{ZC zyafxI^ENs^3Jk0ewf#QBDG3ha#~*%Zj(*_xTjm32#~LE-a5OZlO#qQ8g&Iynq&-1+ zw;-@$)D0#mBj&=D!ZId8eRnX9|7wip_caEH?xPS>Q18ytcn8I+Xy=l zo?m+A>9}rBgX{^$(7X6){?~E)cH=9w>sl=7XAaB#Xzi~UCoHFed7@x>wU5dg^?-W_>+UZnieGxWvA-dRnu5Q}rtVIYXbgg?O`f8`<8e9fO zH-7P(FBkKr>3o?B#0wyB>%ZjLxA1dafMg^C#?RrL+(?jKXJ6V&9D|wu@Qg$>U#Fse zjQfw_9N<*mwy(?yx99@Zl+)R#%YDoO{9)|F&ejtpiYD5;m58bN*pvd|LI}Hl4F15# z|FI%gPo2gNw5vIv73`-M_Q3fvOd+Jh1oM4pzTCK}W_27?Kv2e4E7+TcEzYFhvuGQ+ zk~x3=EBnmTnt3vkzFQ06V2tPt#KZw=FQK9H_%KhB(VD@8s_`2ononV$efU%cJ^()S zUk#ER$o#`$Or29*?+=$QOSg+1=ny%ZJ|<8SvuE)@o*pd3#)R zwOk)c_n;249)6woLEkQHx)(NjZPa8xKBkYUfxVrDM9^bB%@*ITmS82l#NYEUlAoyo zlAq*AhX`uhx?IHm8bfii6qC$IDXCYjSQWKGsq1p>^U%QiVn>dPu3$px6~e9o+h_w9 zn8}(@Y?eyfs180N^{tnUy!5lMZ)3VW83uFx^@DyaVqy~T&yrn2xNOxuTinfSBmyVe zm=|z9lf^uh+lTz6r;68ncrhgcr7Mu$xT`oAE%c!Z)Pzzt#03;Wk1=BzyO(SOe8diP zv=Xm@F<~IvC$Gpik%m{(666^vkHu~oQq zQK)RY6?>Cv@T$3fm~KWjb6*|C7xzF1HTW?P%qX zZ2@u0b2wo4FvxvFz#dy*;^}H%5-a&+I$5GJu|-%aDEF=;y*#ywoZhmY$+W9_PiBg@ z{Jfa~&}@|CJBxDDzs%T|)BgC|Ny3NK3B6wsu*aj$+2XvBDNHWvQBbX1JR3sxNg;b= zf%Ch}Co`_ZT8FTi3zZTR zY(JC;%lt=}i$F4=HO3%`4qq}0>)REwK@PhJ7?giJ8y-rIMKZYnOAO|I3v_GqH8!yo z89;k3Og?D~OLt-N8LT^qo76$;fr1Vi?I=*vdz|lXE=49aIo1-4l@Oq5<0Fz)vXop0}D;(c~PhX4nUf*EU!`I3Jj% z?ieBx?n;spw&y!IHH7WE3SCqjti^Ob^BpQ+0OD0Ewt*!GB;O$N7F1;31zV1QLM~Fi z<;4Ab@yCwVOw1chh`NjX_^rkc@QZ+TxosqmacmXDajgVb(P>G?c zdjd7AO8~&>4WL&5o8$txD4go~Z=JR*>?SIiI4cW5)IU31EB0##{Hn4pk-LYbZhwQ$#}>M26`sxVM@|cweV8}xL^8vhmE+83 zx7pt3HW+Y=3*4HIVH20C*`- ze2`r8!PsGN$`$ew@jxi(!-}(xgJAG=*lrWH4+QHkZ^S7fIovEFO39stuKeqPCuRCh z_I<6=9^b!GYXJp0E2(iJM$Df;KKHTxtIA5Pcr5^q%g~R?E2q02oR5rN753DO2_aL+ zpKwA|axyVZru4VsZ+WE;P#Uw{mZf`nrD=L7O&@Q?=TI2qQvhiPwkb`8p)#kg3V;=p z=3EOSAjHrB|0?zQ*(;>Kgq%QuY^co)qtgN)z^dQr&IqnNq!2zKdldPgT?^ZZ!eHJvYXE;uV(Vn!#*3U10{ysW8#ZEm|0|NAK5vF>r8_obB)Qvx%*LC8 z@-q$x+vajWsAmCsr0tmSScA1IgLl^YhKjh)Pppxa- zPwQF&`3eGp=K2mAB)I1j;p92OAVDs0->PO15VCuaaV;No0%v(=p#j^W#;(@1#$tm@ zutn)&+8D~FDzeIW?8UJ!6C(spCq$WUyFl3i>*2nX^AjKkZxXmM@E+v9nx0k=DwA>e zPuY^7jbrb%;Q297-{A_*6*e2|tXXfG18D9$kgNgcQbYwu+gcA!qZ)J76ga;0KB8c# z-RWGK0nsNk;e3rMY+uJ#m?HqZdo3J<2j&derUma}vJZrPhZ#Oyo4R4Ub&y4nNY*T> zjpfKKn9?8MC=hOkliVMZ*kG)ITj~n4uY>wi)ldOKRs;|Va)>YHynIlkM$8%g;Xb9K zqogp@dmpg}^@?uGJjOzAafccaicKB~r2+Ja3Su7ceq{eZCT%N#z$XuJW+s%~X5DnV zy_-(+d(JGLchlLsxZz;AIOb-4LHkl&b^uq7djjCANs=Rx-Jaut%#{AlzRwt~*OTT# z8mR33mvNXt$K-5!N946tyJw{!$|LziIk{W*iqPcFIUkhAPL!}F&954ue-JP{vM`() z_M=>xL<9(U+`k=*P}$J=2%BJOZHPgNxvOcs8Djnj@HEi`Z?Zn?eEK4MXgiK9aLFa; zjo>AAffX&tSgUw+3Wti5!J3O$NpcltEaPewAjS|XS)#?~nZ=#T?Z)DBe+|<8HHiDm zzLtv%n0aCk zGUUED7vtXX1=fs}9HS)3AyVZRc7Zgg?ldFlJLGTJ92gMIx8ju?*HHDHKhiJJr^o46 zszdauHaUa#<(9%z7VC{SJW!(hluW}JQSvhE{Ie^m7|uPSxb?suOu>iy+V^6f zgel!^X5*(6aG`T{4~BY#^F{E6%f7g8Y0EPdtos`7d;{ml+aaBw=a>8+6NI?SF`>ts z(GJmiBoE0`@N=x0cp~-$d#`MhbJ@P!Q&|6}!6brU1HD}sAv5I!K+;qup=3a6ta^|r zA+!EOBT!>3#ZaiR5xH_J& zO%N>F?ibB=o69C_FN2pbc#sGhl7hqzFxQdlHTj0HDgIAE-x_gq85RzbK=go!JJ1B3 zb7XryA+o^6;TEc(*BdbJ$?@uif_rlfOki`4+=QJGzN;WXVHS_9#M_k^er*3ro>9;atALI=+{b~l2?sT4<>*3M)i?pFg(lb0tC~1}r z;V$5=m`1@=*Gt{=1=t+d4A13^$<+Re+8NwsR@dVfo&XGB6xzDVR>f5e1_FfzQ&3EYKDxn0a-~arL(OK(F~&e}*-?RIU-B>vcskYjq0f(?OkErWRA@E& ziOHkG$y}}dm zkLt>vWgg5kiwlzb%!)4^SmvA!S382lwkRWKWx%{noXRdZOFjTgD0vzlF^kf9z$hZo# zrWk(_w23$y&I3Os#1GfBS=*w-JehEm5W@qYsAt9LAxDR?aQyj|2qkEx$ZQeyoxxN! zJ7R47RGM24mv{_zxoj&hxE&(-IYXd~=|4m)VNe8cW}c~uEm*=dyXF3Eo*)CV@+<8f z1p6@z2NVNDwqz+DN$PP5Ba3ix%V*QLK_cyf=qFN7Q$IWaqB8!7p6rt{G-{xS!Jr<0 z^{k-?UJ^xsU?|IS1c@9p)K-!bBC<8{S@2)>h%BF#*?o52+wyZwOaCvMMDscBli<;2 z4D|nsZ_9B}(%dc~`|}V)3vPoLOiU|yOYBoH)%Ujq=nWA!H8$WBYsMaSJ~;pd-Mj5Y zDd)Z&^sVqWY-|#Vp(wH*l)#KkBOByyx|4&qvjuS^F2jvE<2Tl+9>W`J@ zRf+aBaqmb4pIMFA!qLq%B+XV6dCh>KAnCRux?&6R)3#h76(M0h;fp#4pfQRBNYOdCo&jBx*F&Fne=lfbzy63+ueZs3urE)f#N~vQi zmH&68-!)arr&8?T^;W!r8_(0fn)M@@LzbV_y%{Lulv^|MdFwu}l1<<;TNlO*m1miX zf`+KS2;y6T5KL219@1|&RbYVu>xpeD6UFC8f6Jm5yB*bJ*1plSH_o(|w<17$TtK}m zYB8>fZEaOyypa+;) z!Gi%J*dW@dL?2(?OPCcX^MEVWVPLlKpLnnm-6#hMUEmVIf(ij0bDV6jJ!R3iFI zbTC}+!rb(FilXf7N+U7jNC{RfiDIaPO*{nO0IUnvaai8863QW}2ooiNy07yBz6I{* zT#-~I=3yh^0b=@F38gm?3W62mPIeAV5o5&`YI%i!&S@(RN&$@RXGL%hw!^nn8yArY=0FdA9n0Mh(mv} z350eV;( ztqP{PEq_Z^KoMPFglv&V2b5H(I4mR7LK*fW(7V03Do}sZGJ(BD#mJ&37CQ; zPPtKz&XQ@za9LTWXRP>h=8(!Oe?xRTaTTB!oGEf_ z!($E4O7g-{0NN6{i1CWVb4?4`GOVH2v&e~@vQNU`#0hK!j_LMSX^a>n9L_Q31KEN( z+5bK9JTq})?9n)J`#`8{ra>ifE7`_x~9Tg5-g<2;g$ zi2AT?lL)=P3CoAel0AP%kbAgQu5D?Dr5RlHO}O2rvX7&=Aq?{P1it-)`IPVXf_|*p z5^lGfq=<2;E-8TF&2&?sy|DldtlAoEcTfq)McIoJj@(FCV=vJ}aMk8;yOo*NA%qX- zMFuB_bn*t5>Do12ALL`3$hjYg681VywtqWp?`doSh1`)~DJFyU1Uo%kv+43=-`@qT zf4F@}@`Tw{2^K_is7rYL$k{(eh7pJSF%$EDr-HhKtg6+))NSnUqG_MHXL97dpj}*J zJE+5+LMKPsnqcs&J2nQ>PfVbsd$BMCa8Cq*f&c8YG@1L5!jUWGsNR)*5gB}WviNLr zS8N*p6v0$`<)j~FEq^p|d3iYOZZ#;Tj&U!msY@@xJi$dn4$I+4uwkE}P6mB|bmIfI zPXEy>eR!%gx9j3k--@AhYZlAsGBkHzNw>H%4e$lg{p2+S?dt^j`~f? zov;r_nOg~*vEGOoQdld>S%-nmrE95bY-5pW6t2^>3-xV2KANwZ{6G zn4QG8z7q#ktXtkuKgp|L0H+m7YZ~p6)LcK2wI2x zqHnQ*K(s2dJu8sUAd2*Y$PESzuSnhZJg8_1)pm<2Da<4yu^U3ATbxce0KYh%^$n)l zW7EhwvHWDedv{0%po{|$D^zn+7?}xCP}jj6_(H9Vi_=dk{wCOhMgevVyUj)qVT9P7 zV@UNpq~#Xp9$Lz}F)n{sK+wQ)*Jh@AgfgfYssV5v0{~92lbYh@vV!^cbz`xG;;F5+L z3WkF^JH9JoqTkQ9!9yo6cIJP!N8Vn_-hP#jP;S5KhbjE*EPh$bK)$E+-v}J)p_nU+ zEoWMxNy--AsW~UsO_I}gp*5FJwVhNeI?p+J7nEBnZ|y5xu*%;_@}@za+^T+12}^~pl)U!%TH$b?ZQs;S)s#4|ml5d{ zdFwG%TU4pc$r*uP>l66s09%o^f!HJrr(3ZExM5lGpJ`U9JojbR37hMc1NUNc-6BG; z>~D3{fd(=Pusna=g&`m=M4l@`00ai^)li*5fAL(%i)oaU>Yau)ot2Kf!t78vIrGzl z1J$3K}j0FE}|cWXVc;z-@DgjSeI z?sT?4nhg+S#mDg(uda+CXAJGS8DpVpc}K5rvCLZE`pr@A%TY6Wf(yLio<*UIf5*1M zw-9e}d2JQ}mharV$ji%GVcH>54s&SQZv%_=eqc>vFc}A?Iy^DMBKBL%f-!}Mo1YLba9nS9_mebP*|*83j#J3ou8_*yf}NkutU{3AUw{eri< zf|+$R@wGgKpnqE8ul12NDXqsdO0B$OUW^9cwnhfMa1vp#xDV-3_0XG>Xi~B0lf!S& z(fs+o>FTgmWOyLR!#B6@Vjo!1nhpIPjDaQ3|-J2kBGi2`wPKKne+8@ZV&5F=uLRjtel`jc=lcQdng|k7 zmpE752Ht`0IBz^JO^}iPnqsP3_(gU@+i8VlD6;l{~a|zY(3!K=rKMIl#NjlQ`B~=V~d}x5G zUzyY0%Ob(-SZQbF@ZESugSr;*-Jps;s9-AZ%^C6yt|H#)I{GoqLeh%|2S^w2f`4;j-`gT3(Jdw|%R+ zO>KR<(aN>Y4_B`Y)@{xWweIXp?+kr;O>U+Axqshf7TE&*_aAPkA){=bKb1RRf&YFu za6H!cG^4Py{hgWZ@124c{k{0=vHb<>Hqlv!DRkyf`g8sJ{PfhW-1O7hcVGb`17D8s zKzd(``FsfUn)!^OebfX@h@*N%v(^tH2|giEw-u>-d3PEohQSFptt7ssulbp4j5n`c z0|g?_y1BrB{%G`P0r`gMztf53sUX!e{sC`Es*O9oMgS+%y&t9eNS=gMR$;8y6};sr zb{@vRM)CMh)F(1}H_=CTi}_FW`mjAmw!XCxDh7f1cq{V+RXwtBP<^gpvcy+~?CJv9 zsi<@QHRJ`#HxMCYZmN@UiEuXDEn|%-jJLs>DW_-E45w~J7}VB(KZY9G`Mn&7D$abW zUvCS=t36*T6STeTez)$g|{U?%?i zk7`$}S)2G#MI0L}5EDZ*#njcxCZaHV3B8|B?|%EkX1#a&KYDkkHeY~`>7;Q1=IV!Uc_o>L67TWM ztfx&TNN;OGMyJkN^3Occ(RCf#AS->meRdq%%s4(a1Mqf$dG{@8ns(pJw8xo_N1K(8 z7G%zxHEW&ebXg@@*Th*oGi6w}wb7^K;FXvzAWHSR{W!5&cjQOM2NVFoTo#EB|1Df2 zPyO;Q3l89eIU7q-N!8alF}#2Pm2{_=-6cFk$vl{L$Y88@XM-cV?cVpg@ocB3E9e#%1-n&+$!wjY5_qp;1g$Q<<}&gU7U^?OGfv9X=B< z-YrwvRQVfg8F5)xL>oKiwqSXh_g>Jv_Y1t<-#n)G$b;@7wUE7EP$eA9R|tk_Ma~WI zo8Fae#jmGO$R3x?qCF%v&^S3c15KIC41Z6ddUe43Miw$xbNv6;(Z@{0h+B+wBh@LT zI?l#BnvVZ0A7{-yjAW)6GKQZMMsOznoq=Hn4OwR;o@1{uJ`))dAXh@e>fUJFfq&AL$QctP{Nz;pPZ{7Q(p zC7w$t@t-?`3fu@|zUnITHZ!HIRLA2)u*s`fuM7DG0h)Ia|C)Q@F){4&inZ+Tklniz zOn>G!^|Hyw&gGz7rBVX?#;gaGdXw3=HEv2hXYK~i+d0nnQ1ULq|B-KTB0rqBx~H=+ znfN!oxNBc;0sl>*VdN?A^zw{e`+ojon7BG=1?jG|)gR#4Yl@{UN5mQVim6*@I z#1{F|9~d2=_?|+~JX<60NuT1ozj@0mtTC7Xr_vwcyU`3+t9nU`>YiFL-}$RoIesT+ zz|ErtXAW=D+d!;mUPGY4t9uGS5r16gLC4(%Q8`v*bk5CAD-{acQRt4kyxj zk-m65(KU+n3~Ot>d=QuDz>|Uf2jw=AxEMHa{_vC`#UsR^3vlCXkF1oPR-fhwRQ^Tl zrcIHpZYVVZ`xeBToMeh2c=TB_r!gP&IYoSgkPjjfB|xnAwbis64a$wx6$b1P2NXFZ z^QHB)bCuhcim;~GOK?fo(X=0jh)mmM-`9{}ZaQU{2plV_tHgM%eNX-zgWvfcLh7v| z!&Rgmf8be)PtkG=LN~da#l5Z%+0@)uey0g9jcgRGeZry~F)m@v8brP(Iv6G^BjGzm zn_YW@cdx}r;}<`NH!#Kp&OLf-SguZb)#r2X$6+>4%bt~gOTJJxvCv9=p|fXr8hD|- zq12xyL11&zNX(bjI9i#juMiy1=oeWtK2;^GkhK)fE@GB(9{~s)<=>d*#%6*nEO4rS zK~R7DXU5hZFGNz7tJXomxbOSJVEeyPkvzk zgZjjOe0ju-m-sSjQOEY@dPtQo+uapN@G@apiTijdV^h;5e{jZ`0!uRN26L}m&$7TM zGzcAn4EzW!l>m#&Y{0yyaChL^*(kd?i zaXv|vY;HN_c_vMzvwEB^ngue+Nj&2dz=x@3=?un}Pa5=@~~nv4j_Q(28r; zTDAUW)SLN*wDeOGTu@YuA~2#L6x1NEtzt{`jWOZ6%btJ?Bwp}56R|~9{mB_e3 zjt+89gN~F#Z%l#y4kGzpM-)|NE&gTpcU{Exy3OFP5*Gfa^kB1}Uqs=)RiD+zWv92K-mrMjcFYZ%l z@SSi;7wyY^9c@$n3k8s2l4C8%WeUx2Z{Ao^qxfck%i8TPNZ45jE~xWccWlS zcr4?L@iJ7Z;%-ML>V~iI){C^E`3+a~HmB4(B5pDDfHe1W$VzO2XpS-VWB>uVBTiE0 z6KR>jul0|2@qh+$q0D*mT~Cux#`K*ZPuin3fRHl);qKC4gbLh6G<%bY4+9G3AeO(d z&X96vX=~9stpU4oVMVSGft%`_^cEIDni za!~^L%{`nBG+Tk$*4)rkU+lZy{(Y4}AJl{_K4Na~*rA5V)Y!p>$RtFCqEUPw`fINo zcqV+prNOe*)=UYgP`nX-AxWh3$`QW&=)bW2-@cnD9o2iV9D9wR`!gw2nY!j#+`NdY z_XktOba%DaU35;UdMR#q54DO;NZtJ`vG*qC$K0#wJQ`!&$IUV8e)(E&-GB3@pk#v+ z>`oRSlN@5K!e&8QZ3U|nyF7go{=})yw=#zGUsUpRN&-!{WMr^}gaz=1?9FB5oqpR=p{87zd(f`=#1HgU4^km z-!4?5e+jLlMLe%E%9Mbw-nrvi*uPZXnnzf9s8trP5L(YusA_D?W^hSzc&;*@##iv$ znkgkx>`-oW5M&GnOIH`9&*4fqg&WKdHC>m>!w6jx{-ag3KX35Yj`*>v)_=rb>qo!+ zoo_OsZS!ufP2dlaF9OTcvhxl{ZVgCG#7Ka?5 z&}Bzd@<)H|y|nwYgH^Sc9pcMjf9++wyXUCCb_f8I_Dy~{{ad<>q=o|}3!XN>^%?jl z2#)SM*E`hkG;C;1LAo;?sLydsVqPnM?KqkV08Kl6lfQKX0EBm*wI1Nwf0VplnTao5+R4yvg}) z0lu>QaBtbMtC7F+Fj@_2?ki(6rZYkiw37&e(tLX&BRIp3y@Z z#UkpY0fP&y*wZu+NDZg|t65C;UdYwrYdkQ zL`g??P zDw3M6B-RWjMMrk;Zb&a|b|gLd*+}P`!O%HS5fxf(z~#nEb+sr7Sxc=iuo^i&X!j&# zgHafA;VhLdDVt^f8)Xjqw#nXx>wk6A)IrXg`qs<6u=bB?+)~&gnu54s_RN%sj(zx> z8$I!TK2LvJU>NW%=O|7bsCB4q&oUe|%diW$@-TQH^;XVw8k71Cq5N9w{ZToP1892! z^>sPZ@yY0zc_kA;UePkE^~^uaYPDU|2EPVp<1Y4};r~N_{*u9ex&V>v-?;NI81cNk zZ98&vrjWz>ym|LV2|aI8cON)cvF*?6;JnYx`*_{NUqD@B0dn5_3hSxGR@Lr`_`YaB zA;H@_;md)+hypa1Kk!ML97R$FsEC?hOxB<13)~e`HfuGZFG&^_?aI+;uQDRbJHAG= z`uTdpi=6bE?lmuPBVL)MuP&lJBOd6jvsNTa#S*7m%%g1|rjd+z4SccR$h24jl*N@a zqFw3g+<(-w`7|<-RaBr;6L|c_;;stW^4tFPjj zG|U@JZRaBv?E6YQ7Bk@71xP4O)ymSc-xwnRSeP(%{NLNhsC+ z8xN+XKhx5b-kRK5uc{_X`jwWj+dptY(~^E|Juu!Yd}Xh#L-TS>$ff9V_c~r$33*Jp zBhBMI%)kxkQT&G?SUIo%BD@kq$s3pkMv@yCvEdu@opoW8R01}ODRe8RH;w-3`?-cF zBuP&R(erh%OI9(T?=_!^xAGS^gA&(z=o%n_ftIY)Xjf@2op+I}#+ni31HiZ7lML{E zMq@<81o+CkY&}`sBfhcw{Yl^LNm&Tg;cu?b-xIKU()Uh!8?{2q)8V&gGsJ*(?o#zy z$E*4C+OR-ZEV{t+Z7EO$cg}z`z_ds9xt>z^2I^!mHYT}{4fayH znK0Eu(*yJsMp*J3r{f*UA%giDb|Gp9>)7OlPLixPVyz68-uFi>_)yr1kwrw~V-qIz z3ze;4h>(UM-zPyIK}?1gIumk4GG)xyLJGA$r)5nncy-%ipdH-PA|7}qAI@@$8xp@O zA$gjS53{qgg-IA(z}?hItr%c9-J7W{Ba&w@S(Z4}FSdl~&bZH;?kcsK>NV~`trE7) zXoqv0zh9rV%X?OznbMU|ZJn?fkCp`uHNf7&Iu0#V{6R&m{g38CB96qo4@~b?@Bl$j z3Y~E;NUW=Hp)g*s6(>**+4frZ93GI@b;^l8?_R}ovk95agFj+}BORROm9UFhF3i-XI{?l)06#||S%jZ6E za!%}4CYb8?4${j|(h8?Wpl9sjX;`14?T~F59XNgvXnUDhhTfOR>J5EQb(l>n(uk@h zR`G6H3YU#wg|6c}4p##@Ok+cumgjAlPDGNk6tg#*x3Y1aYS|QTou=styMD7yz{cl- zjl}nootqfcP3S=Dk?P!T5+_t!H&5V`eBcHC@$a7}9V1q%f{f&AqxFycZ=f$Ja~&pi z>#Uix1P22yFN|Db)V*=oA^k3j5OVu)tH^ksOCo3R+&XeI&%Glj`;DzQVl4vWE{ptZ z$bib_h0$I9=^Kk8Re|I~0yAk~%j9T_D_G~JxtP4@Lw*9nHlTs#eFoGLuTwfGOOW`v zaMA+kn`SoxZU-~)>0XQTqBjfH_nEmBk>We~K<0y$XiGsPSV8+@gC=elQ*L0}so1O} zyErv|NJqL4A0Eo=f$4+@95(Rf$Gi;;CQops572sQ;LQ$5!;0oZj(yBxqg?Jg<_cBr4% zSbsp?(os6aFVJvyF%sYNLkr*@;sG;B(xF@relr2QQyub|hT9jQ!YHpNccr)ZCgzhL znyuv&66F+Ry(GzV>uJv0fw2tA^q>e(C@;RAZU7;yvlNzZ@FY)Z!IWId%N z=%KeL3dP~9ya~JYi~)7Dy%Is>Bhc}qg)xTIUP_YkvC}lb9THXbK8WDO^QPzmm&r27 ztVvkmfwO6va5sx8thtNaA)0im^G~8(a$J{%3KE}90RlqYJTHE^n+4&C7;cZrUdUb> zNPb}S>$)^v(roZAkN=!{>2IOZkX_^pXRzfmAo6Bk|5p$Gve+f@M+Rb+<4?5N`1WDm zGLR=C3`CLBg30cEwhK|ZRVtqgSq{8O1h1NMjB^Zrj!lk6wiSkL1sNnH`F-sL3rHMzqKp>`-Wt~eygyp|H< zB1!l=Ps7nv8tlToDAD1WreErsiG6QY3!q^0bLYsu=R2qG<(`)NV}0}X^mQKLtRK2h z1cZ@`F~vsXNs&mE#ydt30Cu?CT&m83W_I7kEUL|lT; z>DTJ~(?H03t;7c2DF$g!A)>mO12Kx!HdmDpf`E}=jNp-#7{Q0Ez*a*5jM5Oxz7JT# zFqZn#dRV!UNhpAya|qQIZ-=Fbg+Xkru)Q!?`lVGXduc2Ffbdc>Ttb+dzTxT-xk2k? zTtG1kO2gS_eF}kmxKorI-#gPpquF)lG%lftQN_qPw0cr5G1yUUY~cU3s60*)aRM>J z_8R4f?-R#&36-_qq1L~K1Nk+(6UG+n*G1$5Av8H@+wUNC%7nsD^{;co*2~*4oh&6> zYe}$rlm@oesSx!Gjn}lP{_9Bsa!AGs`<*?^1xHCUwy?&gKofQNxagz8peS{+y&(FY za&AM4U`3aHl`~foD5aprS$!|z$zW}n0286h17;!&{c_Q*$!JOA$g3x4NI#gha-QFo zkxN^Z`#s3H>N2xVo<2#FtSWL(2E|~C;tmvcft`BbRS$v{eg#PSUNlj1lvuFO5&y-O z(P4iO;5rbF+eSFl{>r_OvMuQoD2+FnIOaJ4D>y&n)g{Sy@@h!KeUom+^Oybq9upxf zweI^xpzL$ch2@c+nD|*&@axN9={A`#__5c>*m|5rddR6o34fKgzFx6H3FzRnnSH!3y7oR=u7oM~qcowAAf`=Qe$S>rp;2Pb`w6n-E zfL#KC(^-&UHPN%HC+D)bQwT%%@(SrUQ`{OdLKBLwF2at@q&jQ{60%>FE46IPjI1Kn z?O-XhGkV^^`J#@rZN@j-%pMCGlZGUW1-Bf#!(|^@3FWmH7WovV-^F0ICJY=BA9Rke zA=t(9t7;g9!PhkJ$9`xFf5X)vszt`g>rn{_L~A5@$dG0D0dIA3yK?VWACPBAe2|(m z3i0EEqA&R_`v~1a(c@VgS~J!!DqMRF4QZ@mQNoNjh`Yfo36vC5h+w?Z)R$8RK5XEZ za_0DIXm##CL%v;JysdEAN^GU+5EL=)VPwXQTH?k`NCwf>J3oEN;FGvWD9q4O}wS{ymh!6eG;hd z`hI|vL|-!;qRP~x{#~m?HVI9{eNPSO!?O$d@LBp>4f>h+C^bJ#e_=lSejXoIq(3r0 zp2lKm?#lEBNIde9g1jo==MjzSV?1g>4L!Zp$vI8*8Xj`dlNDcs*W5#f#3PEF;yie+ zv59TMsO0R+7^|@MqrC6#rtHBf6i|vRzbW)ro7tyn(`1EaVEpIwVnv7*zeip z)}W|t2K&MfNYnBTjHjnmzdt~n$=>CZ$D7%^h;mcXU*uY`Z57S@N#Tn%hXHvP50&ZQ zRc1oB7o%*EPyqP>Y%O}W_0He_?YVyTG9@HsK)X_8_$mSRVcT=RJwcz@{r;ZhOPA+& z&J~zMdqm%~n~WVE26i_V7e#KBO77MD9tW-CviLdG#zUS2^Ee#!t*osqXZ1YqP@>Bm z#+*n^?sTSXQ!V3IpYI&)qkGlttr`vJg}6z9(xV~YR%d`- zuV`Ff-5wus`aRPSr`uh$t^o};(}DR%*7W&>$cFUt9KDn~jO=ZH`bnnfncmwXh(%Es zNavdE5lUP)pOTIHDfO(VrHhMX_zYpU~- z#ge#_R%mhnX~3MtFg1(!8$uX=0iz!$`!8;Jl2XK9GCRklAP^)cUd|o3x?woE8m!s} z`4$9P(7JAL<}(CyNsUvD#P&%eCAgh+4ZotNqSP;eETBVQ zkVI6WYCj60I$aN3ryqxXOK=#nh$HBHeF63WZ-#u|dMAW+MYX_FK?m!8#1QKM zNX6W}71q;>gT8IL>{!mDp;WH?)JSW>e0&Ro`|*}vJnnq9bJDq9lpW{;Naj7x(Eflp zB*jTyZl`L%Y!ISn1MJS&ZQmIU@9su;md`UbgJ%)8+3+j6A2A}-{kYfQf>C|8kMs{u zA7>>xYSK6=1k12gn|7)6_Uxj3iyMY}A_e24KRJXR14UNiOX?yvcta?!zCzZFaJ9Vy_PC89GM9zyfD^RK!byUM+?$VB zd$xr98U03lq5370vmoX+Yr4m|>aypb^|XpD%?*2{}R#Kfe9#S_jCS8orME;eV)CIs~k&e^VDsRK8)h{x3d z-%*&Vw$8-fLc0VUDm9KU4l;+j1E)(A+5`a$WV$L?EgHJ8V0J+1mUNONCIHu-?^95%6k-tcHd_#3__+3(PN5S#p4Q>aTxPdg`x8sgPTl!cj~ktIN<5LoZJ?++ZkW?!};9W(&y=32F4|emv z%l|9QUhH&!-iw5y<7qRiKl%|OV>OuNd+(CxF8s@Og#?M5iz&1GWx=?sxf&zwbbQ?4 zORQKb@3Ie?^xlyz856nLBb;-IC~WT0of=#!??1PCbfyfP;b)uq^JSulv_xhn0^T6A zO23fVJ7#`dz2LGUIV2d$j{$ubsJ>H%WzLH)c^J($B^v{OD2j_S?iDZ^ZmgbswdPDi zdrj#IR=*J2bFso;gqGoCLa0vKtUIc4gMJw9- z1mF^zvg>HHU$WaNw|B|Gldc_BwsyDn{9voNVRzz{_Mbbrk#%lRE#nS)t}nXOeT%vv zDDK#iPS}Q88_6{b5s>L6{m(}F!wXwR+H$CMRo8)UVm;n)55S!s-1`-Ta-;irQ_*Kf@)aO%RVoAVW65RhosBE5%V zqP0alc&80}HK#4;*ptjy@ir=Au4baziI%rrSy>}U>GmKg(uZ}{PC=LH<%DgZntwkIGP2d3-!8_?21Ls z)UzZaCSzKv+a80j1~{jN(em3^L^{(!Bxaa=+zwGsE~Htb!+2wBi#@(RweOeHiv3HA8QFTx4LR zeI$tRIoIeaB;Xz4#yM{u{crNGbBgdi#D2ZsvU>`0JeOQJ0cpnbogelHDkB$zP+z@~ z)i%UgvbVFXJagnNbJ}+{tP)cOkH;!M_f`|1gcIky^f$=cJZV%TsqGQhBjor{VhF*l z4I{I}HBMxPxOUok2EcyLHnoYk-d>X*?I{vH{bt69S}W+jIgb;X%3E1&pyGyQ9@~G$ zjI1GbMtC?~t3R^OJZ-Z%iepf&!~3xB8O4pY#!UKb<7!~8dC=LZ+%FmJM2&jz1V-}k znU~&&JrL{He~z5qel#+L0;hBl!>7g+#&qNktsVKNYdwpYi`gD$(gq5oy7e)wwf0He zzSSAY;Ka1*(4RmlNx~4{i`Ia@vp;9tum~R#vg1Uj%QrIKH7sg7?Kcdp72h&PPni&p ztYrGH-hC^Mp3qM?&#yoTX4-F~_U(mz)}@JWSH(U^k^qxqK5nKRbd7@~K*+r&Fh7?Lq- zFodRj$9Fc28m+O^PGT$>m%g1&9r852tkwV}#=_~IM=#DQl!GS^c`8$?l26{kj8-A! z%7lAy;2Ny>RlLvuZfG1pl*R3^X|BNc6z&AkSl_ZA-kC`Cd%U~E%#EXx5}EDDthIqI zfZ&g&`X$^+s&3IonCN8?NNJA)GG3p6n>=}u=p ze(RZO@1d|(;-+kS#^XLSzDbZ6JDvFD*#(cj$I;9)gF9A);e`t;q80Zv{W+OG$L#MY zIa?3Dg$wWo?a0iRC?YFubBOf5(|n0NYFFxgvZf-CnplLKs=yi444(gGK2E9d1O>wg zopnEN@V7zYJh-UOyda5sB`g?f_go_1>}F%g2(r;97^0EEoE|7$B{HK`!%jgnA!<{d zjQ@3?rGc_#(@qU?MWOM9&h7gND$$d}cJ5L<*nR0uL2_+nMdn%glP51X@lVb1g($j2 zvYcSqXV$}AG;S~?6P$TG&w3djZYDFh2s(HLw2Q17{=r;ZMIcR>yUm$l`jy;8*(l9^l_XjTm-{^kd7XCR+)Sq zJf+i-e%2|fHaW28{^BLqY*krXSu&n zG5hC)A2=T;zq9xiOkU6ArQ8G24kxi)jKfqKa9t zjb#Dg9$#9kzF)C=5VZq~9TyrzupaMazUSf!5g<8^kuYWA4>+T`WKgNf2#J}|LQa=W zVzfTJG@}i)9PP?uMr-1Q8fw;DNC$eG3khnKE0~qymbj9;c+w~4TEaax6Ib(Spu*nk+YaX< zejzCim42OG=(eTFCVgL4Uc8^ckNs|*&-#K7jom8l>c;HXqZc0?E&?a=Q_s~0@&Rmz zzynEB!zyv-iKVm62Hy8_6BlpA|HVsASIpS(8v0c6C2vPxFQX0>3S1r7{7oV0VQ^Fzkw^KuOd1{~); zSU6*!%yHA83!HBrg9npEHAfp-s1M|Prqh5T9i%_Y*aL~)ftmz?JupLDn{fi~#$g)& za|4q7>jaWz&ZC$_qY%;g=gyF-U>c^eRVDB*9K|mJ)#GxV;Xh$h22>G1;PqKrtZtUt zfLBN_YH|LuItK}5z2M`h{hm=387Y|Y1nvEy>R;tL?|rNL!i3$PdB4_Bksj5hZ*e1M zre!b;K|owtx~Pda?5PD(P(R#mLq0Y{kJn;fl0GR6i$y#Lb&4W3NI3Mfg2{>8o=iy_ z-wCS$>}kkz?OSiOACZsUo6W59%0_EeEzfY{{ERL_9_4Q#MS!T@WWdYY)l6t$wsvM8 z?6gK~@fhcSnVAzT+c3|^YnI@*jD1ow`Aed86AcVo9fy`Ui)mVi^pblGn~>P0hEpACmZ2iG!8c8V7)Z%L zY+x}Y=7E{o9gw%K@x-%KL07J>N_b?@gRt8}2C!4bl-$iAeWSL@kQN-ZYnL?`F zA*C7RJd_DV<_5CsL-s8NR>z8xOjxEH3Y{*Q;m*Q*8b$}R>dv2isG-8DnW4hb9CCg$ zhoLHnxu}ehy3OqI!27h`81MI%t!Kh#hIUbji(76 z&6dr^Fw_Kjt@#eut`qS# zEI>+Gdf4EzRQXRH_xuz3OPf<9JdaEi1n9IMyI*)7h7vV}^9<49JUEZ|A=W@G!$AQa zijjr`)A&l_u$&`sHcaZ54{Io}E_3yO()-6(1kX~G7%%2HN_Y$30|E?@P;ilLD{1&J4lPBC6N1NW)O=6~_3Ttyu?K3a4evli) zY_AZJflT%NfxX=`nAv~JKhov@Q?Hm6eQZCV<>&!lVBB)Eq7PBtBxjAbH{z3;cim2m zV@zd}X;kCQR2Ih8OToO(SYPwa9}hbqAr}zwI!m?1QF|~Qb1l$#OQ|3!r!HD zHHW|JNHr$TZcJ4LD^oab>z{kJoZV=u54}A2yH=E|u z-kF){@0m=)oirclsrGiKCt9@K0{#Nk17C5!e$i{c*=m^!{IU$md^g#$g5~X_Qq|b!9J$a*@spGug0SYuJK@C`} zjHnawE6pbMOA-{5w&4sFef$A#tYs3Zf`YcuEs!yBUj%xpMA{G~l+=|ggmAyQ;YD=iy zu5j6AEB-uhLU>a>xR+LI2?*lkhg0KxA>aDS)Z~+m)5;#}!O!`Kx3oVs>_BDh3E|Y` zDxk8lgKez`6}Z;4@v3QqQoATjsa9U80!mF7Yf8+@mTN}ZJQuGQqwplZf-meM2;az(rPQw8u&3wmYt=X=~YdO@e`gy)mIkN z5*l~tobkiVQtn?DPTk_G?M~C7vhOBb98LvVWqy4)p(m@;+WZQZtr_2)wsLE`lTy9A z>RW2sUweAkw}FvHcV~}Kqm^XVAL4!zKQ~-jg$srKNtOMv|NgD|O$_hu!BtyB?G9*b z62C?*=ik55fBz;^So1iOC#qB;`tz?O+@9Q1z2B|;bvt2bUTS>Nnip6zDz1Q6B9|AW zIZZac$m2y`WSaN24L{mM?)HAP|)ZTDA9u+qj}xeBy!dSL%oCV!AyAWeEI zagC$Kc$PJzcb-ZPjxTn9Y7yEgPmDDtZ920oGq$|vp{F_ zO%$xjc^S}V2TIpi?_XHARgQhsKsvHeyN&J& zM!|5|*$K=32mDzNCMdv(@!Ow-?Zxf_EC?F;-Rd=&A=YQXsxpy!6 zegFUbK96DV%$zf4&YU?jbLPw$_c%x189MXM1BB-F5{@Pk`ny&1kjs@^fsA_WwAh@A zEuemFBo70jwJ??6BT7un5^Y`1SVls9)Q{XF<>|7*T1|2{H*#p|2DlM_UJR)vXC%*QkcV6{+lk1;0x5nl>AuWebV(I@|}`KzgZ z=n_o^E9Dfn5;U=nHrT}_!6uFh6xFDQc0kBWKTxMih>b1HZQj?IjYVZsc{qn7)zwLQa3Tueu`~FMYF;}^z+-g$TuKc*jmAP< z;fJ$Le&VF>g*%vV*5SUJwy0#YGU@R{e@l7)OZX;oM^qmXl(8K2U6A?;Q8Fm3xAZ`6JjT1=kGm;Q9&8!&`Cs%-9fA`4|}2;TA z)&uAxg?_Awe&=?HKFdJg(?E~-7o+eS(Y7@2cFqs`!mr~0*{I~~XjC%GQb{va3FuwK zo_~n)pz5k-)-_z!wexk=6rHn>Xo`<-QiTTM+rnb`MlYleXONgpt~&DC<9ZTbjJ>93 z9j293Zb41}%${*z%6)hYcR$_-*ezso6Or>0pK?VA@5jVd)dIEv1>g!|UJ;Y=S$L`F zI^;b77xZiBKhMS6v>97D9$_o|3<@YO;YCOEwu-~xL(6Buhv_MJJ4(4HEKz*W8{SU_ zh#R_IE>w858?+@?m&S)3a}@(VAzoqJ`jWr$CO6gZ`VW=8g!CbrmxMgmS3=GMB=>A- z#3=x4^H<*FX8P%OBY<4YNb#8sy~fc!SOJ!kD*~_<${3CrXv<@x(3Yi*%(nPMKzz|d zfy^V!d^eKm-71(n2gm^1Ba1{f-AwSfFeN@w{{bibMk6N> zl@RqW7D~t;4agZLr2Qa-DQC+HX&!dFCnkLBHQP?hYi>$8}J+(Fr;CGXKzSk z@p{F5W|O_+Ol09rl3Cv?WL_`v2zh;Knqt;!3uLAVIc}CDW1Iom*@SE$At^j{up7}o z;)Q)BJXe_~IIvz-eZPUAs)=B8fvB3ovj?zxo&~`&6G6U0aQjqplx|NMDBMuR~t=9H!1mX zj6^WPK+w)a@QZ8;c~OH+dDDWRjCq0=%QwnyxZ6N*O%RAN>|4Y}Jt?qcdY(q3rZNaxWq?IVDrO~BnRNk)BP z08TamzXc$4Mv}g~g$e0<7i|fp3t}?slgPj7MH-%>hy+0|0Y?8=xhQbqc8%CXm&Ynv zA5c~Lh7hOhmdqE21LwOIoLeOoRDC5tr+2sD{M^JjZoO*%ETjD-MYMm=WYG-vw+$@N z@pP9d$iqzpZ4`nJ3<2^uRn>*!;wsH%?R!L zHeq`;x7@7SS5DofORSR#_?ZQ8pQJfn?{KfldhaqO3JxACl$~}ys9L+06^Yg^mXL{h zRSV=a6EeQLgj}W|eL6@A`6d0=hk=ZS7BYG&GQhgdD5vkj)eB>+H8*iySu1(}q(RMt zCN&Q#YJi|B5#U`}6T!(zMst2r2$~o~^&nB_1Z?IDBx>dzCda+M5)O-5{jTN_-n?fb zD>^TS)$cPEZ@wZP!J7>dGEqO(ECM;ygtRL%-ZLPdHzB7<$RvG%1@ayfGC@HORgk_{ z(9Tdx*?>7i(SQx`&o!2A*C(<8N*}++^{c6m{~js3r>;T58P*|)Z!Sro7}GwjI}sV# z=!^NpC?q2h5yGfc_61byzcCT)XQ4a{=N7L;mTym*kVWwLC**tu>D!D7LeCOBSg+Xw zh(*&23umaiD7NPc&K8XJ+$-9H4tf2a2wQJ55ob)7ZE_eS-C>gSql9FePMm{y-yLaDTa%zhilDJCDJDA&g1oCFWTO6(1v18jys%m}rL6&}nUF6? zNKTgr&w>|E;g7+Kq8AKa%vK1l_+{0;rfkPL0h>9NjeH!(G)B+7MmP?YtErK8xJ_hZ z6|!#>GVe6v5z>|+sbSBo0Ia?b?&StGElmX5)D-rNfgsC7pra7yj+pl%!ghJQ(Tu)V zBp+HC&3GKG4UtcwT__aUA2lRGoJ0mPiylSeytN~Za|sgRF~W^OCsDDnF_?Q@j)Gl< zs)MSEY;Fw71WUx=%SZh8dXKb%q0AhAi&jax-Z22Tvbf;LXZU4oV(>l^tm98Chaso8 z@F)kH2J;I+JMvBlvsN&(EfQee8IItlwkL2R9H>>F|M+3rLd;j#j>I)SyaTC;J z5hoOI#a;P0>pG-AVif*F6<){|1#KPCQs!@eMIML0D3e>L-iVm+=c7}Dx5(ewxRy&roLA;B+<#es157OOL&%qS3!o7119SD&$ zIzGG>!AxL4?ui$;gSG)Uw4h14`JDTB4J;Q%yU9_y2knBnHO-OxoLEW>&c2s@}`uLa>F3SnO&9H9_CU?P-j5Zecj$$sx2Rzgxo zlT~NL0&~DNLFGS)eE(`8Mwg(EAx6G)H;EG6REZ=5!|y6zBLM+hQ}!9XUn79(F#Fiw@YpKI)Z?Hg6%bpt~mmET8FFkR)3HS!-& z`M*gD9##3hjr`gw|Cl&Ix81Mu?>F+xp@qqTU9^G(Y&WU=+mNp)+@(r92FE>=I66qS z;ao`Z;3t*;fY^iCepdNAk*_eks!CL04+m_os1iRI7{;i4IVahkR{5_)FmzWXKH*Re z*s@fK(I|me$3$0fDrQ5zK|D?rsilhK8kKNXW`1AcGHE+CP&T7^q>_`+lq}Ioipwfh zqPl@$qso6z+%K@bt@6WgS5*!DLYDB(l@k6sRwV51r)J3^vt1@nRmmUBi42+1)Y32^ zkB7rAg?u5pleDx1)pFE4fL}OE>I+NsK;9&T|M#Sn@%n*o=b%th;KPRlsn`_8!i0k| z$FcEHx^ls`6;dgKntee@O$Kxd#@ll$xu%7hH|CMeqvJ13SE_HQNEnVFX2+m_{FSKr zq*?HLDnR=0_BnwkE+V&VQ3=Rt&-oE9bv`o0wThS zFHzLLn#{;ST@q^|%77UI;lb87*Ix>)NDKXVeG8URaBanzWDL!dK0aL-TK6Wv7y*MP zpWtujK-<6cUP?FA!oLh`TASrDwvG!ESX%?(WfN%wd<839M>f{F?o=9OQXQP)tj0P`x zbD5m%9u6roINpu->#WmsRiX&= z6|#CrKM=)M$N+wEXhROd#Rd|u+r zoGImRlV4IwR)EqbD!H-+=c5Xzp_^`3I2Yy{boOKkjIPn-90ufJaB(0RIG&6fuD{8U z3UoBaJtR`oA4V~8jUjXdS`F3qJRw`yUQrV-)S)d?C69*~7<}u9T5r%zOQ97kVtexX zS#-EG?bk$Edc{iR1X0d~$T?+?@4?tvo`$}~&MzBO_RWSE4%9bQ033^}`Yx!EHBnH* zP?~+?aZ=ti+Yfg`e@y5d?!0bAt+|26Or-*;KdWzAz!@aJUan9maVWy`#qpi}*=MCf znZyH_DQ?l`Ul&VR=~5_rpd+nMLEC34*^ACL+WZJ1tory8EHtjbXgO5N^^4coW?ZBY zL$y9iL(F;0WqdB;Y0T`6(z4NQ@e6f0RUKPr$f~EpvkS@hspP7bs(%~9s)xs$T4Ikd zn2cxDVnMG@RF&fv8}!6{l;>TJ!Hm!_geoFSjW~u#!BHzBcDZnf+S-8|N%30n4zA)D zTOd&P3>Nb3Dr#coS%F0h=o!*p%4n)0bCXQYRmo34Sd6pW#bSZQLt0Fp&Z<)A|AR!H z_(95bi=$GmpHvkFWpa{Aeji`2~Xoqi_g=0}Wr^6#3au zD1$jIj0U_5qm;3AlJ#a+&x%NbE{;+Mwvz~gPBBY1c04D_yCwU<0-~I`llvk)hF)!;WG+x8_8Ku;6;Byjgyiv&|@gju4lx`857f1YsX=74*U-C0Gtz`CMwrv^HiJ1|0+$pxp9FscN9o*bj8a%rs7`~n z0+sx!1?yhO4P*feQDe6e3mg{dxV_xUoh*`#`*^UofI(P5CMxfsGW6Y-`1 z2sPV8>@fYqxc;?^ou=pp?S7%rDY zypDK93wJlIyGs5B-DyyIl%8wWnRF1Uv1o-m&spW(ftpst z+;A0IVF&n=Ytaf=hL-86CxupMAhp6yI96~1950mT!+zHVLo1wr3LLhf(og~a9OIuh zXhvuS|NMqr_@m+G&p#flYfV#<|E&JX?2FP0HW&$hJm53{mxiqIyl4S#lR4r%mvrz~ zfd!FHfU|6-EwS5V$@&>@v(Id96V~{**{FO+QYob!|WK8~JrqehHZuu+>-j-x&Fq)TXNPe35^_DeIqwd}Unv zO_iANmMF1Nl^AJYSfuhBq9)Yvk;-=&`ERKF-`^APlT>~)BY&LAe_ZUJZ9P?ff|1`x zL6JsS@pJSPt0sI%FHaFfg3QE}uNED*NCE zmH(2Fzf0x6C|mfF%75C(|4HR@nGXCzQQMKfQsu8V@@uJlJPpeHw^aTYM*exo4yRyPIjD(Z zD!~yB!{P1;Qm98@d?Gm&7Sv&tsN5r7u^mkn0(+`;e3KfKd(<2I>KD+!u00 z?0!MwTq{ipr$3j;ngypY0s?0@BK+iS!{*e{L^%wVLa$_D#gPpo9A*r7tzsjsSGChV zm?OPb`>+N)k$s~%5>H#ao0UtmpRs*iON$=AbIG{BPgl3x-)V}&XZNza338wWl)D=1b zM16Wxu8Y1JFF7?2IuXfpRPvwb6odO&xa&#oI~4aX!9XCVhdLlv^1p^CV{0~Bs<_?? zYh$)2Xse}?XIrqI2mouqvS|Js39djE7JsnM;nFvb$n@){taHQ{*xzwsgmV&D(_H?u zIS7k@-4pIxz&klNqkJ+VkT4oF0w{o1EKV-!E)Yvmc^|N@j4_y`-xl=@gfPK)5#QB6 z@FFIRHPPW;omh6!Oef!>IzdeaSJY3X=y=CTK0PdGu)VL6e?gxbd`c26vY3^h63WoD zB_!%C&>UlWJb=>zEP&CRZd?ubg=^^jG*Gkw@!HI}7z~oLqvWt?ttz}aR?<-EZ*w5_eeX^g=0aE>8c zYnwRV0x%7XLntSgrKzzeS&U;+*h|7|_`iq2P?M$IO~7_cp}%c)_@W;He34wU4;&$P4!Y_nDVw?_VDOc}`cZs0K> zt`U7C+t5O_p#{&@g0_cL@^JLN!Ruyxlzu-%#RCvYTDGuU{!F0R20o~ zeVzUjP!2Btd79<$GQw_X2Mt#dNgiKDvuKFB;n73d2NO0U9~xr3IIQeRHpq?UC8;5n zfyVghcJIInylfj2%c>EvU+zq6T zS^~Uq*lG8g)&C}Cc--T1svDtjHjyTP!7BM93(j2v0uv}(bjMq=#|}UiWqV2`!WHjG zB5zj+_flAcw$D{^4+}!CLTE_Alkl;TGx7`*>k^c)b{fwsc)E%K&au5S?L69?BNj2f zHuTDCA<6jVeJMDvj+VT-h;1v#_(UaBo(x{S$}H;+?{Se}3{Cqn>(D%f(aQ~dw#cwML~oaRIHoDZFwg+GJ&E5JYb*y)D8V_G6Y{UAc^9F122Z7&q^5^o#*`}_XJ z?Xe5_)5Eindh&Ovs5Xp}{WxFhg2_|B%(oBcS;xENaGaoHOH)HZ#>6of>Lh-kP$;b1yfhwt*?x`fgH>{%ZkOd2&P+J|kIpliXySdQ&DBL8c7y zL);Z|H=)*CyUrLR@;uD%k}0o?GPWu2N|C%zVHJ}SVw~jeJfdm@CS7 zee!qm6kGDekGjO#n9OMdcQkG01VFHQv9iU*avmoKZP(wCG<-8sw(Jntf#l;V`8fK^ zXqhIev~)~YOc#94POQ@_^Z`c%Yc+2IDyL-|N(rMdeV^TbN?5otvRxThCgqR{Ov~9w z<}lT~Cn0544dwD9`Z^|Nsi0aewG6Jepb0`gRO}4&7PB{;!P?>>l_UB{WqF*1Ra|by z6wKaRh46~8>{dp&Nf6giCp10OP~eyXy@SAWcnAtt8=-9~^u`KJC!ld=JPI@)qB!kJ z*e3L(W$ zKH;y1xX*{c*TvA#QH%}m#lMKB!S_hI1F#VQ-3?*y)ho=w8?A#(GqmNw&}us_v$IRLq}+&sJV0Q@c!PP40vxf1st z~i z0=8qJyvb?$_$MQtq`z{X>*o!YoI9m=@rg&}b+ra8E_AyBY^Ari0N!j?SvpTv`Mm-> zMr9-bpQCNbQ;gm(wK^dNGH)U)qEAIwu|wFw2Fbf=L#Yl-R&+WdT~HqZdIT2Gyy;{w z@%!$joHb?XK<0w`f%2P^5tId1l;s?UCdwyjCsJSO6@wJYgMv_^+(#Fmr7RuDY)zB{ zEGU}`l#_Xb;v6JW*Vb_SOXmO)S6y^L_)W==`3Cj^1H1PTAZFh!gz3fr+(h~X;35S$ z+yLxk0Q#~?R-7d3unlAtha)Y0U2p)-$&U$rBtZJF7#9}44}xSG_6 z4Qf{sX^_oCP%=eI#@2y~UEi7r9+3#>YyB(?f%>)85d`N*u4veiHzY@98wf_32%;r| zWStMU8Y~g~7m(j8$X*6yD-&{&P?WfR`IH5+z^t=CLEd3NUN*$iR}O&CZ~>m_ZUttJ zI}u@~Q!p9Kyv2ex)kJ&qHp$H50g4wN8fd+h1xAESq#N}qF7i!*JGDzf%`%{#F`-^Z zLArN;NYjmyrKMzwX#YpAOV0H&09zS=zI3+2324Nj+Fco*xt`b*Jhn!v1DSJMqFL{U zBF%bU@;P2_W4Q+>dQa5z;8scCss5^28`=9}5bqZH9YWiXKB0=jB$L8L>iXgW1M(FU zawZ_zw6(P1C_u)&mQ7nXS2k^e0ocy~^!4W6H$`+rW)HSxw;pN9XR_bp_2*z}GSC*9 zXn&m}Z(lSr(8d^Oy>?*a=t~khPY#o=Cg5$ol>Y0dSg?)+2o_wD%uCX*!?a^mDWW_J z=8aWVerG_=HXwa7>D=?X0MGm@9W6<)wB#UVL|!KU7>M;1D}q77jWN)A@05~5y8gsy)4N&d>SQ7~s%|tN z>7yD}L@>d&Af{@hg{f zEnX2p@U4l!rReHxAV@V3_?nQe@3B+C$p51S==wy2ft9O_@uHid(Cikv`kH7PACzK$ z7EBk@>vpzJi2b_)Bjl@!1+u;gS$U)Ez$FIcnZxvXq_Uy%aA>SYCAfD&9jID8Mrp-wT2|SO}^G3|Pl`uE1Q@1(p_V`knae zxl&2(yqeea6rUr$tV*6^e?F$NsVA;kwlENGVGR1)O zH6(@iOCcy}4hrZ05n-eWKasYI&*k?@4gJYRq(Sm9qXtG^%w@BQ-8sEJ9~cg%|I9E?3~e>3ghQyY*q&wI4~O?rxHcGbI11dY1A|+OD4?6m6uK3yLFZH) z5bXz*`s~9I<~%Oa!JNA-*W>IaDSc;2LEHa`V$L$QKuAQ#NL&7ct&d*S(v~O_!Moo} zM!anxm|!6AjpG%yGH?-r%-#3mVo?i8`QRtz#tpZN8k6(|Jmd=0tC}hs8Tyqgo^rxn ziOpY&oGndN&c|}qQvr79UzA1~IZ0p;3-%7!(&~>ci?F>H^90);49d2abyscOLKzW) zu#p?#L-;iIkDfEp-8~g}-}frZ1Zy>$!cAW6Qb+VwzSS9bQV@$^*9iL^x5fJLqV?lr z^TV>a6!9m~gTLQPQ>Tb%l%#LKBMoA=xRe#*

    0O9e1qoBH_aU9=GV;D-|Ir({v91%`PW7|9p&@;d41QHJJ0)1dVSgJ zPhKaFaP!%utJ6kaXZiRGEnWKyz2A4FE4Pi;feHUe@1N@RCa;%!z257aUcdHgzeS?o z4^uxk^t!9p8@;~ZbuiZ#m8-U1k=rib|JCRB_Wto+-}CyFFW+oWSN}ggezn(jo4EKs zK7WkY3%nlYb$?&Z-U+@x*Ay*Jl@4xs-u3>E`X?Fjt-aRo=KM3fU)lTb`Sxb|^Ym=5 z@js`jf4(n2f0C>JYA>hBcSASTKjSFBo7ZirmYkMLm0$`Pj~G zJx=xU#$Idh?$zGiZtu|E$Hx!% zI>qbSo4Iy7d%yhwuAKwCcG}GO_U`S4KK^WXSMMiZ?*Kk$#oK9f7eCeOBR<~MU+?Ul z-3`5emT$kG_mB2^nAiDU*YTedwmi_yXOEt4KIeP?nqJOteUQuBJHQ8fzj7a!pXB}7 zR&Fa7uie+_kq5i_)4X2W-T7B|{|@h)Zgq&u5BF;C7@y+($GtY(+?8u_sMC$Mar5i$ z{h8jk--fx!pMPskaOE!<|LWVVyoD=g?<)Vs=fCz^e~2sJ$?MvOx$=z@ zYVSDj>f4*<^L@O3me;k0x%LJg?%J{60hncCUHNNvarsA%a{gmpTlxGX|BmtJCc6B^KK_yS z-}M?l+{W@8{b)!^fw2y};|uLtVKW&G&k**AKjIx?fRz{&?T}YaQ?E z?csI4*XCaD_4=V#`)!A9z5lq^MP3(s-DrO|pZ&%MKE9vV z6TQCd=kt#DGgDptpL~3T_xJERW`bM3m%aa{*A4r)dOv&r?#|A??r>Lr^bt<)^W_$L zz4#PY&VGBqesf^E=`KEZqN{g}_aF4yaE8kt=C%E?u3T|tr%(9!Jzl@``lipnaH^|s zziIH?6j$$aud_~f`LDdzI>Y(xPIBcMdcVs|7k}C7D_$ph{pn1XuQSW(&(mD}X|tU_ zduyk+d;hQ*F8_g#KXjJM-?XdK=4U(I(*Hf%V5Td7KtC6s;Pq`^uF5QzzsbkX^1l5B zgK3*{T>aZ-yYfrC->JWgw>j78RbCf({oU(RzFdbnuD<=I!xrbedcS#nY8&T&?sd!s z&VTA+SMNt3uXu^`Yh3E|46k=z=*n+D!0Auk|J`fFi(Gs)uXVk4^BP@Ad!-BqG|Ltk z5!mAbTO}TV2Vns`1o|AK_ebbYg@J=d*ap_66PDtX%0Gv4`zYKgKny}x=8uMybR#-kXI!Q*fb z`PFH^Hq?bDh}{*`X+W%)zFH;GUv~s$s1mg%Uyri&e7r#-zqa?krA#Bx(1h69*iF3e zqHg+uk2Oo=S|t2tw9zs-uf(!iyDbvsS_l5RfxU4n2)5>;El(BeMUv{%RbyQ}fM7?gl z+@?W%lfbrirQP$yw+LcAz5OF?_VVpM8#K^6C~M)Ze7Qb}+?GDxFNpUIY^(nq#`Ew3 zya?M+Zy>Z|TfKz;l&>?G7>`EA?@iFVQf#=G*rGh`enLFoFpRR>=P9qU!}8SGk+M4y zugN@D59X`#J15%NK2QDKe3_le4Nv4pBxKA_G4_~YSus7>2-gFd;Q*n5;YDAD#o z#3%UJA?U^1@pTe@bJ}c`n0MpEy4ZZy zNtA07`0IK5Ec7!fd=5*Y4f9(M*7x)Mg4kn0y=RE8%KWM(=J`ZWhAQ#U-nSuV{X~Al zAm>U)(U*B*8~A!3=gFyFr$oCOQ*OgV%-Y|?x6wVNt&J1)HudE;3*z0py?GF`_Im`e zUV&|S=})xT+qe5wkk~R$`M$o~R*766AMYQ;w+?J;_G^r9;9K|(22gJhv}fCWkN>o< zGlbZ4p!ff-7Hro`h&@S}PtknCc6sKxgO6>Or_N4!%I`$ETFi5eV7{8yE{U=`g)$&ecfM)eMp^g_y@uZP=~hH4EpE>V((Mt;6&R86F!`!*gx@ALM+NBkL|dnr$u7ZR~;0>5przYPrH zYJ1%vC;#`vdMKvhb>c4vxfcWb)xcKStC+_Xem>VE=BNDCLF}zW-CqL#x4?cku+_$@ zzKsXb`@Q|2pk0;G@K7SwKHcO~4k4)HZp za)XHv^|>MFwuy3k2L4`wJvy+%dC4B*bB70IjtFcke`F9lDzGgtos%cNnAmGR{&t@H zo5YsniL1Rgh`;W0@8l`-R-V|qKK2Rvk++xTDfd~P*q1)`Df+Ruzd%3twwB3;ukyr} zCib7t0{`>Cemk(OJ=1p*xkkZ!*7A0T#J+BIr5pI%7m0T6;=FufaNfQX|Bm2XZEaL0 zwrZZZ^7r`oqv+J2Evs9Pc>P4($MH|jQ?@nnHooklL>+7IHR7iPbzjAQ#h0BI#Jdpd z>f=`TNBrqQ8H@KNzICFk<)oh_a-ZOz8np8<{ztydH9=f;cS_X#8UHlO?2Yb|$f>-B zUxWB9f&Fk`yOM4?p7^!Fd~d|RAzxWynLP2^h~1nguGSACKA*O0qO}rb4#B@Jn6E8U z6XH!1WtDq`*h4-(0lhw``z-!5KKFPK??7w=c**B%9-$siZc$Lja$6AZ;p@GJzVB_z zABq2DQ12c5w|$u>g1D789ZZ=azMRFR9|W<9*iYqYV+8S$@I8D3`G)6+pPr|#m3=v= zw*>o!pzMc1PUXK1{O5ym)|T{zAYQ3B%sBfQAA2rOu7br(gX%B&SO$I2+lzy8Zw9ui zRZsX!@ay~7dx@ONSIZOoAQ4-NU&F_~402xww%YnO;VWjtk3sIUz_$FeKK6W`+_pY8 zI8W|n9~*)$@b())xwisa^V&7xzl-11$KFrmRDO7#*oTSO7x=sR*jGXBo4{6E-z9v- zZ1^e2eID351h&df2>inW+uD)77Q|l<>`wwaEHC?0pVK>j^$uUXuUA70ud-VPw)}8d z5agZ@Z2h)ya%i(^HnKrrcMfcocmjV>BG$hu_pie?Fbnbxj}u?yb5GnI9u&V@iwZP7n zc2m&s9OI1?6gBPxXFPw0e+R4g2K4KP9k}?N1AG(*t`(V4oV;$@-`H z-0Em;Z?A#Y@piI&1LBQRat(>E<#Wx@7D2g|*r$8HIl4}eYlVGA;Li-~~p-o9=d*zYma?y;GY-R$@b?2x$^`2g228ou#@#K^0|&^ z=b+q1f!zsv!@%D-u#@d=LT=Ln`R+lk8}?>_zjGW-A+UGg@OM=V25qILHx~>oXWlBbLTb9)|wO8 z*{HLw3vy2e_S1p=RA49T7dOjBRt@ZGf!!jov!$KYGRXA^?B0RBRbVIUZyn^u2KK1H z9v|4r`UeKNLjwEIz&<>%ll6}Xa+3mka$vt5*vb0u1i2FedrDwW4eVt7lY`unz3Zus;dxWc^Qr+-HIPd0?x~tPa_l+XQwt>a2l5Zg5}^4eVioovgoo zklQh^cMj~~ft{?sTaX(O*rNh_ufR^$9~0#E3GDIM2YUZt^pGGIwlRVDVJW#Ih#%>5 z6Vao+eWBN|9kag;a@Pj-b%A|DU|T)Yn}Xaefqh$G-x1hW&-AV!cTZs77uXL3w$(FT z5aj+7*m^eChQ|WiVy4fKdp0HiJnGr@*#$ zOn(k?zX!JE&#Rd+Gde%8uLild6rDp94Va+LV9HZET! zp6Uj~`#A zanvMom#W0chkSE>k!Kx#g{M{g76D%&mNxwM&U(CKV13?i&^}CH=h-03N^F4D5jsVk zqYaluWo#6C8%JHDuKfO5x18Lj@h|GQ-_yxS;A|dk5%oZO@}zw4oaB~KAAWJ5FTXO- zFaBkLFu4uRfG`l)1LNNr7#t1Z8T@U7xXfYvroi^-4)JdYB$E7|fF7dQh2O#1H7B)O zw0krn8X1j>_K1H=ASW6Bsz4Nt&JD)inE00k-0upMOz&GV6i4>s_Xfsd=>e_eFfRVB zfdiw1NF1C<9>VVnOyD;K4v&9FAd!rJQ^5Vw-Nc;K(a|x{vC$-AlXK$EISx5KIw6`8 zotVg;6itmzj!ucDMbo1hi5&keC=qdi)1uR(GoqO|XO<{2E1Dgh6`dWO6P+8Km&neE z&W|pLE{raUE{-lq|=<*{55T^U`4H8-cs)v-4(x+c0dnxB*5JO1eUIC4WG z&M)UgH$^u`w-CQIx-GgrCx1tDXLMI|cXSWYdvh}US3bHw5y`p_aL@Vz?pJ@9d($7u zhGT1C^r*i>`-wzG?jr6^eu_JhpNYadXt^(kyIo)4PS=;Bm!nq_^>qKG2Hk_1JG>q( z=1#^p3BHw^@ZQ^bqq^&GNqooQdwKHjM<2v@@7djU*&?6BciEZ$nHjNu&Ru1?hb;f_ zW&SYH@ZP9oA>G%Mf6(1dX~VbN1Ess3@(n-a3&yb@xl>2?>Es)JiGGdmX~~!4j)?qW zqJN}jqD&^^o^vQ!q(Y`R6W+m@TSCt$gWd?g`CZve46$6lsI*B+WmxP06gEX_sjq z=Q@-qu|cL|rW4W5B{F=Umf0w?G4U>Wa$SjS0^RcDv~+f#XL3n5ODV5%-3#P4Pt9$S zn&H2_1#&$L^{@vdYQjv-kN=rM zpx&s=9+^Gy_ljeqGh>3Bo_o-sdpMJWo`=w#o%_dXcXzr{2V}+(9q()DE>9Z{%IF@> zl20>OUYfi+Q?Ut|!!n0wj>sGt*FGv}(e9Ky+Q*Iwa>r&S1>WSq=9!8d@Aw=~bIcAW zWN?h$t%S;#v|u38!Xf zWoBp2O3j{~nmH#m!~Zl=bLVB|q~y*|iEHUE$Xr+;dr^Vh#VNTtZc5Fl&FpY< zfpWJL$laQnyDc>nMYk8o-BBQSXMx;Z1#)*6$lX&QcW;3lfA6Jc?@!I}{BnWZg9UO6 z3gjLtkbAg5?mq=`j}*u)%siT!eJnM@Gsp#UPZY>4Dv*1!K<=s3+|#KU?$|4kd$vGM zPs-#Uo=?rVXE^fL;yG68h4*bI%e|c1?klMop3W?gd#yn3_0-(r%p0k>H&ZijrDnKe zu|V#f0=Xrrxp#9i@8x*!=Xf9Fc)5N4VQTK9)C~7n7s!25Aopo%?z5cC=Q-Ze9Pf)9 z@5>x7cip~9&3&Dk;eO8oxo->PzDv!0pOg6^$ID&fA5(KbWqwZ0{gRsDF6EruZ#mxY zIo=;RUhZ<~ofG*7J&~I>B;QgImP2SSR;+ME6vEHm~OfvqSFF_Tlq{wTtxhoDJa<=(*3- z@qJNHj{A3WJge_i&&lT>8WuH5&FMvQX~Wt%x!h-Zo8;u0241tG=7HBDu=$QC$7`A6 zwaW2Y=XkkGs3)P*hU8OV*>cI}m$Dh|+bYoF`UP@&$Ab-ehBZ6nK0#v7jJUi##h)#m zwd^UxY$R)S&Y43t&Ua0z8UA-xAgABXNgKMP=DMb4_*Sbxu3LeeUR-E{UN)E=^a{bW zVecY)kKskwbqGklj? zAh&;kT(~{Q7ASW>YHnO=hHr5T$q}1Hx)C}K!7swr-nmZvi!&?RlQSwDS~H%m&a?`5 z%~jy;xHaNwRi=$1P3!XBrV7!T@w6eORHi!9Ii!*UVQ&($V@t3j98dLY< zc>0N^x|gxyJoQ_}dFs`Qr^M@ciq_7rMU}PV<=5PGKc%J(;z*sijFzNgRQzTn)&n(?$&JY7AWt`Sdb$J09Tw63OgSW4PoQ+5Mq*Ne0DHPtrI zcC5yVoM=8@V&NhmtYsJ&1@w8byRSyh~ z*LQHGc#aL?X>oI9<94QMkFCgFr`B{ADQ&ih>&E?7DPG#u<7wRI0mQans0i+52(d#ti?8MQe$p3BtYF>#sw z;^~BVdZecDHl13`9#t_uDl5iEB`r*j%N!R^HJ5qCCoHq4s?8#|{DXCjSLAM6&9O#2 zt+;ADclJZtVSi)#QaoiZbw^@FE=!c*MF>pYvE%l`d2wrQI#qkB_5^M1c(03(^olx) ziExB6pS2eWut=X_>yAs&k9>DD6Kw z8&sUCvy-O8r|PU#ajMQ*?pQ9K8gG$!nu*Uj72~swJ7W~{+8}K&>QX-5E>qP@#qrd) z$x%kjJaDS>lBV$)CZh=RC1NcUYZ)@dRkRF6^Rx^_w6E6UbCjD4ku_N3csf-*8O1$T zgr)7JxfjJ-xhUSsMRBjj5#qGTwD>jkSusa6Q_eX|ImVg3t!dnX+xk_CD-#*4vqw>U zW-F=^?-lfb=Ayl{$l39GjVH~xV22&W0|;@GVvY~#nX&hi!$uz zTGPt$lq(SSs__{nJ_FCI$UlBK5Abgg?GH@d*(UDQit#dNIkICB*FUxw(`>AyRe`+9 z>D=z_mai0BtFo@E&_C5!^J9>sT@7MkOx})EXZBY4&SlnW+MC)ZWR7Sa$lx!KR?2@#lRLL^=>u7mg z8)3c;Pa8B^*0z;!b5h3DvKs4_h^*&Jlw7vt^5&m^vR+uLdDM=lA=<{%tmPukx2!8; znQU3LmaN}yS$i&PZCEWmd!afS+xxLYv;liaICZ_Qe#uX}WqoSP5U!co>-jcqNi6=Zvm z)0rn}Y}}A%YBqvS(Z(?wdsWFU@e?;H;l>7>K{R#+)ylSQC7gC5t7mme8#m#p9XEDc zW|^;uu}P$-dEB^Z)P0$~8Bg+T9&O>r9#M~F8O1h>FBt~_hhk|&Pb*_C&F zkdv*mPiZ4>+07YUz3f@J4f}ARQTuo}T1}lrD|@WjdX=WCud`eSrUT+0 z=nzlcxu`8`I1s-jXf&0jv2D(JxwRaaCziYZp%<=~v)9d8*OK|%h^}Pq*b46WGF3$5 ziuFhGd}Vz%h+j^%aR|?kS^V$Ow58JAv*&nuR#IwMJk7Vb)XGZ#3WCEaFx{S2Hd8g* zndkemqkgHm?8fG_pL}|7*s^`YtnGN7(DoPUuwZn)rh4LVaQwufo-cGy7rG}3v(FUn z#q)!DT5xpS%4nW9Ob+`*D>G(WakWS1eNIuO_VuIe0gQSIQO_YB5RK!ng@!Cw?l?Zu zQ;6eKoT>ES=#XXO!FVe+9-6njd!EtF>j<7Pm}prvNTwaE6F=BxEToh3gxUV2-D zliBYzxcxsigUKvv*x>em*QV9ZxBUk(pV9{HA>r~_4cEHM==|jdMHO@LFecmTWNjA- zr>+j~NQ~Fsj(IyC+}i8-cWqc{X?Fd?sM-0}-yQe*ByZzPtZ;C9p)GlKIW1zE%@nrs zmk*#yxzc=$WkKkO~HG$pTp zwkPW7xBWkN$xH74YPZn(hu1yV)}VNwvE@-L|N2{rP+bdQWO?jx+go|XG??$ywV!

    FLw#b-qYE2PP~n@oz7>pE4!{u;ru$2zrc?w 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

    >{_-1P)fd3K9kFaLRh?m5Rz}gD>F%e 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ℜ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 z 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�-J)d&imxy9M$tPnb##q8T04CkT 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 N_3;O}BJk3<{y(7Av$FsI diff --git a/venv2/bin/wheel b/venv2/bin/wheel deleted file mode 100755 index 34ec289..0000000 --- a/venv2/bin/wheel +++ /dev/null @@ -1,10 +0,0 @@ -#!/home/sean/Downloads/BMS-View/venv2/bin/python2.7 -# -*- coding: utf-8 -*- -import re -import sys - -from wheel.cli import main - -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/venv2/lib/python2.7/LICENSE.txt b/venv2/lib/python2.7/LICENSE.txt deleted file mode 120000 index fad3dca..0000000 --- a/venv2/lib/python2.7/LICENSE.txt +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/LICENSE.txt \ No newline at end of file diff --git a/venv2/lib/python2.7/UserDict.py b/venv2/lib/python2.7/UserDict.py deleted file mode 120000 index 1dcde33..0000000 --- a/venv2/lib/python2.7/UserDict.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/UserDict.py \ No newline at end of file diff --git a/venv2/lib/python2.7/_abcoll.py b/venv2/lib/python2.7/_abcoll.py deleted file mode 120000 index e39c38d..0000000 --- a/venv2/lib/python2.7/_abcoll.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/_abcoll.py \ No newline at end of file diff --git a/venv2/lib/python2.7/_weakrefset.py b/venv2/lib/python2.7/_weakrefset.py deleted file mode 120000 index a3c1cd4..0000000 --- a/venv2/lib/python2.7/_weakrefset.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/_weakrefset.py \ No newline at end of file diff --git a/venv2/lib/python2.7/abc.py b/venv2/lib/python2.7/abc.py deleted file mode 120000 index cb3e5d1..0000000 --- a/venv2/lib/python2.7/abc.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/abc.py \ No newline at end of file diff --git a/venv2/lib/python2.7/codecs.py b/venv2/lib/python2.7/codecs.py deleted file mode 120000 index 50169dc..0000000 --- a/venv2/lib/python2.7/codecs.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/codecs.py \ No newline at end of file diff --git a/venv2/lib/python2.7/copy_reg.py b/venv2/lib/python2.7/copy_reg.py deleted file mode 120000 index 5dc0af3..0000000 --- a/venv2/lib/python2.7/copy_reg.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/copy_reg.py \ No newline at end of file diff --git a/venv2/lib/python2.7/distutils/__init__.py b/venv2/lib/python2.7/distutils/__init__.py deleted file mode 100644 index b9b0f24..0000000 --- a/venv2/lib/python2.7/distutils/__init__.py +++ /dev/null @@ -1,134 +0,0 @@ -import os -import sys -import warnings - -# opcode is not a virtualenv module, so we can use it to find the stdlib -# Important! To work on pypy, this must be a module that resides in the -# lib-python/modified-x.y.z directory -import opcode - -dirname = os.path.dirname - -distutils_path = os.path.join(os.path.dirname(opcode.__file__), "distutils") -if os.path.normpath(distutils_path) == os.path.dirname(os.path.normpath(__file__)): - warnings.warn("The virtualenv distutils package at %s appears to be in the same location as the system distutils?") -else: - __path__.insert(0, distutils_path) # noqa: F821 - if sys.version_info < (3, 4): - import imp - - real_distutils = imp.load_module("_virtualenv_distutils", None, distutils_path, ("", "", imp.PKG_DIRECTORY)) - else: - import importlib.machinery - - distutils_path = os.path.join(distutils_path, "__init__.py") - loader = importlib.machinery.SourceFileLoader("_virtualenv_distutils", distutils_path) - if sys.version_info < (3, 5): - import types - - real_distutils = types.ModuleType(loader.name) - else: - import importlib.util - - spec = importlib.util.spec_from_loader(loader.name, loader) - real_distutils = importlib.util.module_from_spec(spec) - loader.exec_module(real_distutils) - - # Copy the relevant attributes - try: - __revision__ = real_distutils.__revision__ - except AttributeError: - pass - __version__ = real_distutils.__version__ - -from distutils import dist, sysconfig # isort:skip - -try: - basestring -except NameError: - basestring = str - -# patch build_ext (distutils doesn't know how to get the libs directory -# path on windows - it hardcodes the paths around the patched sys.prefix) - -if sys.platform == "win32": - from distutils.command.build_ext import build_ext as old_build_ext - - class build_ext(old_build_ext): - def finalize_options(self): - if self.library_dirs is None: - self.library_dirs = [] - elif isinstance(self.library_dirs, basestring): - self.library_dirs = self.library_dirs.split(os.pathsep) - - self.library_dirs.insert(0, os.path.join(sys.real_prefix, "Libs")) - old_build_ext.finalize_options(self) - - from distutils.command import build_ext as build_ext_module - - build_ext_module.build_ext = build_ext - -# distutils.dist patches: - -old_find_config_files = dist.Distribution.find_config_files - - -def find_config_files(self): - found = old_find_config_files(self) - if os.name == "posix": - user_filename = ".pydistutils.cfg" - else: - user_filename = "pydistutils.cfg" - user_filename = os.path.join(sys.prefix, user_filename) - if os.path.isfile(user_filename): - for item in list(found): - if item.endswith("pydistutils.cfg"): - found.remove(item) - found.append(user_filename) - return found - - -dist.Distribution.find_config_files = find_config_files - -# distutils.sysconfig patches: - -old_get_python_inc = sysconfig.get_python_inc - - -def sysconfig_get_python_inc(plat_specific=0, prefix=None): - if prefix is None: - prefix = sys.real_prefix - return old_get_python_inc(plat_specific, prefix) - - -sysconfig_get_python_inc.__doc__ = old_get_python_inc.__doc__ -sysconfig.get_python_inc = sysconfig_get_python_inc - -old_get_python_lib = sysconfig.get_python_lib - - -def sysconfig_get_python_lib(plat_specific=0, standard_lib=0, prefix=None): - if standard_lib and prefix is None: - prefix = sys.real_prefix - return old_get_python_lib(plat_specific, standard_lib, prefix) - - -sysconfig_get_python_lib.__doc__ = old_get_python_lib.__doc__ -sysconfig.get_python_lib = sysconfig_get_python_lib - -old_get_config_vars = sysconfig.get_config_vars - - -def sysconfig_get_config_vars(*args): - real_vars = old_get_config_vars(*args) - if sys.platform == "win32": - lib_dir = os.path.join(sys.real_prefix, "libs") - if isinstance(real_vars, dict) and "LIBDIR" not in real_vars: - real_vars["LIBDIR"] = lib_dir # asked for all - elif isinstance(real_vars, list) and "LIBDIR" in args: - real_vars = real_vars + [lib_dir] # asked for list - return real_vars - - -sysconfig_get_config_vars.__doc__ = old_get_config_vars.__doc__ -sysconfig.get_config_vars = sysconfig_get_config_vars diff --git a/venv2/lib/python2.7/distutils/distutils.cfg b/venv2/lib/python2.7/distutils/distutils.cfg deleted file mode 100644 index 1af230e..0000000 --- a/venv2/lib/python2.7/distutils/distutils.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# This is a config file local to this virtualenv installation -# You may include options that will be used by all distutils commands, -# and by easy_install. For instance: -# -# [easy_install] -# find_links = http://mylocalsite diff --git a/venv2/lib/python2.7/encodings b/venv2/lib/python2.7/encodings deleted file mode 120000 index 1250ad8..0000000 --- a/venv2/lib/python2.7/encodings +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/encodings \ No newline at end of file diff --git a/venv2/lib/python2.7/fnmatch.py b/venv2/lib/python2.7/fnmatch.py deleted file mode 120000 index ec3e10c..0000000 --- a/venv2/lib/python2.7/fnmatch.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/fnmatch.py \ No newline at end of file diff --git a/venv2/lib/python2.7/genericpath.py b/venv2/lib/python2.7/genericpath.py deleted file mode 120000 index cb8897c..0000000 --- a/venv2/lib/python2.7/genericpath.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/genericpath.py \ No newline at end of file diff --git a/venv2/lib/python2.7/lib-dynload b/venv2/lib/python2.7/lib-dynload deleted file mode 120000 index c706a1e..0000000 --- a/venv2/lib/python2.7/lib-dynload +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/lib-dynload \ No newline at end of file diff --git a/venv2/lib/python2.7/linecache.py b/venv2/lib/python2.7/linecache.py deleted file mode 120000 index 943c429..0000000 --- a/venv2/lib/python2.7/linecache.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/linecache.py \ No newline at end of file diff --git a/venv2/lib/python2.7/locale.py b/venv2/lib/python2.7/locale.py deleted file mode 120000 index 92c243c..0000000 --- a/venv2/lib/python2.7/locale.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/locale.py \ No newline at end of file diff --git a/venv2/lib/python2.7/no-global-site-packages.txt b/venv2/lib/python2.7/no-global-site-packages.txt deleted file mode 100644 index e69de29..0000000 diff --git a/venv2/lib/python2.7/ntpath.py b/venv2/lib/python2.7/ntpath.py deleted file mode 120000 index 5659ae1..0000000 --- a/venv2/lib/python2.7/ntpath.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/ntpath.py \ No newline at end of file diff --git a/venv2/lib/python2.7/orig-prefix.txt b/venv2/lib/python2.7/orig-prefix.txt deleted file mode 100644 index e25db58..0000000 --- a/venv2/lib/python2.7/orig-prefix.txt +++ /dev/null @@ -1 +0,0 @@ -/usr \ No newline at end of file diff --git a/venv2/lib/python2.7/os.py b/venv2/lib/python2.7/os.py deleted file mode 120000 index 950fc8d..0000000 --- a/venv2/lib/python2.7/os.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/os.py \ No newline at end of file diff --git a/venv2/lib/python2.7/posixpath.py b/venv2/lib/python2.7/posixpath.py deleted file mode 120000 index 30cb8ca..0000000 --- a/venv2/lib/python2.7/posixpath.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/posixpath.py \ No newline at end of file diff --git a/venv2/lib/python2.7/re.py b/venv2/lib/python2.7/re.py deleted file mode 120000 index 56a0731..0000000 --- a/venv2/lib/python2.7/re.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/re.py \ No newline at end of file diff --git a/venv2/lib/python2.7/site-packages/easy_install.py b/venv2/lib/python2.7/site-packages/easy_install.py deleted file mode 100644 index d87e984..0000000 --- a/venv2/lib/python2.7/site-packages/easy_install.py +++ /dev/null @@ -1,5 +0,0 @@ -"""Run the EasyInstall command""" - -if __name__ == '__main__': - from setuptools.command.easy_install import main - main() diff --git a/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/INSTALLER b/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/LICENSE.txt b/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/LICENSE.txt deleted file mode 100644 index 737fec5..0000000 --- a/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2008-2019 The pip developers (see AUTHORS.txt file) - -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. diff --git a/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/METADATA b/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/METADATA deleted file mode 100644 index d7aa9a4..0000000 --- a/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/METADATA +++ /dev/null @@ -1,75 +0,0 @@ -Metadata-Version: 2.1 -Name: pip -Version: 19.1.1 -Summary: The PyPA recommended tool for installing Python packages. -Home-page: https://pip.pypa.io/ -Author: The pip developers -Author-email: pypa-dev@groups.google.com -License: MIT -Keywords: distutils easy_install egg setuptools wheel virtualenv -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Topic :: Software Development :: Build Tools -Classifier: Programming Language :: Python -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 :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* - -pip - The Python Package Installer -================================== - -.. image:: https://img.shields.io/pypi/v/pip.svg - :target: https://pypi.org/project/pip/ - -.. image:: https://readthedocs.org/projects/pip/badge/?version=latest - :target: https://pip.pypa.io/en/latest - -pip is the `package installer`_ for Python. You can use pip to install packages from the `Python Package Index`_ and other indexes. - -Please take a look at our documentation for how to install and use pip: - -* `Installation`_ -* `Usage`_ -* `Release notes`_ - -If you find bugs, need help, or want to talk to the developers please use our mailing lists or chat rooms: - -* `Issue tracking`_ -* `Discourse channel`_ -* `User IRC`_ - -If you want to get involved head over to GitHub to get the source code and feel free to jump on the developer mailing lists and chat rooms: - -* `GitHub page`_ -* `Dev mailing list`_ -* `Dev IRC`_ - -Code of Conduct ---------------- - -Everyone interacting in the pip project's codebases, issue trackers, chat -rooms, and mailing lists is expected to follow the `PyPA Code of Conduct`_. - -.. _package installer: https://packaging.python.org/en/latest/current/ -.. _Python Package Index: https://pypi.org -.. _Installation: https://pip.pypa.io/en/stable/installing.html -.. _Usage: https://pip.pypa.io/en/stable/ -.. _Release notes: https://pip.pypa.io/en/stable/news.html -.. _GitHub page: https://github.com/pypa/pip -.. _Issue tracking: https://github.com/pypa/pip/issues -.. _Discourse channel: https://discuss.python.org/c/packaging -.. _Dev mailing list: https://groups.google.com/forum/#!forum/pypa-dev -.. _User IRC: https://webchat.freenode.net/?channels=%23pypa -.. _Dev IRC: https://webchat.freenode.net/?channels=%23pypa-dev -.. _PyPA Code of Conduct: https://www.pypa.io/en/latest/code-of-conduct/ - - diff --git a/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/RECORD b/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/RECORD deleted file mode 100644 index 51ad87e..0000000 --- a/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/RECORD +++ /dev/null @@ -1,618 +0,0 @@ -../../../bin/pip,sha256=6WLnsIaScsFb417DvpIGBhQzLrKBPj2uJBVGEV5NOmI,248 -../../../bin/pip2,sha256=6WLnsIaScsFb417DvpIGBhQzLrKBPj2uJBVGEV5NOmI,248 -../../../bin/pip2.7,sha256=6WLnsIaScsFb417DvpIGBhQzLrKBPj2uJBVGEV5NOmI,248 -pip-19.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -pip-19.1.1.dist-info/LICENSE.txt,sha256=W6Ifuwlk-TatfRU2LR7W1JMcyMj5_y1NkRkOEJvnRDE,1090 -pip-19.1.1.dist-info/METADATA,sha256=bLFqR8At4rsCvM1hJTM98bOrT26dNZLeTLo_0PYIZCs,2892 -pip-19.1.1.dist-info/RECORD,, -pip-19.1.1.dist-info/WHEEL,sha256=HX-v9-noUkyUoxyZ1PMSuS7auUxDAR4VBdoYLqD0xws,110 -pip-19.1.1.dist-info/entry_points.txt,sha256=S_zfxY25QtQDVY1BiLAmOKSkkI5llzCKPLiYOSEupsY,98 -pip-19.1.1.dist-info/top_level.txt,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -pip/__init__.py,sha256=A9ZYTNji94NmcmoIbn-XLsEni4ac8BoiAt7guiAW27g,23 -pip/__init__.pyc,, -pip/__main__.py,sha256=L3IHqBeasELUHvwy5CT_izVEMhM12tve289qut49DvU,623 -pip/__main__.pyc,, -pip/_internal/__init__.py,sha256=Di4rpoQhA2Kx0Dm0THczf61CDOXcPokR2FIpyKkRm1Y,2870 -pip/_internal/__init__.pyc,, -pip/_internal/build_env.py,sha256=ZUpR-00pxQc-Mw750jyBVA-oWb4WHtpK63pfiTHd8qU,7392 -pip/_internal/build_env.pyc,, -pip/_internal/cache.py,sha256=PQesJm1JrjgAya3VyV6qkbnfACG23c1wQ7PaSw_0F-Y,7656 -pip/_internal/cache.pyc,, -pip/_internal/cli/__init__.py,sha256=FkHBgpxxb-_gd6r1FjnNhfMOzAUYyXoXKJ6abijfcFU,132 -pip/_internal/cli/__init__.pyc,, -pip/_internal/cli/autocompletion.py,sha256=ptvsMdGjq42pzoY4skABVF43u2xAtLJlXAulPi-A10Y,6083 -pip/_internal/cli/autocompletion.pyc,, -pip/_internal/cli/base_command.py,sha256=2SbVZ2o3KmVdeJlK4l1lP6y_ZMFZ8VkDp9ns1ByZ-xM,12629 -pip/_internal/cli/base_command.pyc,, -pip/_internal/cli/cmdoptions.py,sha256=IA1XAgTJ1oWXp1oF3CkE8mpUx8vqIysyd7hlEZk7wWE,23813 -pip/_internal/cli/cmdoptions.pyc,, -pip/_internal/cli/main_parser.py,sha256=YH_w_hApq2pyS_G5tZlbIe7g_HUIcKE820jhnv0piVA,3002 -pip/_internal/cli/main_parser.pyc,, -pip/_internal/cli/parser.py,sha256=VZKUKJPbU6I2cHPLDOikin-aCx7OvLcZ3fzYp3xytd8,9378 -pip/_internal/cli/parser.pyc,, -pip/_internal/cli/status_codes.py,sha256=F6uDG6Gj7RNKQJUDnd87QKqI16Us-t-B0wPF_4QMpWc,156 -pip/_internal/cli/status_codes.pyc,, -pip/_internal/commands/__init__.py,sha256=7fscm9bUGJInZwWY7VjH2pPC7HUWQWyjYMEIB33L9CY,2223 -pip/_internal/commands/__init__.pyc,, -pip/_internal/commands/check.py,sha256=liigNVif0iz2mBfhvsajrLZT5zM5KIvgmKvhAW91EzA,1430 -pip/_internal/commands/check.pyc,, -pip/_internal/commands/completion.py,sha256=hqvCvoxsIHjysiD7olHKTqK2lzE1_lS6LWn69kN5qyI,2929 -pip/_internal/commands/completion.pyc,, -pip/_internal/commands/configuration.py,sha256=Il76e-ERfEHtW2GbV1aTR6o-xurh-LVv2NCea7erP4s,8020 -pip/_internal/commands/configuration.pyc,, -pip/_internal/commands/download.py,sha256=XPe3Kuj9iZfXwOiJq70mYVYNZD5lJCLnGT_C61cOsKw,6623 -pip/_internal/commands/download.pyc,, -pip/_internal/commands/freeze.py,sha256=VvS3G0wrm_9BH3B7Ex5msLL_1UQTtCq5G8dDI63Iemo,3259 -pip/_internal/commands/freeze.pyc,, -pip/_internal/commands/hash.py,sha256=K1JycsD-rpjqrRcL_ijacY9UKmI82pQcLYq4kCM4Pv0,1681 -pip/_internal/commands/hash.pyc,, -pip/_internal/commands/help.py,sha256=MwBhPJpW1Dt3GfJV3V8V6kgAy_pXT0jGrZJB1wCTW-E,1090 -pip/_internal/commands/help.pyc,, -pip/_internal/commands/install.py,sha256=vSb8TfUHwz3HJ5cA-JnPP3X84ONQ0wkCztw0pHFbmsc,22841 -pip/_internal/commands/install.pyc,, -pip/_internal/commands/list.py,sha256=EtKEUotPbLCzzcWrZqEiEXi4ic00dgUOKUeNU0y7Pfg,10166 -pip/_internal/commands/list.pyc,, -pip/_internal/commands/search.py,sha256=sLZ9icKMEEGekHvzRRZMiTd1zCFIZeDptyyU1mQCYzk,4728 -pip/_internal/commands/search.pyc,, -pip/_internal/commands/show.py,sha256=bE-ucu8fAjTTENpRRKhwD3QSWR8Rss7YgKAbMJoxock,6273 -pip/_internal/commands/show.pyc,, -pip/_internal/commands/uninstall.py,sha256=h0gfPF5jylDESx_IHgF6bZME7QAEOHzQHdn65GP-jrE,2963 -pip/_internal/commands/uninstall.pyc,, -pip/_internal/commands/wheel.py,sha256=7MNPZqK9WWxZC3TgzvMBH-RPRlOFLpwq927lkzUiUjI,7167 -pip/_internal/commands/wheel.pyc,, -pip/_internal/configuration.py,sha256=xit1f8ZdnHz-AHzWAKTUa_gZzlIIM-5AgK30glB71ik,13115 -pip/_internal/configuration.pyc,, -pip/_internal/download.py,sha256=0_8jUtL4SLZe4qo8Fe66qkbO69gUG-IPbp932WOHyFs,35147 -pip/_internal/download.pyc,, -pip/_internal/exceptions.py,sha256=ryXWmEJpSHr3yXXk1efWHSzQwAjBdBJiKR5kCQvjgPA,9117 -pip/_internal/exceptions.pyc,, -pip/_internal/index.py,sha256=BO6jpJRvb_6HaS4meE8Lj_lyAX7IRP6pRof-zG-_hYw,42268 -pip/_internal/index.pyc,, -pip/_internal/locations.py,sha256=-N3f1I24gcPTdW52onPnySDoQUIn_TtPYV99WwsjxRE,6932 -pip/_internal/locations.pyc,, -pip/_internal/models/__init__.py,sha256=3DHUd_qxpPozfzouoqa9g9ts1Czr5qaHfFxbnxriepM,63 -pip/_internal/models/__init__.pyc,, -pip/_internal/models/candidate.py,sha256=_IzS-yw0h2UHfZALsZ2mxkeGNSNuNGspjSn2JfZ-ZHM,1045 -pip/_internal/models/candidate.pyc,, -pip/_internal/models/format_control.py,sha256=ap8Swa26ocSXBxIuCvaDBRZjxdKUFuwC-bfqXQHWtKw,2250 -pip/_internal/models/format_control.pyc,, -pip/_internal/models/index.py,sha256=K59A8-hVhBM20Xkahr4dTwP7OjkJyEqXH11UwHFVgqM,1060 -pip/_internal/models/index.pyc,, -pip/_internal/models/link.py,sha256=Hqu72UgH266njr2z2kTnIG-sQiPtjENDbPqXFzT-84s,4783 -pip/_internal/models/link.pyc,, -pip/_internal/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_internal/operations/__init__.pyc,, -pip/_internal/operations/check.py,sha256=CZHaksHKUMo58wGHGhhKlPrpcRMHObouzzyd9pMRFt8,5109 -pip/_internal/operations/check.pyc,, -pip/_internal/operations/freeze.py,sha256=_Ffl2HpoWLLHaiB1XyTjKIA3QWC8H-E1ib6xJgX_mRE,9279 -pip/_internal/operations/freeze.pyc,, -pip/_internal/operations/prepare.py,sha256=jQ6FaxA2u_MYnDQxcu6YCfmJ9sfhqrKN9vdd4-5N6lU,16931 -pip/_internal/operations/prepare.pyc,, -pip/_internal/pep425tags.py,sha256=jyBorYxepVJeHNo69TE-3UxJXsGO2XvGxveSWQDi_Wo,13128 -pip/_internal/pep425tags.pyc,, -pip/_internal/pyproject.py,sha256=OlCw7pSqST68hUF_eV-YVaqJ4I7z_ROJwvgra-2C_5I,6464 -pip/_internal/pyproject.pyc,, -pip/_internal/req/__init__.py,sha256=Y2SjAuMFsSt3dkiK8kkiQAfv8sHrjl0PAT63FKFT0tM,2364 -pip/_internal/req/__init__.pyc,, -pip/_internal/req/constructors.py,sha256=4KlO_-G89XYZW1VnzHwV34oCvR6ilmxFqSSGLgv4PEw,11399 -pip/_internal/req/constructors.pyc,, -pip/_internal/req/req_file.py,sha256=mZoQvhHZJwgljrXDH8CLXaNoUK4sM8_bRfK9Po2fM80,13714 -pip/_internal/req/req_file.pyc,, -pip/_internal/req/req_install.py,sha256=SGJLNpyZwzOL_EqfviIvAoZgxAoivxmFBN1cOU7DX9s,40061 -pip/_internal/req/req_install.pyc,, -pip/_internal/req/req_set.py,sha256=PaDc5EswLQhxBMFbuKbJ0frZbMNKocmA8OGqIWT-9EY,7860 -pip/_internal/req/req_set.pyc,, -pip/_internal/req/req_tracker.py,sha256=wBpDzSDSYwpUfW4K43NrEOCCp1r6stuubfLc65Y95EM,3129 -pip/_internal/req/req_tracker.pyc,, -pip/_internal/req/req_uninstall.py,sha256=rVOk8BRM_L9rsUUr9lmkV6Lm9N1Os7TEIDir6tT1Q7U,23105 -pip/_internal/req/req_uninstall.pyc,, -pip/_internal/resolve.py,sha256=rZDMkyhUIbaytY9KsYQVez8nl21xLXgaDt8xuHvyGMI,15128 -pip/_internal/resolve.pyc,, -pip/_internal/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_internal/utils/__init__.pyc,, -pip/_internal/utils/appdirs.py,sha256=r9i0BZLK9KcvrzI5tqlw8ehRTtSehWGERFLy7YppG3g,9398 -pip/_internal/utils/appdirs.pyc,, -pip/_internal/utils/compat.py,sha256=Q0cmYGBaKB4tV5E0CG11339YLxuCaqdUCSJd9vinMc8,8551 -pip/_internal/utils/compat.pyc,, -pip/_internal/utils/deprecation.py,sha256=HYUvfCZUxwLIFlYHeZM3VmuFhXTdlw0rk4-cC14bKw4,3080 -pip/_internal/utils/deprecation.pyc,, -pip/_internal/utils/encoding.py,sha256=tudXCoAPe9fZvNK4cmWQs2frREZ-QuGCwF_SlTyz6cI,1218 -pip/_internal/utils/encoding.pyc,, -pip/_internal/utils/filesystem.py,sha256=ojaIDvOFOtkpKme5se6X2N8ARmQxu8cxvaaI-NFqVtk,990 -pip/_internal/utils/filesystem.pyc,, -pip/_internal/utils/glibc.py,sha256=9_1wY9Lmca4xzOQDF1A6ITW_N80j_BXwN7Sx7vBqP4k,3282 -pip/_internal/utils/glibc.pyc,, -pip/_internal/utils/hashes.py,sha256=_6l8M_nqmLZjs-o2lP2rB7ZleAT05WOuqgwBa8uFYR8,3527 -pip/_internal/utils/hashes.pyc,, -pip/_internal/utils/logging.py,sha256=qSYK7Wf_oiCr1VR4qvAq_TtpY3SIKSlVDgnAeQqSjHc,11671 -pip/_internal/utils/logging.pyc,, -pip/_internal/utils/misc.py,sha256=QsYl2j5rU5Mh_CEsSf1W8GB6HvPOfioj30Emqz7mg7s,32434 -pip/_internal/utils/misc.pyc,, -pip/_internal/utils/models.py,sha256=DQYZSRhjvSdDTAaJLLCpDtxAn1S_-v_8nlNjv4T2jwY,1042 -pip/_internal/utils/models.pyc,, -pip/_internal/utils/outdated.py,sha256=sEe1l902jiOl3tArf6omqVd44s4BT9DOk3a3CXtJNNI,5868 -pip/_internal/utils/outdated.pyc,, -pip/_internal/utils/packaging.py,sha256=frr5M-ORe30rRKbH6pwqp_jkX1T8rx-UGDlj8vG5HII,2743 -pip/_internal/utils/packaging.pyc,, -pip/_internal/utils/setuptools_build.py,sha256=0blfscmNJW_iZ5DcswJeDB_PbtTEjfK9RL1R1WEDW2E,278 -pip/_internal/utils/setuptools_build.pyc,, -pip/_internal/utils/temp_dir.py,sha256=0Xq5ZlOd2OOeHwKM6hGy66gnMGAbyhio7DtjLHd7DFg,5339 -pip/_internal/utils/temp_dir.pyc,, -pip/_internal/utils/typing.py,sha256=bF73ImJzIaxLLEVwfEaSJzFGqV9LaxkQBvDULIyr1jI,1125 -pip/_internal/utils/typing.pyc,, -pip/_internal/utils/ui.py,sha256=yRqmi2V4OeTYP9SnXhuXKlyRx8xJ79AjLRgvLCZ4E1E,13812 -pip/_internal/utils/ui.pyc,, -pip/_internal/vcs/__init__.py,sha256=kgwOhkt6ddbKosZytktLydMUb_e-JpXMstJF9YpSOwM,19205 -pip/_internal/vcs/__init__.pyc,, -pip/_internal/vcs/bazaar.py,sha256=3lA6CKyrYpoJuxjTa8oTozszNcqdYILqEhKLJ41RMug,3231 -pip/_internal/vcs/bazaar.pyc,, -pip/_internal/vcs/git.py,sha256=x0PQDgzWho544gfqtE9CXoUkN34zE4YkpgrbTcWEte4,12960 -pip/_internal/vcs/git.pyc,, -pip/_internal/vcs/mercurial.py,sha256=AbH4IWdLCsjUxFnIHRvijV-7SNhfjDZJJFzQ1e_b48Q,3355 -pip/_internal/vcs/mercurial.pyc,, -pip/_internal/vcs/subversion.py,sha256=cMH4MEobSj68gaSiBD53KXVJnEbhtuUJjL8U1Kk_v70,8167 -pip/_internal/vcs/subversion.pyc,, -pip/_internal/wheel.py,sha256=-MijhN1BIuaQkb3909smA63wkbvdRrdtr1CUDxnQTqA,41189 -pip/_internal/wheel.pyc,, -pip/_vendor/__init__.py,sha256=iip2nWwH_riYqnDnM0q4BJFrWE-XWjYfxCejJKct0WM,4654 -pip/_vendor/__init__.pyc,, -pip/_vendor/appdirs.py,sha256=BENKsvcA08IpccD9345-rMrg3aXWFA1q6BFEglnHg6I,24547 -pip/_vendor/appdirs.pyc,, -pip/_vendor/cachecontrol/__init__.py,sha256=6cRPchVqkAkeUtYTSW8qCetjSqJo-GxP-n4VMVDbvmc,302 -pip/_vendor/cachecontrol/__init__.pyc,, -pip/_vendor/cachecontrol/_cmd.py,sha256=URGE0KrA87QekCG3SGPatlSPT571dZTDjNa-ZXX3pDc,1295 -pip/_vendor/cachecontrol/_cmd.pyc,, -pip/_vendor/cachecontrol/adapter.py,sha256=eBGAtVNRZgtl_Kj5JV54miqL9YND-D0JZPahwY8kFtY,4863 -pip/_vendor/cachecontrol/adapter.pyc,, -pip/_vendor/cachecontrol/cache.py,sha256=1fc4wJP8HYt1ycnJXeEw5pCpeBL2Cqxx6g9Fb0AYDWQ,805 -pip/_vendor/cachecontrol/cache.pyc,, -pip/_vendor/cachecontrol/caches/__init__.py,sha256=-gHNKYvaeD0kOk5M74eOrsSgIKUtC6i6GfbmugGweEo,86 -pip/_vendor/cachecontrol/caches/__init__.pyc,, -pip/_vendor/cachecontrol/caches/file_cache.py,sha256=8vrSzzGcdfEfICago1uSFbkumNJMGLbCdEkXsmUIExw,4177 -pip/_vendor/cachecontrol/caches/file_cache.pyc,, -pip/_vendor/cachecontrol/caches/redis_cache.py,sha256=HxelMpNCo-dYr2fiJDwM3hhhRmxUYtB5tXm1GpAAT4Y,856 -pip/_vendor/cachecontrol/caches/redis_cache.pyc,, -pip/_vendor/cachecontrol/compat.py,sha256=kHNvMRdt6s_Xwqq_9qJmr9ou3wYMOMUMxPPcwNxT8Mc,695 -pip/_vendor/cachecontrol/compat.pyc,, -pip/_vendor/cachecontrol/controller.py,sha256=U7g-YwizQ2O5NRgK_MZreF1ntM4E49C3PuF3od-Vwz4,13698 -pip/_vendor/cachecontrol/controller.pyc,, -pip/_vendor/cachecontrol/filewrapper.py,sha256=vACKO8Llzu_ZWyjV1Fxn1MA4TGU60N5N3GSrAFdAY2Q,2533 -pip/_vendor/cachecontrol/filewrapper.pyc,, -pip/_vendor/cachecontrol/heuristics.py,sha256=BFGHJ3yQcxvZizfo90LLZ04T_Z5XSCXvFotrp7Us0sc,4070 -pip/_vendor/cachecontrol/heuristics.pyc,, -pip/_vendor/cachecontrol/serialize.py,sha256=GebE34fgToyWwAsRPguh8hEPN6CqoG-5hRMXRsjVABQ,6954 -pip/_vendor/cachecontrol/serialize.pyc,, -pip/_vendor/cachecontrol/wrapper.py,sha256=sfr9YHWx-5TwNz1H5rT6QOo8ggII6v3vbEDjQFwR6wc,671 -pip/_vendor/cachecontrol/wrapper.pyc,, -pip/_vendor/certifi/__init__.py,sha256=-M1moep9D6jZnOAT0qnM1dpoEHMPage7Osv5xLRLyFg,52 -pip/_vendor/certifi/__init__.pyc,, -pip/_vendor/certifi/__main__.py,sha256=NaCn6WtWME-zzVWQ2j4zFyl8cY4knDa9CwtHNIeFPhM,53 -pip/_vendor/certifi/__main__.pyc,, -pip/_vendor/certifi/cacert.pem,sha256=OXuDPlrPiaJwm5ZEAamspo0ktiNJtyu-OGhOWGqgeic,284518 -pip/_vendor/certifi/core.py,sha256=EuFc2BsToG5O1-qsx4BSjQ1r1-7WRtH87b1WflZOWhI,218 -pip/_vendor/certifi/core.pyc,, -pip/_vendor/chardet/__init__.py,sha256=YsP5wQlsHJ2auF1RZJfypiSrCA7_bQiRm3ES_NI76-Y,1559 -pip/_vendor/chardet/__init__.pyc,, -pip/_vendor/chardet/big5freq.py,sha256=D_zK5GyzoVsRes0HkLJziltFQX0bKCLOrFe9_xDvO_8,31254 -pip/_vendor/chardet/big5freq.pyc,, -pip/_vendor/chardet/big5prober.py,sha256=kBxHbdetBpPe7xrlb-e990iot64g_eGSLd32lB7_h3M,1757 -pip/_vendor/chardet/big5prober.pyc,, -pip/_vendor/chardet/chardistribution.py,sha256=3woWS62KrGooKyqz4zQSnjFbJpa6V7g02daAibTwcl8,9411 -pip/_vendor/chardet/chardistribution.pyc,, -pip/_vendor/chardet/charsetgroupprober.py,sha256=6bDu8YIiRuScX4ca9Igb0U69TA2PGXXDej6Cc4_9kO4,3787 -pip/_vendor/chardet/charsetgroupprober.pyc,, -pip/_vendor/chardet/charsetprober.py,sha256=KSmwJErjypyj0bRZmC5F5eM7c8YQgLYIjZXintZNstg,5110 -pip/_vendor/chardet/charsetprober.pyc,, -pip/_vendor/chardet/cli/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 -pip/_vendor/chardet/cli/__init__.pyc,, -pip/_vendor/chardet/cli/chardetect.py,sha256=DI8dlV3FBD0c0XA_y3sQ78z754DUv1J8n34RtDjOXNw,2774 -pip/_vendor/chardet/cli/chardetect.pyc,, -pip/_vendor/chardet/codingstatemachine.py,sha256=VYp_6cyyki5sHgXDSZnXW4q1oelHc3cu9AyQTX7uug8,3590 -pip/_vendor/chardet/codingstatemachine.pyc,, -pip/_vendor/chardet/compat.py,sha256=PKTzHkSbtbHDqS9PyujMbX74q1a8mMpeQTDVsQhZMRw,1134 -pip/_vendor/chardet/compat.pyc,, -pip/_vendor/chardet/cp949prober.py,sha256=TZ434QX8zzBsnUvL_8wm4AQVTZ2ZkqEEQL_lNw9f9ow,1855 -pip/_vendor/chardet/cp949prober.pyc,, -pip/_vendor/chardet/enums.py,sha256=Aimwdb9as1dJKZaFNUH2OhWIVBVd6ZkJJ_WK5sNY8cU,1661 -pip/_vendor/chardet/enums.pyc,, -pip/_vendor/chardet/escprober.py,sha256=kkyqVg1Yw3DIOAMJ2bdlyQgUFQhuHAW8dUGskToNWSc,3950 -pip/_vendor/chardet/escprober.pyc,, -pip/_vendor/chardet/escsm.py,sha256=RuXlgNvTIDarndvllNCk5WZBIpdCxQ0kcd9EAuxUh84,10510 -pip/_vendor/chardet/escsm.pyc,, -pip/_vendor/chardet/eucjpprober.py,sha256=iD8Jdp0ISRjgjiVN7f0e8xGeQJ5GM2oeZ1dA8nbSeUw,3749 -pip/_vendor/chardet/eucjpprober.pyc,, -pip/_vendor/chardet/euckrfreq.py,sha256=-7GdmvgWez4-eO4SuXpa7tBiDi5vRXQ8WvdFAzVaSfo,13546 -pip/_vendor/chardet/euckrfreq.pyc,, -pip/_vendor/chardet/euckrprober.py,sha256=MqFMTQXxW4HbzIpZ9lKDHB3GN8SP4yiHenTmf8g_PxY,1748 -pip/_vendor/chardet/euckrprober.pyc,, -pip/_vendor/chardet/euctwfreq.py,sha256=No1WyduFOgB5VITUA7PLyC5oJRNzRyMbBxaKI1l16MA,31621 -pip/_vendor/chardet/euctwfreq.pyc,, -pip/_vendor/chardet/euctwprober.py,sha256=13p6EP4yRaxqnP4iHtxHOJ6R2zxHq1_m8hTRjzVZ95c,1747 -pip/_vendor/chardet/euctwprober.pyc,, -pip/_vendor/chardet/gb2312freq.py,sha256=JX8lsweKLmnCwmk8UHEQsLgkr_rP_kEbvivC4qPOrlc,20715 -pip/_vendor/chardet/gb2312freq.pyc,, -pip/_vendor/chardet/gb2312prober.py,sha256=gGvIWi9WhDjE-xQXHvNIyrnLvEbMAYgyUSZ65HUfylw,1754 -pip/_vendor/chardet/gb2312prober.pyc,, -pip/_vendor/chardet/hebrewprober.py,sha256=c3SZ-K7hvyzGY6JRAZxJgwJ_sUS9k0WYkvMY00YBYFo,13838 -pip/_vendor/chardet/hebrewprober.pyc,, -pip/_vendor/chardet/jisfreq.py,sha256=vpmJv2Bu0J8gnMVRPHMFefTRvo_ha1mryLig8CBwgOg,25777 -pip/_vendor/chardet/jisfreq.pyc,, -pip/_vendor/chardet/jpcntx.py,sha256=PYlNqRUQT8LM3cT5FmHGP0iiscFlTWED92MALvBungo,19643 -pip/_vendor/chardet/jpcntx.pyc,, -pip/_vendor/chardet/langbulgarianmodel.py,sha256=1HqQS9Pbtnj1xQgxitJMvw8X6kKr5OockNCZWfEQrPE,12839 -pip/_vendor/chardet/langbulgarianmodel.pyc,, -pip/_vendor/chardet/langcyrillicmodel.py,sha256=LODajvsetH87yYDDQKA2CULXUH87tI223dhfjh9Zx9c,17948 -pip/_vendor/chardet/langcyrillicmodel.pyc,, -pip/_vendor/chardet/langgreekmodel.py,sha256=8YAW7bU8YwSJap0kIJSbPMw1BEqzGjWzqcqf0WgUKAA,12688 -pip/_vendor/chardet/langgreekmodel.pyc,, -pip/_vendor/chardet/langhebrewmodel.py,sha256=JSnqmE5E62tDLTPTvLpQsg5gOMO4PbdWRvV7Avkc0HA,11345 -pip/_vendor/chardet/langhebrewmodel.pyc,, -pip/_vendor/chardet/langhungarianmodel.py,sha256=RhapYSG5l0ZaO-VV4Fan5sW0WRGQqhwBM61yx3yxyOA,12592 -pip/_vendor/chardet/langhungarianmodel.pyc,, -pip/_vendor/chardet/langthaimodel.py,sha256=8l0173Gu_W6G8mxmQOTEF4ls2YdE7FxWf3QkSxEGXJQ,11290 -pip/_vendor/chardet/langthaimodel.pyc,, -pip/_vendor/chardet/langturkishmodel.py,sha256=W22eRNJsqI6uWAfwXSKVWWnCerYqrI8dZQTm_M0lRFk,11102 -pip/_vendor/chardet/langturkishmodel.pyc,, -pip/_vendor/chardet/latin1prober.py,sha256=S2IoORhFk39FEFOlSFWtgVybRiP6h7BlLldHVclNkU8,5370 -pip/_vendor/chardet/latin1prober.pyc,, -pip/_vendor/chardet/mbcharsetprober.py,sha256=AR95eFH9vuqSfvLQZN-L5ijea25NOBCoXqw8s5O9xLQ,3413 -pip/_vendor/chardet/mbcharsetprober.pyc,, -pip/_vendor/chardet/mbcsgroupprober.py,sha256=h6TRnnYq2OxG1WdD5JOyxcdVpn7dG0q-vB8nWr5mbh4,2012 -pip/_vendor/chardet/mbcsgroupprober.pyc,, -pip/_vendor/chardet/mbcssm.py,sha256=SY32wVIF3HzcjY3BaEspy9metbNSKxIIB0RKPn7tjpI,25481 -pip/_vendor/chardet/mbcssm.pyc,, -pip/_vendor/chardet/sbcharsetprober.py,sha256=LDSpCldDCFlYwUkGkwD2oFxLlPWIWXT09akH_2PiY74,5657 -pip/_vendor/chardet/sbcharsetprober.pyc,, -pip/_vendor/chardet/sbcsgroupprober.py,sha256=1IprcCB_k1qfmnxGC6MBbxELlKqD3scW6S8YIwdeyXA,3546 -pip/_vendor/chardet/sbcsgroupprober.pyc,, -pip/_vendor/chardet/sjisprober.py,sha256=IIt-lZj0WJqK4rmUZzKZP4GJlE8KUEtFYVuY96ek5MQ,3774 -pip/_vendor/chardet/sjisprober.pyc,, -pip/_vendor/chardet/universaldetector.py,sha256=qL0174lSZE442eB21nnktT9_VcAye07laFWUeUrjttY,12485 -pip/_vendor/chardet/universaldetector.pyc,, -pip/_vendor/chardet/utf8prober.py,sha256=IdD8v3zWOsB8OLiyPi-y_fqwipRFxV9Nc1eKBLSuIEw,2766 -pip/_vendor/chardet/utf8prober.pyc,, -pip/_vendor/chardet/version.py,sha256=sp3B08mrDXB-pf3K9fqJ_zeDHOCLC8RrngQyDFap_7g,242 -pip/_vendor/chardet/version.pyc,, -pip/_vendor/colorama/__init__.py,sha256=lJdY6COz9uM_pXwuk9oLr0fp8H8q2RrUqN16GKabvq4,239 -pip/_vendor/colorama/__init__.pyc,, -pip/_vendor/colorama/ansi.py,sha256=Fi0un-QLqRm-v7o_nKiOqyC8PapBJK7DLV_q9LKtTO0,2524 -pip/_vendor/colorama/ansi.pyc,, -pip/_vendor/colorama/ansitowin32.py,sha256=u8QaqdqS_xYSfNkPM1eRJLHz6JMWPodaJaP0mxgHCDc,10462 -pip/_vendor/colorama/ansitowin32.pyc,, -pip/_vendor/colorama/initialise.py,sha256=PprovDNxMTrvoNHFcL2NZjpH2XzDc8BLxLxiErfUl4k,1915 -pip/_vendor/colorama/initialise.pyc,, -pip/_vendor/colorama/win32.py,sha256=bJ8Il9jwaBN5BJ8bmN6FoYZ1QYuMKv2j8fGrXh7TJjw,5404 -pip/_vendor/colorama/win32.pyc,, -pip/_vendor/colorama/winterm.py,sha256=2y_2b7Zsv34feAsP67mLOVc-Bgq51mdYGo571VprlrM,6438 -pip/_vendor/colorama/winterm.pyc,, -pip/_vendor/distlib/__init__.py,sha256=7uthK6m96pTekk8hjlT-MybcwYmmxwP8gEOxXVg1f2s,581 -pip/_vendor/distlib/__init__.pyc,, -pip/_vendor/distlib/_backport/__init__.py,sha256=bqS_dTOH6uW9iGgd0uzfpPjo6vZ4xpPZ7kyfZJ2vNaw,274 -pip/_vendor/distlib/_backport/__init__.pyc,, -pip/_vendor/distlib/_backport/misc.py,sha256=KWecINdbFNOxSOP1fGF680CJnaC6S4fBRgEtaYTw0ig,971 -pip/_vendor/distlib/_backport/misc.pyc,, -pip/_vendor/distlib/_backport/shutil.py,sha256=VW1t3uYqUjWZH7jV-6QiimLhnldoV5uIpH4EuiT1jfw,25647 -pip/_vendor/distlib/_backport/shutil.pyc,, -pip/_vendor/distlib/_backport/sysconfig.cfg,sha256=swZKxq9RY5e9r3PXCrlvQPMsvOdiWZBTHLEbqS8LJLU,2617 -pip/_vendor/distlib/_backport/sysconfig.py,sha256=JdJ9ztRy4Hc-b5-VS74x3nUtdEIVr_OBvMsIb8O2sjc,26964 -pip/_vendor/distlib/_backport/sysconfig.pyc,, -pip/_vendor/distlib/_backport/tarfile.py,sha256=Ihp7rXRcjbIKw8COm9wSePV9ARGXbSF9gGXAMn2Q-KU,92628 -pip/_vendor/distlib/_backport/tarfile.pyc,, -pip/_vendor/distlib/compat.py,sha256=xdNZmqFN5HwF30HjRn5M415pcC2kgXRBXn767xS8v-M,41404 -pip/_vendor/distlib/compat.pyc,, -pip/_vendor/distlib/database.py,sha256=-KJH63AJ7hqjLtGCwOTrionhKr2Vsytdwkjyo8UdEco,51029 -pip/_vendor/distlib/database.pyc,, -pip/_vendor/distlib/index.py,sha256=Dd1kIV06XIdynNpKxHMMRRIKsXuoUsG7QIzntfVtZCI,21073 -pip/_vendor/distlib/index.pyc,, -pip/_vendor/distlib/locators.py,sha256=S9G2IsZp0RnMMbXGrT-gu7892pNpy1XMlUEuUHX3OI8,51828 -pip/_vendor/distlib/locators.pyc,, -pip/_vendor/distlib/manifest.py,sha256=nQEhYmgoreaBZzyFzwYsXxJARu3fo4EkunU163U16iE,14811 -pip/_vendor/distlib/manifest.pyc,, -pip/_vendor/distlib/markers.py,sha256=6Ac3cCfFBERexiESWIOXmg-apIP8l2esafNSX3KMy-8,4387 -pip/_vendor/distlib/markers.pyc,, -pip/_vendor/distlib/metadata.py,sha256=BNCnpRfFVslyZcosr4vnE_YbkRb3TNxXtk7TrDszJdc,40172 -pip/_vendor/distlib/metadata.pyc,, -pip/_vendor/distlib/resources.py,sha256=2FGv0ZHF14KXjLIlL0R991lyQQGcewOS4mJ-5n-JVnc,10766 -pip/_vendor/distlib/resources.pyc,, -pip/_vendor/distlib/scripts.py,sha256=NYqRJ2uuEuJwr_NNLzWH0m_s_YsobDFQb6HqxuQ2Sew,16638 -pip/_vendor/distlib/scripts.pyc,, -pip/_vendor/distlib/t32.exe,sha256=ftub1bsSPUCOnBn-eCtcarKTk0N0CBEP53BumkIxWJE,92672 -pip/_vendor/distlib/t64.exe,sha256=iChOG627LWTHY8-jzSwlo9SYU5a-0JHwQu4AqDz8I68,102400 -pip/_vendor/distlib/util.py,sha256=gwKL5geJKmtR4GeIUnoMAWjsPPG3tVP_mFxw_Sx-isc,59681 -pip/_vendor/distlib/util.pyc,, -pip/_vendor/distlib/version.py,sha256=_n7F6juvQGAcn769E_SHa7fOcf5ERlEVymJ_EjPRwGw,23391 -pip/_vendor/distlib/version.pyc,, -pip/_vendor/distlib/w32.exe,sha256=NPYPpt7PIjVqABEu1CzabbDyHHkJpuw-_qZq_48H0j0,89088 -pip/_vendor/distlib/w64.exe,sha256=Yb-qr1OQEzL8KRGTk-XHUZDwMSljfQeZnVoTk-K4e7E,99328 -pip/_vendor/distlib/wheel.py,sha256=gV53KDG7BgbxsdeKjnATbP47gTEJRNylcIeE1TFin1o,39880 -pip/_vendor/distlib/wheel.pyc,, -pip/_vendor/distro.py,sha256=X2So5kjrRKyMbQJ90Xgy93HU5eFtujCzKaYNeoy1k1c,43251 -pip/_vendor/distro.pyc,, -pip/_vendor/html5lib/__init__.py,sha256=Ztrn7UvF-wIFAgRBBa0ML-Gu5AffH3BPX_INJx4SaBI,1162 -pip/_vendor/html5lib/__init__.pyc,, -pip/_vendor/html5lib/_ihatexml.py,sha256=3LBtJMlzgwM8vpQiU1TvGmEEmNH72sV0yD8yS53y07A,16705 -pip/_vendor/html5lib/_ihatexml.pyc,, -pip/_vendor/html5lib/_inputstream.py,sha256=bPUWcAfJScK4xkjQQaG_HsI2BvEVbFvI0AsodDYPQj0,32552 -pip/_vendor/html5lib/_inputstream.pyc,, -pip/_vendor/html5lib/_tokenizer.py,sha256=YAaOEBD6qc5ISq9Xt9Nif1OFgcybTTfMdwqBkZhpAq4,76580 -pip/_vendor/html5lib/_tokenizer.pyc,, -pip/_vendor/html5lib/_trie/__init__.py,sha256=8VR1bcgD2OpeS2XExpu5yBhP_Q1K-lwKbBKICBPf1kU,289 -pip/_vendor/html5lib/_trie/__init__.pyc,, -pip/_vendor/html5lib/_trie/_base.py,sha256=uJHVhzif9S0MJXgy9F98iEev5evi_rgUk5BmEbUSp8c,930 -pip/_vendor/html5lib/_trie/_base.pyc,, -pip/_vendor/html5lib/_trie/datrie.py,sha256=EQpqSfkZRuTbE-DuhW7xMdVDxdZNZ0CfmnYfHA_3zxM,1178 -pip/_vendor/html5lib/_trie/datrie.pyc,, -pip/_vendor/html5lib/_trie/py.py,sha256=wXmQLrZRf4MyWNyg0m3h81m9InhLR7GJ002mIIZh-8o,1775 -pip/_vendor/html5lib/_trie/py.pyc,, -pip/_vendor/html5lib/_utils.py,sha256=ismpASeqa2jqEPQjHUj8vReAf7yIoKnvLN5fuOw6nv0,4015 -pip/_vendor/html5lib/_utils.pyc,, -pip/_vendor/html5lib/constants.py,sha256=4lmZWLtEPRLnl8NzftOoYTJdo6jpeMtP6dqQC0g_bWQ,83518 -pip/_vendor/html5lib/constants.pyc,, -pip/_vendor/html5lib/filters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/html5lib/filters/__init__.pyc,, -pip/_vendor/html5lib/filters/alphabeticalattributes.py,sha256=lViZc2JMCclXi_5gduvmdzrRxtO5Xo9ONnbHBVCsykU,919 -pip/_vendor/html5lib/filters/alphabeticalattributes.pyc,, -pip/_vendor/html5lib/filters/base.py,sha256=z-IU9ZAYjpsVsqmVt7kuWC63jR11hDMr6CVrvuao8W0,286 -pip/_vendor/html5lib/filters/base.pyc,, -pip/_vendor/html5lib/filters/inject_meta_charset.py,sha256=egDXUEHXmAG9504xz0K6ALDgYkvUrC2q15YUVeNlVQg,2945 -pip/_vendor/html5lib/filters/inject_meta_charset.pyc,, -pip/_vendor/html5lib/filters/lint.py,sha256=jk6q56xY0ojiYfvpdP-OZSm9eTqcAdRqhCoPItemPYA,3643 -pip/_vendor/html5lib/filters/lint.pyc,, -pip/_vendor/html5lib/filters/optionaltags.py,sha256=8lWT75J0aBOHmPgfmqTHSfPpPMp01T84NKu0CRedxcE,10588 -pip/_vendor/html5lib/filters/optionaltags.pyc,, -pip/_vendor/html5lib/filters/sanitizer.py,sha256=4ON02KNjuqda1lCw5_JCUZxb0BzWR5M7ON84dtJ7dm0,26248 -pip/_vendor/html5lib/filters/sanitizer.pyc,, -pip/_vendor/html5lib/filters/whitespace.py,sha256=8eWqZxd4UC4zlFGW6iyY6f-2uuT8pOCSALc3IZt7_t4,1214 -pip/_vendor/html5lib/filters/whitespace.pyc,, -pip/_vendor/html5lib/html5parser.py,sha256=g5g2ezkusHxhi7b23vK_-d6K6BfIJRbqIQmvQ9z4EgI,118963 -pip/_vendor/html5lib/html5parser.pyc,, -pip/_vendor/html5lib/serializer.py,sha256=yfcfBHse2wDs6ojxn-kieJjLT5s1ipilQJ0gL3-rJis,15758 -pip/_vendor/html5lib/serializer.pyc,, -pip/_vendor/html5lib/treeadapters/__init__.py,sha256=A0rY5gXIe4bJOiSGRO_j_tFhngRBO8QZPzPtPw5dFzo,679 -pip/_vendor/html5lib/treeadapters/__init__.pyc,, -pip/_vendor/html5lib/treeadapters/genshi.py,sha256=CH27pAsDKmu4ZGkAUrwty7u0KauGLCZRLPMzaO3M5vo,1715 -pip/_vendor/html5lib/treeadapters/genshi.pyc,, -pip/_vendor/html5lib/treeadapters/sax.py,sha256=BKS8woQTnKiqeffHsxChUqL4q2ZR_wb5fc9MJ3zQC8s,1776 -pip/_vendor/html5lib/treeadapters/sax.pyc,, -pip/_vendor/html5lib/treebuilders/__init__.py,sha256=AysSJyvPfikCMMsTVvaxwkgDieELD5dfR8FJIAuq7hY,3592 -pip/_vendor/html5lib/treebuilders/__init__.pyc,, -pip/_vendor/html5lib/treebuilders/base.py,sha256=wQGp5yy22TNG8tJ6aREe4UUeTR7A99dEz0BXVaedWb4,14579 -pip/_vendor/html5lib/treebuilders/base.pyc,, -pip/_vendor/html5lib/treebuilders/dom.py,sha256=SY3MsijXyzdNPc8aK5IQsupBoM8J67y56DgNtGvsb9g,8835 -pip/_vendor/html5lib/treebuilders/dom.pyc,, -pip/_vendor/html5lib/treebuilders/etree.py,sha256=aqIBOGj_dFYqBURIcTegGNBhAIJOw5iFDHb4jrkYH-8,12764 -pip/_vendor/html5lib/treebuilders/etree.pyc,, -pip/_vendor/html5lib/treebuilders/etree_lxml.py,sha256=9V0dXxbJYYq-Skgb5-_OL2NkVYpjioEb4CHajo0e9yI,14122 -pip/_vendor/html5lib/treebuilders/etree_lxml.pyc,, -pip/_vendor/html5lib/treewalkers/__init__.py,sha256=yhXxHpjlSqfQyUag3v8-vWjMPriFBU8YRAPNpDgBTn8,5714 -pip/_vendor/html5lib/treewalkers/__init__.pyc,, -pip/_vendor/html5lib/treewalkers/base.py,sha256=ouiOsuSzvI0KgzdWP8PlxIaSNs9falhbiinAEc_UIJY,7476 -pip/_vendor/html5lib/treewalkers/base.pyc,, -pip/_vendor/html5lib/treewalkers/dom.py,sha256=EHyFR8D8lYNnyDU9lx_IKigVJRyecUGua0mOi7HBukc,1413 -pip/_vendor/html5lib/treewalkers/dom.pyc,, -pip/_vendor/html5lib/treewalkers/etree.py,sha256=sz1o6mmE93NQ53qJFDO7HKyDtuwgK-Ay3qSFZPC6u00,4550 -pip/_vendor/html5lib/treewalkers/etree.pyc,, -pip/_vendor/html5lib/treewalkers/etree_lxml.py,sha256=sY6wfRshWTllu6n48TPWpKsQRPp-0CQrT0hj_AdzHSU,6309 -pip/_vendor/html5lib/treewalkers/etree_lxml.pyc,, -pip/_vendor/html5lib/treewalkers/genshi.py,sha256=4D2PECZ5n3ZN3qu3jMl9yY7B81jnQApBQSVlfaIuYbA,2309 -pip/_vendor/html5lib/treewalkers/genshi.pyc,, -pip/_vendor/idna/__init__.py,sha256=9Nt7xpyet3DmOrPUGooDdAwmHZZu1qUAy2EaJ93kGiQ,58 -pip/_vendor/idna/__init__.pyc,, -pip/_vendor/idna/codec.py,sha256=lvYb7yu7PhAqFaAIAdWcwgaWI2UmgseUua-1c0AsG0A,3299 -pip/_vendor/idna/codec.pyc,, -pip/_vendor/idna/compat.py,sha256=R-h29D-6mrnJzbXxymrWUW7iZUvy-26TQwZ0ij57i4U,232 -pip/_vendor/idna/compat.pyc,, -pip/_vendor/idna/core.py,sha256=JDCZZ_PLESqIgEbU8mPyoEufWwoOiIqygA17-QZIe3s,11733 -pip/_vendor/idna/core.pyc,, -pip/_vendor/idna/idnadata.py,sha256=HXaPFw6_YAJ0qppACPu0YLAULtRs3QovRM_CCZHGdY0,40899 -pip/_vendor/idna/idnadata.pyc,, -pip/_vendor/idna/intranges.py,sha256=TY1lpxZIQWEP6tNqjZkFA5hgoMWOj1OBmnUG8ihT87E,1749 -pip/_vendor/idna/intranges.pyc,, -pip/_vendor/idna/package_data.py,sha256=kIzeKKXEouXLR4srqwf9Q3zv-NffKSOz5aSDOJARPB0,21 -pip/_vendor/idna/package_data.pyc,, -pip/_vendor/idna/uts46data.py,sha256=oLyNZ1pBaiBlj9zFzLFRd_P7J8MkRcgDisjExZR_4MY,198292 -pip/_vendor/idna/uts46data.pyc,, -pip/_vendor/ipaddress.py,sha256=2OgbkeAD2rLkcXqbcvof3J5R7lRwjNLoBySyTkBtKnc,79852 -pip/_vendor/ipaddress.pyc,, -pip/_vendor/lockfile/__init__.py,sha256=Tqpz90DwKYfhPsfzVOJl84TL87pdFE5ePNHdXAxs4Tk,9371 -pip/_vendor/lockfile/__init__.pyc,, -pip/_vendor/lockfile/linklockfile.py,sha256=C7OH3H4GdK68u4FQgp8fkP2kO4fyUTSyj3X6blgfobc,2652 -pip/_vendor/lockfile/linklockfile.pyc,, -pip/_vendor/lockfile/mkdirlockfile.py,sha256=e3qgIL-etZMLsS-3ft19iW_8IQ360HNkGOqE3yBKsUw,3096 -pip/_vendor/lockfile/mkdirlockfile.pyc,, -pip/_vendor/lockfile/pidlockfile.py,sha256=ukH9uk6NFuxyVmG5QiWw4iKq3fT7MjqUguX95avYPIY,6090 -pip/_vendor/lockfile/pidlockfile.pyc,, -pip/_vendor/lockfile/sqlitelockfile.py,sha256=o2TMkMRY0iwn-iL1XMRRIFStMUkS4i3ajceeYNntKFg,5506 -pip/_vendor/lockfile/sqlitelockfile.pyc,, -pip/_vendor/lockfile/symlinklockfile.py,sha256=ABwXXmvTHvCl5viPblShL3PG-gGsLiT1roAMfDRwhi8,2616 -pip/_vendor/lockfile/symlinklockfile.pyc,, -pip/_vendor/msgpack/__init__.py,sha256=y0bk2YbzK6J2e0J_dyreN6nD7yM2IezT6m_tU2h-Mdg,1677 -pip/_vendor/msgpack/__init__.pyc,, -pip/_vendor/msgpack/_version.py,sha256=dN7wVIjbyuQIJ35B2o6gymQNDLPlj_7-uTfgCv7KErM,20 -pip/_vendor/msgpack/_version.pyc,, -pip/_vendor/msgpack/exceptions.py,sha256=lPkAi_u12NlFajDz4FELSHEdfU8hrR3zeTvKX8aQuz4,1056 -pip/_vendor/msgpack/exceptions.pyc,, -pip/_vendor/msgpack/fallback.py,sha256=h0ll8xnq12mI9PuQ9Qd_Ihtt08Sp8L0JqhG9KY8Vyjk,36411 -pip/_vendor/msgpack/fallback.pyc,, -pip/_vendor/packaging/__about__.py,sha256=Wg0-hNgTU2_lBZcGBh5pm1R9yroQ3rv-X0rig8KjA6o,744 -pip/_vendor/packaging/__about__.pyc,, -pip/_vendor/packaging/__init__.py,sha256=6enbp5XgRfjBjsI9-bn00HjHf5TH21PDMOKkJW8xw-w,562 -pip/_vendor/packaging/__init__.pyc,, -pip/_vendor/packaging/_compat.py,sha256=Ugdm-qcneSchW25JrtMIKgUxfEEBcCAz6WrEeXeqz9o,865 -pip/_vendor/packaging/_compat.pyc,, -pip/_vendor/packaging/_structures.py,sha256=pVd90XcXRGwpZRB_qdFuVEibhCHpX_bL5zYr9-N0mc8,1416 -pip/_vendor/packaging/_structures.pyc,, -pip/_vendor/packaging/markers.py,sha256=-QjvJkhSJBxBogO9J_EpPQudHaaLV3rgVYsBDqn-ZLc,8234 -pip/_vendor/packaging/markers.pyc,, -pip/_vendor/packaging/requirements.py,sha256=grcnFU8x7KD230JaFLXtWl3VClLuOmsOy4c-m55tOWs,4700 -pip/_vendor/packaging/requirements.pyc,, -pip/_vendor/packaging/specifiers.py,sha256=0ZzQpcUnvrQ6LjR-mQRLzMr8G6hdRv-mY0VSf_amFtI,27778 -pip/_vendor/packaging/specifiers.pyc,, -pip/_vendor/packaging/utils.py,sha256=VaTC0Ei7zO2xl9ARiWmz2YFLFt89PuuhLbAlXMyAGms,1520 -pip/_vendor/packaging/utils.pyc,, -pip/_vendor/packaging/version.py,sha256=Npdwnb8OHedj_2L86yiUqscujb7w_i5gmSK1PhOAFzg,11978 -pip/_vendor/packaging/version.pyc,, -pip/_vendor/pep517/__init__.py,sha256=nOY747zTld3oTdEetBG6DWxEcZXTeOQk0aHvbR-sa5w,84 -pip/_vendor/pep517/__init__.pyc,, -pip/_vendor/pep517/_in_process.py,sha256=xMY2kLutkjCti5WqTmKOLRRL3o8Ds_k-fObFyuMv1tk,6061 -pip/_vendor/pep517/_in_process.pyc,, -pip/_vendor/pep517/build.py,sha256=-n8PT-ugS1TdqoTUY1vatDQjrLtx48K_-Quu2MuQBiA,2699 -pip/_vendor/pep517/build.pyc,, -pip/_vendor/pep517/check.py,sha256=Lu7nMdYu1JVV58fE3hv-d_avTy5h0yO9LsIzAt82Clk,5885 -pip/_vendor/pep517/check.pyc,, -pip/_vendor/pep517/colorlog.py,sha256=Tk9AuYm_cLF3BKTBoSTJt9bRryn0aFojIQOwbfVUTxQ,4098 -pip/_vendor/pep517/colorlog.pyc,, -pip/_vendor/pep517/compat.py,sha256=4SFG4QN-cNj8ebSa0wV0HUtEEQWwmbok2a0uk1gYEOM,631 -pip/_vendor/pep517/compat.pyc,, -pip/_vendor/pep517/envbuild.py,sha256=9-u4KffexPMEm52rTaIjEOxsCAd2DMByxzv5H566QLw,5763 -pip/_vendor/pep517/envbuild.pyc,, -pip/_vendor/pep517/wrappers.py,sha256=9dZn-q7F5KyQKUJMie2uKwur2FG0CLXz_kLZzkJOhZc,5912 -pip/_vendor/pep517/wrappers.pyc,, -pip/_vendor/pkg_resources/__init__.py,sha256=ZVHzk7ZiFIIgE2RTJj8F7wwjdMGrAngMWtQo-rGNsm4,107910 -pip/_vendor/pkg_resources/__init__.pyc,, -pip/_vendor/pkg_resources/py31compat.py,sha256=CRk8fkiPRDLsbi5pZcKsHI__Pbmh_94L8mr9Qy9Ab2U,562 -pip/_vendor/pkg_resources/py31compat.pyc,, -pip/_vendor/progress/__init__.py,sha256=fcbQQXo5np2CoQyhSH5XprkicwLZNLePR3uIahznSO0,4857 -pip/_vendor/progress/__init__.pyc,, -pip/_vendor/progress/bar.py,sha256=QuDuVNcmXgpxtNtxO0Fq72xKigxABaVmxYGBw4J3Z_E,2854 -pip/_vendor/progress/bar.pyc,, -pip/_vendor/progress/counter.py,sha256=MznyBrvPWrOlGe4MZAlGUb9q3aODe6_aNYeAE_VNoYA,1372 -pip/_vendor/progress/counter.pyc,, -pip/_vendor/progress/spinner.py,sha256=k8JbDW94T0-WXuXfxZIFhdoNPYp3jfnpXqBnfRv5fGs,1380 -pip/_vendor/progress/spinner.pyc,, -pip/_vendor/pyparsing.py,sha256=sxGUe_YcWBB5ZoHec0m1iJtgcj4iKv_SGfdA_zVCYII,245385 -pip/_vendor/pyparsing.pyc,, -pip/_vendor/pytoml/__init__.py,sha256=W_SKx36Hsew-Fty36BOpreLm4uF4V_Tgkm_z9rIoOE8,127 -pip/_vendor/pytoml/__init__.pyc,, -pip/_vendor/pytoml/core.py,sha256=9CrLLTs1PdWjEwRnYzt_i4dhHcZvGxs_GsMlYAX3iY4,509 -pip/_vendor/pytoml/core.pyc,, -pip/_vendor/pytoml/parser.py,sha256=2tDXkldqPQJhyadXzL2rGhVbjUyBNeXXhaEfncHl2iQ,10326 -pip/_vendor/pytoml/parser.pyc,, -pip/_vendor/pytoml/test.py,sha256=2nQs4aX3XQEaaQCx6x_OJTS2Hb0_IiTZRqNOeDmLCzo,1021 -pip/_vendor/pytoml/test.pyc,, -pip/_vendor/pytoml/utils.py,sha256=JCLHx77Hu1R3F-bRgiROIiKyCzLwyebnp5P35cRJxWs,1665 -pip/_vendor/pytoml/utils.pyc,, -pip/_vendor/pytoml/writer.py,sha256=WbNNQg3sh_V-s3kt88LkNNbxEq6pPDdhRE-daJzArcI,3198 -pip/_vendor/pytoml/writer.pyc,, -pip/_vendor/requests/__init__.py,sha256=ZI8kbaEzLAxsqex3MmMPr-v24d1RfZbNAOY8fUxg2Xw,4074 -pip/_vendor/requests/__init__.pyc,, -pip/_vendor/requests/__version__.py,sha256=8KG3anaNCi-PEclPPOHJ_cv1udY_L1_njVr84gRZ9HM,436 -pip/_vendor/requests/__version__.pyc,, -pip/_vendor/requests/_internal_utils.py,sha256=Zx3PnEUccyfsB-ie11nZVAW8qClJy0gx1qNME7rgT18,1096 -pip/_vendor/requests/_internal_utils.pyc,, -pip/_vendor/requests/adapters.py,sha256=e-bmKEApNVqFdylxuMJJfiaHdlmS_zhWhIMEzlHvGuc,21548 -pip/_vendor/requests/adapters.pyc,, -pip/_vendor/requests/api.py,sha256=hWZgfD7OriCZFOnpeq0bv2pbXDl8YXfxDwAcU036qDs,6253 -pip/_vendor/requests/api.pyc,, -pip/_vendor/requests/auth.py,sha256=QB2-cSUj1jrvWZfPXttsZpyAacQgtKLVk14vQW9TpSE,10206 -pip/_vendor/requests/auth.pyc,, -pip/_vendor/requests/certs.py,sha256=nXRVq9DtGmv_1AYbwjTu9UrgAcdJv05ZvkNeaoLOZxY,465 -pip/_vendor/requests/certs.pyc,, -pip/_vendor/requests/compat.py,sha256=FZX4Q_EMKiMnhZpZ3g_gOsT-j2ca9ij2gehDx1cwYeo,1941 -pip/_vendor/requests/compat.pyc,, -pip/_vendor/requests/cookies.py,sha256=Y-bKX6TvW3FnYlE6Au0SXtVVWcaNdFvuAwQxw-G0iTI,18430 -pip/_vendor/requests/cookies.pyc,, -pip/_vendor/requests/exceptions.py,sha256=-mLam3TAx80V09EaH3H-ZxR61eAVuLRZ8zgBBSLjK44,3197 -pip/_vendor/requests/exceptions.pyc,, -pip/_vendor/requests/help.py,sha256=SJPVcoXeo7KfK4AxJN5eFVQCjr0im87tU2n7ubLsksU,3578 -pip/_vendor/requests/help.pyc,, -pip/_vendor/requests/hooks.py,sha256=QReGyy0bRcr5rkwCuObNakbYsc7EkiKeBwG4qHekr2Q,757 -pip/_vendor/requests/hooks.pyc,, -pip/_vendor/requests/models.py,sha256=6s-37iAqXVptq8z7U_LoH_pbIPrCQUm_Z8QuIGE29Q0,34275 -pip/_vendor/requests/models.pyc,, -pip/_vendor/requests/packages.py,sha256=njJmVifY4aSctuW3PP5EFRCxjEwMRDO6J_feG2dKWsI,695 -pip/_vendor/requests/packages.pyc,, -pip/_vendor/requests/sessions.py,sha256=DjbCotDW6xSAaBsjbW-L8l4N0UcwmrxVNgSrZgIjGWM,29332 -pip/_vendor/requests/sessions.pyc,, -pip/_vendor/requests/status_codes.py,sha256=XWlcpBjbCtq9sSqpH9_KKxgnLTf9Z__wCWolq21ySlg,4129 -pip/_vendor/requests/status_codes.pyc,, -pip/_vendor/requests/structures.py,sha256=zoP8qly2Jak5e89HwpqjN1z2diztI-_gaqts1raJJBc,2981 -pip/_vendor/requests/structures.pyc,, -pip/_vendor/requests/utils.py,sha256=LtPJ1db6mJff2TJSJWKi7rBpzjPS3mSOrjC9zRhoD3A,30049 -pip/_vendor/requests/utils.pyc,, -pip/_vendor/retrying.py,sha256=k3fflf5_Mm0XcIJYhB7Tj34bqCCPhUDkYbx1NvW2FPE,9972 -pip/_vendor/retrying.pyc,, -pip/_vendor/six.py,sha256=h9jch2pS86y4R36pKRS3LOYUCVFNIJMRwjZ4fJDtJ44,32452 -pip/_vendor/six.pyc,, -pip/_vendor/urllib3/__init__.py,sha256=EZviRQA_iuL_94EeJHY4JAArRXbRCkAzA0HH9iXZ15s,2722 -pip/_vendor/urllib3/__init__.pyc,, -pip/_vendor/urllib3/_collections.py,sha256=-CAKsDE-WdubAjlBSZLx7b0e7WKenaNGwWvGLDEF1TM,10746 -pip/_vendor/urllib3/_collections.pyc,, -pip/_vendor/urllib3/connection.py,sha256=KLFvknLgllcMkgJ-zUsFjCzOt9P03fDoIpTPz_vqXCw,13839 -pip/_vendor/urllib3/connection.pyc,, -pip/_vendor/urllib3/connectionpool.py,sha256=rgc_3D0VsD5VDxr4KzzA8Plee0Rmerm5WKb71FcxWu8,35097 -pip/_vendor/urllib3/connectionpool.pyc,, -pip/_vendor/urllib3/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/urllib3/contrib/__init__.pyc,, -pip/_vendor/urllib3/contrib/_appengine_environ.py,sha256=lhYXvB5_oGKSeurX7za3XhcGyERvNjXRQ3eJp2GmQ3M,717 -pip/_vendor/urllib3/contrib/_appengine_environ.pyc,, -pip/_vendor/urllib3/contrib/_securetransport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/urllib3/contrib/_securetransport/__init__.pyc,, -pip/_vendor/urllib3/contrib/_securetransport/bindings.py,sha256=x2kLSh-ASZKsun0FxtraBuLVe3oHuth4YW6yZ5Vof-w,17560 -pip/_vendor/urllib3/contrib/_securetransport/bindings.pyc,, -pip/_vendor/urllib3/contrib/_securetransport/low_level.py,sha256=Umy5u-3Z957GirdapnicXVOpHaM4xdOZABJuJxfaeJA,12162 -pip/_vendor/urllib3/contrib/_securetransport/low_level.pyc,, -pip/_vendor/urllib3/contrib/appengine.py,sha256=VvDpkc5gf9dTXNxXmyG1mPdON_3DrYG_eW4uOqN98oQ,10938 -pip/_vendor/urllib3/contrib/appengine.pyc,, -pip/_vendor/urllib3/contrib/ntlmpool.py,sha256=5ZpMF7N9B6NEjVU-r-xjDOV_-hkNvsDoNc84J2yqauI,4459 -pip/_vendor/urllib3/contrib/ntlmpool.pyc,, -pip/_vendor/urllib3/contrib/pyopenssl.py,sha256=-kI_9y99Iwybv6Wy8IF8PugVl61BeMBEEqGwrDYNCuc,15823 -pip/_vendor/urllib3/contrib/pyopenssl.pyc,, -pip/_vendor/urllib3/contrib/securetransport.py,sha256=BqXSlChN9_hjCWgyN6JdcgvBUdc37QCCX4u3_8zE_9o,30309 -pip/_vendor/urllib3/contrib/securetransport.pyc,, -pip/_vendor/urllib3/contrib/socks.py,sha256=Iom0snbHkCuZbZ7Sle2Kueha1W0jYAJ0SyCOtePLaio,6391 -pip/_vendor/urllib3/contrib/socks.pyc,, -pip/_vendor/urllib3/exceptions.py,sha256=rFeIfBNKC8KJ61ux-MtJyJlEC9G9ggkmCeF751JwVR4,6604 -pip/_vendor/urllib3/exceptions.pyc,, -pip/_vendor/urllib3/fields.py,sha256=D_TE_SK15YatdbhWDMN0OE3X6UCJn1RTkANINCYOobE,5943 -pip/_vendor/urllib3/fields.pyc,, -pip/_vendor/urllib3/filepost.py,sha256=40CROlpRKVBpFUkD0R6wJf_PpvbcRQRFUu0OOQlFkKM,2436 -pip/_vendor/urllib3/filepost.pyc,, -pip/_vendor/urllib3/packages/__init__.py,sha256=nlChrGzkjCkmhCX9HrF_qHPUgosfsPQkVIJxiiLhk9g,109 -pip/_vendor/urllib3/packages/__init__.pyc,, -pip/_vendor/urllib3/packages/backports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/urllib3/packages/backports/__init__.pyc,, -pip/_vendor/urllib3/packages/backports/makefile.py,sha256=so2z9BiNM8kh38Ve5tomQP_mp2_ubEqzdlCpLZKzzCI,1456 -pip/_vendor/urllib3/packages/backports/makefile.pyc,, -pip/_vendor/urllib3/packages/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 -pip/_vendor/urllib3/packages/six.pyc,, -pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py,sha256=WBVbxQBojNAxfZwNavkox3BgJiMA9BJmm-_fwd0jD_o,688 -pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.pyc,, -pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py,sha256=E-9J-kAaUn76WMZ4PpzKUxM4C3yjY7mopOpbPIy3Dso,5700 -pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.pyc,, -pip/_vendor/urllib3/poolmanager.py,sha256=csE6Bh6L0FJ3iNOHk2z8KhMT8Eiq976b6pk8I6vrOC8,16853 -pip/_vendor/urllib3/poolmanager.pyc,, -pip/_vendor/urllib3/request.py,sha256=OfelFYzPnxGlU3amEz9uBLjCBOriwgJh4QC_aW9SF3U,5991 -pip/_vendor/urllib3/request.pyc,, -pip/_vendor/urllib3/response.py,sha256=ta1jp4B5PGBWzoAV1s48WLuHCRICQnK7F9m_kyK4Z8g,25609 -pip/_vendor/urllib3/response.pyc,, -pip/_vendor/urllib3/util/__init__.py,sha256=6Ran4oAVIy40Cu_oEPWnNV9bwF5rXx6G1DUZ7oehjPY,1044 -pip/_vendor/urllib3/util/__init__.pyc,, -pip/_vendor/urllib3/util/connection.py,sha256=-AyqcRTuNUHuo5ndtsU0Og_nMyCGATC-kYqOUdBHwIQ,4639 -pip/_vendor/urllib3/util/connection.pyc,, -pip/_vendor/urllib3/util/queue.py,sha256=myTX3JDHntglKQNBf3b6dasHH-uF-W59vzGSQiFdAfI,497 -pip/_vendor/urllib3/util/queue.pyc,, -pip/_vendor/urllib3/util/request.py,sha256=H5_lrHvtwl2U2BbT1UYN9HpruNc1gsNFlz2njQmhPrQ,3705 -pip/_vendor/urllib3/util/request.pyc,, -pip/_vendor/urllib3/util/response.py,sha256=028PNXDZhwBtnm2uXvnAHi_l9_AAGrAMH2Igh2AbgWg,2586 -pip/_vendor/urllib3/util/response.pyc,, -pip/_vendor/urllib3/util/retry.py,sha256=kFQTesNiwPp6ZeQo9VHeUO7b8qA-_l3BnErCAOEPo4Q,15105 -pip/_vendor/urllib3/util/retry.pyc,, -pip/_vendor/urllib3/util/ssl_.py,sha256=4qqBDM82bufhqqEd0b-99sObz95XmEVEXDVi5iAyCeE,13172 -pip/_vendor/urllib3/util/ssl_.pyc,, -pip/_vendor/urllib3/util/timeout.py,sha256=7lHNrgL5YH2cI1j-yZnzV_J8jBlRVdmFhQaNyM1_2b8,9757 -pip/_vendor/urllib3/util/timeout.pyc,, -pip/_vendor/urllib3/util/url.py,sha256=qCY_HHUXvo05wAsEERALgExtlgxLnAHSQ7ce1b-g3SM,6487 -pip/_vendor/urllib3/util/url.pyc,, -pip/_vendor/urllib3/util/wait.py,sha256=p4BZo_Ukp5JF0Dn6jro7cUfqIjnU6WFtuoA6poaV5Jk,5403 -pip/_vendor/urllib3/util/wait.pyc,, -pip/_vendor/webencodings/__init__.py,sha256=qOBJIuPy_4ByYH6W_bNgJF-qYQ2DoU-dKsDu5yRWCXg,10579 -pip/_vendor/webencodings/__init__.pyc,, -pip/_vendor/webencodings/labels.py,sha256=4AO_KxTddqGtrL9ns7kAPjb0CcN6xsCIxbK37HY9r3E,8979 -pip/_vendor/webencodings/labels.pyc,, -pip/_vendor/webencodings/mklabels.py,sha256=GYIeywnpaLnP0GSic8LFWgd0UVvO_l1Nc6YoF-87R_4,1305 -pip/_vendor/webencodings/mklabels.pyc,, -pip/_vendor/webencodings/tests.py,sha256=OtGLyjhNY1fvkW1GvLJ_FV9ZoqC9Anyjr7q3kxTbzNs,6563 -pip/_vendor/webencodings/tests.pyc,, -pip/_vendor/webencodings/x_user_defined.py,sha256=yOqWSdmpytGfUgh_Z6JYgDNhoc-BAHyyeeT15Fr42tM,4307 -pip/_vendor/webencodings/x_user_defined.pyc,, diff --git a/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/WHEEL b/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/WHEEL deleted file mode 100644 index c8240f0..0000000 --- a/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.33.1) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/entry_points.txt b/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/entry_points.txt deleted file mode 100644 index f5809cb..0000000 --- a/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/entry_points.txt +++ /dev/null @@ -1,5 +0,0 @@ -[console_scripts] -pip = pip._internal:main -pip3 = pip._internal:main -pip3.7 = pip._internal:main - diff --git a/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/top_level.txt b/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/top_level.txt deleted file mode 100644 index a1b589e..0000000 --- a/venv2/lib/python2.7/site-packages/pip-19.1.1.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv2/lib/python2.7/site-packages/pip/__init__.py b/venv2/lib/python2.7/site-packages/pip/__init__.py deleted file mode 100644 index 5d05da3..0000000 --- a/venv2/lib/python2.7/site-packages/pip/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "19.1.1" diff --git a/venv2/lib/python2.7/site-packages/pip/__main__.py b/venv2/lib/python2.7/site-packages/pip/__main__.py deleted file mode 100644 index 0c223f8..0000000 --- a/venv2/lib/python2.7/site-packages/pip/__main__.py +++ /dev/null @@ -1,19 +0,0 @@ -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 import main as _main # isort:skip # noqa - -if __name__ == '__main__': - sys.exit(_main()) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/__init__.py b/venv2/lib/python2.7/site-packages/pip/_internal/__init__.py deleted file mode 100644 index 9c1637c..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/__init__.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python -from __future__ import absolute_import - -import locale -import logging -import os -import warnings - -import sys - -# 2016-06-17 barry@debian.org: urllib3 1.14 added optional support for socks, -# but if invoked (i.e. imported), it will issue a warning to stderr if socks -# isn't available. requests unconditionally imports urllib3's socks contrib -# module, triggering this warning. The warning breaks DEP-8 tests (because of -# the stderr output) and is just plain annoying in normal usage. I don't want -# to add socks as yet another dependency for pip, nor do I want to allow-stderr -# in the DEP-8 tests, so just suppress the warning. pdb tells me this has to -# be done before the import of pip.vcs. -from pip._vendor.urllib3.exceptions import DependencyWarning -warnings.filterwarnings("ignore", category=DependencyWarning) # noqa - -# We want to inject the use of SecureTransport as early as possible so that any -# references or sessions or what have you are ensured to have it, however we -# only want to do this in the case that we're running on macOS and the linked -# OpenSSL is too old to handle TLSv1.2 -try: - import ssl -except ImportError: - pass -else: - # Checks for OpenSSL 1.0.1 on MacOS - if sys.platform == "darwin" and ssl.OPENSSL_VERSION_NUMBER < 0x1000100f: - try: - from pip._vendor.urllib3.contrib import securetransport - except (ImportError, OSError): - pass - else: - securetransport.inject_into_urllib3() - -from pip._internal.cli.autocompletion import autocomplete -from pip._internal.cli.main_parser import parse_command -from pip._internal.commands import commands_dict -from pip._internal.exceptions import PipError -from pip._internal.utils import deprecation -from pip._internal.vcs import git, mercurial, subversion, bazaar # noqa -from pip._vendor.urllib3.exceptions import InsecureRequestWarning - -logger = logging.getLogger(__name__) - -# Hide the InsecureRequestWarning from urllib3 -warnings.filterwarnings("ignore", category=InsecureRequestWarning) - - -def main(args=None): - if args is None: - args = sys.argv[1:] - - # Configure our deprecation warnings to be sent through loggers - deprecation.install_warning_logger() - - autocomplete() - - try: - cmd_name, cmd_args = parse_command(args) - except PipError as exc: - sys.stderr.write("ERROR: %s" % exc) - sys.stderr.write(os.linesep) - sys.exit(1) - - # Needed for locale.getpreferredencoding(False) to work - # in pip._internal.utils.encoding.auto_decode - try: - locale.setlocale(locale.LC_ALL, '') - except locale.Error as e: - # setlocale can apparently crash if locale are uninitialized - logger.debug("Ignoring error %s when setting locale", e) - command = commands_dict[cmd_name](isolated=("--isolated" in cmd_args)) - return command.main(cmd_args) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/build_env.py b/venv2/lib/python2.7/site-packages/pip/_internal/build_env.py deleted file mode 100644 index 89830e7..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/build_env.py +++ /dev/null @@ -1,215 +0,0 @@ -"""Build Environment used for isolation during sdist building -""" - -import logging -import os -import sys -import textwrap -from collections import OrderedDict -from distutils.sysconfig import get_python_lib -from sysconfig import get_paths - -from pip._vendor.pkg_resources import Requirement, VersionConflict, WorkingSet - -from pip import __file__ as pip_location -from pip._internal.utils.misc import call_subprocess -from pip._internal.utils.temp_dir import TempDirectory -from pip._internal.utils.typing import MYPY_CHECK_RUNNING -from pip._internal.utils.ui import open_spinner - -if MYPY_CHECK_RUNNING: - from typing import Tuple, Set, Iterable, Optional, List - from pip._internal.index import PackageFinder - -logger = logging.getLogger(__name__) - - -class _Prefix: - - def __init__(self, path): - # type: (str) -> None - self.path = path - self.setup = False - self.bin_dir = get_paths( - 'nt' if os.name == 'nt' else 'posix_prefix', - vars={'base': path, 'platbase': path} - )['scripts'] - # Note: prefer distutils' sysconfig to get the - # library paths so PyPy is correctly supported. - purelib = get_python_lib(plat_specific=False, prefix=path) - platlib = get_python_lib(plat_specific=True, prefix=path) - if purelib == platlib: - self.lib_dirs = [purelib] - else: - self.lib_dirs = [purelib, platlib] - - -class BuildEnvironment(object): - """Creates and manages an isolated environment to install build deps - """ - - def __init__(self): - # type: () -> None - self._temp_dir = TempDirectory(kind="build-env") - self._temp_dir.create() - - self._prefixes = OrderedDict(( - (name, _Prefix(os.path.join(self._temp_dir.path, name))) - for name in ('normal', 'overlay') - )) - - self._bin_dirs = [] # type: List[str] - self._lib_dirs = [] # type: List[str] - for prefix in reversed(list(self._prefixes.values())): - self._bin_dirs.append(prefix.bin_dir) - self._lib_dirs.extend(prefix.lib_dirs) - - # Customize site to: - # - ensure .pth files are honored - # - prevent access to system site packages - system_sites = { - os.path.normcase(site) for site in ( - get_python_lib(plat_specific=False), - get_python_lib(plat_specific=True), - ) - } - self._site_dir = os.path.join(self._temp_dir.path, 'site') - if not os.path.exists(self._site_dir): - os.mkdir(self._site_dir) - with open(os.path.join(self._site_dir, 'sitecustomize.py'), 'w') as fp: - fp.write(textwrap.dedent( - ''' - import os, site, sys - - # First, drop system-sites related paths. - original_sys_path = sys.path[:] - known_paths = set() - for path in {system_sites!r}: - site.addsitedir(path, known_paths=known_paths) - system_paths = set( - os.path.normcase(path) - for path in sys.path[len(original_sys_path):] - ) - original_sys_path = [ - path for path in original_sys_path - if os.path.normcase(path) not in system_paths - ] - sys.path = original_sys_path - - # Second, add lib directories. - # ensuring .pth file are processed. - for path in {lib_dirs!r}: - assert not path in sys.path - site.addsitedir(path) - ''' - ).format(system_sites=system_sites, lib_dirs=self._lib_dirs)) - - def __enter__(self): - self._save_env = { - name: os.environ.get(name, None) - for name in ('PATH', 'PYTHONNOUSERSITE', 'PYTHONPATH') - } - - path = self._bin_dirs[:] - old_path = self._save_env['PATH'] - if old_path: - path.extend(old_path.split(os.pathsep)) - - pythonpath = [self._site_dir] - - os.environ.update({ - 'PATH': os.pathsep.join(path), - 'PYTHONNOUSERSITE': '1', - 'PYTHONPATH': os.pathsep.join(pythonpath), - }) - - def __exit__(self, exc_type, exc_val, exc_tb): - for varname, old_value in self._save_env.items(): - if old_value is None: - os.environ.pop(varname, None) - else: - os.environ[varname] = old_value - - def cleanup(self): - # type: () -> None - self._temp_dir.cleanup() - - def check_requirements(self, reqs): - # type: (Iterable[str]) -> Tuple[Set[Tuple[str, str]], Set[str]] - """Return 2 sets: - - conflicting requirements: set of (installed, wanted) reqs tuples - - missing requirements: set of reqs - """ - missing = set() - conflicting = set() - if reqs: - ws = WorkingSet(self._lib_dirs) - for req in reqs: - try: - if ws.find(Requirement.parse(req)) is None: - missing.add(req) - except VersionConflict as e: - conflicting.add((str(e.args[0].as_requirement()), - str(e.args[1]))) - return conflicting, missing - - def install_requirements( - self, - finder, # type: PackageFinder - requirements, # type: Iterable[str] - prefix_as_string, # type: str - message # type: Optional[str] - ): - # type: (...) -> None - prefix = self._prefixes[prefix_as_string] - assert not prefix.setup - prefix.setup = True - if not requirements: - return - args = [ - sys.executable, os.path.dirname(pip_location), 'install', - '--ignore-installed', '--no-user', '--prefix', prefix.path, - '--no-warn-script-location', - ] # type: List[str] - if logger.getEffectiveLevel() <= logging.DEBUG: - args.append('-v') - for format_control in ('no_binary', 'only_binary'): - formats = getattr(finder.format_control, format_control) - args.extend(('--' + format_control.replace('_', '-'), - ','.join(sorted(formats or {':none:'})))) - if finder.index_urls: - args.extend(['-i', finder.index_urls[0]]) - for extra_index in finder.index_urls[1:]: - args.extend(['--extra-index-url', extra_index]) - else: - args.append('--no-index') - for link in finder.find_links: - args.extend(['--find-links', link]) - for _, host, _ in finder.secure_origins: - args.extend(['--trusted-host', host]) - if finder.allow_all_prereleases: - args.append('--pre') - args.append('--') - args.extend(requirements) - with open_spinner(message) as spinner: - call_subprocess(args, spinner=spinner) - - -class NoOpBuildEnvironment(BuildEnvironment): - """A no-op drop-in replacement for BuildEnvironment - """ - - def __init__(self): - pass - - def __enter__(self): - pass - - def __exit__(self, exc_type, exc_val, exc_tb): - pass - - def cleanup(self): - pass - - def install_requirements(self, finder, requirements, prefix, message): - raise NotImplementedError() diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/cache.py b/venv2/lib/python2.7/site-packages/pip/_internal/cache.py deleted file mode 100644 index 9379343..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/cache.py +++ /dev/null @@ -1,224 +0,0 @@ -"""Cache Management -""" - -import errno -import hashlib -import logging -import os - -from pip._vendor.packaging.utils import canonicalize_name - -from pip._internal.download import path_to_url -from pip._internal.models.link import Link -from pip._internal.utils.compat import expanduser -from pip._internal.utils.temp_dir import TempDirectory -from pip._internal.utils.typing import MYPY_CHECK_RUNNING -from pip._internal.wheel import InvalidWheelFilename, Wheel - -if MYPY_CHECK_RUNNING: - from typing import Optional, Set, List, Any - from pip._internal.index import FormatControl - -logger = logging.getLogger(__name__) - - -class Cache(object): - """An abstract class - provides cache directories for data from links - - - :param cache_dir: The root of the cache. - :param format_control: An object of FormatControl class to limit - binaries being read from the cache. - :param allowed_formats: which formats of files the cache should store. - ('binary' and 'source' are the only allowed values) - """ - - def __init__(self, cache_dir, format_control, allowed_formats): - # type: (str, FormatControl, Set[str]) -> None - super(Cache, self).__init__() - self.cache_dir = expanduser(cache_dir) if cache_dir else None - self.format_control = format_control - self.allowed_formats = allowed_formats - - _valid_formats = {"source", "binary"} - assert self.allowed_formats.union(_valid_formats) == _valid_formats - - def _get_cache_path_parts(self, link): - # type: (Link) -> List[str] - """Get parts of part that must be os.path.joined with cache_dir - """ - - # We want to generate an url to use as our cache key, we don't want to - # just re-use the URL because it might have other items in the fragment - # and we don't care about those. - key_parts = [link.url_without_fragment] - if link.hash_name is not None and link.hash is not None: - key_parts.append("=".join([link.hash_name, link.hash])) - key_url = "#".join(key_parts) - - # Encode our key url with sha224, we'll use this because it has similar - # security properties to sha256, but with a shorter total output (and - # thus less secure). However the differences don't make a lot of - # difference for our use case here. - hashed = hashlib.sha224(key_url.encode()).hexdigest() - - # We want to nest the directories some to prevent having a ton of top - # level directories where we might run out of sub directories on some - # FS. - parts = [hashed[:2], hashed[2:4], hashed[4:6], hashed[6:]] - - return parts - - def _get_candidates(self, link, package_name): - # type: (Link, Optional[str]) -> List[Any] - can_not_cache = ( - not self.cache_dir or - not package_name or - not link - ) - if can_not_cache: - return [] - - canonical_name = canonicalize_name(package_name) - formats = self.format_control.get_allowed_formats( - canonical_name - ) - if not self.allowed_formats.intersection(formats): - return [] - - root = self.get_path_for_link(link) - try: - return os.listdir(root) - except OSError as err: - if err.errno in {errno.ENOENT, errno.ENOTDIR}: - return [] - raise - - def get_path_for_link(self, link): - # type: (Link) -> str - """Return a directory to store cached items in for link. - """ - raise NotImplementedError() - - def get(self, link, package_name): - # type: (Link, Optional[str]) -> Link - """Returns a link to a cached item if it exists, otherwise returns the - passed link. - """ - raise NotImplementedError() - - def _link_for_candidate(self, link, candidate): - # type: (Link, str) -> Link - root = self.get_path_for_link(link) - path = os.path.join(root, candidate) - - return Link(path_to_url(path)) - - def cleanup(self): - # type: () -> None - pass - - -class SimpleWheelCache(Cache): - """A cache of wheels for future installs. - """ - - def __init__(self, cache_dir, format_control): - # type: (str, FormatControl) -> None - super(SimpleWheelCache, self).__init__( - cache_dir, format_control, {"binary"} - ) - - def get_path_for_link(self, link): - # type: (Link) -> str - """Return a directory to store cached wheels for link - - Because there are M wheels for any one sdist, we provide a directory - to cache them in, and then consult that directory when looking up - cache hits. - - We only insert things into the cache if they have plausible version - numbers, so that we don't contaminate the cache with things that were - not unique. E.g. ./package might have dozens of installs done for it - and build a version of 0.0...and if we built and cached a wheel, we'd - end up using the same wheel even if the source has been edited. - - :param link: The link of the sdist for which this will cache wheels. - """ - parts = self._get_cache_path_parts(link) - - # Store wheels within the root cache_dir - return os.path.join(self.cache_dir, "wheels", *parts) - - def get(self, link, package_name): - # type: (Link, Optional[str]) -> Link - candidates = [] - - for wheel_name in self._get_candidates(link, package_name): - try: - wheel = Wheel(wheel_name) - except InvalidWheelFilename: - continue - if not wheel.supported(): - # Built for a different python/arch/etc - continue - candidates.append((wheel.support_index_min(), wheel_name)) - - if not candidates: - return link - - return self._link_for_candidate(link, min(candidates)[1]) - - -class EphemWheelCache(SimpleWheelCache): - """A SimpleWheelCache that creates it's own temporary cache directory - """ - - def __init__(self, format_control): - # type: (FormatControl) -> None - self._temp_dir = TempDirectory(kind="ephem-wheel-cache") - self._temp_dir.create() - - super(EphemWheelCache, self).__init__( - self._temp_dir.path, format_control - ) - - def cleanup(self): - # type: () -> None - self._temp_dir.cleanup() - - -class WheelCache(Cache): - """Wraps EphemWheelCache and SimpleWheelCache into a single Cache - - This Cache allows for gracefully degradation, using the ephem wheel cache - when a certain link is not found in the simple wheel cache first. - """ - - def __init__(self, cache_dir, format_control): - # type: (str, FormatControl) -> None - super(WheelCache, self).__init__( - cache_dir, format_control, {'binary'} - ) - self._wheel_cache = SimpleWheelCache(cache_dir, format_control) - self._ephem_cache = EphemWheelCache(format_control) - - def get_path_for_link(self, link): - # type: (Link) -> str - return self._wheel_cache.get_path_for_link(link) - - def get_ephem_path_for_link(self, link): - # type: (Link) -> str - return self._ephem_cache.get_path_for_link(link) - - def get(self, link, package_name): - # type: (Link, Optional[str]) -> Link - retval = self._wheel_cache.get(link, package_name) - if retval is link: - retval = self._ephem_cache.get(link, package_name) - return retval - - def cleanup(self): - # type: () -> None - self._wheel_cache.cleanup() - self._ephem_cache.cleanup() diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/cli/__init__.py b/venv2/lib/python2.7/site-packages/pip/_internal/cli/__init__.py deleted file mode 100644 index e589bb9..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/cli/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -"""Subpackage containing all of pip's command line interface related code -""" - -# This file intentionally does not import submodules diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/cli/autocompletion.py b/venv2/lib/python2.7/site-packages/pip/_internal/cli/autocompletion.py deleted file mode 100644 index 0a04199..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/cli/autocompletion.py +++ /dev/null @@ -1,152 +0,0 @@ -"""Logic that powers autocompletion installed by ``pip completion``. -""" - -import optparse -import os -import sys - -from pip._internal.cli.main_parser import create_main_parser -from pip._internal.commands import commands_dict, get_summaries -from pip._internal.utils.misc import get_installed_distributions - - -def autocomplete(): - """Entry Point for completion of main and subcommand options. - """ - # Don't complete if user hasn't sourced bash_completion file. - if 'PIP_AUTO_COMPLETE' not in os.environ: - return - cwords = os.environ['COMP_WORDS'].split()[1:] - cword = int(os.environ['COMP_CWORD']) - try: - current = cwords[cword - 1] - except IndexError: - current = '' - - subcommands = [cmd for cmd, summary in get_summaries()] - options = [] - # subcommand - try: - subcommand_name = [w for w in cwords if w in subcommands][0] - except IndexError: - subcommand_name = None - - parser = create_main_parser() - # subcommand options - if subcommand_name: - # special case: 'help' subcommand has no options - if subcommand_name == 'help': - sys.exit(1) - # special case: list locally installed dists for show and uninstall - should_list_installed = ( - subcommand_name in ['show', 'uninstall'] and - not current.startswith('-') - ) - if should_list_installed: - installed = [] - lc = current.lower() - for dist in get_installed_distributions(local_only=True): - if dist.key.startswith(lc) and dist.key not in cwords[1:]: - installed.append(dist.key) - # if there are no dists installed, fall back to option completion - if installed: - for dist in installed: - print(dist) - sys.exit(1) - - subcommand = commands_dict[subcommand_name]() - - for opt in subcommand.parser.option_list_all: - if opt.help != optparse.SUPPRESS_HELP: - for opt_str in opt._long_opts + opt._short_opts: - options.append((opt_str, opt.nargs)) - - # filter out previously specified options from available options - prev_opts = [x.split('=')[0] for x in cwords[1:cword - 1]] - options = [(x, v) for (x, v) in options if x not in prev_opts] - # filter options by current input - options = [(k, v) for k, v in options if k.startswith(current)] - # get completion type given cwords and available subcommand options - completion_type = get_path_completion_type( - cwords, cword, subcommand.parser.option_list_all, - ) - # get completion files and directories if ``completion_type`` is - # ````, ```` or ```` - if completion_type: - options = auto_complete_paths(current, completion_type) - options = ((opt, 0) for opt in options) - for option in options: - opt_label = option[0] - # append '=' to options which require args - if option[1] and option[0][:2] == "--": - opt_label += '=' - print(opt_label) - else: - # show main parser options only when necessary - - opts = [i.option_list for i in parser.option_groups] - opts.append(parser.option_list) - opts = (o for it in opts for o in it) - if current.startswith('-'): - for opt in opts: - if opt.help != optparse.SUPPRESS_HELP: - subcommands += opt._long_opts + opt._short_opts - else: - # get completion type given cwords and all available options - completion_type = get_path_completion_type(cwords, cword, opts) - if completion_type: - subcommands = auto_complete_paths(current, completion_type) - - print(' '.join([x for x in subcommands if x.startswith(current)])) - sys.exit(1) - - -def get_path_completion_type(cwords, cword, opts): - """Get the type of path completion (``file``, ``dir``, ``path`` or None) - - :param cwords: same as the environmental variable ``COMP_WORDS`` - :param cword: same as the environmental variable ``COMP_CWORD`` - :param opts: The available options to check - :return: path completion type (``file``, ``dir``, ``path`` or None) - """ - if cword < 2 or not cwords[cword - 2].startswith('-'): - return - for opt in opts: - if opt.help == optparse.SUPPRESS_HELP: - continue - for o in str(opt).split('/'): - if cwords[cword - 2].split('=')[0] == o: - if not opt.metavar or any( - x in ('path', 'file', 'dir') - for x in opt.metavar.split('/')): - return opt.metavar - - -def auto_complete_paths(current, completion_type): - """If ``completion_type`` is ``file`` or ``path``, list all regular files - and directories starting with ``current``; otherwise only list directories - starting with ``current``. - - :param current: The word to be completed - :param completion_type: path completion type(`file`, `path` or `dir`)i - :return: A generator of regular files and/or directories - """ - directory, filename = os.path.split(current) - current_path = os.path.abspath(directory) - # Don't complete paths if they can't be accessed - if not os.access(current_path, os.R_OK): - return - filename = os.path.normcase(filename) - # list all files that start with ``filename`` - file_list = (x for x in os.listdir(current_path) - if os.path.normcase(x).startswith(filename)) - for f in file_list: - opt = os.path.join(current_path, f) - comp_file = os.path.normcase(os.path.join(directory, f)) - # complete regular files when there is not ```` after option - # complete directories when there is ````, ```` or - # ````after option - if completion_type != 'dir' and os.path.isfile(opt): - yield comp_file - elif os.path.isdir(opt): - yield os.path.join(comp_file, '') diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/cli/base_command.py b/venv2/lib/python2.7/site-packages/pip/_internal/cli/base_command.py deleted file mode 100644 index f6108c9..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/cli/base_command.py +++ /dev/null @@ -1,340 +0,0 @@ -"""Base Command class, and related routines""" -from __future__ import absolute_import, print_function - -import logging -import logging.config -import optparse -import os -import platform -import sys -import traceback - -from pip._internal.cli import cmdoptions -from pip._internal.cli.parser import ( - ConfigOptionParser, UpdatingDefaultsHelpFormatter, -) -from pip._internal.cli.status_codes import ( - ERROR, PREVIOUS_BUILD_DIR_ERROR, SUCCESS, UNKNOWN_ERROR, - VIRTUALENV_NOT_FOUND, -) -from pip._internal.download import PipSession -from pip._internal.exceptions import ( - BadCommand, CommandError, InstallationError, PreviousBuildDirError, - UninstallationError, -) -from pip._internal.index import PackageFinder -from pip._internal.locations import running_under_virtualenv -from pip._internal.req.constructors import ( - install_req_from_editable, install_req_from_line, -) -from pip._internal.req.req_file import parse_requirements -from pip._internal.utils.deprecation import deprecated -from pip._internal.utils.logging import BrokenStdoutLoggingError, setup_logging -from pip._internal.utils.misc import ( - get_prog, normalize_path, redact_password_from_url, -) -from pip._internal.utils.outdated import pip_version_check -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import Optional, List, Tuple, Any - from optparse import Values - from pip._internal.cache import WheelCache - from pip._internal.req.req_set import RequirementSet - -__all__ = ['Command'] - -logger = logging.getLogger(__name__) - - -class Command(object): - name = None # type: Optional[str] - usage = None # type: Optional[str] - ignore_require_venv = False # type: bool - - def __init__(self, isolated=False): - # type: (bool) -> None - parser_kw = { - 'usage': self.usage, - 'prog': '%s %s' % (get_prog(), self.name), - 'formatter': UpdatingDefaultsHelpFormatter(), - 'add_help_option': False, - 'name': self.name, - 'description': self.__doc__, - 'isolated': isolated, - } - - self.parser = ConfigOptionParser(**parser_kw) - - # Commands should add options to this option group - optgroup_name = '%s Options' % self.name.capitalize() - self.cmd_opts = optparse.OptionGroup(self.parser, optgroup_name) - - # Add the general options - gen_opts = cmdoptions.make_option_group( - cmdoptions.general_group, - self.parser, - ) - self.parser.add_option_group(gen_opts) - - def run(self, options, args): - # type: (Values, List[Any]) -> Any - raise NotImplementedError - - def _build_session(self, options, retries=None, timeout=None): - # type: (Values, Optional[int], Optional[int]) -> PipSession - session = PipSession( - cache=( - normalize_path(os.path.join(options.cache_dir, "http")) - if options.cache_dir else None - ), - retries=retries if retries is not None else options.retries, - insecure_hosts=options.trusted_hosts, - ) - - # Handle custom ca-bundles from the user - if options.cert: - session.verify = options.cert - - # Handle SSL client certificate - if options.client_cert: - session.cert = options.client_cert - - # Handle timeouts - if options.timeout or timeout: - session.timeout = ( - timeout if timeout is not None else options.timeout - ) - - # Handle configured proxies - if options.proxy: - session.proxies = { - "http": options.proxy, - "https": options.proxy, - } - - # Determine if we can prompt the user for authentication or not - session.auth.prompting = not options.no_input - - return session - - def parse_args(self, args): - # type: (List[str]) -> Tuple - # factored out for testability - return self.parser.parse_args(args) - - def main(self, args): - # type: (List[str]) -> int - options, args = self.parse_args(args) - - # Set verbosity so that it can be used elsewhere. - self.verbosity = options.verbose - options.quiet - - level_number = setup_logging( - verbosity=self.verbosity, - no_color=options.no_color, - user_log_file=options.log, - ) - - if sys.version_info[:2] == (3, 4): - deprecated( - "Python 3.4 support has been deprecated. pip 19.1 will be the " - "last one supporting it. Please upgrade your Python as Python " - "3.4 won't be maintained after March 2019 (cf PEP 429).", - replacement=None, - gone_in='19.2', - ) - elif sys.version_info[:2] == (2, 7): - message = ( - "A future version of pip will drop support for Python 2.7." - ) - if platform.python_implementation() == "CPython": - message = ( - "Python 2.7 will reach the end of its life on January " - "1st, 2020. Please upgrade your Python as Python 2.7 " - "won't be maintained after that date. " - ) + message - deprecated(message, replacement=None, gone_in=None) - - # TODO: Try to get these passing down from the command? - # without resorting to os.environ to hold these. - # This also affects isolated builds and it should. - - if options.no_input: - os.environ['PIP_NO_INPUT'] = '1' - - if options.exists_action: - os.environ['PIP_EXISTS_ACTION'] = ' '.join(options.exists_action) - - if options.require_venv and not self.ignore_require_venv: - # If a venv is required check if it can really be found - if not running_under_virtualenv(): - logger.critical( - 'Could not find an activated virtualenv (required).' - ) - sys.exit(VIRTUALENV_NOT_FOUND) - - try: - status = self.run(options, args) - # FIXME: all commands should return an exit status - # and when it is done, isinstance is not needed anymore - if isinstance(status, int): - return status - except PreviousBuildDirError as exc: - logger.critical(str(exc)) - logger.debug('Exception information:', exc_info=True) - - return PREVIOUS_BUILD_DIR_ERROR - except (InstallationError, UninstallationError, BadCommand) as exc: - logger.critical(str(exc)) - logger.debug('Exception information:', exc_info=True) - - return ERROR - except CommandError as exc: - logger.critical('%s', exc) - logger.debug('Exception information:', exc_info=True) - - return ERROR - except BrokenStdoutLoggingError: - # Bypass our logger and write any remaining messages to stderr - # because stdout no longer works. - print('ERROR: Pipe to stdout was broken', file=sys.stderr) - if level_number <= logging.DEBUG: - traceback.print_exc(file=sys.stderr) - - return ERROR - except KeyboardInterrupt: - logger.critical('Operation cancelled by user') - logger.debug('Exception information:', exc_info=True) - - return ERROR - except BaseException: - logger.critical('Exception:', exc_info=True) - - return UNKNOWN_ERROR - finally: - allow_version_check = ( - # Does this command have the index_group options? - hasattr(options, "no_index") and - # Is this command allowed to perform this check? - not (options.disable_pip_version_check or options.no_index) - ) - # Check if we're using the latest version of pip available - if allow_version_check: - session = self._build_session( - options, - retries=0, - timeout=min(5, options.timeout) - ) - with session: - pip_version_check(session, options) - - # Shutdown the logging module - logging.shutdown() - - return SUCCESS - - -class RequirementCommand(Command): - - @staticmethod - def populate_requirement_set(requirement_set, # type: RequirementSet - args, # type: List[str] - options, # type: Values - finder, # type: PackageFinder - session, # type: PipSession - name, # type: str - wheel_cache # type: Optional[WheelCache] - ): - # type: (...) -> None - """ - Marshal cmd line args into a requirement set. - """ - # NOTE: As a side-effect, options.require_hashes and - # requirement_set.require_hashes may be updated - - for filename in options.constraints: - for req_to_add in parse_requirements( - filename, - constraint=True, finder=finder, options=options, - session=session, wheel_cache=wheel_cache): - req_to_add.is_direct = True - requirement_set.add_requirement(req_to_add) - - for req in args: - req_to_add = install_req_from_line( - req, None, isolated=options.isolated_mode, - use_pep517=options.use_pep517, - wheel_cache=wheel_cache - ) - req_to_add.is_direct = True - requirement_set.add_requirement(req_to_add) - - for req in options.editables: - req_to_add = install_req_from_editable( - req, - isolated=options.isolated_mode, - use_pep517=options.use_pep517, - wheel_cache=wheel_cache - ) - req_to_add.is_direct = True - requirement_set.add_requirement(req_to_add) - - for filename in options.requirements: - for req_to_add in parse_requirements( - filename, - finder=finder, options=options, session=session, - wheel_cache=wheel_cache, - use_pep517=options.use_pep517): - req_to_add.is_direct = True - requirement_set.add_requirement(req_to_add) - # If --require-hashes was a line in a requirements file, tell - # RequirementSet about it: - requirement_set.require_hashes = options.require_hashes - - if not (args or options.editables or options.requirements): - opts = {'name': name} - if options.find_links: - raise CommandError( - 'You must give at least one requirement to %(name)s ' - '(maybe you meant "pip %(name)s %(links)s"?)' % - dict(opts, links=' '.join(options.find_links))) - else: - raise CommandError( - 'You must give at least one requirement to %(name)s ' - '(see "pip help %(name)s")' % opts) - - def _build_package_finder( - self, - options, # type: Values - session, # type: PipSession - platform=None, # type: Optional[str] - python_versions=None, # type: Optional[List[str]] - abi=None, # type: Optional[str] - implementation=None # type: Optional[str] - ): - # type: (...) -> PackageFinder - """ - Create a package finder appropriate to this requirement command. - """ - index_urls = [options.index_url] + options.extra_index_urls - if options.no_index: - logger.debug( - 'Ignoring indexes: %s', - ','.join(redact_password_from_url(url) for url in index_urls), - ) - index_urls = [] - - return PackageFinder( - find_links=options.find_links, - format_control=options.format_control, - index_urls=index_urls, - trusted_hosts=options.trusted_hosts, - allow_all_prereleases=options.pre, - session=session, - platform=platform, - versions=python_versions, - abi=abi, - implementation=implementation, - prefer_binary=options.prefer_binary, - ) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/cli/cmdoptions.py b/venv2/lib/python2.7/site-packages/pip/_internal/cli/cmdoptions.py deleted file mode 100644 index a09e38f..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/cli/cmdoptions.py +++ /dev/null @@ -1,809 +0,0 @@ -""" -shared options and groups - -The principle here is to define options once, but *not* instantiate them -globally. One reason being that options with action='append' can carry state -between parses. pip parses general options twice internally, and shouldn't -pass on state. To be consistent, all options will follow this design. - -""" -from __future__ import absolute_import - -import textwrap -import warnings -from distutils.util import strtobool -from functools import partial -from optparse import SUPPRESS_HELP, Option, OptionGroup - -from pip._internal.exceptions import CommandError -from pip._internal.locations import USER_CACHE_DIR, src_prefix -from pip._internal.models.format_control import FormatControl -from pip._internal.models.index import PyPI -from pip._internal.utils.hashes import STRONG_HASHES -from pip._internal.utils.typing import MYPY_CHECK_RUNNING -from pip._internal.utils.ui import BAR_TYPES - -if MYPY_CHECK_RUNNING: - from typing import Any, Callable, Dict, Optional - from optparse import OptionParser, Values - from pip._internal.cli.parser import ConfigOptionParser - - -def raise_option_error(parser, option, msg): - """ - Raise an option parsing error using parser.error(). - - Args: - parser: an OptionParser instance. - option: an Option instance. - msg: the error text. - """ - msg = '{} error: {}'.format(option, msg) - msg = textwrap.fill(' '.join(msg.split())) - parser.error(msg) - - -def make_option_group(group, parser): - # type: (Dict[str, Any], ConfigOptionParser) -> OptionGroup - """ - Return an OptionGroup object - group -- assumed to be dict with 'name' and 'options' keys - parser -- an optparse Parser - """ - option_group = OptionGroup(parser, group['name']) - for option in group['options']: - option_group.add_option(option()) - return option_group - - -def check_install_build_global(options, check_options=None): - # type: (Values, Optional[Values]) -> None - """Disable wheels if per-setup.py call options are set. - - :param options: The OptionParser options to update. - :param check_options: The options to check, if not supplied defaults to - options. - """ - if check_options is None: - check_options = options - - def getname(n): - return getattr(check_options, n, None) - names = ["build_options", "global_options", "install_options"] - if any(map(getname, names)): - control = options.format_control - control.disallow_binaries() - warnings.warn( - 'Disabling all use of wheels due to the use of --build-options ' - '/ --global-options / --install-options.', stacklevel=2, - ) - - -def check_dist_restriction(options, check_target=False): - # type: (Values, bool) -> None - """Function for determining if custom platform options are allowed. - - :param options: The OptionParser options. - :param check_target: Whether or not to check if --target is being used. - """ - dist_restriction_set = any([ - options.python_version, - options.platform, - options.abi, - options.implementation, - ]) - - binary_only = FormatControl(set(), {':all:'}) - sdist_dependencies_allowed = ( - options.format_control != binary_only and - not options.ignore_dependencies - ) - - # Installations or downloads using dist restrictions must not combine - # source distributions and dist-specific wheels, as they are not - # guaranteed to be locally compatible. - if dist_restriction_set and sdist_dependencies_allowed: - raise CommandError( - "When restricting platform and interpreter constraints using " - "--python-version, --platform, --abi, or --implementation, " - "either --no-deps must be set, or --only-binary=:all: must be " - "set and --no-binary must not be set (or must be set to " - ":none:)." - ) - - if check_target: - if dist_restriction_set and not options.target_dir: - raise CommandError( - "Can not use any platform or abi specific options unless " - "installing via '--target'" - ) - - -########### -# options # -########### - -help_ = partial( - Option, - '-h', '--help', - dest='help', - action='help', - help='Show help.', -) # type: Callable[..., Option] - -isolated_mode = partial( - Option, - "--isolated", - dest="isolated_mode", - action="store_true", - default=False, - help=( - "Run pip in an isolated mode, ignoring environment variables and user " - "configuration." - ), -) # type: Callable[..., Option] - -require_virtualenv = partial( - Option, - # Run only if inside a virtualenv, bail if not. - '--require-virtualenv', '--require-venv', - dest='require_venv', - action='store_true', - default=False, - help=SUPPRESS_HELP -) # type: Callable[..., Option] - -verbose = partial( - Option, - '-v', '--verbose', - dest='verbose', - action='count', - default=0, - help='Give more output. Option is additive, and can be used up to 3 times.' -) # type: Callable[..., Option] - -no_color = partial( - Option, - '--no-color', - dest='no_color', - action='store_true', - default=False, - help="Suppress colored output", -) # type: Callable[..., Option] - -version = partial( - Option, - '-V', '--version', - dest='version', - action='store_true', - help='Show version and exit.', -) # type: Callable[..., Option] - -quiet = partial( - Option, - '-q', '--quiet', - dest='quiet', - action='count', - default=0, - help=( - 'Give less output. Option is additive, and can be used up to 3' - ' times (corresponding to WARNING, ERROR, and CRITICAL logging' - ' levels).' - ), -) # type: Callable[..., Option] - -progress_bar = partial( - Option, - '--progress-bar', - dest='progress_bar', - type='choice', - choices=list(BAR_TYPES.keys()), - default='on', - help=( - 'Specify type of progress to be displayed [' + - '|'.join(BAR_TYPES.keys()) + '] (default: %default)' - ), -) # type: Callable[..., Option] - -log = partial( - Option, - "--log", "--log-file", "--local-log", - dest="log", - metavar="path", - help="Path to a verbose appending log." -) # type: Callable[..., Option] - -no_input = partial( - Option, - # Don't ask for input - '--no-input', - dest='no_input', - action='store_true', - default=False, - help=SUPPRESS_HELP -) # type: Callable[..., Option] - -proxy = partial( - Option, - '--proxy', - dest='proxy', - type='str', - default='', - help="Specify a proxy in the form [user:passwd@]proxy.server:port." -) # type: Callable[..., Option] - -retries = partial( - Option, - '--retries', - dest='retries', - type='int', - default=5, - help="Maximum number of retries each connection should attempt " - "(default %default times).", -) # type: Callable[..., Option] - -timeout = partial( - Option, - '--timeout', '--default-timeout', - metavar='sec', - dest='timeout', - type='float', - default=15, - help='Set the socket timeout (default %default seconds).', -) # type: Callable[..., Option] - -skip_requirements_regex = partial( - Option, - # A regex to be used to skip requirements - '--skip-requirements-regex', - dest='skip_requirements_regex', - type='str', - default='', - help=SUPPRESS_HELP, -) # type: Callable[..., Option] - - -def exists_action(): - # type: () -> Option - return Option( - # Option when path already exist - '--exists-action', - dest='exists_action', - type='choice', - choices=['s', 'i', 'w', 'b', 'a'], - default=[], - action='append', - metavar='action', - help="Default action when a path already exists: " - "(s)witch, (i)gnore, (w)ipe, (b)ackup, (a)bort.", - ) - - -cert = partial( - Option, - '--cert', - dest='cert', - type='str', - metavar='path', - help="Path to alternate CA bundle.", -) # type: Callable[..., Option] - -client_cert = partial( - Option, - '--client-cert', - dest='client_cert', - type='str', - default=None, - metavar='path', - help="Path to SSL client certificate, a single file containing the " - "private key and the certificate in PEM format.", -) # type: Callable[..., Option] - -index_url = partial( - Option, - '-i', '--index-url', '--pypi-url', - dest='index_url', - metavar='URL', - default=PyPI.simple_url, - help="Base URL of Python Package Index (default %default). " - "This should point to a repository compliant with PEP 503 " - "(the simple repository API) or a local directory laid out " - "in the same format.", -) # type: Callable[..., Option] - - -def extra_index_url(): - return Option( - '--extra-index-url', - dest='extra_index_urls', - metavar='URL', - action='append', - default=[], - help="Extra URLs of package indexes to use in addition to " - "--index-url. Should follow the same rules as " - "--index-url.", - ) - - -no_index = partial( - Option, - '--no-index', - dest='no_index', - action='store_true', - default=False, - help='Ignore package index (only looking at --find-links URLs instead).', -) # type: Callable[..., Option] - - -def find_links(): - # type: () -> Option - return Option( - '-f', '--find-links', - dest='find_links', - action='append', - default=[], - metavar='url', - help="If a url or path to an html file, then parse for links to " - "archives. If a local path or file:// url that's a directory, " - "then look for archives in the directory listing.", - ) - - -def trusted_host(): - # type: () -> Option - return Option( - "--trusted-host", - dest="trusted_hosts", - action="append", - metavar="HOSTNAME", - default=[], - help="Mark this host as trusted, even though it does not have valid " - "or any HTTPS.", - ) - - -def constraints(): - # type: () -> Option - return Option( - '-c', '--constraint', - dest='constraints', - action='append', - default=[], - metavar='file', - help='Constrain versions using the given constraints file. ' - 'This option can be used multiple times.' - ) - - -def requirements(): - # type: () -> Option - return Option( - '-r', '--requirement', - dest='requirements', - action='append', - default=[], - metavar='file', - help='Install from the given requirements file. ' - 'This option can be used multiple times.' - ) - - -def editable(): - # type: () -> Option - return Option( - '-e', '--editable', - dest='editables', - action='append', - default=[], - metavar='path/url', - help=('Install a project in editable mode (i.e. setuptools ' - '"develop mode") from a local project path or a VCS url.'), - ) - - -src = partial( - Option, - '--src', '--source', '--source-dir', '--source-directory', - dest='src_dir', - metavar='dir', - default=src_prefix, - help='Directory to check out editable projects into. ' - 'The default in a virtualenv is "/src". ' - 'The default for global installs is "/src".' -) # type: Callable[..., Option] - - -def _get_format_control(values, option): - # type: (Values, Option) -> Any - """Get a format_control object.""" - return getattr(values, option.dest) - - -def _handle_no_binary(option, opt_str, value, parser): - # type: (Option, str, str, OptionParser) -> None - existing = _get_format_control(parser.values, option) - FormatControl.handle_mutual_excludes( - value, existing.no_binary, existing.only_binary, - ) - - -def _handle_only_binary(option, opt_str, value, parser): - # type: (Option, str, str, OptionParser) -> None - existing = _get_format_control(parser.values, option) - FormatControl.handle_mutual_excludes( - value, existing.only_binary, existing.no_binary, - ) - - -def no_binary(): - # type: () -> Option - format_control = FormatControl(set(), set()) - return Option( - "--no-binary", dest="format_control", action="callback", - callback=_handle_no_binary, type="str", - default=format_control, - help="Do not use binary packages. Can be supplied multiple times, and " - "each time adds to the existing value. Accepts either :all: to " - "disable all binary packages, :none: to empty the set, or one or " - "more package names with commas between them. Note that some " - "packages are tricky to compile and may fail to install when " - "this option is used on them.", - ) - - -def only_binary(): - # type: () -> Option - format_control = FormatControl(set(), set()) - return Option( - "--only-binary", dest="format_control", action="callback", - callback=_handle_only_binary, type="str", - default=format_control, - help="Do not use source packages. Can be supplied multiple times, and " - "each time adds to the existing value. Accepts either :all: to " - "disable all source packages, :none: to empty the set, or one or " - "more package names with commas between them. Packages without " - "binary distributions will fail to install when this option is " - "used on them.", - ) - - -platform = partial( - Option, - '--platform', - dest='platform', - metavar='platform', - default=None, - help=("Only use wheels compatible with . " - "Defaults to the platform of the running system."), -) # type: Callable[..., Option] - - -python_version = partial( - Option, - '--python-version', - dest='python_version', - metavar='python_version', - default=None, - help=("Only use wheels compatible with Python " - "interpreter version . If not specified, then the " - "current system interpreter minor version is used. A major " - "version (e.g. '2') can be specified to match all " - "minor revs of that major version. A minor version " - "(e.g. '34') can also be specified."), -) # type: Callable[..., Option] - - -implementation = partial( - Option, - '--implementation', - dest='implementation', - metavar='implementation', - default=None, - help=("Only use wheels compatible with Python " - "implementation , e.g. 'pp', 'jy', 'cp', " - " or 'ip'. If not specified, then the current " - "interpreter implementation is used. Use 'py' to force " - "implementation-agnostic wheels."), -) # type: Callable[..., Option] - - -abi = partial( - Option, - '--abi', - dest='abi', - metavar='abi', - default=None, - help=("Only use wheels compatible with Python " - "abi , e.g. 'pypy_41'. If not specified, then the " - "current interpreter abi tag is used. Generally " - "you will need to specify --implementation, " - "--platform, and --python-version when using " - "this option."), -) # type: Callable[..., Option] - - -def prefer_binary(): - # type: () -> Option - return Option( - "--prefer-binary", - dest="prefer_binary", - action="store_true", - default=False, - help="Prefer older binary packages over newer source packages." - ) - - -cache_dir = partial( - Option, - "--cache-dir", - dest="cache_dir", - default=USER_CACHE_DIR, - metavar="dir", - help="Store the cache data in ." -) # type: Callable[..., Option] - - -def no_cache_dir_callback(option, opt, value, parser): - """ - Process a value provided for the --no-cache-dir option. - - This is an optparse.Option callback for the --no-cache-dir option. - """ - # The value argument will be None if --no-cache-dir is passed via the - # command-line, since the option doesn't accept arguments. However, - # the value can be non-None if the option is triggered e.g. by an - # environment variable, like PIP_NO_CACHE_DIR=true. - if value is not None: - # Then parse the string value to get argument error-checking. - try: - strtobool(value) - except ValueError as exc: - raise_option_error(parser, option=option, msg=str(exc)) - - # Originally, setting PIP_NO_CACHE_DIR to a value that strtobool() - # converted to 0 (like "false" or "no") caused cache_dir to be disabled - # rather than enabled (logic would say the latter). Thus, we disable - # the cache directory not just on values that parse to True, but (for - # backwards compatibility reasons) also on values that parse to False. - # In other words, always set it to False if the option is provided in - # some (valid) form. - parser.values.cache_dir = False - - -no_cache = partial( - Option, - "--no-cache-dir", - dest="cache_dir", - action="callback", - callback=no_cache_dir_callback, - help="Disable the cache.", -) # type: Callable[..., Option] - -no_deps = partial( - Option, - '--no-deps', '--no-dependencies', - dest='ignore_dependencies', - action='store_true', - default=False, - help="Don't install package dependencies.", -) # type: Callable[..., Option] - -build_dir = partial( - Option, - '-b', '--build', '--build-dir', '--build-directory', - dest='build_dir', - metavar='dir', - help='Directory to unpack packages into and build in. Note that ' - 'an initial build still takes place in a temporary directory. ' - 'The location of temporary directories can be controlled by setting ' - 'the TMPDIR environment variable (TEMP on Windows) appropriately. ' - 'When passed, build directories are not cleaned in case of failures.' -) # type: Callable[..., Option] - -ignore_requires_python = partial( - Option, - '--ignore-requires-python', - dest='ignore_requires_python', - action='store_true', - help='Ignore the Requires-Python information.' -) # type: Callable[..., Option] - -no_build_isolation = partial( - Option, - '--no-build-isolation', - dest='build_isolation', - action='store_false', - default=True, - help='Disable isolation when building a modern source distribution. ' - 'Build dependencies specified by PEP 518 must be already installed ' - 'if this option is used.' -) # type: Callable[..., Option] - - -def no_use_pep517_callback(option, opt, value, parser): - """ - Process a value provided for the --no-use-pep517 option. - - This is an optparse.Option callback for the no_use_pep517 option. - """ - # Since --no-use-pep517 doesn't accept arguments, the value argument - # will be None if --no-use-pep517 is passed via the command-line. - # However, the value can be non-None if the option is triggered e.g. - # by an environment variable, for example "PIP_NO_USE_PEP517=true". - if value is not None: - msg = """A value was passed for --no-use-pep517, - probably using either the PIP_NO_USE_PEP517 environment variable - or the "no-use-pep517" config file option. Use an appropriate value - of the PIP_USE_PEP517 environment variable or the "use-pep517" - config file option instead. - """ - raise_option_error(parser, option=option, msg=msg) - - # Otherwise, --no-use-pep517 was passed via the command-line. - parser.values.use_pep517 = False - - -use_pep517 = partial( - Option, - '--use-pep517', - dest='use_pep517', - action='store_true', - default=None, - help='Use PEP 517 for building source distributions ' - '(use --no-use-pep517 to force legacy behaviour).' -) # type: Any - -no_use_pep517 = partial( - Option, - '--no-use-pep517', - dest='use_pep517', - action='callback', - callback=no_use_pep517_callback, - default=None, - help=SUPPRESS_HELP -) # type: Any - -install_options = partial( - Option, - '--install-option', - dest='install_options', - action='append', - metavar='options', - help="Extra arguments to be supplied to the setup.py install " - "command (use like --install-option=\"--install-scripts=/usr/local/" - "bin\"). Use multiple --install-option options to pass multiple " - "options to setup.py install. If you are using an option with a " - "directory path, be sure to use absolute path.", -) # type: Callable[..., Option] - -global_options = partial( - Option, - '--global-option', - dest='global_options', - action='append', - metavar='options', - help="Extra global options to be supplied to the setup.py " - "call before the install command.", -) # type: Callable[..., Option] - -no_clean = partial( - Option, - '--no-clean', - action='store_true', - default=False, - help="Don't clean up build directories." -) # type: Callable[..., Option] - -pre = partial( - Option, - '--pre', - action='store_true', - default=False, - help="Include pre-release and development versions. By default, " - "pip only finds stable versions.", -) # type: Callable[..., Option] - -disable_pip_version_check = partial( - Option, - "--disable-pip-version-check", - dest="disable_pip_version_check", - action="store_true", - default=False, - help="Don't periodically check PyPI to determine whether a new version " - "of pip is available for download. Implied with --no-index.", -) # type: Callable[..., Option] - - -# Deprecated, Remove later -always_unzip = partial( - Option, - '-Z', '--always-unzip', - dest='always_unzip', - action='store_true', - help=SUPPRESS_HELP, -) # type: Callable[..., Option] - - -def _merge_hash(option, opt_str, value, parser): - # type: (Option, str, str, OptionParser) -> None - """Given a value spelled "algo:digest", append the digest to a list - pointed to in a dict by the algo name.""" - if not parser.values.hashes: - parser.values.hashes = {} - try: - algo, digest = value.split(':', 1) - except ValueError: - parser.error('Arguments to %s must be a hash name ' - 'followed by a value, like --hash=sha256:abcde...' % - opt_str) - if algo not in STRONG_HASHES: - parser.error('Allowed hash algorithms for %s are %s.' % - (opt_str, ', '.join(STRONG_HASHES))) - parser.values.hashes.setdefault(algo, []).append(digest) - - -hash = partial( - Option, - '--hash', - # Hash values eventually end up in InstallRequirement.hashes due to - # __dict__ copying in process_line(). - dest='hashes', - action='callback', - callback=_merge_hash, - type='string', - help="Verify that the package's archive matches this " - 'hash before installing. Example: --hash=sha256:abcdef...', -) # type: Callable[..., Option] - - -require_hashes = partial( - Option, - '--require-hashes', - dest='require_hashes', - action='store_true', - default=False, - help='Require a hash to check each requirement against, for ' - 'repeatable installs. This option is implied when any package in a ' - 'requirements file has a --hash option.', -) # type: Callable[..., Option] - - -########## -# groups # -########## - -general_group = { - 'name': 'General Options', - 'options': [ - help_, - isolated_mode, - require_virtualenv, - verbose, - version, - quiet, - log, - no_input, - proxy, - retries, - timeout, - skip_requirements_regex, - exists_action, - trusted_host, - cert, - client_cert, - cache_dir, - no_cache, - disable_pip_version_check, - no_color, - ] -} # type: Dict[str, Any] - -index_group = { - 'name': 'Package Index Options', - 'options': [ - index_url, - extra_index_url, - no_index, - find_links, - ] -} # type: Dict[str, Any] diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/cli/main_parser.py b/venv2/lib/python2.7/site-packages/pip/_internal/cli/main_parser.py deleted file mode 100644 index 767f35d..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/cli/main_parser.py +++ /dev/null @@ -1,104 +0,0 @@ -"""A single place for constructing and exposing the main parser -""" - -import os -import sys - -from pip import __version__ -from pip._internal.cli import cmdoptions -from pip._internal.cli.parser import ( - ConfigOptionParser, UpdatingDefaultsHelpFormatter, -) -from pip._internal.commands import ( - commands_dict, get_similar_commands, get_summaries, -) -from pip._internal.exceptions import CommandError -from pip._internal.utils.misc import get_prog -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import Tuple, List - - -__all__ = ["create_main_parser", "parse_command"] - - -def create_main_parser(): - # type: () -> ConfigOptionParser - """Creates and returns the main parser for pip's CLI - """ - - parser_kw = { - 'usage': '\n%prog [options]', - 'add_help_option': False, - 'formatter': UpdatingDefaultsHelpFormatter(), - 'name': 'global', - 'prog': get_prog(), - } - - parser = ConfigOptionParser(**parser_kw) - parser.disable_interspersed_args() - - pip_pkg_dir = os.path.abspath(os.path.join( - os.path.dirname(__file__), "..", "..", - )) - parser.version = 'pip %s from %s (python %s)' % ( - __version__, pip_pkg_dir, sys.version[:3], - ) - - # add the general options - gen_opts = cmdoptions.make_option_group(cmdoptions.general_group, parser) - parser.add_option_group(gen_opts) - - # so the help formatter knows - parser.main = True # type: ignore - - # create command listing for description - command_summaries = get_summaries() - description = [''] + ['%-27s %s' % (i, j) for i, j in command_summaries] - parser.description = '\n'.join(description) - - return parser - - -def parse_command(args): - # type: (List[str]) -> Tuple[str, List[str]] - parser = create_main_parser() - - # Note: parser calls disable_interspersed_args(), so the result of this - # call is to split the initial args into the general options before the - # subcommand and everything else. - # For example: - # args: ['--timeout=5', 'install', '--user', 'INITools'] - # general_options: ['--timeout==5'] - # args_else: ['install', '--user', 'INITools'] - general_options, args_else = parser.parse_args(args) - - # --version - if general_options.version: - sys.stdout.write(parser.version) # type: ignore - sys.stdout.write(os.linesep) - sys.exit() - - # pip || pip help -> print_help() - if not args_else or (args_else[0] == 'help' and len(args_else) == 1): - parser.print_help() - sys.exit() - - # the subcommand name - cmd_name = args_else[0] - - if cmd_name not in commands_dict: - guess = get_similar_commands(cmd_name) - - msg = ['unknown command "%s"' % cmd_name] - if guess: - msg.append('maybe you meant "%s"' % guess) - - raise CommandError(' - '.join(msg)) - - # all the args without the subcommand - cmd_args = args[:] - cmd_args.remove(cmd_name) - - return cmd_name, cmd_args diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/cli/parser.py b/venv2/lib/python2.7/site-packages/pip/_internal/cli/parser.py deleted file mode 100644 index e1eaac4..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/cli/parser.py +++ /dev/null @@ -1,261 +0,0 @@ -"""Base option parser setup""" -from __future__ import absolute_import - -import logging -import optparse -import sys -import textwrap -from distutils.util import strtobool - -from pip._vendor.six import string_types - -from pip._internal.cli.status_codes import UNKNOWN_ERROR -from pip._internal.configuration import Configuration, ConfigurationError -from pip._internal.utils.compat import get_terminal_size - -logger = logging.getLogger(__name__) - - -class PrettyHelpFormatter(optparse.IndentedHelpFormatter): - """A prettier/less verbose help formatter for optparse.""" - - def __init__(self, *args, **kwargs): - # help position must be aligned with __init__.parseopts.description - kwargs['max_help_position'] = 30 - kwargs['indent_increment'] = 1 - kwargs['width'] = get_terminal_size()[0] - 2 - optparse.IndentedHelpFormatter.__init__(self, *args, **kwargs) - - def format_option_strings(self, option): - return self._format_option_strings(option, ' <%s>', ', ') - - def _format_option_strings(self, option, mvarfmt=' <%s>', optsep=', '): - """ - Return a comma-separated list of option strings and metavars. - - :param option: tuple of (short opt, long opt), e.g: ('-f', '--format') - :param mvarfmt: metavar format string - evaluated as mvarfmt % metavar - :param optsep: separator - """ - opts = [] - - if option._short_opts: - opts.append(option._short_opts[0]) - if option._long_opts: - opts.append(option._long_opts[0]) - if len(opts) > 1: - opts.insert(1, optsep) - - if option.takes_value(): - metavar = option.metavar or option.dest.lower() - opts.append(mvarfmt % metavar.lower()) - - return ''.join(opts) - - def format_heading(self, heading): - if heading == 'Options': - return '' - return heading + ':\n' - - def format_usage(self, usage): - """ - Ensure there is only one newline between usage and the first heading - if there is no description. - """ - msg = '\nUsage: %s\n' % self.indent_lines(textwrap.dedent(usage), " ") - return msg - - def format_description(self, description): - # leave full control over description to us - if description: - if hasattr(self.parser, 'main'): - label = 'Commands' - else: - label = 'Description' - # some doc strings have initial newlines, some don't - description = description.lstrip('\n') - # some doc strings have final newlines and spaces, some don't - description = description.rstrip() - # dedent, then reindent - description = self.indent_lines(textwrap.dedent(description), " ") - description = '%s:\n%s\n' % (label, description) - return description - else: - return '' - - def format_epilog(self, epilog): - # leave full control over epilog to us - if epilog: - return epilog - else: - return '' - - def indent_lines(self, text, indent): - new_lines = [indent + line for line in text.split('\n')] - return "\n".join(new_lines) - - -class UpdatingDefaultsHelpFormatter(PrettyHelpFormatter): - """Custom help formatter for use in ConfigOptionParser. - - This is updates the defaults before expanding them, allowing - them to show up correctly in the help listing. - """ - - def expand_default(self, option): - if self.parser is not None: - self.parser._update_defaults(self.parser.defaults) - return optparse.IndentedHelpFormatter.expand_default(self, option) - - -class CustomOptionParser(optparse.OptionParser): - - def insert_option_group(self, idx, *args, **kwargs): - """Insert an OptionGroup at a given position.""" - group = self.add_option_group(*args, **kwargs) - - self.option_groups.pop() - self.option_groups.insert(idx, group) - - return group - - @property - def option_list_all(self): - """Get a list of all options, including those in option groups.""" - res = self.option_list[:] - for i in self.option_groups: - res.extend(i.option_list) - - return res - - -class ConfigOptionParser(CustomOptionParser): - """Custom option parser which updates its defaults by checking the - configuration files and environmental variables""" - - def __init__(self, *args, **kwargs): - self.name = kwargs.pop('name') - - isolated = kwargs.pop("isolated", False) - self.config = Configuration(isolated) - - assert self.name - optparse.OptionParser.__init__(self, *args, **kwargs) - - def check_default(self, option, key, val): - try: - return option.check_value(key, val) - except optparse.OptionValueError as exc: - print("An error occurred during configuration: %s" % exc) - sys.exit(3) - - def _get_ordered_configuration_items(self): - # Configuration gives keys in an unordered manner. Order them. - override_order = ["global", self.name, ":env:"] - - # Pool the options into different groups - section_items = {name: [] for name in override_order} - for section_key, val in self.config.items(): - # ignore empty values - if not val: - logger.debug( - "Ignoring configuration key '%s' as it's value is empty.", - section_key - ) - continue - - section, key = section_key.split(".", 1) - if section in override_order: - section_items[section].append((key, val)) - - # Yield each group in their override order - for section in override_order: - for key, val in section_items[section]: - yield key, val - - def _update_defaults(self, defaults): - """Updates the given defaults with values from the config files and - the environ. Does a little special handling for certain types of - options (lists).""" - - # Accumulate complex default state. - self.values = optparse.Values(self.defaults) - late_eval = set() - # Then set the options with those values - for key, val in self._get_ordered_configuration_items(): - # '--' because configuration supports only long names - option = self.get_option('--' + key) - - # Ignore options not present in this parser. E.g. non-globals put - # in [global] by users that want them to apply to all applicable - # commands. - if option is None: - continue - - if option.action in ('store_true', 'store_false', 'count'): - try: - val = strtobool(val) - except ValueError: - error_msg = invalid_config_error_message( - option.action, key, val - ) - self.error(error_msg) - - elif option.action == 'append': - val = val.split() - val = [self.check_default(option, key, v) for v in val] - elif option.action == 'callback': - late_eval.add(option.dest) - opt_str = option.get_opt_string() - val = option.convert_value(opt_str, val) - # From take_action - args = option.callback_args or () - kwargs = option.callback_kwargs or {} - option.callback(option, opt_str, val, self, *args, **kwargs) - else: - val = self.check_default(option, key, val) - - defaults[option.dest] = val - - for key in late_eval: - defaults[key] = getattr(self.values, key) - self.values = None - return defaults - - def get_default_values(self): - """Overriding to make updating the defaults after instantiation of - the option parser possible, _update_defaults() does the dirty work.""" - if not self.process_default_values: - # Old, pre-Optik 1.5 behaviour. - return optparse.Values(self.defaults) - - # Load the configuration, or error out in case of an error - try: - self.config.load() - except ConfigurationError as err: - self.exit(UNKNOWN_ERROR, str(err)) - - defaults = self._update_defaults(self.defaults.copy()) # ours - for option in self._get_all_options(): - default = defaults.get(option.dest) - if isinstance(default, string_types): - opt_str = option.get_opt_string() - defaults[option.dest] = option.check_value(opt_str, default) - return optparse.Values(defaults) - - def error(self, msg): - self.print_usage(sys.stderr) - self.exit(UNKNOWN_ERROR, "%s\n" % msg) - - -def invalid_config_error_message(action, key, val): - """Returns a better error message when invalid configuration option - is provided.""" - if action in ('store_true', 'store_false'): - return ("{0} is not a valid value for {1} option, " - "please specify a boolean value like yes/no, " - "true/false or 1/0 instead.").format(val, key) - - return ("{0} is not a valid value for {1} option, " - "please specify a numerical value like 1/0 " - "instead.").format(val, key) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/cli/status_codes.py b/venv2/lib/python2.7/site-packages/pip/_internal/cli/status_codes.py deleted file mode 100644 index 275360a..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/cli/status_codes.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import absolute_import - -SUCCESS = 0 -ERROR = 1 -UNKNOWN_ERROR = 2 -VIRTUALENV_NOT_FOUND = 3 -PREVIOUS_BUILD_DIR_ERROR = 4 -NO_MATCHES_FOUND = 23 diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/commands/__init__.py b/venv2/lib/python2.7/site-packages/pip/_internal/commands/__init__.py deleted file mode 100644 index 2e90db3..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/commands/__init__.py +++ /dev/null @@ -1,79 +0,0 @@ -""" -Package containing all pip commands -""" -from __future__ import absolute_import - -from pip._internal.commands.completion import CompletionCommand -from pip._internal.commands.configuration import ConfigurationCommand -from pip._internal.commands.download import DownloadCommand -from pip._internal.commands.freeze import FreezeCommand -from pip._internal.commands.hash import HashCommand -from pip._internal.commands.help import HelpCommand -from pip._internal.commands.list import ListCommand -from pip._internal.commands.check import CheckCommand -from pip._internal.commands.search import SearchCommand -from pip._internal.commands.show import ShowCommand -from pip._internal.commands.install import InstallCommand -from pip._internal.commands.uninstall import UninstallCommand -from pip._internal.commands.wheel import WheelCommand - -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import List, Type - from pip._internal.cli.base_command import Command - -commands_order = [ - InstallCommand, - DownloadCommand, - UninstallCommand, - FreezeCommand, - ListCommand, - ShowCommand, - CheckCommand, - ConfigurationCommand, - SearchCommand, - WheelCommand, - HashCommand, - CompletionCommand, - HelpCommand, -] # type: List[Type[Command]] - -commands_dict = {c.name: c for c in commands_order} - - -def get_summaries(ordered=True): - """Yields sorted (command name, command summary) tuples.""" - - if ordered: - cmditems = _sort_commands(commands_dict, commands_order) - else: - cmditems = commands_dict.items() - - for name, command_class in cmditems: - yield (name, command_class.summary) - - -def get_similar_commands(name): - """Command name auto-correct.""" - from difflib import get_close_matches - - name = name.lower() - - close_commands = get_close_matches(name, commands_dict.keys()) - - if close_commands: - return close_commands[0] - else: - return False - - -def _sort_commands(cmddict, order): - def keyfn(key): - try: - return order.index(key[1]) - except ValueError: - # unordered items should come last - return 0xff - - return sorted(cmddict.items(), key=keyfn) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/commands/check.py b/venv2/lib/python2.7/site-packages/pip/_internal/commands/check.py deleted file mode 100644 index 801cecc..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/commands/check.py +++ /dev/null @@ -1,41 +0,0 @@ -import logging - -from pip._internal.cli.base_command import Command -from pip._internal.operations.check import ( - check_package_set, create_package_set_from_installed, -) - -logger = logging.getLogger(__name__) - - -class CheckCommand(Command): - """Verify installed packages have compatible dependencies.""" - name = 'check' - usage = """ - %prog [options]""" - summary = 'Verify installed packages have compatible dependencies.' - - def run(self, options, args): - package_set, parsing_probs = create_package_set_from_installed() - missing, conflicting = check_package_set(package_set) - - for project_name in missing: - version = package_set[project_name].version - for dependency in missing[project_name]: - logger.info( - "%s %s requires %s, which is not installed.", - project_name, version, dependency[0], - ) - - for project_name in conflicting: - version = package_set[project_name].version - for dep_name, dep_version, req in conflicting[project_name]: - logger.info( - "%s %s has requirement %s, but you have %s %s.", - project_name, version, req, dep_name, dep_version, - ) - - if missing or conflicting or parsing_probs: - return 1 - else: - logger.info("No broken requirements found.") diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/commands/completion.py b/venv2/lib/python2.7/site-packages/pip/_internal/commands/completion.py deleted file mode 100644 index 2fcdd39..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/commands/completion.py +++ /dev/null @@ -1,94 +0,0 @@ -from __future__ import absolute_import - -import sys -import textwrap - -from pip._internal.cli.base_command import Command -from pip._internal.utils.misc import get_prog - -BASE_COMPLETION = """ -# pip %(shell)s completion start%(script)s# pip %(shell)s completion end -""" - -COMPLETION_SCRIPTS = { - 'bash': """ - _pip_completion() - { - COMPREPLY=( $( COMP_WORDS="${COMP_WORDS[*]}" \\ - COMP_CWORD=$COMP_CWORD \\ - PIP_AUTO_COMPLETE=1 $1 ) ) - } - complete -o default -F _pip_completion %(prog)s - """, - 'zsh': """ - function _pip_completion { - local words cword - read -Ac words - read -cn cword - reply=( $( COMP_WORDS="$words[*]" \\ - COMP_CWORD=$(( cword-1 )) \\ - PIP_AUTO_COMPLETE=1 $words[1] ) ) - } - compctl -K _pip_completion %(prog)s - """, - 'fish': """ - function __fish_complete_pip - set -lx COMP_WORDS (commandline -o) "" - set -lx COMP_CWORD ( \\ - math (contains -i -- (commandline -t) $COMP_WORDS)-1 \\ - ) - set -lx PIP_AUTO_COMPLETE 1 - string split \\ -- (eval $COMP_WORDS[1]) - end - complete -fa "(__fish_complete_pip)" -c %(prog)s - """, -} - - -class CompletionCommand(Command): - """A helper command to be used for command completion.""" - name = 'completion' - summary = 'A helper command used for command completion.' - ignore_require_venv = True - - def __init__(self, *args, **kw): - super(CompletionCommand, self).__init__(*args, **kw) - - cmd_opts = self.cmd_opts - - cmd_opts.add_option( - '--bash', '-b', - action='store_const', - const='bash', - dest='shell', - help='Emit completion code for bash') - cmd_opts.add_option( - '--zsh', '-z', - action='store_const', - const='zsh', - dest='shell', - help='Emit completion code for zsh') - cmd_opts.add_option( - '--fish', '-f', - action='store_const', - const='fish', - dest='shell', - help='Emit completion code for fish') - - self.parser.insert_option_group(0, cmd_opts) - - def run(self, options, args): - """Prints the completion code of the given shell""" - shells = COMPLETION_SCRIPTS.keys() - shell_options = ['--' + shell for shell in sorted(shells)] - if options.shell in shells: - script = textwrap.dedent( - COMPLETION_SCRIPTS.get(options.shell, '') % { - 'prog': get_prog(), - } - ) - print(BASE_COMPLETION % {'script': script, 'shell': options.shell}) - else: - sys.stderr.write( - 'ERROR: You must pass %s\n' % ' or '.join(shell_options) - ) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/commands/configuration.py b/venv2/lib/python2.7/site-packages/pip/_internal/commands/configuration.py deleted file mode 100644 index 950e205..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/commands/configuration.py +++ /dev/null @@ -1,253 +0,0 @@ -import logging -import os -import subprocess - -from pip._internal.cli.base_command import Command -from pip._internal.cli.status_codes import ERROR, SUCCESS -from pip._internal.configuration import Configuration, kinds -from pip._internal.exceptions import PipError -from pip._internal.locations import running_under_virtualenv, site_config_file -from pip._internal.utils.deprecation import deprecated -from pip._internal.utils.misc import get_prog - -logger = logging.getLogger(__name__) - - -class ConfigurationCommand(Command): - """Manage local and global configuration. - - Subcommands: - - list: List the active configuration (or from the file specified) - edit: Edit the configuration file in an editor - get: Get the value associated with name - set: Set the name=value - unset: Unset the value associated with name - - If none of --user, --global and --site are passed, a virtual - environment configuration file is used if one is active and the file - exists. Otherwise, all modifications happen on the to the user file by - default. - """ - - name = 'config' - usage = """ - %prog [] list - %prog [] [--editor ] edit - - %prog [] get name - %prog [] set name value - %prog [] unset name - """ - - summary = "Manage local and global configuration." - - def __init__(self, *args, **kwargs): - super(ConfigurationCommand, self).__init__(*args, **kwargs) - - self.configuration = None - - self.cmd_opts.add_option( - '--editor', - dest='editor', - action='store', - default=None, - help=( - 'Editor to use to edit the file. Uses VISUAL or EDITOR ' - 'environment variables if not provided.' - ) - ) - - self.cmd_opts.add_option( - '--global', - dest='global_file', - action='store_true', - default=False, - help='Use the system-wide configuration file only' - ) - - self.cmd_opts.add_option( - '--user', - dest='user_file', - action='store_true', - default=False, - help='Use the user configuration file only' - ) - - self.cmd_opts.add_option( - '--site', - dest='site_file', - action='store_true', - default=False, - help='Use the current environment configuration file only' - ) - - self.cmd_opts.add_option( - '--venv', - dest='venv_file', - action='store_true', - default=False, - help=( - '[Deprecated] Use the current environment configuration ' - 'file in a virtual environment only' - ) - ) - - self.parser.insert_option_group(0, self.cmd_opts) - - def run(self, options, args): - handlers = { - "list": self.list_values, - "edit": self.open_in_editor, - "get": self.get_name, - "set": self.set_name_value, - "unset": self.unset_name - } - - # Determine action - if not args or args[0] not in handlers: - logger.error("Need an action ({}) to perform.".format( - ", ".join(sorted(handlers))) - ) - return ERROR - - action = args[0] - - # Determine which configuration files are to be loaded - # Depends on whether the command is modifying. - try: - load_only = self._determine_file( - options, need_value=(action in ["get", "set", "unset", "edit"]) - ) - except PipError as e: - logger.error(e.args[0]) - return ERROR - - # Load a new configuration - self.configuration = Configuration( - isolated=options.isolated_mode, load_only=load_only - ) - self.configuration.load() - - # Error handling happens here, not in the action-handlers. - try: - handlers[action](options, args[1:]) - except PipError as e: - logger.error(e.args[0]) - return ERROR - - return SUCCESS - - def _determine_file(self, options, need_value): - # Convert legacy venv_file option to site_file or error - if options.venv_file and not options.site_file: - if running_under_virtualenv(): - options.site_file = True - deprecated( - "The --venv option has been deprecated.", - replacement="--site", - gone_in="19.3", - ) - else: - raise PipError( - "Legacy --venv option requires a virtual environment. " - "Use --site instead." - ) - - file_options = [key for key, value in ( - (kinds.USER, options.user_file), - (kinds.GLOBAL, options.global_file), - (kinds.SITE, options.site_file), - ) if value] - - if not file_options: - if not need_value: - return None - # Default to user, unless there's a site file. - elif os.path.exists(site_config_file): - return kinds.SITE - else: - return kinds.USER - elif len(file_options) == 1: - return file_options[0] - - raise PipError( - "Need exactly one file to operate upon " - "(--user, --site, --global) to perform." - ) - - def list_values(self, options, args): - self._get_n_args(args, "list", n=0) - - for key, value in sorted(self.configuration.items()): - logger.info("%s=%r", key, value) - - def get_name(self, options, args): - key = self._get_n_args(args, "get [name]", n=1) - value = self.configuration.get_value(key) - - logger.info("%s", value) - - def set_name_value(self, options, args): - key, value = self._get_n_args(args, "set [name] [value]", n=2) - self.configuration.set_value(key, value) - - self._save_configuration() - - def unset_name(self, options, args): - key = self._get_n_args(args, "unset [name]", n=1) - self.configuration.unset_value(key) - - self._save_configuration() - - def open_in_editor(self, options, args): - editor = self._determine_editor(options) - - fname = self.configuration.get_file_to_edit() - if fname is None: - raise PipError("Could not determine appropriate file.") - - try: - subprocess.check_call([editor, fname]) - except subprocess.CalledProcessError as e: - raise PipError( - "Editor Subprocess exited with exit code {}" - .format(e.returncode) - ) - - def _get_n_args(self, args, example, n): - """Helper to make sure the command got the right number of arguments - """ - if len(args) != n: - msg = ( - 'Got unexpected number of arguments, expected {}. ' - '(example: "{} config {}")' - ).format(n, get_prog(), example) - raise PipError(msg) - - if n == 1: - return args[0] - else: - return args - - def _save_configuration(self): - # We successfully ran a modifying command. Need to save the - # configuration. - try: - self.configuration.save() - except Exception: - logger.error( - "Unable to save configuration. Please report this as a bug.", - exc_info=1 - ) - raise PipError("Internal Error.") - - def _determine_editor(self, options): - if options.editor is not None: - return options.editor - elif "VISUAL" in os.environ: - return os.environ["VISUAL"] - elif "EDITOR" in os.environ: - return os.environ["EDITOR"] - else: - raise PipError("Could not determine editor to use.") diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/commands/download.py b/venv2/lib/python2.7/site-packages/pip/_internal/commands/download.py deleted file mode 100644 index a57e4bc..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/commands/download.py +++ /dev/null @@ -1,176 +0,0 @@ -from __future__ import absolute_import - -import logging -import os - -from pip._internal.cli import cmdoptions -from pip._internal.cli.base_command import RequirementCommand -from pip._internal.operations.prepare import RequirementPreparer -from pip._internal.req import RequirementSet -from pip._internal.req.req_tracker import RequirementTracker -from pip._internal.resolve import Resolver -from pip._internal.utils.filesystem import check_path_owner -from pip._internal.utils.misc import ensure_dir, normalize_path -from pip._internal.utils.temp_dir import TempDirectory - -logger = logging.getLogger(__name__) - - -class DownloadCommand(RequirementCommand): - """ - Download packages from: - - - PyPI (and other indexes) using requirement specifiers. - - VCS project urls. - - Local project directories. - - Local or remote source archives. - - pip also supports downloading from "requirements files", which provide - an easy way to specify a whole environment to be downloaded. - """ - name = 'download' - - usage = """ - %prog [options] [package-index-options] ... - %prog [options] -r [package-index-options] ... - %prog [options] ... - %prog [options] ... - %prog [options] ...""" - - summary = 'Download packages.' - - def __init__(self, *args, **kw): - super(DownloadCommand, self).__init__(*args, **kw) - - cmd_opts = self.cmd_opts - - cmd_opts.add_option(cmdoptions.constraints()) - cmd_opts.add_option(cmdoptions.requirements()) - cmd_opts.add_option(cmdoptions.build_dir()) - cmd_opts.add_option(cmdoptions.no_deps()) - cmd_opts.add_option(cmdoptions.global_options()) - cmd_opts.add_option(cmdoptions.no_binary()) - cmd_opts.add_option(cmdoptions.only_binary()) - cmd_opts.add_option(cmdoptions.prefer_binary()) - cmd_opts.add_option(cmdoptions.src()) - cmd_opts.add_option(cmdoptions.pre()) - cmd_opts.add_option(cmdoptions.no_clean()) - cmd_opts.add_option(cmdoptions.require_hashes()) - cmd_opts.add_option(cmdoptions.progress_bar()) - cmd_opts.add_option(cmdoptions.no_build_isolation()) - cmd_opts.add_option(cmdoptions.use_pep517()) - cmd_opts.add_option(cmdoptions.no_use_pep517()) - - cmd_opts.add_option( - '-d', '--dest', '--destination-dir', '--destination-directory', - dest='download_dir', - metavar='dir', - default=os.curdir, - help=("Download packages into ."), - ) - - cmd_opts.add_option(cmdoptions.platform()) - cmd_opts.add_option(cmdoptions.python_version()) - cmd_opts.add_option(cmdoptions.implementation()) - cmd_opts.add_option(cmdoptions.abi()) - - index_opts = cmdoptions.make_option_group( - cmdoptions.index_group, - self.parser, - ) - - self.parser.insert_option_group(0, index_opts) - self.parser.insert_option_group(0, cmd_opts) - - def run(self, options, args): - options.ignore_installed = True - # editable doesn't really make sense for `pip download`, but the bowels - # of the RequirementSet code require that property. - options.editables = [] - - if options.python_version: - python_versions = [options.python_version] - else: - python_versions = None - - cmdoptions.check_dist_restriction(options) - - options.src_dir = os.path.abspath(options.src_dir) - options.download_dir = normalize_path(options.download_dir) - - ensure_dir(options.download_dir) - - with self._build_session(options) as session: - finder = self._build_package_finder( - options=options, - session=session, - platform=options.platform, - python_versions=python_versions, - abi=options.abi, - implementation=options.implementation, - ) - build_delete = (not (options.no_clean or options.build_dir)) - if options.cache_dir and not check_path_owner(options.cache_dir): - logger.warning( - "The directory '%s' or its parent directory is not owned " - "by the current user and caching wheels has been " - "disabled. check the permissions and owner of that " - "directory. If executing pip with sudo, you may want " - "sudo's -H flag.", - options.cache_dir, - ) - options.cache_dir = None - - with RequirementTracker() as req_tracker, TempDirectory( - options.build_dir, delete=build_delete, kind="download" - ) as directory: - - requirement_set = RequirementSet( - require_hashes=options.require_hashes, - ) - self.populate_requirement_set( - requirement_set, - args, - options, - finder, - session, - self.name, - None - ) - - preparer = RequirementPreparer( - build_dir=directory.path, - src_dir=options.src_dir, - download_dir=options.download_dir, - wheel_download_dir=None, - progress_bar=options.progress_bar, - build_isolation=options.build_isolation, - req_tracker=req_tracker, - ) - - resolver = Resolver( - preparer=preparer, - finder=finder, - session=session, - wheel_cache=None, - use_user_site=False, - upgrade_strategy="to-satisfy-only", - force_reinstall=False, - ignore_dependencies=options.ignore_dependencies, - ignore_requires_python=False, - ignore_installed=True, - isolated=options.isolated_mode, - ) - resolver.resolve(requirement_set) - - downloaded = ' '.join([ - req.name for req in requirement_set.successfully_downloaded - ]) - if downloaded: - logger.info('Successfully downloaded %s', downloaded) - - # Clean up - if not options.no_clean: - requirement_set.cleanup_files() - - return requirement_set diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/commands/freeze.py b/venv2/lib/python2.7/site-packages/pip/_internal/commands/freeze.py deleted file mode 100644 index dc9c53a..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/commands/freeze.py +++ /dev/null @@ -1,96 +0,0 @@ -from __future__ import absolute_import - -import sys - -from pip._internal.cache import WheelCache -from pip._internal.cli.base_command import Command -from pip._internal.models.format_control import FormatControl -from pip._internal.operations.freeze import freeze -from pip._internal.utils.compat import stdlib_pkgs - -DEV_PKGS = {'pip', 'setuptools', 'distribute', 'wheel'} - - -class FreezeCommand(Command): - """ - Output installed packages in requirements format. - - packages are listed in a case-insensitive sorted order. - """ - name = 'freeze' - usage = """ - %prog [options]""" - summary = 'Output installed packages in requirements format.' - log_streams = ("ext://sys.stderr", "ext://sys.stderr") - - def __init__(self, *args, **kw): - super(FreezeCommand, self).__init__(*args, **kw) - - self.cmd_opts.add_option( - '-r', '--requirement', - dest='requirements', - action='append', - default=[], - metavar='file', - help="Use the order in the given requirements file and its " - "comments when generating output. This option can be " - "used multiple times.") - self.cmd_opts.add_option( - '-f', '--find-links', - dest='find_links', - action='append', - default=[], - metavar='URL', - help='URL for finding packages, which will be added to the ' - 'output.') - self.cmd_opts.add_option( - '-l', '--local', - dest='local', - action='store_true', - default=False, - help='If in a virtualenv that has global access, do not output ' - 'globally-installed packages.') - self.cmd_opts.add_option( - '--user', - dest='user', - action='store_true', - default=False, - help='Only output packages installed in user-site.') - self.cmd_opts.add_option( - '--all', - dest='freeze_all', - action='store_true', - help='Do not skip these packages in the output:' - ' %s' % ', '.join(DEV_PKGS)) - self.cmd_opts.add_option( - '--exclude-editable', - dest='exclude_editable', - action='store_true', - help='Exclude editable package from output.') - - self.parser.insert_option_group(0, self.cmd_opts) - - def run(self, options, args): - format_control = FormatControl(set(), set()) - wheel_cache = WheelCache(options.cache_dir, format_control) - skip = set(stdlib_pkgs) - if not options.freeze_all: - skip.update(DEV_PKGS) - - freeze_kwargs = dict( - requirement=options.requirements, - find_links=options.find_links, - local_only=options.local, - user_only=options.user, - skip_regex=options.skip_requirements_regex, - isolated=options.isolated_mode, - wheel_cache=wheel_cache, - skip=skip, - exclude_editable=options.exclude_editable, - ) - - try: - for line in freeze(**freeze_kwargs): - sys.stdout.write(line + '\n') - finally: - wheel_cache.cleanup() diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/commands/hash.py b/venv2/lib/python2.7/site-packages/pip/_internal/commands/hash.py deleted file mode 100644 index 423440e..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/commands/hash.py +++ /dev/null @@ -1,57 +0,0 @@ -from __future__ import absolute_import - -import hashlib -import logging -import sys - -from pip._internal.cli.base_command import Command -from pip._internal.cli.status_codes import ERROR -from pip._internal.utils.hashes import FAVORITE_HASH, STRONG_HASHES -from pip._internal.utils.misc import read_chunks - -logger = logging.getLogger(__name__) - - -class HashCommand(Command): - """ - Compute a hash of a local package archive. - - These can be used with --hash in a requirements file to do repeatable - installs. - - """ - name = 'hash' - usage = '%prog [options] ...' - summary = 'Compute hashes of package archives.' - ignore_require_venv = True - - def __init__(self, *args, **kw): - super(HashCommand, self).__init__(*args, **kw) - self.cmd_opts.add_option( - '-a', '--algorithm', - dest='algorithm', - choices=STRONG_HASHES, - action='store', - default=FAVORITE_HASH, - help='The hash algorithm to use: one of %s' % - ', '.join(STRONG_HASHES)) - self.parser.insert_option_group(0, self.cmd_opts) - - def run(self, options, args): - if not args: - self.parser.print_usage(sys.stderr) - return ERROR - - algorithm = options.algorithm - for path in args: - logger.info('%s:\n--hash=%s:%s', - path, algorithm, _hash_of_file(path, algorithm)) - - -def _hash_of_file(path, algorithm): - """Return the hash digest of a file.""" - with open(path, 'rb') as archive: - hash = hashlib.new(algorithm) - for chunk in read_chunks(archive): - hash.update(chunk) - return hash.hexdigest() diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/commands/help.py b/venv2/lib/python2.7/site-packages/pip/_internal/commands/help.py deleted file mode 100644 index 49a81cb..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/commands/help.py +++ /dev/null @@ -1,37 +0,0 @@ -from __future__ import absolute_import - -from pip._internal.cli.base_command import Command -from pip._internal.cli.status_codes import SUCCESS -from pip._internal.exceptions import CommandError - - -class HelpCommand(Command): - """Show help for commands""" - name = 'help' - usage = """ - %prog """ - summary = 'Show help for commands.' - ignore_require_venv = True - - def run(self, options, args): - from pip._internal.commands import commands_dict, get_similar_commands - - try: - # 'pip help' with no args is handled by pip.__init__.parseopt() - cmd_name = args[0] # the command we need help for - except IndexError: - return SUCCESS - - if cmd_name not in commands_dict: - guess = get_similar_commands(cmd_name) - - msg = ['unknown command "%s"' % cmd_name] - if guess: - msg.append('maybe you meant "%s"' % guess) - - raise CommandError(' - '.join(msg)) - - command = commands_dict[cmd_name]() - command.parser.print_help() - - return SUCCESS diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/commands/install.py b/venv2/lib/python2.7/site-packages/pip/_internal/commands/install.py deleted file mode 100644 index c13da44..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/commands/install.py +++ /dev/null @@ -1,587 +0,0 @@ -from __future__ import absolute_import - -import errno -import logging -import operator -import os -import shutil -from optparse import SUPPRESS_HELP - -from pip._vendor import pkg_resources - -from pip._internal.cache import WheelCache -from pip._internal.cli import cmdoptions -from pip._internal.cli.base_command import RequirementCommand -from pip._internal.cli.status_codes import ERROR -from pip._internal.exceptions import ( - CommandError, InstallationError, PreviousBuildDirError, -) -from pip._internal.locations import distutils_scheme, virtualenv_no_global -from pip._internal.operations.check import check_install_conflicts -from pip._internal.operations.prepare import RequirementPreparer -from pip._internal.req import RequirementSet, install_given_reqs -from pip._internal.req.req_tracker import RequirementTracker -from pip._internal.resolve import Resolver -from pip._internal.utils.filesystem import check_path_owner -from pip._internal.utils.misc import ( - ensure_dir, get_installed_version, - protect_pip_from_modification_on_windows, -) -from pip._internal.utils.temp_dir import TempDirectory -from pip._internal.wheel import WheelBuilder - -logger = logging.getLogger(__name__) - - -def is_wheel_installed(): - """ - Return whether the wheel package is installed. - """ - try: - import wheel # noqa: F401 - except ImportError: - return False - - return True - - -def build_wheels(builder, pep517_requirements, legacy_requirements, session): - """ - Build wheels for requirements, depending on whether wheel is installed. - """ - # We don't build wheels for legacy requirements if wheel is not installed. - should_build_legacy = is_wheel_installed() - - # Always build PEP 517 requirements - build_failures = builder.build( - pep517_requirements, - session=session, autobuilding=True - ) - - if should_build_legacy: - # We don't care about failures building legacy - # requirements, as we'll fall through to a direct - # install for those. - builder.build( - legacy_requirements, - session=session, autobuilding=True - ) - - return build_failures - - -class InstallCommand(RequirementCommand): - """ - Install packages from: - - - PyPI (and other indexes) using requirement specifiers. - - VCS project urls. - - Local project directories. - - Local or remote source archives. - - pip also supports installing from "requirements files", which provide - an easy way to specify a whole environment to be installed. - """ - name = 'install' - - usage = """ - %prog [options] [package-index-options] ... - %prog [options] -r [package-index-options] ... - %prog [options] [-e] ... - %prog [options] [-e] ... - %prog [options] ...""" - - summary = 'Install packages.' - - def __init__(self, *args, **kw): - super(InstallCommand, self).__init__(*args, **kw) - - cmd_opts = self.cmd_opts - - cmd_opts.add_option(cmdoptions.requirements()) - cmd_opts.add_option(cmdoptions.constraints()) - cmd_opts.add_option(cmdoptions.no_deps()) - cmd_opts.add_option(cmdoptions.pre()) - - cmd_opts.add_option(cmdoptions.editable()) - cmd_opts.add_option( - '-t', '--target', - dest='target_dir', - metavar='dir', - default=None, - help='Install packages into . ' - 'By default this will not replace existing files/folders in ' - '. Use --upgrade to replace existing packages in ' - 'with new versions.' - ) - cmd_opts.add_option(cmdoptions.platform()) - cmd_opts.add_option(cmdoptions.python_version()) - cmd_opts.add_option(cmdoptions.implementation()) - cmd_opts.add_option(cmdoptions.abi()) - - cmd_opts.add_option( - '--user', - dest='use_user_site', - action='store_true', - help="Install to the Python user install directory for your " - "platform. Typically ~/.local/, or %APPDATA%\\Python on " - "Windows. (See the Python documentation for site.USER_BASE " - "for full details.)") - cmd_opts.add_option( - '--no-user', - dest='use_user_site', - action='store_false', - help=SUPPRESS_HELP) - cmd_opts.add_option( - '--root', - dest='root_path', - metavar='dir', - default=None, - help="Install everything relative to this alternate root " - "directory.") - cmd_opts.add_option( - '--prefix', - dest='prefix_path', - metavar='dir', - default=None, - help="Installation prefix where lib, bin and other top-level " - "folders are placed") - - cmd_opts.add_option(cmdoptions.build_dir()) - - cmd_opts.add_option(cmdoptions.src()) - - cmd_opts.add_option( - '-U', '--upgrade', - dest='upgrade', - action='store_true', - help='Upgrade all specified packages to the newest available ' - 'version. The handling of dependencies depends on the ' - 'upgrade-strategy used.' - ) - - cmd_opts.add_option( - '--upgrade-strategy', - dest='upgrade_strategy', - default='only-if-needed', - choices=['only-if-needed', 'eager'], - help='Determines how dependency upgrading should be handled ' - '[default: %default]. ' - '"eager" - dependencies are upgraded regardless of ' - 'whether the currently installed version satisfies the ' - 'requirements of the upgraded package(s). ' - '"only-if-needed" - are upgraded only when they do not ' - 'satisfy the requirements of the upgraded package(s).' - ) - - cmd_opts.add_option( - '--force-reinstall', - dest='force_reinstall', - action='store_true', - help='Reinstall all packages even if they are already ' - 'up-to-date.') - - cmd_opts.add_option( - '-I', '--ignore-installed', - dest='ignore_installed', - action='store_true', - help='Ignore the installed packages (reinstalling instead).') - - cmd_opts.add_option(cmdoptions.ignore_requires_python()) - cmd_opts.add_option(cmdoptions.no_build_isolation()) - cmd_opts.add_option(cmdoptions.use_pep517()) - cmd_opts.add_option(cmdoptions.no_use_pep517()) - - cmd_opts.add_option(cmdoptions.install_options()) - cmd_opts.add_option(cmdoptions.global_options()) - - cmd_opts.add_option( - "--compile", - action="store_true", - dest="compile", - default=True, - help="Compile Python source files to bytecode", - ) - - cmd_opts.add_option( - "--no-compile", - action="store_false", - dest="compile", - help="Do not compile Python source files to bytecode", - ) - - cmd_opts.add_option( - "--no-warn-script-location", - action="store_false", - dest="warn_script_location", - default=True, - help="Do not warn when installing scripts outside PATH", - ) - cmd_opts.add_option( - "--no-warn-conflicts", - action="store_false", - dest="warn_about_conflicts", - default=True, - help="Do not warn about broken dependencies", - ) - - cmd_opts.add_option(cmdoptions.no_binary()) - cmd_opts.add_option(cmdoptions.only_binary()) - cmd_opts.add_option(cmdoptions.prefer_binary()) - cmd_opts.add_option(cmdoptions.no_clean()) - cmd_opts.add_option(cmdoptions.require_hashes()) - cmd_opts.add_option(cmdoptions.progress_bar()) - - index_opts = cmdoptions.make_option_group( - cmdoptions.index_group, - self.parser, - ) - - self.parser.insert_option_group(0, index_opts) - self.parser.insert_option_group(0, cmd_opts) - - def run(self, options, args): - cmdoptions.check_install_build_global(options) - upgrade_strategy = "to-satisfy-only" - if options.upgrade: - upgrade_strategy = options.upgrade_strategy - - if options.build_dir: - options.build_dir = os.path.abspath(options.build_dir) - - cmdoptions.check_dist_restriction(options, check_target=True) - - if options.python_version: - python_versions = [options.python_version] - else: - python_versions = None - - options.src_dir = os.path.abspath(options.src_dir) - install_options = options.install_options or [] - if options.use_user_site: - if options.prefix_path: - raise CommandError( - "Can not combine '--user' and '--prefix' as they imply " - "different installation locations" - ) - if virtualenv_no_global(): - raise InstallationError( - "Can not perform a '--user' install. User site-packages " - "are not visible in this virtualenv." - ) - install_options.append('--user') - install_options.append('--prefix=') - - target_temp_dir = TempDirectory(kind="target") - if options.target_dir: - options.ignore_installed = True - options.target_dir = os.path.abspath(options.target_dir) - if (os.path.exists(options.target_dir) and not - os.path.isdir(options.target_dir)): - raise CommandError( - "Target path exists but is not a directory, will not " - "continue." - ) - - # Create a target directory for using with the target option - target_temp_dir.create() - install_options.append('--home=' + target_temp_dir.path) - - global_options = options.global_options or [] - - with self._build_session(options) as session: - finder = self._build_package_finder( - options=options, - session=session, - platform=options.platform, - python_versions=python_versions, - abi=options.abi, - implementation=options.implementation, - ) - build_delete = (not (options.no_clean or options.build_dir)) - wheel_cache = WheelCache(options.cache_dir, options.format_control) - - if options.cache_dir and not check_path_owner(options.cache_dir): - logger.warning( - "The directory '%s' or its parent directory is not owned " - "by the current user and caching wheels has been " - "disabled. check the permissions and owner of that " - "directory. If executing pip with sudo, you may want " - "sudo's -H flag.", - options.cache_dir, - ) - options.cache_dir = None - - with RequirementTracker() as req_tracker, TempDirectory( - options.build_dir, delete=build_delete, kind="install" - ) as directory: - requirement_set = RequirementSet( - require_hashes=options.require_hashes, - check_supported_wheels=not options.target_dir, - ) - - try: - self.populate_requirement_set( - requirement_set, args, options, finder, session, - self.name, wheel_cache - ) - preparer = RequirementPreparer( - build_dir=directory.path, - src_dir=options.src_dir, - download_dir=None, - wheel_download_dir=None, - progress_bar=options.progress_bar, - build_isolation=options.build_isolation, - req_tracker=req_tracker, - ) - - resolver = Resolver( - preparer=preparer, - finder=finder, - session=session, - wheel_cache=wheel_cache, - use_user_site=options.use_user_site, - upgrade_strategy=upgrade_strategy, - force_reinstall=options.force_reinstall, - ignore_dependencies=options.ignore_dependencies, - ignore_requires_python=options.ignore_requires_python, - ignore_installed=options.ignore_installed, - isolated=options.isolated_mode, - use_pep517=options.use_pep517 - ) - resolver.resolve(requirement_set) - - protect_pip_from_modification_on_windows( - modifying_pip=requirement_set.has_requirement("pip") - ) - - # Consider legacy and PEP517-using requirements separately - legacy_requirements = [] - pep517_requirements = [] - for req in requirement_set.requirements.values(): - if req.use_pep517: - pep517_requirements.append(req) - else: - legacy_requirements.append(req) - - wheel_builder = WheelBuilder( - finder, preparer, wheel_cache, - build_options=[], global_options=[], - ) - - build_failures = build_wheels( - builder=wheel_builder, - pep517_requirements=pep517_requirements, - legacy_requirements=legacy_requirements, - session=session, - ) - - # If we're using PEP 517, we cannot do a direct install - # so we fail here. - if build_failures: - raise InstallationError( - "Could not build wheels for {} which use" - " PEP 517 and cannot be installed directly".format( - ", ".join(r.name for r in build_failures))) - - to_install = resolver.get_installation_order( - requirement_set - ) - - # Consistency Checking of the package set we're installing. - should_warn_about_conflicts = ( - not options.ignore_dependencies and - options.warn_about_conflicts - ) - if should_warn_about_conflicts: - self._warn_about_conflicts(to_install) - - # Don't warn about script install locations if - # --target has been specified - warn_script_location = options.warn_script_location - if options.target_dir: - warn_script_location = False - - installed = install_given_reqs( - to_install, - install_options, - global_options, - root=options.root_path, - home=target_temp_dir.path, - prefix=options.prefix_path, - pycompile=options.compile, - warn_script_location=warn_script_location, - use_user_site=options.use_user_site, - ) - - lib_locations = get_lib_location_guesses( - user=options.use_user_site, - home=target_temp_dir.path, - root=options.root_path, - prefix=options.prefix_path, - isolated=options.isolated_mode, - ) - working_set = pkg_resources.WorkingSet(lib_locations) - - reqs = sorted(installed, key=operator.attrgetter('name')) - items = [] - for req in reqs: - item = req.name - try: - installed_version = get_installed_version( - req.name, working_set=working_set - ) - if installed_version: - item += '-' + installed_version - except Exception: - pass - items.append(item) - installed = ' '.join(items) - if installed: - logger.info('Successfully installed %s', installed) - except EnvironmentError as error: - show_traceback = (self.verbosity >= 1) - - message = create_env_error_message( - error, show_traceback, options.use_user_site, - ) - logger.error(message, exc_info=show_traceback) - - return ERROR - except PreviousBuildDirError: - options.no_clean = True - raise - finally: - # Clean up - if not options.no_clean: - requirement_set.cleanup_files() - wheel_cache.cleanup() - - if options.target_dir: - self._handle_target_dir( - options.target_dir, target_temp_dir, options.upgrade - ) - return requirement_set - - def _handle_target_dir(self, target_dir, target_temp_dir, upgrade): - ensure_dir(target_dir) - - # Checking both purelib and platlib directories for installed - # packages to be moved to target directory - lib_dir_list = [] - - with target_temp_dir: - # Checking both purelib and platlib directories for installed - # packages to be moved to target directory - scheme = distutils_scheme('', home=target_temp_dir.path) - purelib_dir = scheme['purelib'] - platlib_dir = scheme['platlib'] - data_dir = scheme['data'] - - if os.path.exists(purelib_dir): - lib_dir_list.append(purelib_dir) - if os.path.exists(platlib_dir) and platlib_dir != purelib_dir: - lib_dir_list.append(platlib_dir) - if os.path.exists(data_dir): - lib_dir_list.append(data_dir) - - for lib_dir in lib_dir_list: - for item in os.listdir(lib_dir): - if lib_dir == data_dir: - ddir = os.path.join(data_dir, item) - if any(s.startswith(ddir) for s in lib_dir_list[:-1]): - continue - target_item_dir = os.path.join(target_dir, item) - if os.path.exists(target_item_dir): - if not upgrade: - logger.warning( - 'Target directory %s already exists. Specify ' - '--upgrade to force replacement.', - target_item_dir - ) - continue - if os.path.islink(target_item_dir): - logger.warning( - 'Target directory %s already exists and is ' - 'a link. Pip will not automatically replace ' - 'links, please remove if replacement is ' - 'desired.', - target_item_dir - ) - continue - if os.path.isdir(target_item_dir): - shutil.rmtree(target_item_dir) - else: - os.remove(target_item_dir) - - shutil.move( - os.path.join(lib_dir, item), - target_item_dir - ) - - def _warn_about_conflicts(self, to_install): - try: - package_set, _dep_info = check_install_conflicts(to_install) - except Exception: - logger.error("Error checking for conflicts.", exc_info=True) - return - missing, conflicting = _dep_info - - # NOTE: There is some duplication here from pip check - for project_name in missing: - version = package_set[project_name][0] - for dependency in missing[project_name]: - logger.critical( - "%s %s requires %s, which is not installed.", - project_name, version, dependency[1], - ) - - for project_name in conflicting: - version = package_set[project_name][0] - for dep_name, dep_version, req in conflicting[project_name]: - logger.critical( - "%s %s has requirement %s, but you'll have %s %s which is " - "incompatible.", - project_name, version, req, dep_name, dep_version, - ) - - -def get_lib_location_guesses(*args, **kwargs): - scheme = distutils_scheme('', *args, **kwargs) - return [scheme['purelib'], scheme['platlib']] - - -def create_env_error_message(error, show_traceback, using_user_site): - """Format an error message for an EnvironmentError - - It may occur anytime during the execution of the install command. - """ - parts = [] - - # Mention the error if we are not going to show a traceback - parts.append("Could not install packages due to an EnvironmentError") - if not show_traceback: - parts.append(": ") - parts.append(str(error)) - else: - parts.append(".") - - # Spilt the error indication from a helper message (if any) - parts[-1] += "\n" - - # Suggest useful actions to the user: - # (1) using user site-packages or (2) verifying the permissions - if error.errno == errno.EACCES: - user_option_part = "Consider using the `--user` option" - permissions_part = "Check the permissions" - - if not using_user_site: - parts.extend([ - user_option_part, " or ", - permissions_part.lower(), - ]) - else: - parts.append(permissions_part) - parts.append(".\n") - - return "".join(parts).strip() + "\n" diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/commands/list.py b/venv2/lib/python2.7/site-packages/pip/_internal/commands/list.py deleted file mode 100644 index d70782d..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/commands/list.py +++ /dev/null @@ -1,302 +0,0 @@ -from __future__ import absolute_import - -import json -import logging - -from pip._vendor import six -from pip._vendor.six.moves import zip_longest - -from pip._internal.cli import cmdoptions -from pip._internal.cli.base_command import Command -from pip._internal.exceptions import CommandError -from pip._internal.index import PackageFinder -from pip._internal.utils.misc import ( - dist_is_editable, get_installed_distributions, -) -from pip._internal.utils.packaging import get_installer - -logger = logging.getLogger(__name__) - - -class ListCommand(Command): - """ - List installed packages, including editables. - - Packages are listed in a case-insensitive sorted order. - """ - name = 'list' - usage = """ - %prog [options]""" - summary = 'List installed packages.' - - def __init__(self, *args, **kw): - super(ListCommand, self).__init__(*args, **kw) - - cmd_opts = self.cmd_opts - - cmd_opts.add_option( - '-o', '--outdated', - action='store_true', - default=False, - help='List outdated packages') - cmd_opts.add_option( - '-u', '--uptodate', - action='store_true', - default=False, - help='List uptodate packages') - cmd_opts.add_option( - '-e', '--editable', - action='store_true', - default=False, - help='List editable projects.') - cmd_opts.add_option( - '-l', '--local', - action='store_true', - default=False, - help=('If in a virtualenv that has global access, do not list ' - 'globally-installed packages.'), - ) - self.cmd_opts.add_option( - '--user', - dest='user', - action='store_true', - default=False, - help='Only output packages installed in user-site.') - - cmd_opts.add_option( - '--pre', - action='store_true', - default=False, - help=("Include pre-release and development versions. By default, " - "pip only finds stable versions."), - ) - - cmd_opts.add_option( - '--format', - action='store', - dest='list_format', - default="columns", - choices=('columns', 'freeze', 'json'), - help="Select the output format among: columns (default), freeze, " - "or json", - ) - - cmd_opts.add_option( - '--not-required', - action='store_true', - dest='not_required', - help="List packages that are not dependencies of " - "installed packages.", - ) - - cmd_opts.add_option( - '--exclude-editable', - action='store_false', - dest='include_editable', - help='Exclude editable package from output.', - ) - cmd_opts.add_option( - '--include-editable', - action='store_true', - dest='include_editable', - help='Include editable package from output.', - default=True, - ) - index_opts = cmdoptions.make_option_group( - cmdoptions.index_group, self.parser - ) - - self.parser.insert_option_group(0, index_opts) - self.parser.insert_option_group(0, cmd_opts) - - def _build_package_finder(self, options, index_urls, session): - """ - Create a package finder appropriate to this list command. - """ - return PackageFinder( - find_links=options.find_links, - index_urls=index_urls, - allow_all_prereleases=options.pre, - trusted_hosts=options.trusted_hosts, - session=session, - ) - - def run(self, options, args): - if options.outdated and options.uptodate: - raise CommandError( - "Options --outdated and --uptodate cannot be combined.") - - packages = get_installed_distributions( - local_only=options.local, - user_only=options.user, - editables_only=options.editable, - include_editables=options.include_editable, - ) - - # get_not_required must be called firstly in order to find and - # filter out all dependencies correctly. Otherwise a package - # can't be identified as requirement because some parent packages - # could be filtered out before. - if options.not_required: - packages = self.get_not_required(packages, options) - - if options.outdated: - packages = self.get_outdated(packages, options) - elif options.uptodate: - packages = self.get_uptodate(packages, options) - - self.output_package_listing(packages, options) - - def get_outdated(self, packages, options): - return [ - dist for dist in self.iter_packages_latest_infos(packages, options) - if dist.latest_version > dist.parsed_version - ] - - def get_uptodate(self, packages, options): - return [ - dist for dist in self.iter_packages_latest_infos(packages, options) - if dist.latest_version == dist.parsed_version - ] - - def get_not_required(self, packages, options): - dep_keys = set() - for dist in packages: - dep_keys.update(requirement.key for requirement in dist.requires()) - return {pkg for pkg in packages if pkg.key not in dep_keys} - - def iter_packages_latest_infos(self, packages, options): - index_urls = [options.index_url] + options.extra_index_urls - if options.no_index: - logger.debug('Ignoring indexes: %s', ','.join(index_urls)) - index_urls = [] - - with self._build_session(options) as session: - finder = self._build_package_finder(options, index_urls, session) - - for dist in packages: - typ = 'unknown' - all_candidates = finder.find_all_candidates(dist.key) - if not options.pre: - # Remove prereleases - all_candidates = [candidate for candidate in all_candidates - if not candidate.version.is_prerelease] - - evaluator = finder.candidate_evaluator - best_candidate = evaluator.get_best_candidate(all_candidates) - if best_candidate is None: - continue - - remote_version = best_candidate.version - if best_candidate.location.is_wheel: - typ = 'wheel' - else: - typ = 'sdist' - # This is dirty but makes the rest of the code much cleaner - dist.latest_version = remote_version - dist.latest_filetype = typ - yield dist - - def output_package_listing(self, packages, options): - packages = sorted( - packages, - key=lambda dist: dist.project_name.lower(), - ) - if options.list_format == 'columns' and packages: - data, header = format_for_columns(packages, options) - self.output_package_listing_columns(data, header) - elif options.list_format == 'freeze': - for dist in packages: - if options.verbose >= 1: - logger.info("%s==%s (%s)", dist.project_name, - dist.version, dist.location) - else: - logger.info("%s==%s", dist.project_name, dist.version) - elif options.list_format == 'json': - logger.info(format_for_json(packages, options)) - - def output_package_listing_columns(self, data, header): - # insert the header first: we need to know the size of column names - if len(data) > 0: - data.insert(0, header) - - pkg_strings, sizes = tabulate(data) - - # Create and add a separator. - if len(data) > 0: - pkg_strings.insert(1, " ".join(map(lambda x: '-' * x, sizes))) - - for val in pkg_strings: - logger.info(val) - - -def tabulate(vals): - # From pfmoore on GitHub: - # https://github.com/pypa/pip/issues/3651#issuecomment-216932564 - assert len(vals) > 0 - - sizes = [0] * max(len(x) for x in vals) - for row in vals: - sizes = [max(s, len(str(c))) for s, c in zip_longest(sizes, row)] - - result = [] - for row in vals: - display = " ".join([str(c).ljust(s) if c is not None else '' - for s, c in zip_longest(sizes, row)]) - result.append(display) - - return result, sizes - - -def format_for_columns(pkgs, options): - """ - Convert the package data into something usable - by output_package_listing_columns. - """ - running_outdated = options.outdated - # Adjust the header for the `pip list --outdated` case. - if running_outdated: - header = ["Package", "Version", "Latest", "Type"] - else: - header = ["Package", "Version"] - - data = [] - if options.verbose >= 1 or any(dist_is_editable(x) for x in pkgs): - header.append("Location") - if options.verbose >= 1: - header.append("Installer") - - for proj in pkgs: - # if we're working on the 'outdated' list, separate out the - # latest_version and type - row = [proj.project_name, proj.version] - - if running_outdated: - row.append(proj.latest_version) - row.append(proj.latest_filetype) - - if options.verbose >= 1 or dist_is_editable(proj): - row.append(proj.location) - if options.verbose >= 1: - row.append(get_installer(proj)) - - data.append(row) - - return data, header - - -def format_for_json(packages, options): - data = [] - for dist in packages: - info = { - 'name': dist.project_name, - 'version': six.text_type(dist.version), - } - if options.verbose >= 1: - info['location'] = dist.location - info['installer'] = get_installer(dist) - if options.outdated: - info['latest_version'] = six.text_type(dist.latest_version) - info['latest_filetype'] = dist.latest_filetype - data.append(info) - return json.dumps(data) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/commands/search.py b/venv2/lib/python2.7/site-packages/pip/_internal/commands/search.py deleted file mode 100644 index c157a31..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/commands/search.py +++ /dev/null @@ -1,135 +0,0 @@ -from __future__ import absolute_import - -import logging -import sys -import textwrap -from collections import OrderedDict - -from pip._vendor import pkg_resources -from pip._vendor.packaging.version import parse as parse_version -# NOTE: XMLRPC Client is not annotated in typeshed as on 2017-07-17, which is -# why we ignore the type on this import -from pip._vendor.six.moves import xmlrpc_client # type: ignore - -from pip._internal.cli.base_command import Command -from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS -from pip._internal.download import PipXmlrpcTransport -from pip._internal.exceptions import CommandError -from pip._internal.models.index import PyPI -from pip._internal.utils.compat import get_terminal_size -from pip._internal.utils.logging import indent_log - -logger = logging.getLogger(__name__) - - -class SearchCommand(Command): - """Search for PyPI packages whose name or summary contains .""" - name = 'search' - usage = """ - %prog [options] """ - summary = 'Search PyPI for packages.' - ignore_require_venv = True - - def __init__(self, *args, **kw): - super(SearchCommand, self).__init__(*args, **kw) - self.cmd_opts.add_option( - '-i', '--index', - dest='index', - metavar='URL', - default=PyPI.pypi_url, - help='Base URL of Python Package Index (default %default)') - - self.parser.insert_option_group(0, self.cmd_opts) - - def run(self, options, args): - if not args: - raise CommandError('Missing required argument (search query).') - query = args - pypi_hits = self.search(query, options) - hits = transform_hits(pypi_hits) - - terminal_width = None - if sys.stdout.isatty(): - terminal_width = get_terminal_size()[0] - - print_results(hits, terminal_width=terminal_width) - if pypi_hits: - return SUCCESS - return NO_MATCHES_FOUND - - def search(self, query, options): - index_url = options.index - with self._build_session(options) as session: - transport = PipXmlrpcTransport(index_url, session) - pypi = xmlrpc_client.ServerProxy(index_url, transport) - hits = pypi.search({'name': query, 'summary': query}, 'or') - return hits - - -def transform_hits(hits): - """ - The list from pypi is really a list of versions. We want a list of - packages with the list of versions stored inline. This converts the - list from pypi into one we can use. - """ - packages = OrderedDict() - for hit in hits: - name = hit['name'] - summary = hit['summary'] - version = hit['version'] - - if name not in packages.keys(): - packages[name] = { - 'name': name, - 'summary': summary, - 'versions': [version], - } - else: - packages[name]['versions'].append(version) - - # if this is the highest version, replace summary and score - if version == highest_version(packages[name]['versions']): - packages[name]['summary'] = summary - - return list(packages.values()) - - -def print_results(hits, name_column_width=None, terminal_width=None): - if not hits: - return - if name_column_width is None: - name_column_width = max([ - len(hit['name']) + len(highest_version(hit.get('versions', ['-']))) - for hit in hits - ]) + 4 - - installed_packages = [p.project_name for p in pkg_resources.working_set] - for hit in hits: - name = hit['name'] - summary = hit['summary'] or '' - latest = highest_version(hit.get('versions', ['-'])) - if terminal_width is not None: - target_width = terminal_width - name_column_width - 5 - if target_width > 10: - # wrap and indent summary to fit terminal - summary = textwrap.wrap(summary, target_width) - summary = ('\n' + ' ' * (name_column_width + 3)).join(summary) - - line = '%-*s - %s' % (name_column_width, - '%s (%s)' % (name, latest), summary) - try: - logger.info(line) - if name in installed_packages: - dist = pkg_resources.get_distribution(name) - with indent_log(): - if dist.version == latest: - logger.info('INSTALLED: %s (latest)', dist.version) - else: - logger.info('INSTALLED: %s', dist.version) - logger.info('LATEST: %s', latest) - except UnicodeEncodeError: - pass - - -def highest_version(versions): - return max(versions, key=parse_version) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/commands/show.py b/venv2/lib/python2.7/site-packages/pip/_internal/commands/show.py deleted file mode 100644 index a18a902..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/commands/show.py +++ /dev/null @@ -1,168 +0,0 @@ -from __future__ import absolute_import - -import logging -import os -from email.parser import FeedParser - -from pip._vendor import pkg_resources -from pip._vendor.packaging.utils import canonicalize_name - -from pip._internal.cli.base_command import Command -from pip._internal.cli.status_codes import ERROR, SUCCESS - -logger = logging.getLogger(__name__) - - -class ShowCommand(Command): - """ - Show information about one or more installed packages. - - The output is in RFC-compliant mail header format. - """ - name = 'show' - usage = """ - %prog [options] ...""" - summary = 'Show information about installed packages.' - ignore_require_venv = True - - def __init__(self, *args, **kw): - super(ShowCommand, self).__init__(*args, **kw) - self.cmd_opts.add_option( - '-f', '--files', - dest='files', - action='store_true', - default=False, - help='Show the full list of installed files for each package.') - - self.parser.insert_option_group(0, self.cmd_opts) - - def run(self, options, args): - if not args: - logger.warning('ERROR: Please provide a package name or names.') - return ERROR - query = args - - results = search_packages_info(query) - if not print_results( - results, list_files=options.files, verbose=options.verbose): - return ERROR - return SUCCESS - - -def search_packages_info(query): - """ - Gather details from installed distributions. Print distribution name, - version, location, and installed files. Installed files requires a - pip generated 'installed-files.txt' in the distributions '.egg-info' - directory. - """ - installed = {} - for p in pkg_resources.working_set: - installed[canonicalize_name(p.project_name)] = p - - query_names = [canonicalize_name(name) for name in query] - - for dist in [installed[pkg] for pkg in query_names if pkg in installed]: - package = { - 'name': dist.project_name, - 'version': dist.version, - 'location': dist.location, - 'requires': [dep.project_name for dep in dist.requires()], - } - file_list = None - metadata = None - if isinstance(dist, pkg_resources.DistInfoDistribution): - # RECORDs should be part of .dist-info metadatas - if dist.has_metadata('RECORD'): - lines = dist.get_metadata_lines('RECORD') - paths = [l.split(',')[0] for l in lines] - paths = [os.path.join(dist.location, p) for p in paths] - file_list = [os.path.relpath(p, dist.location) for p in paths] - - if dist.has_metadata('METADATA'): - metadata = dist.get_metadata('METADATA') - else: - # Otherwise use pip's log for .egg-info's - if dist.has_metadata('installed-files.txt'): - paths = dist.get_metadata_lines('installed-files.txt') - paths = [os.path.join(dist.egg_info, p) for p in paths] - file_list = [os.path.relpath(p, dist.location) for p in paths] - - if dist.has_metadata('PKG-INFO'): - metadata = dist.get_metadata('PKG-INFO') - - if dist.has_metadata('entry_points.txt'): - entry_points = dist.get_metadata_lines('entry_points.txt') - package['entry_points'] = entry_points - - if dist.has_metadata('INSTALLER'): - for line in dist.get_metadata_lines('INSTALLER'): - if line.strip(): - package['installer'] = line.strip() - break - - # @todo: Should pkg_resources.Distribution have a - # `get_pkg_info` method? - feed_parser = FeedParser() - feed_parser.feed(metadata) - pkg_info_dict = feed_parser.close() - for key in ('metadata-version', 'summary', - 'home-page', 'author', 'author-email', 'license'): - package[key] = pkg_info_dict.get(key) - - # It looks like FeedParser cannot deal with repeated headers - classifiers = [] - for line in metadata.splitlines(): - if line.startswith('Classifier: '): - classifiers.append(line[len('Classifier: '):]) - package['classifiers'] = classifiers - - if file_list: - package['files'] = sorted(file_list) - yield package - - -def print_results(distributions, list_files=False, verbose=False): - """ - Print the informations from installed distributions found. - """ - results_printed = False - for i, dist in enumerate(distributions): - results_printed = True - if i > 0: - logger.info("---") - - name = dist.get('name', '') - required_by = [ - pkg.project_name for pkg in pkg_resources.working_set - if name in [required.name for required in pkg.requires()] - ] - - logger.info("Name: %s", name) - logger.info("Version: %s", dist.get('version', '')) - logger.info("Summary: %s", dist.get('summary', '')) - logger.info("Home-page: %s", dist.get('home-page', '')) - logger.info("Author: %s", dist.get('author', '')) - logger.info("Author-email: %s", dist.get('author-email', '')) - logger.info("License: %s", dist.get('license', '')) - logger.info("Location: %s", dist.get('location', '')) - logger.info("Requires: %s", ', '.join(dist.get('requires', []))) - logger.info("Required-by: %s", ', '.join(required_by)) - - if verbose: - logger.info("Metadata-Version: %s", - dist.get('metadata-version', '')) - logger.info("Installer: %s", dist.get('installer', '')) - logger.info("Classifiers:") - for classifier in dist.get('classifiers', []): - logger.info(" %s", classifier) - logger.info("Entry-points:") - for entry in dist.get('entry_points', []): - logger.info(" %s", entry.strip()) - if list_files: - logger.info("Files:") - for line in dist.get('files', []): - logger.info(" %s", line.strip()) - if "files" not in dist: - logger.info("Cannot locate installed-files.txt") - return results_printed diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/commands/uninstall.py b/venv2/lib/python2.7/site-packages/pip/_internal/commands/uninstall.py deleted file mode 100644 index 0cd6f54..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/commands/uninstall.py +++ /dev/null @@ -1,78 +0,0 @@ -from __future__ import absolute_import - -from pip._vendor.packaging.utils import canonicalize_name - -from pip._internal.cli.base_command import Command -from pip._internal.exceptions import InstallationError -from pip._internal.req import parse_requirements -from pip._internal.req.constructors import install_req_from_line -from pip._internal.utils.misc import protect_pip_from_modification_on_windows - - -class UninstallCommand(Command): - """ - Uninstall packages. - - pip is able to uninstall most installed packages. Known exceptions are: - - - Pure distutils packages installed with ``python setup.py install``, which - leave behind no metadata to determine what files were installed. - - Script wrappers installed by ``python setup.py develop``. - """ - name = 'uninstall' - usage = """ - %prog [options] ... - %prog [options] -r ...""" - summary = 'Uninstall packages.' - - def __init__(self, *args, **kw): - super(UninstallCommand, self).__init__(*args, **kw) - self.cmd_opts.add_option( - '-r', '--requirement', - dest='requirements', - action='append', - default=[], - metavar='file', - help='Uninstall all the packages listed in the given requirements ' - 'file. This option can be used multiple times.', - ) - self.cmd_opts.add_option( - '-y', '--yes', - dest='yes', - action='store_true', - help="Don't ask for confirmation of uninstall deletions.") - - self.parser.insert_option_group(0, self.cmd_opts) - - def run(self, options, args): - with self._build_session(options) as session: - reqs_to_uninstall = {} - for name in args: - req = install_req_from_line( - name, isolated=options.isolated_mode, - ) - if req.name: - reqs_to_uninstall[canonicalize_name(req.name)] = req - for filename in options.requirements: - for req in parse_requirements( - filename, - options=options, - session=session): - if req.name: - reqs_to_uninstall[canonicalize_name(req.name)] = req - if not reqs_to_uninstall: - raise InstallationError( - 'You must give at least one requirement to %(name)s (see ' - '"pip help %(name)s")' % dict(name=self.name) - ) - - protect_pip_from_modification_on_windows( - modifying_pip="pip" in reqs_to_uninstall - ) - - for req in reqs_to_uninstall.values(): - uninstall_pathset = req.uninstall( - auto_confirm=options.yes, verbose=self.verbosity > 0, - ) - if uninstall_pathset: - uninstall_pathset.commit() diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/commands/wheel.py b/venv2/lib/python2.7/site-packages/pip/_internal/commands/wheel.py deleted file mode 100644 index cd72a3d..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/commands/wheel.py +++ /dev/null @@ -1,186 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import - -import logging -import os - -from pip._internal.cache import WheelCache -from pip._internal.cli import cmdoptions -from pip._internal.cli.base_command import RequirementCommand -from pip._internal.exceptions import CommandError, PreviousBuildDirError -from pip._internal.operations.prepare import RequirementPreparer -from pip._internal.req import RequirementSet -from pip._internal.req.req_tracker import RequirementTracker -from pip._internal.resolve import Resolver -from pip._internal.utils.temp_dir import TempDirectory -from pip._internal.wheel import WheelBuilder - -logger = logging.getLogger(__name__) - - -class WheelCommand(RequirementCommand): - """ - Build Wheel archives for your requirements and dependencies. - - Wheel is a built-package format, and offers the advantage of not - recompiling your software during every install. For more details, see the - wheel docs: https://wheel.readthedocs.io/en/latest/ - - Requirements: setuptools>=0.8, and wheel. - - 'pip wheel' uses the bdist_wheel setuptools extension from the wheel - package to build individual wheels. - - """ - - name = 'wheel' - usage = """ - %prog [options] ... - %prog [options] -r ... - %prog [options] [-e] ... - %prog [options] [-e] ... - %prog [options] ...""" - - summary = 'Build wheels from your requirements.' - - def __init__(self, *args, **kw): - super(WheelCommand, self).__init__(*args, **kw) - - cmd_opts = self.cmd_opts - - cmd_opts.add_option( - '-w', '--wheel-dir', - dest='wheel_dir', - metavar='dir', - default=os.curdir, - help=("Build wheels into , where the default is the " - "current working directory."), - ) - cmd_opts.add_option(cmdoptions.no_binary()) - cmd_opts.add_option(cmdoptions.only_binary()) - cmd_opts.add_option(cmdoptions.prefer_binary()) - cmd_opts.add_option( - '--build-option', - dest='build_options', - metavar='options', - action='append', - help="Extra arguments to be supplied to 'setup.py bdist_wheel'.", - ) - cmd_opts.add_option(cmdoptions.no_build_isolation()) - cmd_opts.add_option(cmdoptions.use_pep517()) - cmd_opts.add_option(cmdoptions.no_use_pep517()) - cmd_opts.add_option(cmdoptions.constraints()) - cmd_opts.add_option(cmdoptions.editable()) - cmd_opts.add_option(cmdoptions.requirements()) - cmd_opts.add_option(cmdoptions.src()) - cmd_opts.add_option(cmdoptions.ignore_requires_python()) - cmd_opts.add_option(cmdoptions.no_deps()) - cmd_opts.add_option(cmdoptions.build_dir()) - cmd_opts.add_option(cmdoptions.progress_bar()) - - cmd_opts.add_option( - '--global-option', - dest='global_options', - action='append', - metavar='options', - help="Extra global options to be supplied to the setup.py " - "call before the 'bdist_wheel' command.") - - cmd_opts.add_option( - '--pre', - action='store_true', - default=False, - help=("Include pre-release and development versions. By default, " - "pip only finds stable versions."), - ) - - cmd_opts.add_option(cmdoptions.no_clean()) - cmd_opts.add_option(cmdoptions.require_hashes()) - - index_opts = cmdoptions.make_option_group( - cmdoptions.index_group, - self.parser, - ) - - self.parser.insert_option_group(0, index_opts) - self.parser.insert_option_group(0, cmd_opts) - - def run(self, options, args): - cmdoptions.check_install_build_global(options) - - index_urls = [options.index_url] + options.extra_index_urls - if options.no_index: - logger.debug('Ignoring indexes: %s', ','.join(index_urls)) - index_urls = [] - - if options.build_dir: - options.build_dir = os.path.abspath(options.build_dir) - - options.src_dir = os.path.abspath(options.src_dir) - - with self._build_session(options) as session: - finder = self._build_package_finder(options, session) - build_delete = (not (options.no_clean or options.build_dir)) - wheel_cache = WheelCache(options.cache_dir, options.format_control) - - with RequirementTracker() as req_tracker, TempDirectory( - options.build_dir, delete=build_delete, kind="wheel" - ) as directory: - - requirement_set = RequirementSet( - require_hashes=options.require_hashes, - ) - - try: - self.populate_requirement_set( - requirement_set, args, options, finder, session, - self.name, wheel_cache - ) - - preparer = RequirementPreparer( - build_dir=directory.path, - src_dir=options.src_dir, - download_dir=None, - wheel_download_dir=options.wheel_dir, - progress_bar=options.progress_bar, - build_isolation=options.build_isolation, - req_tracker=req_tracker, - ) - - resolver = Resolver( - preparer=preparer, - finder=finder, - session=session, - wheel_cache=wheel_cache, - use_user_site=False, - upgrade_strategy="to-satisfy-only", - force_reinstall=False, - ignore_dependencies=options.ignore_dependencies, - ignore_requires_python=options.ignore_requires_python, - ignore_installed=True, - isolated=options.isolated_mode, - use_pep517=options.use_pep517 - ) - resolver.resolve(requirement_set) - - # build wheels - wb = WheelBuilder( - finder, preparer, wheel_cache, - build_options=options.build_options or [], - global_options=options.global_options or [], - no_clean=options.no_clean, - ) - build_failures = wb.build( - requirement_set.requirements.values(), session=session, - ) - if len(build_failures) != 0: - raise CommandError( - "Failed to build one or more wheels" - ) - except PreviousBuildDirError: - options.no_clean = True - raise - finally: - if not options.no_clean: - requirement_set.cleanup_files() - wheel_cache.cleanup() diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/configuration.py b/venv2/lib/python2.7/site-packages/pip/_internal/configuration.py deleted file mode 100644 index b199fa7..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/configuration.py +++ /dev/null @@ -1,384 +0,0 @@ -"""Configuration management setup - -Some terminology: -- name - As written in config files. -- value - Value associated with a name -- key - Name combined with it's section (section.name) -- variant - A single word describing where the configuration key-value pair came from -""" - -import locale -import logging -import os - -from pip._vendor.six.moves import configparser - -from pip._internal.exceptions import ( - ConfigurationError, ConfigurationFileCouldNotBeLoaded, -) -from pip._internal.locations import ( - global_config_files, legacy_config_file, new_config_file, site_config_file, -) -from pip._internal.utils.misc import ensure_dir, enum -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import ( - Any, Dict, Iterable, List, NewType, Optional, Tuple - ) - - RawConfigParser = configparser.RawConfigParser # Shorthand - Kind = NewType("Kind", str) - -logger = logging.getLogger(__name__) - - -# NOTE: Maybe use the optionx attribute to normalize keynames. -def _normalize_name(name): - # type: (str) -> str - """Make a name consistent regardless of source (environment or file) - """ - name = name.lower().replace('_', '-') - if name.startswith('--'): - name = name[2:] # only prefer long opts - return name - - -def _disassemble_key(name): - # type: (str) -> List[str] - return name.split(".", 1) - - -# The kinds of configurations there are. -kinds = enum( - USER="user", # User Specific - GLOBAL="global", # System Wide - SITE="site", # [Virtual] Environment Specific - ENV="env", # from PIP_CONFIG_FILE - ENV_VAR="env-var", # from Environment Variables -) - - -class Configuration(object): - """Handles management of configuration. - - Provides an interface to accessing and managing configuration files. - - This class converts provides an API that takes "section.key-name" style - keys and stores the value associated with it as "key-name" under the - section "section". - - This allows for a clean interface wherein the both the section and the - key-name are preserved in an easy to manage form in the configuration files - and the data stored is also nice. - """ - - def __init__(self, isolated, load_only=None): - # type: (bool, Kind) -> None - super(Configuration, self).__init__() - - _valid_load_only = [kinds.USER, kinds.GLOBAL, kinds.SITE, None] - if load_only not in _valid_load_only: - raise ConfigurationError( - "Got invalid value for load_only - should be one of {}".format( - ", ".join(map(repr, _valid_load_only[:-1])) - ) - ) - self.isolated = isolated # type: bool - self.load_only = load_only # type: Optional[Kind] - - # The order here determines the override order. - self._override_order = [ - kinds.GLOBAL, kinds.USER, kinds.SITE, kinds.ENV, kinds.ENV_VAR - ] - - self._ignore_env_names = ["version", "help"] - - # Because we keep track of where we got the data from - self._parsers = { - variant: [] for variant in self._override_order - } # type: Dict[Kind, List[Tuple[str, RawConfigParser]]] - self._config = { - variant: {} for variant in self._override_order - } # type: Dict[Kind, Dict[str, Any]] - self._modified_parsers = [] # type: List[Tuple[str, RawConfigParser]] - - def load(self): - # type: () -> None - """Loads configuration from configuration files and environment - """ - self._load_config_files() - if not self.isolated: - self._load_environment_vars() - - def get_file_to_edit(self): - # type: () -> Optional[str] - """Returns the file with highest priority in configuration - """ - assert self.load_only is not None, \ - "Need to be specified a file to be editing" - - try: - return self._get_parser_to_modify()[0] - except IndexError: - return None - - def items(self): - # type: () -> Iterable[Tuple[str, Any]] - """Returns key-value pairs like dict.items() representing the loaded - configuration - """ - return self._dictionary.items() - - def get_value(self, key): - # type: (str) -> Any - """Get a value from the configuration. - """ - try: - return self._dictionary[key] - except KeyError: - raise ConfigurationError("No such key - {}".format(key)) - - def set_value(self, key, value): - # type: (str, Any) -> None - """Modify a value in the configuration. - """ - self._ensure_have_load_only() - - fname, parser = self._get_parser_to_modify() - - if parser is not None: - section, name = _disassemble_key(key) - - # Modify the parser and the configuration - if not parser.has_section(section): - parser.add_section(section) - parser.set(section, name, value) - - self._config[self.load_only][key] = value - self._mark_as_modified(fname, parser) - - def unset_value(self, key): - # type: (str) -> None - """Unset a value in the configuration. - """ - self._ensure_have_load_only() - - if key not in self._config[self.load_only]: - raise ConfigurationError("No such key - {}".format(key)) - - fname, parser = self._get_parser_to_modify() - - if parser is not None: - section, name = _disassemble_key(key) - - # Remove the key in the parser - modified_something = False - if parser.has_section(section): - # Returns whether the option was removed or not - modified_something = parser.remove_option(section, name) - - if modified_something: - # name removed from parser, section may now be empty - section_iter = iter(parser.items(section)) - try: - val = next(section_iter) - except StopIteration: - val = None - - if val is None: - parser.remove_section(section) - - self._mark_as_modified(fname, parser) - else: - raise ConfigurationError( - "Fatal Internal error [id=1]. Please report as a bug." - ) - - del self._config[self.load_only][key] - - def save(self): - # type: () -> None - """Save the current in-memory state. - """ - self._ensure_have_load_only() - - for fname, parser in self._modified_parsers: - logger.info("Writing to %s", fname) - - # Ensure directory exists. - ensure_dir(os.path.dirname(fname)) - - with open(fname, "w") as f: - parser.write(f) - - # - # Private routines - # - - def _ensure_have_load_only(self): - # type: () -> None - if self.load_only is None: - raise ConfigurationError("Needed a specific file to be modifying.") - logger.debug("Will be working with %s variant only", self.load_only) - - @property - def _dictionary(self): - # type: () -> Dict[str, Any] - """A dictionary representing the loaded configuration. - """ - # NOTE: Dictionaries are not populated if not loaded. So, conditionals - # are not needed here. - retval = {} - - for variant in self._override_order: - retval.update(self._config[variant]) - - return retval - - def _load_config_files(self): - # type: () -> None - """Loads configuration from configuration files - """ - config_files = dict(self._iter_config_files()) - if config_files[kinds.ENV][0:1] == [os.devnull]: - logger.debug( - "Skipping loading configuration files due to " - "environment's PIP_CONFIG_FILE being os.devnull" - ) - return - - for variant, files in config_files.items(): - for fname in files: - # If there's specific variant set in `load_only`, load only - # that variant, not the others. - if self.load_only is not None and variant != self.load_only: - logger.debug( - "Skipping file '%s' (variant: %s)", fname, variant - ) - continue - - parser = self._load_file(variant, fname) - - # Keeping track of the parsers used - self._parsers[variant].append((fname, parser)) - - def _load_file(self, variant, fname): - # type: (Kind, str) -> RawConfigParser - logger.debug("For variant '%s', will try loading '%s'", variant, fname) - parser = self._construct_parser(fname) - - for section in parser.sections(): - items = parser.items(section) - self._config[variant].update(self._normalized_keys(section, items)) - - return parser - - def _construct_parser(self, fname): - # type: (str) -> RawConfigParser - parser = configparser.RawConfigParser() - # If there is no such file, don't bother reading it but create the - # parser anyway, to hold the data. - # Doing this is useful when modifying and saving files, where we don't - # need to construct a parser. - if os.path.exists(fname): - try: - parser.read(fname) - except UnicodeDecodeError: - # See https://github.com/pypa/pip/issues/4963 - raise ConfigurationFileCouldNotBeLoaded( - reason="contains invalid {} characters".format( - locale.getpreferredencoding(False) - ), - fname=fname, - ) - except configparser.Error as error: - # See https://github.com/pypa/pip/issues/4893 - raise ConfigurationFileCouldNotBeLoaded(error=error) - return parser - - def _load_environment_vars(self): - # type: () -> None - """Loads configuration from environment variables - """ - self._config[kinds.ENV_VAR].update( - self._normalized_keys(":env:", self._get_environ_vars()) - ) - - def _normalized_keys(self, section, items): - # type: (str, Iterable[Tuple[str, Any]]) -> Dict[str, Any] - """Normalizes items to construct a dictionary with normalized keys. - - This routine is where the names become keys and are made the same - regardless of source - configuration files or environment. - """ - normalized = {} - for name, val in items: - key = section + "." + _normalize_name(name) - normalized[key] = val - return normalized - - def _get_environ_vars(self): - # type: () -> Iterable[Tuple[str, str]] - """Returns a generator with all environmental vars with prefix PIP_""" - for key, val in os.environ.items(): - should_be_yielded = ( - key.startswith("PIP_") and - key[4:].lower() not in self._ignore_env_names - ) - if should_be_yielded: - yield key[4:].lower(), val - - # XXX: This is patched in the tests. - def _iter_config_files(self): - # type: () -> Iterable[Tuple[Kind, List[str]]] - """Yields variant and configuration files associated with it. - - This should be treated like items of a dictionary. - """ - # SMELL: Move the conditions out of this function - - # environment variables have the lowest priority - config_file = os.environ.get('PIP_CONFIG_FILE', None) - if config_file is not None: - yield kinds.ENV, [config_file] - else: - yield kinds.ENV, [] - - # at the base we have any global configuration - yield kinds.GLOBAL, list(global_config_files) - - # per-user configuration next - should_load_user_config = not self.isolated and not ( - config_file and os.path.exists(config_file) - ) - if should_load_user_config: - # The legacy config file is overridden by the new config file - yield kinds.USER, [legacy_config_file, new_config_file] - - # finally virtualenv configuration first trumping others - yield kinds.SITE, [site_config_file] - - def _get_parser_to_modify(self): - # type: () -> Tuple[str, RawConfigParser] - # Determine which parser to modify - parsers = self._parsers[self.load_only] - if not parsers: - # This should not happen if everything works correctly. - raise ConfigurationError( - "Fatal Internal error [id=2]. Please report as a bug." - ) - - # Use the highest priority parser. - return parsers[-1] - - # XXX: This is patched in the tests. - def _mark_as_modified(self, fname, parser): - # type: (str, RawConfigParser) -> None - file_parser_tuple = (fname, parser) - if file_parser_tuple not in self._modified_parsers: - self._modified_parsers.append(file_parser_tuple) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/download.py b/venv2/lib/python2.7/site-packages/pip/_internal/download.py deleted file mode 100644 index 2683cf0..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/download.py +++ /dev/null @@ -1,979 +0,0 @@ -from __future__ import absolute_import - -import cgi -import email.utils -import getpass -import json -import logging -import mimetypes -import os -import platform -import re -import shutil -import sys - -from pip._vendor import requests, six, urllib3 -from pip._vendor.cachecontrol import CacheControlAdapter -from pip._vendor.cachecontrol.caches import FileCache -from pip._vendor.lockfile import LockError -from pip._vendor.requests.adapters import BaseAdapter, HTTPAdapter -from pip._vendor.requests.auth import AuthBase, HTTPBasicAuth -from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response -from pip._vendor.requests.structures import CaseInsensitiveDict -from pip._vendor.requests.utils import get_netrc_auth -# NOTE: XMLRPC Client is not annotated in typeshed as on 2017-07-17, which is -# why we ignore the type on this import -from pip._vendor.six.moves import xmlrpc_client # type: ignore -from pip._vendor.six.moves.urllib import parse as urllib_parse -from pip._vendor.six.moves.urllib import request as urllib_request -from pip._vendor.urllib3.util import IS_PYOPENSSL - -import pip -from pip._internal.exceptions import HashMismatch, InstallationError -from pip._internal.locations import write_delete_marker_file -from pip._internal.models.index import PyPI -from pip._internal.utils.encoding import auto_decode -from pip._internal.utils.filesystem import check_path_owner -from pip._internal.utils.glibc import libc_ver -from pip._internal.utils.misc import ( - ARCHIVE_EXTENSIONS, ask_path_exists, backup_dir, consume, display_path, - format_size, get_installed_version, rmtree, split_auth_from_netloc, - splitext, unpack_file, -) -from pip._internal.utils.temp_dir import TempDirectory -from pip._internal.utils.typing import MYPY_CHECK_RUNNING -from pip._internal.utils.ui import DownloadProgressProvider -from pip._internal.vcs import vcs - -if MYPY_CHECK_RUNNING: - from typing import ( - Optional, Tuple, Dict, IO, Text, Union - ) - from pip._internal.models.link import Link - from pip._internal.utils.hashes import Hashes - from pip._internal.vcs import AuthInfo - -try: - import ssl # noqa -except ImportError: - ssl = None - -HAS_TLS = (ssl is not None) or IS_PYOPENSSL - -__all__ = ['get_file_content', - 'is_url', 'url_to_path', 'path_to_url', - 'is_archive_file', 'unpack_vcs_link', - 'unpack_file_url', 'is_vcs_url', 'is_file_url', - 'unpack_http_url', 'unpack_url'] - - -logger = logging.getLogger(__name__) - - -# These are environment variables present when running under various -# CI systems. For each variable, some CI systems that use the variable -# are indicated. The collection was chosen so that for each of a number -# of popular systems, at least one of the environment variables is used. -# This list is used to provide some indication of and lower bound for -# CI traffic to PyPI. Thus, it is okay if the list is not comprehensive. -# For more background, see: https://github.com/pypa/pip/issues/5499 -CI_ENVIRONMENT_VARIABLES = ( - # Azure Pipelines - 'BUILD_BUILDID', - # Jenkins - 'BUILD_ID', - # AppVeyor, CircleCI, Codeship, Gitlab CI, Shippable, Travis CI - 'CI', -) - - -def looks_like_ci(): - # type: () -> bool - """ - Return whether it looks like pip is running under CI. - """ - # We don't use the method of checking for a tty (e.g. using isatty()) - # because some CI systems mimic a tty (e.g. Travis CI). Thus that - # method doesn't provide definitive information in either direction. - return any(name in os.environ for name in CI_ENVIRONMENT_VARIABLES) - - -def user_agent(): - """ - Return a string representing the user agent. - """ - data = { - "installer": {"name": "pip", "version": pip.__version__}, - "python": platform.python_version(), - "implementation": { - "name": platform.python_implementation(), - }, - } - - if data["implementation"]["name"] == 'CPython': - data["implementation"]["version"] = platform.python_version() - elif data["implementation"]["name"] == 'PyPy': - if sys.pypy_version_info.releaselevel == 'final': - pypy_version_info = sys.pypy_version_info[:3] - else: - pypy_version_info = sys.pypy_version_info - data["implementation"]["version"] = ".".join( - [str(x) for x in pypy_version_info] - ) - elif data["implementation"]["name"] == 'Jython': - # Complete Guess - data["implementation"]["version"] = platform.python_version() - elif data["implementation"]["name"] == 'IronPython': - # Complete Guess - data["implementation"]["version"] = platform.python_version() - - if sys.platform.startswith("linux"): - from pip._vendor import distro - distro_infos = dict(filter( - lambda x: x[1], - zip(["name", "version", "id"], distro.linux_distribution()), - )) - libc = dict(filter( - lambda x: x[1], - zip(["lib", "version"], libc_ver()), - )) - if libc: - distro_infos["libc"] = libc - if distro_infos: - data["distro"] = distro_infos - - if sys.platform.startswith("darwin") and platform.mac_ver()[0]: - data["distro"] = {"name": "macOS", "version": platform.mac_ver()[0]} - - if platform.system(): - data.setdefault("system", {})["name"] = platform.system() - - if platform.release(): - data.setdefault("system", {})["release"] = platform.release() - - if platform.machine(): - data["cpu"] = platform.machine() - - if HAS_TLS: - data["openssl_version"] = ssl.OPENSSL_VERSION - - setuptools_version = get_installed_version("setuptools") - if setuptools_version is not None: - data["setuptools_version"] = setuptools_version - - # Use None rather than False so as not to give the impression that - # pip knows it is not being run under CI. Rather, it is a null or - # inconclusive result. Also, we include some value rather than no - # value to make it easier to know that the check has been run. - data["ci"] = True if looks_like_ci() else None - - user_data = os.environ.get("PIP_USER_AGENT_USER_DATA") - if user_data is not None: - data["user_data"] = user_data - - return "{data[installer][name]}/{data[installer][version]} {json}".format( - data=data, - json=json.dumps(data, separators=(",", ":"), sort_keys=True), - ) - - -class MultiDomainBasicAuth(AuthBase): - - def __init__(self, prompting=True): - # type: (bool) -> None - self.prompting = prompting - self.passwords = {} # type: Dict[str, AuthInfo] - - def __call__(self, req): - parsed = urllib_parse.urlparse(req.url) - - # Split the credentials from the netloc. - netloc, url_user_password = split_auth_from_netloc(parsed.netloc) - - # Set the url of the request to the url without any credentials - req.url = urllib_parse.urlunparse(parsed[:1] + (netloc,) + parsed[2:]) - - # Use any stored credentials that we have for this netloc - username, password = self.passwords.get(netloc, (None, None)) - - # Use the credentials embedded in the url if we have none stored - if username is None: - username, password = url_user_password - - # Get creds from netrc if we still don't have them - if username is None and password is None: - netrc_auth = get_netrc_auth(req.url) - username, password = netrc_auth if netrc_auth else (None, None) - - if username or password: - # Store the username and password - self.passwords[netloc] = (username, password) - - # Send the basic auth with this request - req = HTTPBasicAuth(username or "", password or "")(req) - - # Attach a hook to handle 401 responses - req.register_hook("response", self.handle_401) - - return req - - def handle_401(self, resp, **kwargs): - # We only care about 401 responses, anything else we want to just - # pass through the actual response - if resp.status_code != 401: - return resp - - # We are not able to prompt the user so simply return the response - if not self.prompting: - return resp - - parsed = urllib_parse.urlparse(resp.url) - - # Prompt the user for a new username and password - username = six.moves.input("User for %s: " % parsed.netloc) - password = getpass.getpass("Password: ") - - # Store the new username and password to use for future requests - if username or password: - self.passwords[parsed.netloc] = (username, password) - - # Consume content and release the original connection to allow our new - # request to reuse the same one. - resp.content - resp.raw.release_conn() - - # Add our new username and password to the request - req = HTTPBasicAuth(username or "", password or "")(resp.request) - req.register_hook("response", self.warn_on_401) - - # Send our new request - new_resp = resp.connection.send(req, **kwargs) - new_resp.history.append(resp) - - return new_resp - - def warn_on_401(self, resp, **kwargs): - # warn user that they provided incorrect credentials - if resp.status_code == 401: - logger.warning('401 Error, Credentials not correct for %s', - resp.request.url) - - -class LocalFSAdapter(BaseAdapter): - - def send(self, request, stream=None, timeout=None, verify=None, cert=None, - proxies=None): - pathname = url_to_path(request.url) - - resp = Response() - resp.status_code = 200 - resp.url = request.url - - try: - stats = os.stat(pathname) - except OSError as exc: - resp.status_code = 404 - resp.raw = exc - else: - modified = email.utils.formatdate(stats.st_mtime, usegmt=True) - content_type = mimetypes.guess_type(pathname)[0] or "text/plain" - resp.headers = CaseInsensitiveDict({ - "Content-Type": content_type, - "Content-Length": stats.st_size, - "Last-Modified": modified, - }) - - resp.raw = open(pathname, "rb") - resp.close = resp.raw.close - - return resp - - def close(self): - pass - - -class SafeFileCache(FileCache): - """ - A file based cache which is safe to use even when the target directory may - not be accessible or writable. - """ - - def __init__(self, *args, **kwargs): - super(SafeFileCache, self).__init__(*args, **kwargs) - - # Check to ensure that the directory containing our cache directory - # is owned by the user current executing pip. If it does not exist - # we will check the parent directory until we find one that does exist. - # If it is not owned by the user executing pip then we will disable - # the cache and log a warning. - if not check_path_owner(self.directory): - logger.warning( - "The directory '%s' or its parent directory is not owned by " - "the current user and the cache has been disabled. Please " - "check the permissions and owner of that directory. If " - "executing pip with sudo, you may want sudo's -H flag.", - self.directory, - ) - - # Set our directory to None to disable the Cache - self.directory = None - - def get(self, *args, **kwargs): - # If we don't have a directory, then the cache should be a no-op. - if self.directory is None: - return - - try: - return super(SafeFileCache, self).get(*args, **kwargs) - except (LockError, OSError, IOError): - # We intentionally silence this error, if we can't access the cache - # then we can just skip caching and process the request as if - # caching wasn't enabled. - pass - - def set(self, *args, **kwargs): - # If we don't have a directory, then the cache should be a no-op. - if self.directory is None: - return - - try: - return super(SafeFileCache, self).set(*args, **kwargs) - except (LockError, OSError, IOError): - # We intentionally silence this error, if we can't access the cache - # then we can just skip caching and process the request as if - # caching wasn't enabled. - pass - - def delete(self, *args, **kwargs): - # If we don't have a directory, then the cache should be a no-op. - if self.directory is None: - return - - try: - return super(SafeFileCache, self).delete(*args, **kwargs) - except (LockError, OSError, IOError): - # We intentionally silence this error, if we can't access the cache - # then we can just skip caching and process the request as if - # caching wasn't enabled. - pass - - -class InsecureHTTPAdapter(HTTPAdapter): - - def cert_verify(self, conn, url, verify, cert): - conn.cert_reqs = 'CERT_NONE' - conn.ca_certs = None - - -class PipSession(requests.Session): - - timeout = None # type: Optional[int] - - def __init__(self, *args, **kwargs): - retries = kwargs.pop("retries", 0) - cache = kwargs.pop("cache", None) - insecure_hosts = kwargs.pop("insecure_hosts", []) - - super(PipSession, self).__init__(*args, **kwargs) - - # Attach our User Agent to the request - self.headers["User-Agent"] = user_agent() - - # Attach our Authentication handler to the session - self.auth = MultiDomainBasicAuth() - - # Create our urllib3.Retry instance which will allow us to customize - # how we handle retries. - retries = urllib3.Retry( - # Set the total number of retries that a particular request can - # have. - total=retries, - - # A 503 error from PyPI typically means that the Fastly -> Origin - # connection got interrupted in some way. A 503 error in general - # is typically considered a transient error so we'll go ahead and - # retry it. - # A 500 may indicate transient error in Amazon S3 - # A 520 or 527 - may indicate transient error in CloudFlare - status_forcelist=[500, 503, 520, 527], - - # Add a small amount of back off between failed requests in - # order to prevent hammering the service. - backoff_factor=0.25, - ) - - # We want to _only_ cache responses on securely fetched origins. We do - # this because we can't validate the response of an insecurely fetched - # origin, and we don't want someone to be able to poison the cache and - # require manual eviction from the cache to fix it. - if cache: - secure_adapter = CacheControlAdapter( - cache=SafeFileCache(cache, use_dir_lock=True), - max_retries=retries, - ) - else: - secure_adapter = HTTPAdapter(max_retries=retries) - - # Our Insecure HTTPAdapter disables HTTPS validation. It does not - # support caching (see above) so we'll use it for all http:// URLs as - # well as any https:// host that we've marked as ignoring TLS errors - # for. - insecure_adapter = InsecureHTTPAdapter(max_retries=retries) - - self.mount("https://", secure_adapter) - self.mount("http://", insecure_adapter) - - # Enable file:// urls - self.mount("file://", LocalFSAdapter()) - - # We want to use a non-validating adapter for any requests which are - # deemed insecure. - for host in insecure_hosts: - self.mount("https://{}/".format(host), insecure_adapter) - - def request(self, method, url, *args, **kwargs): - # Allow setting a default timeout on a session - kwargs.setdefault("timeout", self.timeout) - - # Dispatch the actual request - return super(PipSession, self).request(method, url, *args, **kwargs) - - -def get_file_content(url, comes_from=None, session=None): - # type: (str, Optional[str], Optional[PipSession]) -> Tuple[str, Text] - """Gets the content of a file; it may be a filename, file: URL, or - http: URL. Returns (location, content). Content is unicode. - - :param url: File path or url. - :param comes_from: Origin description of requirements. - :param session: Instance of pip.download.PipSession. - """ - if session is None: - raise TypeError( - "get_file_content() missing 1 required keyword argument: 'session'" - ) - - match = _scheme_re.search(url) - if match: - scheme = match.group(1).lower() - if (scheme == 'file' and comes_from and - comes_from.startswith('http')): - raise InstallationError( - 'Requirements file %s references URL %s, which is local' - % (comes_from, url)) - if scheme == 'file': - path = url.split(':', 1)[1] - path = path.replace('\\', '/') - match = _url_slash_drive_re.match(path) - if match: - path = match.group(1) + ':' + path.split('|', 1)[1] - path = urllib_parse.unquote(path) - if path.startswith('/'): - path = '/' + path.lstrip('/') - url = path - else: - # FIXME: catch some errors - resp = session.get(url) - resp.raise_for_status() - return resp.url, resp.text - try: - with open(url, 'rb') as f: - content = auto_decode(f.read()) - except IOError as exc: - raise InstallationError( - 'Could not open requirements file: %s' % str(exc) - ) - return url, content - - -_scheme_re = re.compile(r'^(http|https|file):', re.I) -_url_slash_drive_re = re.compile(r'/*([a-z])\|', re.I) - - -def is_url(name): - # type: (Union[str, Text]) -> bool - """Returns true if the name looks like a URL""" - if ':' not in name: - return False - scheme = name.split(':', 1)[0].lower() - return scheme in ['http', 'https', 'file', 'ftp'] + vcs.all_schemes - - -def url_to_path(url): - # type: (str) -> str - """ - Convert a file: URL to a path. - """ - assert url.startswith('file:'), ( - "You can only turn file: urls into filenames (not %r)" % url) - - _, netloc, path, _, _ = urllib_parse.urlsplit(url) - - if not netloc or netloc == 'localhost': - # According to RFC 8089, same as empty authority. - netloc = '' - elif sys.platform == 'win32': - # If we have a UNC path, prepend UNC share notation. - netloc = '\\\\' + netloc - else: - raise ValueError( - 'non-local file URIs are not supported on this platform: %r' - % url - ) - - path = urllib_request.url2pathname(netloc + path) - return path - - -def path_to_url(path): - # type: (Union[str, Text]) -> str - """ - Convert a path to a file: URL. The path will be made absolute and have - quoted path parts. - """ - path = os.path.normpath(os.path.abspath(path)) - url = urllib_parse.urljoin('file:', urllib_request.pathname2url(path)) - return url - - -def is_archive_file(name): - # type: (str) -> bool - """Return True if `name` is a considered as an archive file.""" - ext = splitext(name)[1].lower() - if ext in ARCHIVE_EXTENSIONS: - return True - return False - - -def unpack_vcs_link(link, location): - vcs_backend = _get_used_vcs_backend(link) - vcs_backend.unpack(location) - - -def _get_used_vcs_backend(link): - for backend in vcs.backends: - if link.scheme in backend.schemes: - vcs_backend = backend(link.url) - return vcs_backend - - -def is_vcs_url(link): - # type: (Link) -> bool - return bool(_get_used_vcs_backend(link)) - - -def is_file_url(link): - # type: (Link) -> bool - return link.url.lower().startswith('file:') - - -def is_dir_url(link): - # type: (Link) -> bool - """Return whether a file:// Link points to a directory. - - ``link`` must not have any other scheme but file://. Call is_file_url() - first. - - """ - link_path = url_to_path(link.url_without_fragment) - return os.path.isdir(link_path) - - -def _progress_indicator(iterable, *args, **kwargs): - return iterable - - -def _download_url( - resp, # type: Response - link, # type: Link - content_file, # type: IO - hashes, # type: Hashes - progress_bar # type: str -): - # type: (...) -> None - try: - total_length = int(resp.headers['content-length']) - except (ValueError, KeyError, TypeError): - total_length = 0 - - cached_resp = getattr(resp, "from_cache", False) - if logger.getEffectiveLevel() > logging.INFO: - show_progress = False - elif cached_resp: - show_progress = False - elif total_length > (40 * 1000): - show_progress = True - elif not total_length: - show_progress = True - else: - show_progress = False - - show_url = link.show_url - - def resp_read(chunk_size): - try: - # Special case for urllib3. - for chunk in resp.raw.stream( - chunk_size, - # We use decode_content=False here because we don't - # want urllib3 to mess with the raw bytes we get - # from the server. If we decompress inside of - # urllib3 then we cannot verify the checksum - # because the checksum will be of the compressed - # file. This breakage will only occur if the - # server adds a Content-Encoding header, which - # depends on how the server was configured: - # - Some servers will notice that the file isn't a - # compressible file and will leave the file alone - # and with an empty Content-Encoding - # - Some servers will notice that the file is - # already compressed and will leave the file - # alone and will add a Content-Encoding: gzip - # header - # - Some servers won't notice anything at all and - # will take a file that's already been compressed - # and compress it again and set the - # Content-Encoding: gzip header - # - # By setting this not to decode automatically we - # hope to eliminate problems with the second case. - decode_content=False): - yield chunk - except AttributeError: - # Standard file-like object. - while True: - chunk = resp.raw.read(chunk_size) - if not chunk: - break - yield chunk - - def written_chunks(chunks): - for chunk in chunks: - content_file.write(chunk) - yield chunk - - progress_indicator = _progress_indicator - - if link.netloc == PyPI.netloc: - url = show_url - else: - url = link.url_without_fragment - - if show_progress: # We don't show progress on cached responses - progress_indicator = DownloadProgressProvider(progress_bar, - max=total_length) - if total_length: - logger.info("Downloading %s (%s)", url, format_size(total_length)) - else: - logger.info("Downloading %s", url) - elif cached_resp: - logger.info("Using cached %s", url) - else: - logger.info("Downloading %s", url) - - logger.debug('Downloading from URL %s', link) - - downloaded_chunks = written_chunks( - progress_indicator( - resp_read(CONTENT_CHUNK_SIZE), - CONTENT_CHUNK_SIZE - ) - ) - if hashes: - hashes.check_against_chunks(downloaded_chunks) - else: - consume(downloaded_chunks) - - -def _copy_file(filename, location, link): - copy = True - download_location = os.path.join(location, link.filename) - if os.path.exists(download_location): - response = ask_path_exists( - 'The file %s exists. (i)gnore, (w)ipe, (b)ackup, (a)abort' % - display_path(download_location), ('i', 'w', 'b', 'a')) - if response == 'i': - copy = False - elif response == 'w': - logger.warning('Deleting %s', display_path(download_location)) - os.remove(download_location) - elif response == 'b': - dest_file = backup_dir(download_location) - logger.warning( - 'Backing up %s to %s', - display_path(download_location), - display_path(dest_file), - ) - shutil.move(download_location, dest_file) - elif response == 'a': - sys.exit(-1) - if copy: - shutil.copy(filename, download_location) - logger.info('Saved %s', display_path(download_location)) - - -def unpack_http_url( - link, # type: Link - location, # type: str - download_dir=None, # type: Optional[str] - session=None, # type: Optional[PipSession] - hashes=None, # type: Optional[Hashes] - progress_bar="on" # type: str -): - # type: (...) -> None - if session is None: - raise TypeError( - "unpack_http_url() missing 1 required keyword argument: 'session'" - ) - - with TempDirectory(kind="unpack") as temp_dir: - # If a download dir is specified, is the file already downloaded there? - already_downloaded_path = None - if download_dir: - already_downloaded_path = _check_download_dir(link, - download_dir, - hashes) - - if already_downloaded_path: - from_path = already_downloaded_path - content_type = mimetypes.guess_type(from_path)[0] - else: - # let's download to a tmp dir - from_path, content_type = _download_http_url(link, - session, - temp_dir.path, - hashes, - progress_bar) - - # unpack the archive to the build dir location. even when only - # downloading archives, they have to be unpacked to parse dependencies - unpack_file(from_path, location, content_type, link) - - # a download dir is specified; let's copy the archive there - if download_dir and not already_downloaded_path: - _copy_file(from_path, download_dir, link) - - if not already_downloaded_path: - os.unlink(from_path) - - -def unpack_file_url( - link, # type: Link - location, # type: str - download_dir=None, # type: Optional[str] - hashes=None # type: Optional[Hashes] -): - # type: (...) -> None - """Unpack link into location. - - If download_dir is provided and link points to a file, make a copy - of the link file inside download_dir. - """ - link_path = url_to_path(link.url_without_fragment) - - # If it's a url to a local directory - if is_dir_url(link): - if os.path.isdir(location): - rmtree(location) - shutil.copytree(link_path, location, symlinks=True) - if download_dir: - logger.info('Link is a directory, ignoring download_dir') - return - - # If --require-hashes is off, `hashes` is either empty, the - # link's embedded hash, or MissingHashes; it is required to - # match. If --require-hashes is on, we are satisfied by any - # hash in `hashes` matching: a URL-based or an option-based - # one; no internet-sourced hash will be in `hashes`. - if hashes: - hashes.check_against_path(link_path) - - # If a download dir is specified, is the file already there and valid? - already_downloaded_path = None - if download_dir: - already_downloaded_path = _check_download_dir(link, - download_dir, - hashes) - - if already_downloaded_path: - from_path = already_downloaded_path - else: - from_path = link_path - - content_type = mimetypes.guess_type(from_path)[0] - - # unpack the archive to the build dir location. even when only downloading - # archives, they have to be unpacked to parse dependencies - unpack_file(from_path, location, content_type, link) - - # a download dir is specified and not already downloaded - if download_dir and not already_downloaded_path: - _copy_file(from_path, download_dir, link) - - -class PipXmlrpcTransport(xmlrpc_client.Transport): - """Provide a `xmlrpclib.Transport` implementation via a `PipSession` - object. - """ - - def __init__(self, index_url, session, use_datetime=False): - xmlrpc_client.Transport.__init__(self, use_datetime) - index_parts = urllib_parse.urlparse(index_url) - self._scheme = index_parts.scheme - self._session = session - - def request(self, host, handler, request_body, verbose=False): - parts = (self._scheme, host, handler, None, None, None) - url = urllib_parse.urlunparse(parts) - try: - headers = {'Content-Type': 'text/xml'} - response = self._session.post(url, data=request_body, - headers=headers, stream=True) - response.raise_for_status() - self.verbose = verbose - return self.parse_response(response.raw) - except requests.HTTPError as exc: - logger.critical( - "HTTP error %s while getting %s", - exc.response.status_code, url, - ) - raise - - -def unpack_url( - link, # type: Optional[Link] - location, # type: Optional[str] - download_dir=None, # type: Optional[str] - only_download=False, # type: bool - session=None, # type: Optional[PipSession] - hashes=None, # type: Optional[Hashes] - progress_bar="on" # type: str -): - # type: (...) -> None - """Unpack link. - If link is a VCS link: - if only_download, export into download_dir and ignore location - else unpack into location - for other types of link: - - unpack into location - - if download_dir, copy the file into download_dir - - if only_download, mark location for deletion - - :param hashes: A Hashes object, one of whose embedded hashes must match, - or HashMismatch will be raised. If the Hashes is empty, no matches are - required, and unhashable types of requirements (like VCS ones, which - would ordinarily raise HashUnsupported) are allowed. - """ - # non-editable vcs urls - if is_vcs_url(link): - unpack_vcs_link(link, location) - - # file urls - elif is_file_url(link): - unpack_file_url(link, location, download_dir, hashes=hashes) - - # http urls - else: - if session is None: - session = PipSession() - - unpack_http_url( - link, - location, - download_dir, - session, - hashes=hashes, - progress_bar=progress_bar - ) - if only_download: - write_delete_marker_file(location) - - -def _download_http_url( - link, # type: Link - session, # type: PipSession - temp_dir, # type: str - hashes, # type: Hashes - progress_bar # type: str -): - # type: (...) -> Tuple[str, str] - """Download link url into temp_dir using provided session""" - target_url = link.url.split('#', 1)[0] - try: - resp = session.get( - target_url, - # We use Accept-Encoding: identity here because requests - # defaults to accepting compressed responses. This breaks in - # a variety of ways depending on how the server is configured. - # - Some servers will notice that the file isn't a compressible - # file and will leave the file alone and with an empty - # Content-Encoding - # - Some servers will notice that the file is already - # compressed and will leave the file alone and will add a - # Content-Encoding: gzip header - # - Some servers won't notice anything at all and will take - # a file that's already been compressed and compress it again - # and set the Content-Encoding: gzip header - # By setting this to request only the identity encoding We're - # hoping to eliminate the third case. Hopefully there does not - # exist a server which when given a file will notice it is - # already compressed and that you're not asking for a - # compressed file and will then decompress it before sending - # because if that's the case I don't think it'll ever be - # possible to make this work. - headers={"Accept-Encoding": "identity"}, - stream=True, - ) - resp.raise_for_status() - except requests.HTTPError as exc: - logger.critical( - "HTTP error %s while getting %s", exc.response.status_code, link, - ) - raise - - content_type = resp.headers.get('content-type', '') - filename = link.filename # fallback - # Have a look at the Content-Disposition header for a better guess - content_disposition = resp.headers.get('content-disposition') - if content_disposition: - type, params = cgi.parse_header(content_disposition) - # We use ``or`` here because we don't want to use an "empty" value - # from the filename param. - filename = params.get('filename') or filename - ext = splitext(filename)[1] - if not ext: - ext = mimetypes.guess_extension(content_type) - if ext: - filename += ext - if not ext and link.url != resp.url: - ext = os.path.splitext(resp.url)[1] - if ext: - filename += ext - file_path = os.path.join(temp_dir, filename) - with open(file_path, 'wb') as content_file: - _download_url(resp, link, content_file, hashes, progress_bar) - return file_path, content_type - - -def _check_download_dir(link, download_dir, hashes): - # type: (Link, str, Hashes) -> Optional[str] - """ Check download_dir for previously downloaded file with correct hash - If a correct file is found return its path else None - """ - download_path = os.path.join(download_dir, link.filename) - if os.path.exists(download_path): - # If already downloaded, does its hash match? - logger.info('File was already downloaded %s', download_path) - if hashes: - try: - hashes.check_against_path(download_path) - except HashMismatch: - logger.warning( - 'Previously-downloaded file %s has bad hash. ' - 'Re-downloading.', - download_path - ) - os.unlink(download_path) - return None - return download_path - return None diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/exceptions.py b/venv2/lib/python2.7/site-packages/pip/_internal/exceptions.py deleted file mode 100644 index 7b291a1..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/exceptions.py +++ /dev/null @@ -1,274 +0,0 @@ -"""Exceptions used throughout package""" -from __future__ import absolute_import - -from itertools import chain, groupby, repeat - -from pip._vendor.six import iteritems - -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import Optional - from pip._internal.req.req_install import InstallRequirement - - -class PipError(Exception): - """Base pip exception""" - - -class ConfigurationError(PipError): - """General exception in configuration""" - - -class InstallationError(PipError): - """General exception during installation""" - - -class UninstallationError(PipError): - """General exception during uninstallation""" - - -class DistributionNotFound(InstallationError): - """Raised when a distribution cannot be found to satisfy a requirement""" - - -class RequirementsFileParseError(InstallationError): - """Raised when a general error occurs parsing a requirements file line.""" - - -class BestVersionAlreadyInstalled(PipError): - """Raised when the most up-to-date version of a package is already - installed.""" - - -class BadCommand(PipError): - """Raised when virtualenv or a command is not found""" - - -class CommandError(PipError): - """Raised when there is an error in command-line arguments""" - - -class PreviousBuildDirError(PipError): - """Raised when there's a previous conflicting build directory""" - - -class InvalidWheelFilename(InstallationError): - """Invalid wheel filename.""" - - -class UnsupportedWheel(InstallationError): - """Unsupported wheel.""" - - -class HashErrors(InstallationError): - """Multiple HashError instances rolled into one for reporting""" - - def __init__(self): - self.errors = [] - - def append(self, error): - self.errors.append(error) - - def __str__(self): - lines = [] - self.errors.sort(key=lambda e: e.order) - for cls, errors_of_cls in groupby(self.errors, lambda e: e.__class__): - lines.append(cls.head) - lines.extend(e.body() for e in errors_of_cls) - if lines: - return '\n'.join(lines) - - def __nonzero__(self): - return bool(self.errors) - - def __bool__(self): - return self.__nonzero__() - - -class HashError(InstallationError): - """ - A failure to verify a package against known-good hashes - - :cvar order: An int sorting hash exception classes by difficulty of - recovery (lower being harder), so the user doesn't bother fretting - about unpinned packages when he has deeper issues, like VCS - dependencies, to deal with. Also keeps error reports in a - deterministic order. - :cvar head: A section heading for display above potentially many - exceptions of this kind - :ivar req: The InstallRequirement that triggered this error. This is - pasted on after the exception is instantiated, because it's not - typically available earlier. - - """ - req = None # type: Optional[InstallRequirement] - head = '' - - def body(self): - """Return a summary of me for display under the heading. - - This default implementation simply prints a description of the - triggering requirement. - - :param req: The InstallRequirement that provoked this error, with - populate_link() having already been called - - """ - return ' %s' % self._requirement_name() - - def __str__(self): - return '%s\n%s' % (self.head, self.body()) - - def _requirement_name(self): - """Return a description of the requirement that triggered me. - - This default implementation returns long description of the req, with - line numbers - - """ - return str(self.req) if self.req else 'unknown package' - - -class VcsHashUnsupported(HashError): - """A hash was provided for a version-control-system-based requirement, but - we don't have a method for hashing those.""" - - order = 0 - head = ("Can't verify hashes for these requirements because we don't " - "have a way to hash version control repositories:") - - -class DirectoryUrlHashUnsupported(HashError): - """A hash was provided for a version-control-system-based requirement, but - we don't have a method for hashing those.""" - - order = 1 - head = ("Can't verify hashes for these file:// requirements because they " - "point to directories:") - - -class HashMissing(HashError): - """A hash was needed for a requirement but is absent.""" - - order = 2 - head = ('Hashes are required in --require-hashes mode, but they are ' - 'missing from some requirements. Here is a list of those ' - 'requirements along with the hashes their downloaded archives ' - 'actually had. Add lines like these to your requirements files to ' - 'prevent tampering. (If you did not enable --require-hashes ' - 'manually, note that it turns on automatically when any package ' - 'has a hash.)') - - def __init__(self, gotten_hash): - """ - :param gotten_hash: The hash of the (possibly malicious) archive we - just downloaded - """ - self.gotten_hash = gotten_hash - - def body(self): - # Dodge circular import. - from pip._internal.utils.hashes import FAVORITE_HASH - - package = None - if self.req: - # In the case of URL-based requirements, display the original URL - # seen in the requirements file rather than the package name, - # so the output can be directly copied into the requirements file. - package = (self.req.original_link if self.req.original_link - # In case someone feeds something downright stupid - # to InstallRequirement's constructor. - else getattr(self.req, 'req', None)) - return ' %s --hash=%s:%s' % (package or 'unknown package', - FAVORITE_HASH, - self.gotten_hash) - - -class HashUnpinned(HashError): - """A requirement had a hash specified but was not pinned to a specific - version.""" - - order = 3 - head = ('In --require-hashes mode, all requirements must have their ' - 'versions pinned with ==. These do not:') - - -class HashMismatch(HashError): - """ - Distribution file hash values don't match. - - :ivar package_name: The name of the package that triggered the hash - mismatch. Feel free to write to this after the exception is raise to - improve its error message. - - """ - order = 4 - head = ('THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS ' - 'FILE. If you have updated the package versions, please update ' - 'the hashes. Otherwise, examine the package contents carefully; ' - 'someone may have tampered with them.') - - def __init__(self, allowed, gots): - """ - :param allowed: A dict of algorithm names pointing to lists of allowed - hex digests - :param gots: A dict of algorithm names pointing to hashes we - actually got from the files under suspicion - """ - self.allowed = allowed - self.gots = gots - - def body(self): - return ' %s:\n%s' % (self._requirement_name(), - self._hash_comparison()) - - def _hash_comparison(self): - """ - Return a comparison of actual and expected hash values. - - Example:: - - Expected sha256 abcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcde - or 123451234512345123451234512345123451234512345 - Got bcdefbcdefbcdefbcdefbcdefbcdefbcdefbcdefbcdef - - """ - def hash_then_or(hash_name): - # For now, all the decent hashes have 6-char names, so we can get - # away with hard-coding space literals. - return chain([hash_name], repeat(' or')) - - lines = [] - for hash_name, expecteds in iteritems(self.allowed): - prefix = hash_then_or(hash_name) - lines.extend((' Expected %s %s' % (next(prefix), e)) - for e in expecteds) - lines.append(' Got %s\n' % - self.gots[hash_name].hexdigest()) - prefix = ' or' - return '\n'.join(lines) - - -class UnsupportedPythonVersion(InstallationError): - """Unsupported python version according to Requires-Python package - metadata.""" - - -class ConfigurationFileCouldNotBeLoaded(ConfigurationError): - """When there are errors while loading a configuration file - """ - - def __init__(self, reason="could not be loaded", fname=None, error=None): - super(ConfigurationFileCouldNotBeLoaded, self).__init__(error) - self.reason = reason - self.fname = fname - self.error = error - - def __str__(self): - if self.fname is not None: - message_part = " in {}.".format(self.fname) - else: - assert self.error is not None - message_part = ".\n{}\n".format(self.error.message) - return "Configuration file {}{}".format(self.reason, message_part) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/index.py b/venv2/lib/python2.7/site-packages/pip/_internal/index.py deleted file mode 100644 index ff614b3..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/index.py +++ /dev/null @@ -1,1108 +0,0 @@ -"""Routines related to PyPI, indexes""" -from __future__ import absolute_import - -import cgi -import itertools -import logging -import mimetypes -import os -import posixpath -import re -import sys -from collections import namedtuple - -from pip._vendor import html5lib, requests, six -from pip._vendor.distlib.compat import unescape -from pip._vendor.packaging import specifiers -from pip._vendor.packaging.utils import canonicalize_name -from pip._vendor.packaging.version import parse as parse_version -from pip._vendor.requests.exceptions import HTTPError, RetryError, SSLError -from pip._vendor.six.moves.urllib import parse as urllib_parse -from pip._vendor.six.moves.urllib import request as urllib_request - -from pip._internal.download import HAS_TLS, is_url, path_to_url, url_to_path -from pip._internal.exceptions import ( - BestVersionAlreadyInstalled, DistributionNotFound, InvalidWheelFilename, - UnsupportedWheel, -) -from pip._internal.models.candidate import InstallationCandidate -from pip._internal.models.format_control import FormatControl -from pip._internal.models.index import PyPI -from pip._internal.models.link import Link -from pip._internal.pep425tags import get_supported -from pip._internal.utils.compat import ipaddress -from pip._internal.utils.logging import indent_log -from pip._internal.utils.misc import ( - ARCHIVE_EXTENSIONS, SUPPORTED_EXTENSIONS, WHEEL_EXTENSION, normalize_path, - redact_password_from_url, -) -from pip._internal.utils.packaging import check_requires_python -from pip._internal.utils.typing import MYPY_CHECK_RUNNING -from pip._internal.wheel import Wheel - -if MYPY_CHECK_RUNNING: - from logging import Logger - from typing import ( - Tuple, Optional, Any, List, Union, Callable, Set, Sequence, - Iterable, MutableMapping - ) - from pip._vendor.packaging.version import _BaseVersion - from pip._vendor.requests import Response - from pip._internal.pep425tags import Pep425Tag - from pip._internal.req import InstallRequirement - from pip._internal.download import PipSession - - SecureOrigin = Tuple[str, str, Optional[str]] - BuildTag = Tuple[Any, ...] # either empty tuple or Tuple[int, str] - CandidateSortingKey = Tuple[int, _BaseVersion, BuildTag, Optional[int]] - - -__all__ = ['FormatControl', 'FoundCandidates', 'PackageFinder'] - - -SECURE_ORIGINS = [ - # protocol, hostname, port - # Taken from Chrome's list of secure origins (See: http://bit.ly/1qrySKC) - ("https", "*", "*"), - ("*", "localhost", "*"), - ("*", "127.0.0.0/8", "*"), - ("*", "::1/128", "*"), - ("file", "*", None), - # ssh is always secure. - ("ssh", "*", "*"), -] # type: List[SecureOrigin] - - -logger = logging.getLogger(__name__) - - -def _match_vcs_scheme(url): - # type: (str) -> Optional[str] - """Look for VCS schemes in the URL. - - Returns the matched VCS scheme, or None if there's no match. - """ - from pip._internal.vcs import VcsSupport - for scheme in VcsSupport.schemes: - if url.lower().startswith(scheme) and url[len(scheme)] in '+:': - return scheme - return None - - -def _is_url_like_archive(url): - # type: (str) -> bool - """Return whether the URL looks like an archive. - """ - filename = Link(url).filename - for bad_ext in ARCHIVE_EXTENSIONS: - if filename.endswith(bad_ext): - return True - return False - - -class _NotHTML(Exception): - def __init__(self, content_type, request_desc): - # type: (str, str) -> None - super(_NotHTML, self).__init__(content_type, request_desc) - self.content_type = content_type - self.request_desc = request_desc - - -def _ensure_html_header(response): - # type: (Response) -> None - """Check the Content-Type header to ensure the response contains HTML. - - Raises `_NotHTML` if the content type is not text/html. - """ - content_type = response.headers.get("Content-Type", "") - if not content_type.lower().startswith("text/html"): - raise _NotHTML(content_type, response.request.method) - - -class _NotHTTP(Exception): - pass - - -def _ensure_html_response(url, session): - # type: (str, PipSession) -> None - """Send a HEAD request to the URL, and ensure the response contains HTML. - - Raises `_NotHTTP` if the URL is not available for a HEAD request, or - `_NotHTML` if the content type is not text/html. - """ - scheme, netloc, path, query, fragment = urllib_parse.urlsplit(url) - if scheme not in {'http', 'https'}: - raise _NotHTTP() - - resp = session.head(url, allow_redirects=True) - resp.raise_for_status() - - _ensure_html_header(resp) - - -def _get_html_response(url, session): - # type: (str, PipSession) -> Response - """Access an HTML page with GET, and return the response. - - This consists of three parts: - - 1. If the URL looks suspiciously like an archive, send a HEAD first to - check the Content-Type is HTML, to avoid downloading a large file. - Raise `_NotHTTP` if the content type cannot be determined, or - `_NotHTML` if it is not HTML. - 2. Actually perform the request. Raise HTTP exceptions on network failures. - 3. Check the Content-Type header to make sure we got HTML, and raise - `_NotHTML` otherwise. - """ - if _is_url_like_archive(url): - _ensure_html_response(url, session=session) - - logger.debug('Getting page %s', redact_password_from_url(url)) - - resp = session.get( - url, - headers={ - "Accept": "text/html", - # We don't want to blindly returned cached data for - # /simple/, because authors generally expecting that - # twine upload && pip install will function, but if - # they've done a pip install in the last ~10 minutes - # it won't. Thus by setting this to zero we will not - # blindly use any cached data, however the benefit of - # using max-age=0 instead of no-cache, is that we will - # still support conditional requests, so we will still - # minimize traffic sent in cases where the page hasn't - # changed at all, we will just always incur the round - # trip for the conditional GET now instead of only - # once per 10 minutes. - # For more information, please see pypa/pip#5670. - "Cache-Control": "max-age=0", - }, - ) - resp.raise_for_status() - - # The check for archives above only works if the url ends with - # something that looks like an archive. However that is not a - # requirement of an url. Unless we issue a HEAD request on every - # url we cannot know ahead of time for sure if something is HTML - # or not. However we can check after we've downloaded it. - _ensure_html_header(resp) - - return resp - - -def _handle_get_page_fail( - link, # type: Link - reason, # type: Union[str, Exception] - meth=None # type: Optional[Callable[..., None]] -): - # type: (...) -> None - if meth is None: - meth = logger.debug - meth("Could not fetch URL %s: %s - skipping", link, reason) - - -def _get_html_page(link, session=None): - # type: (Link, Optional[PipSession]) -> Optional[HTMLPage] - if session is None: - raise TypeError( - "_get_html_page() missing 1 required keyword argument: 'session'" - ) - - url = link.url.split('#', 1)[0] - - # Check for VCS schemes that do not support lookup as web pages. - vcs_scheme = _match_vcs_scheme(url) - if vcs_scheme: - logger.debug('Cannot look at %s URL %s', vcs_scheme, link) - return None - - # Tack index.html onto file:// URLs that point to directories - scheme, _, path, _, _, _ = urllib_parse.urlparse(url) - if (scheme == 'file' and os.path.isdir(urllib_request.url2pathname(path))): - # add trailing slash if not present so urljoin doesn't trim - # final segment - if not url.endswith('/'): - url += '/' - url = urllib_parse.urljoin(url, 'index.html') - logger.debug(' file: URL is directory, getting %s', url) - - try: - resp = _get_html_response(url, session=session) - except _NotHTTP: - logger.debug( - 'Skipping page %s because it looks like an archive, and cannot ' - 'be checked by HEAD.', link, - ) - except _NotHTML as exc: - logger.debug( - 'Skipping page %s because the %s request got Content-Type: %s', - link, exc.request_desc, exc.content_type, - ) - except HTTPError as exc: - _handle_get_page_fail(link, exc) - except RetryError as exc: - _handle_get_page_fail(link, exc) - except SSLError as exc: - reason = "There was a problem confirming the ssl certificate: " - reason += str(exc) - _handle_get_page_fail(link, reason, meth=logger.info) - except requests.ConnectionError as exc: - _handle_get_page_fail(link, "connection error: %s" % exc) - except requests.Timeout: - _handle_get_page_fail(link, "timed out") - else: - return HTMLPage(resp.content, resp.url, resp.headers) - return None - - -class CandidateEvaluator(object): - - def __init__( - self, - valid_tags, # type: List[Pep425Tag] - prefer_binary=False # type: bool - - ): - # type: (...) -> None - self._prefer_binary = prefer_binary - self._valid_tags = valid_tags - - def is_wheel_supported(self, wheel): - # type: (Wheel) -> bool - return wheel.supported(self._valid_tags) - - def _sort_key(self, candidate): - # type: (InstallationCandidate) -> CandidateSortingKey - """ - Function used to generate link sort key for link tuples. - The greater the return value, the more preferred it is. - If not finding wheels, then sorted by version only. - If finding wheels, then the sort order is by version, then: - 1. existing installs - 2. wheels ordered via Wheel.support_index_min(self._valid_tags) - 3. source archives - If prefer_binary was set, then all wheels are sorted above sources. - Note: it was considered to embed this logic into the Link - comparison operators, but then different sdist links - with the same version, would have to be considered equal - """ - support_num = len(self._valid_tags) - build_tag = tuple() # type: BuildTag - binary_preference = 0 - if candidate.location.is_wheel: - # can raise InvalidWheelFilename - wheel = Wheel(candidate.location.filename) - if not wheel.supported(self._valid_tags): - raise UnsupportedWheel( - "%s is not a supported wheel for this platform. It " - "can't be sorted." % wheel.filename - ) - if self._prefer_binary: - binary_preference = 1 - pri = -(wheel.support_index_min(self._valid_tags)) - if wheel.build_tag is not None: - match = re.match(r'^(\d+)(.*)$', wheel.build_tag) - build_tag_groups = match.groups() - build_tag = (int(build_tag_groups[0]), build_tag_groups[1]) - else: # sdist - pri = -(support_num) - return (binary_preference, candidate.version, build_tag, pri) - - def get_best_candidate(self, candidates): - # type: (List[InstallationCandidate]) -> InstallationCandidate - """ - Return the best candidate per the instance's sort order, or None if - no candidates are given. - """ - if not candidates: - return None - - return max(candidates, key=self._sort_key) - - -class FoundCandidates(object): - """A collection of candidates, returned by `PackageFinder.find_candidates`. - - This class is only intended to be instantiated by PackageFinder through - the `from_specifier()` constructor. - - Arguments: - - * `candidates`: A sequence of all available candidates found. - * `specifier`: Specifier to filter applicable versions. - * `prereleases`: Whether prereleases should be accounted. Pass None to - infer from the specifier. - * `evaluator`: A CandidateEvaluator object to sort applicable candidates - by order of preference. - """ - - def __init__( - self, - candidates, # type: List[InstallationCandidate] - versions, # type: Set[str] - evaluator, # type: CandidateEvaluator - ): - # type: (...) -> None - self._candidates = candidates - self._evaluator = evaluator - self._versions = versions - - @classmethod - def from_specifier( - cls, - candidates, # type: List[InstallationCandidate] - specifier, # type: specifiers.BaseSpecifier - prereleases, # type: Optional[bool] - evaluator, # type: CandidateEvaluator - ): - # type: (...) -> FoundCandidates - versions = { - str(v) for v in specifier.filter( - # We turn the version object into a str here because otherwise - # when we're debundled but setuptools isn't, Python will see - # packaging.version.Version and - # pkg_resources._vendor.packaging.version.Version as different - # types. This way we'll use a str as a common data interchange - # format. If we stop using the pkg_resources provided specifier - # and start using our own, we can drop the cast to str(). - (str(c.version) for c in candidates), - prereleases=prereleases, - ) - } - return cls(candidates, versions, evaluator) - - def iter_all(self): - # type: () -> Iterable[InstallationCandidate] - """Iterate through all candidates. - """ - return iter(self._candidates) - - def iter_applicable(self): - # type: () -> Iterable[InstallationCandidate] - """Iterate through candidates matching the versions associated with - this instance. - """ - # Again, converting version to str to deal with debundling. - return (c for c in self.iter_all() if str(c.version) in self._versions) - - def get_best(self): - # type: () -> Optional[InstallationCandidate] - """Return the best candidate available, or None if no applicable - candidates are found. - """ - candidates = list(self.iter_applicable()) - return self._evaluator.get_best_candidate(candidates) - - -class PackageFinder(object): - """This finds packages. - - This is meant to match easy_install's technique for looking for - packages, by reading pages and looking for appropriate links. - """ - - def __init__( - self, - find_links, # type: List[str] - index_urls, # type: List[str] - allow_all_prereleases=False, # type: bool - trusted_hosts=None, # type: Optional[Iterable[str]] - session=None, # type: Optional[PipSession] - format_control=None, # type: Optional[FormatControl] - platform=None, # type: Optional[str] - versions=None, # type: Optional[List[str]] - abi=None, # type: Optional[str] - implementation=None, # type: Optional[str] - prefer_binary=False # type: bool - ): - # type: (...) -> None - """Create a PackageFinder. - - :param format_control: A FormatControl object or None. Used to control - the selection of source packages / binary packages when consulting - the index and links. - :param platform: A string or None. If None, searches for packages - that are supported by the current system. Otherwise, will find - packages that can be built on the platform passed in. These - packages will only be downloaded for distribution: they will - not be built locally. - :param versions: A list of strings or None. This is passed directly - to pep425tags.py in the get_supported() method. - :param abi: A string or None. This is passed directly - to pep425tags.py in the get_supported() method. - :param implementation: A string or None. This is passed directly - to pep425tags.py in the get_supported() method. - :param prefer_binary: Whether to prefer an old, but valid, binary - dist over a new source dist. - """ - if session is None: - raise TypeError( - "PackageFinder() missing 1 required keyword argument: " - "'session'" - ) - - # Build find_links. If an argument starts with ~, it may be - # a local file relative to a home directory. So try normalizing - # it and if it exists, use the normalized version. - # This is deliberately conservative - it might be fine just to - # blindly normalize anything starting with a ~... - self.find_links = [] # type: List[str] - for link in find_links: - if link.startswith('~'): - new_link = normalize_path(link) - if os.path.exists(new_link): - link = new_link - self.find_links.append(link) - - self.index_urls = index_urls - - # These are boring links that have already been logged somehow: - self.logged_links = set() # type: Set[Link] - - self.format_control = format_control or FormatControl(set(), set()) - - # Domains that we won't emit warnings for when not using HTTPS - self.secure_origins = [ - ("*", host, "*") - for host in (trusted_hosts if trusted_hosts else []) - ] # type: List[SecureOrigin] - - # Do we want to allow _all_ pre-releases? - self.allow_all_prereleases = allow_all_prereleases - - # The Session we'll use to make requests - self.session = session - - # The valid tags to check potential found wheel candidates against - valid_tags = get_supported( - versions=versions, - platform=platform, - abi=abi, - impl=implementation, - ) - self.candidate_evaluator = CandidateEvaluator( - valid_tags=valid_tags, prefer_binary=prefer_binary, - ) - - # If we don't have TLS enabled, then WARN if anyplace we're looking - # relies on TLS. - if not HAS_TLS: - for link in itertools.chain(self.index_urls, self.find_links): - parsed = urllib_parse.urlparse(link) - if parsed.scheme == "https": - logger.warning( - "pip is configured with locations that require " - "TLS/SSL, however the ssl module in Python is not " - "available." - ) - break - - def get_formatted_locations(self): - # type: () -> str - lines = [] - if self.index_urls and self.index_urls != [PyPI.simple_url]: - lines.append( - "Looking in indexes: {}".format(", ".join( - redact_password_from_url(url) for url in self.index_urls)) - ) - if self.find_links: - lines.append( - "Looking in links: {}".format(", ".join(self.find_links)) - ) - return "\n".join(lines) - - @staticmethod - def _sort_locations(locations, expand_dir=False): - # type: (Sequence[str], bool) -> Tuple[List[str], List[str]] - """ - Sort locations into "files" (archives) and "urls", and return - a pair of lists (files,urls) - """ - files = [] - urls = [] - - # puts the url for the given file path into the appropriate list - def sort_path(path): - url = path_to_url(path) - if mimetypes.guess_type(url, strict=False)[0] == 'text/html': - urls.append(url) - else: - files.append(url) - - for url in locations: - - is_local_path = os.path.exists(url) - is_file_url = url.startswith('file:') - - if is_local_path or is_file_url: - if is_local_path: - path = url - else: - path = url_to_path(url) - if os.path.isdir(path): - if expand_dir: - path = os.path.realpath(path) - for item in os.listdir(path): - sort_path(os.path.join(path, item)) - elif is_file_url: - urls.append(url) - else: - logger.warning( - "Path '{0}' is ignored: " - "it is a directory.".format(path), - ) - elif os.path.isfile(path): - sort_path(path) - else: - logger.warning( - "Url '%s' is ignored: it is neither a file " - "nor a directory.", url, - ) - elif is_url(url): - # Only add url with clear scheme - urls.append(url) - else: - logger.warning( - "Url '%s' is ignored. It is either a non-existing " - "path or lacks a specific scheme.", url, - ) - - return files, urls - - def _validate_secure_origin(self, logger, location): - # type: (Logger, Link) -> bool - # Determine if this url used a secure transport mechanism - parsed = urllib_parse.urlparse(str(location)) - origin = (parsed.scheme, parsed.hostname, parsed.port) - - # The protocol to use to see if the protocol matches. - # Don't count the repository type as part of the protocol: in - # cases such as "git+ssh", only use "ssh". (I.e., Only verify against - # the last scheme.) - protocol = origin[0].rsplit('+', 1)[-1] - - # Determine if our origin is a secure origin by looking through our - # hardcoded list of secure origins, as well as any additional ones - # configured on this PackageFinder instance. - for secure_origin in (SECURE_ORIGINS + self.secure_origins): - if protocol != secure_origin[0] and secure_origin[0] != "*": - continue - - try: - # We need to do this decode dance to ensure that we have a - # unicode object, even on Python 2.x. - addr = ipaddress.ip_address( - origin[1] - if ( - isinstance(origin[1], six.text_type) or - origin[1] is None - ) - else origin[1].decode("utf8") - ) - network = ipaddress.ip_network( - secure_origin[1] - if isinstance(secure_origin[1], six.text_type) - # setting secure_origin[1] to proper Union[bytes, str] - # creates problems in other places - else secure_origin[1].decode("utf8") # type: ignore - ) - except ValueError: - # We don't have both a valid address or a valid network, so - # we'll check this origin against hostnames. - if (origin[1] and - origin[1].lower() != secure_origin[1].lower() and - secure_origin[1] != "*"): - continue - else: - # We have a valid address and network, so see if the address - # is contained within the network. - if addr not in network: - continue - - # Check to see if the port patches - if (origin[2] != secure_origin[2] and - secure_origin[2] != "*" and - secure_origin[2] is not None): - continue - - # If we've gotten here, then this origin matches the current - # secure origin and we should return True - return True - - # If we've gotten to this point, then the origin isn't secure and we - # will not accept it as a valid location to search. We will however - # log a warning that we are ignoring it. - logger.warning( - "The repository located at %s is not a trusted or secure host and " - "is being ignored. If this repository is available via HTTPS we " - "recommend you use HTTPS instead, otherwise you may silence " - "this warning and allow it anyway with '--trusted-host %s'.", - parsed.hostname, - parsed.hostname, - ) - - return False - - def _get_index_urls_locations(self, project_name): - # type: (str) -> List[str] - """Returns the locations found via self.index_urls - - Checks the url_name on the main (first in the list) index and - use this url_name to produce all locations - """ - - def mkurl_pypi_url(url): - loc = posixpath.join( - url, - urllib_parse.quote(canonicalize_name(project_name))) - # For maximum compatibility with easy_install, ensure the path - # ends in a trailing slash. Although this isn't in the spec - # (and PyPI can handle it without the slash) some other index - # implementations might break if they relied on easy_install's - # behavior. - if not loc.endswith('/'): - loc = loc + '/' - return loc - - return [mkurl_pypi_url(url) for url in self.index_urls] - - def find_all_candidates(self, project_name): - # type: (str) -> List[Optional[InstallationCandidate]] - """Find all available InstallationCandidate for project_name - - This checks index_urls and find_links. - All versions found are returned as an InstallationCandidate list. - - See _link_package_versions for details on which files are accepted - """ - index_locations = self._get_index_urls_locations(project_name) - index_file_loc, index_url_loc = self._sort_locations(index_locations) - fl_file_loc, fl_url_loc = self._sort_locations( - self.find_links, expand_dir=True, - ) - - file_locations = (Link(url) for url in itertools.chain( - index_file_loc, fl_file_loc, - )) - - # We trust every url that the user has given us whether it was given - # via --index-url or --find-links. - # We want to filter out any thing which does not have a secure origin. - url_locations = [ - link for link in itertools.chain( - (Link(url) for url in index_url_loc), - (Link(url) for url in fl_url_loc), - ) - if self._validate_secure_origin(logger, link) - ] - - logger.debug('%d location(s) to search for versions of %s:', - len(url_locations), project_name) - - for location in url_locations: - logger.debug('* %s', location) - - canonical_name = canonicalize_name(project_name) - formats = self.format_control.get_allowed_formats(canonical_name) - search = Search(project_name, canonical_name, formats) - find_links_versions = self._package_versions( - # We trust every directly linked archive in find_links - (Link(url, '-f') for url in self.find_links), - search - ) - - page_versions = [] - for page in self._get_pages(url_locations, project_name): - logger.debug('Analyzing links from page %s', page.url) - with indent_log(): - page_versions.extend( - self._package_versions(page.iter_links(), search) - ) - - file_versions = self._package_versions(file_locations, search) - if file_versions: - file_versions.sort(reverse=True) - logger.debug( - 'Local files found: %s', - ', '.join([ - url_to_path(candidate.location.url) - for candidate in file_versions - ]) - ) - - # This is an intentional priority ordering - return file_versions + find_links_versions + page_versions - - def find_candidates( - self, - project_name, # type: str - specifier=None, # type: Optional[specifiers.BaseSpecifier] - ): - """Find matches for the given project and specifier. - - If given, `specifier` should implement `filter` to allow version - filtering (e.g. ``packaging.specifiers.SpecifierSet``). - - Returns a `FoundCandidates` instance. - """ - if specifier is None: - specifier = specifiers.SpecifierSet() - return FoundCandidates.from_specifier( - self.find_all_candidates(project_name), - specifier=specifier, - prereleases=(self.allow_all_prereleases or None), - evaluator=self.candidate_evaluator, - ) - - def find_requirement(self, req, upgrade): - # type: (InstallRequirement, bool) -> Optional[Link] - """Try to find a Link matching req - - Expects req, an InstallRequirement and upgrade, a boolean - Returns a Link if found, - Raises DistributionNotFound or BestVersionAlreadyInstalled otherwise - """ - candidates = self.find_candidates(req.name, req.specifier) - best_candidate = candidates.get_best() - - installed_version = None # type: Optional[_BaseVersion] - if req.satisfied_by is not None: - installed_version = parse_version(req.satisfied_by.version) - - def _format_versions(cand_iter): - # This repeated parse_version and str() conversion is needed to - # handle different vendoring sources from pip and pkg_resources. - # If we stop using the pkg_resources provided specifier and start - # using our own, we can drop the cast to str(). - return ", ".join(sorted( - {str(c.version) for c in cand_iter}, - key=parse_version, - )) or "none" - - if installed_version is None and best_candidate is None: - logger.critical( - 'Could not find a version that satisfies the requirement %s ' - '(from versions: %s)', - req, - _format_versions(candidates.iter_all()), - ) - - raise DistributionNotFound( - 'No matching distribution found for %s' % req - ) - - best_installed = False - if installed_version and ( - best_candidate is None or - best_candidate.version <= installed_version): - best_installed = True - - if not upgrade and installed_version is not None: - if best_installed: - logger.debug( - 'Existing installed version (%s) is most up-to-date and ' - 'satisfies requirement', - installed_version, - ) - else: - logger.debug( - 'Existing installed version (%s) satisfies requirement ' - '(most up-to-date version is %s)', - installed_version, - best_candidate.version, - ) - return None - - if best_installed: - # We have an existing version, and its the best version - logger.debug( - 'Installed version (%s) is most up-to-date (past versions: ' - '%s)', - installed_version, - _format_versions(candidates.iter_applicable()), - ) - raise BestVersionAlreadyInstalled - - logger.debug( - 'Using version %s (newest of versions: %s)', - best_candidate.version, - _format_versions(candidates.iter_applicable()), - ) - return best_candidate.location - - def _get_pages(self, locations, project_name): - # type: (Iterable[Link], str) -> Iterable[HTMLPage] - """ - Yields (page, page_url) from the given locations, skipping - locations that have errors. - """ - seen = set() # type: Set[Link] - for location in locations: - if location in seen: - continue - seen.add(location) - - page = _get_html_page(location, session=self.session) - if page is None: - continue - - yield page - - _py_version_re = re.compile(r'-py([123]\.?[0-9]?)$') - - def _sort_links(self, links): - # type: (Iterable[Link]) -> List[Link] - """ - Returns elements of links in order, non-egg links first, egg links - second, while eliminating duplicates - """ - eggs, no_eggs = [], [] - seen = set() # type: Set[Link] - for link in links: - if link not in seen: - seen.add(link) - if link.egg_fragment: - eggs.append(link) - else: - no_eggs.append(link) - return no_eggs + eggs - - def _package_versions( - self, - links, # type: Iterable[Link] - search # type: Search - ): - # type: (...) -> List[Optional[InstallationCandidate]] - result = [] - for link in self._sort_links(links): - v = self._link_package_versions(link, search) - if v is not None: - result.append(v) - return result - - def _log_skipped_link(self, link, reason): - # type: (Link, str) -> None - if link not in self.logged_links: - logger.debug('Skipping link %s; %s', link, reason) - self.logged_links.add(link) - - def _link_package_versions(self, link, search): - # type: (Link, Search) -> Optional[InstallationCandidate] - """Return an InstallationCandidate or None""" - version = None - if link.egg_fragment: - egg_info = link.egg_fragment - ext = link.ext - else: - egg_info, ext = link.splitext() - if not ext: - self._log_skipped_link(link, 'not a file') - return None - if ext not in SUPPORTED_EXTENSIONS: - self._log_skipped_link( - link, 'unsupported archive format: %s' % ext, - ) - return None - if "binary" not in search.formats and ext == WHEEL_EXTENSION: - self._log_skipped_link( - link, 'No binaries permitted for %s' % search.supplied, - ) - return None - if "macosx10" in link.path and ext == '.zip': - self._log_skipped_link(link, 'macosx10 one') - return None - if ext == WHEEL_EXTENSION: - try: - wheel = Wheel(link.filename) - except InvalidWheelFilename: - self._log_skipped_link(link, 'invalid wheel filename') - return None - if canonicalize_name(wheel.name) != search.canonical: - self._log_skipped_link( - link, 'wrong project name (not %s)' % search.supplied) - return None - - if not self.candidate_evaluator.is_wheel_supported(wheel): - self._log_skipped_link( - link, 'it is not compatible with this Python') - return None - - version = wheel.version - - # This should be up by the search.ok_binary check, but see issue 2700. - if "source" not in search.formats and ext != WHEEL_EXTENSION: - self._log_skipped_link( - link, 'No sources permitted for %s' % search.supplied, - ) - return None - - if not version: - version = _egg_info_matches(egg_info, search.canonical) - if not version: - self._log_skipped_link( - link, 'Missing project version for %s' % search.supplied) - return None - - match = self._py_version_re.search(version) - if match: - version = version[:match.start()] - py_version = match.group(1) - if py_version != sys.version[:3]: - self._log_skipped_link( - link, 'Python version is incorrect') - return None - try: - support_this_python = check_requires_python(link.requires_python) - except specifiers.InvalidSpecifier: - logger.debug("Package %s has an invalid Requires-Python entry: %s", - link.filename, link.requires_python) - support_this_python = True - - if not support_this_python: - logger.debug("The package %s is incompatible with the python " - "version in use. Acceptable python versions are: %s", - link, link.requires_python) - return None - logger.debug('Found link %s, version: %s', link, version) - - return InstallationCandidate(search.supplied, version, link) - - -def _find_name_version_sep(egg_info, canonical_name): - # type: (str, str) -> int - """Find the separator's index based on the package's canonical name. - - `egg_info` must be an egg info string for the given package, and - `canonical_name` must be the package's canonical name. - - This function is needed since the canonicalized name does not necessarily - have the same length as the egg info's name part. An example:: - - >>> egg_info = 'foo__bar-1.0' - >>> canonical_name = 'foo-bar' - >>> _find_name_version_sep(egg_info, canonical_name) - 8 - """ - # Project name and version must be separated by one single dash. Find all - # occurrences of dashes; if the string in front of it matches the canonical - # name, this is the one separating the name and version parts. - for i, c in enumerate(egg_info): - if c != "-": - continue - if canonicalize_name(egg_info[:i]) == canonical_name: - return i - raise ValueError("{} does not match {}".format(egg_info, canonical_name)) - - -def _egg_info_matches(egg_info, canonical_name): - # type: (str, str) -> Optional[str] - """Pull the version part out of a string. - - :param egg_info: The string to parse. E.g. foo-2.1 - :param canonical_name: The canonicalized name of the package this - belongs to. - """ - try: - version_start = _find_name_version_sep(egg_info, canonical_name) + 1 - except ValueError: - return None - version = egg_info[version_start:] - if not version: - return None - return version - - -def _determine_base_url(document, page_url): - """Determine the HTML document's base URL. - - This looks for a ```` tag in the HTML document. If present, its href - attribute denotes the base URL of anchor tags in the document. If there is - no such tag (or if it does not have a valid href attribute), the HTML - file's URL is used as the base URL. - - :param document: An HTML document representation. The current - implementation expects the result of ``html5lib.parse()``. - :param page_url: The URL of the HTML document. - """ - for base in document.findall(".//base"): - href = base.get("href") - if href is not None: - return href - return page_url - - -def _get_encoding_from_headers(headers): - """Determine if we have any encoding information in our headers. - """ - if headers and "Content-Type" in headers: - content_type, params = cgi.parse_header(headers["Content-Type"]) - if "charset" in params: - return params['charset'] - return None - - -def _clean_link(url): - # type: (str) -> str - """Makes sure a link is fully encoded. That is, if a ' ' shows up in - the link, it will be rewritten to %20 (while not over-quoting - % or other characters).""" - # Split the URL into parts according to the general structure - # `scheme://netloc/path;parameters?query#fragment`. Note that the - # `netloc` can be empty and the URI will then refer to a local - # filesystem path. - result = urllib_parse.urlparse(url) - # In both cases below we unquote prior to quoting to make sure - # nothing is double quoted. - if result.netloc == "": - # On Windows the path part might contain a drive letter which - # should not be quoted. On Linux where drive letters do not - # exist, the colon should be quoted. We rely on urllib.request - # to do the right thing here. - path = urllib_request.pathname2url( - urllib_request.url2pathname(result.path)) - else: - # In addition to the `/` character we protect `@` so that - # revision strings in VCS URLs are properly parsed. - path = urllib_parse.quote(urllib_parse.unquote(result.path), safe="/@") - return urllib_parse.urlunparse(result._replace(path=path)) - - -class HTMLPage(object): - """Represents one page, along with its URL""" - - def __init__(self, content, url, headers=None): - # type: (bytes, str, MutableMapping[str, str]) -> None - self.content = content - self.url = url - self.headers = headers - - def __str__(self): - return redact_password_from_url(self.url) - - def iter_links(self): - # type: () -> Iterable[Link] - """Yields all links in the page""" - document = html5lib.parse( - self.content, - transport_encoding=_get_encoding_from_headers(self.headers), - namespaceHTMLElements=False, - ) - base_url = _determine_base_url(document, self.url) - for anchor in document.findall(".//a"): - if anchor.get("href"): - href = anchor.get("href") - url = _clean_link(urllib_parse.urljoin(base_url, href)) - pyrequire = anchor.get('data-requires-python') - pyrequire = unescape(pyrequire) if pyrequire else None - yield Link(url, self.url, requires_python=pyrequire) - - -Search = namedtuple('Search', 'supplied canonical formats') -"""Capture key aspects of a search. - -:attribute supplied: The user supplied package. -:attribute canonical: The canonical package name. -:attribute formats: The formats allowed for this package. Should be a set - with 'binary' or 'source' or both in it. -""" diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/locations.py b/venv2/lib/python2.7/site-packages/pip/_internal/locations.py deleted file mode 100644 index 10860f7..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/locations.py +++ /dev/null @@ -1,211 +0,0 @@ -"""Locations where we look for configs, install stuff, etc""" -from __future__ import absolute_import - -import os -import os.path -import platform -import site -import sys -import sysconfig -from distutils import sysconfig as distutils_sysconfig -from distutils.command.install import SCHEME_KEYS # type: ignore - -from pip._internal.utils import appdirs -from pip._internal.utils.compat import WINDOWS, expanduser -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import Any, Union, Dict, List, Optional - - -# Application Directories -USER_CACHE_DIR = appdirs.user_cache_dir("pip") - - -DELETE_MARKER_MESSAGE = '''\ -This file is placed here by pip to indicate the source was put -here by pip. - -Once this package is successfully installed this source code will be -deleted (unless you remove this file). -''' -PIP_DELETE_MARKER_FILENAME = 'pip-delete-this-directory.txt' - - -def write_delete_marker_file(directory): - # type: (str) -> None - """ - Write the pip delete marker file into this directory. - """ - filepath = os.path.join(directory, PIP_DELETE_MARKER_FILENAME) - with open(filepath, 'w') as marker_fp: - marker_fp.write(DELETE_MARKER_MESSAGE) - - -def running_under_virtualenv(): - # type: () -> bool - """ - Return True if we're running inside a virtualenv, False otherwise. - - """ - if hasattr(sys, 'real_prefix'): - return True - elif sys.prefix != getattr(sys, "base_prefix", sys.prefix): - return True - - return False - - -def virtualenv_no_global(): - # type: () -> bool - """ - Return True if in a venv and no system site packages. - """ - # this mirrors the logic in virtualenv.py for locating the - # no-global-site-packages.txt file - site_mod_dir = os.path.dirname(os.path.abspath(site.__file__)) - no_global_file = os.path.join(site_mod_dir, 'no-global-site-packages.txt') - if running_under_virtualenv() and os.path.isfile(no_global_file): - return True - else: - return False - - -if running_under_virtualenv(): - src_prefix = os.path.join(sys.prefix, 'src') -else: - # FIXME: keep src in cwd for now (it is not a temporary folder) - try: - src_prefix = os.path.join(os.getcwd(), 'src') - except OSError: - # In case the current working directory has been renamed or deleted - sys.exit( - "The folder you are executing pip from can no longer be found." - ) - -# under macOS + virtualenv sys.prefix is not properly resolved -# it is something like /path/to/python/bin/.. -# Note: using realpath due to tmp dirs on OSX being symlinks -src_prefix = os.path.abspath(src_prefix) - -# FIXME doesn't account for venv linked to global site-packages - -site_packages = sysconfig.get_path("purelib") # type: Optional[str] - -# This is because of a bug in PyPy's sysconfig module, see -# https://bitbucket.org/pypy/pypy/issues/2506/sysconfig-returns-incorrect-paths -# for more information. -if platform.python_implementation().lower() == "pypy": - site_packages = distutils_sysconfig.get_python_lib() -try: - # Use getusersitepackages if this is present, as it ensures that the - # value is initialised properly. - user_site = site.getusersitepackages() -except AttributeError: - user_site = site.USER_SITE -user_dir = expanduser('~') -if WINDOWS: - bin_py = os.path.join(sys.prefix, 'Scripts') - bin_user = os.path.join(user_site, 'Scripts') - # buildout uses 'bin' on Windows too? - if not os.path.exists(bin_py): - bin_py = os.path.join(sys.prefix, 'bin') - bin_user = os.path.join(user_site, 'bin') - - config_basename = 'pip.ini' - - legacy_storage_dir = os.path.join(user_dir, 'pip') - legacy_config_file = os.path.join( - legacy_storage_dir, - config_basename, - ) -else: - bin_py = os.path.join(sys.prefix, 'bin') - bin_user = os.path.join(user_site, 'bin') - - config_basename = 'pip.conf' - - legacy_storage_dir = os.path.join(user_dir, '.pip') - legacy_config_file = os.path.join( - legacy_storage_dir, - config_basename, - ) - # Forcing to use /usr/local/bin for standard macOS framework installs - # Also log to ~/Library/Logs/ for use with the Console.app log viewer - if sys.platform[:6] == 'darwin' and sys.prefix[:16] == '/System/Library/': - bin_py = '/usr/local/bin' - -global_config_files = [ - os.path.join(path, config_basename) - for path in appdirs.site_config_dirs('pip') -] - -site_config_file = os.path.join(sys.prefix, config_basename) -new_config_file = os.path.join(appdirs.user_config_dir("pip"), config_basename) - - -def distutils_scheme(dist_name, user=False, home=None, root=None, - isolated=False, prefix=None): - # type:(str, bool, str, str, bool, str) -> dict - """ - Return a distutils install scheme - """ - from distutils.dist import Distribution - - scheme = {} - - if isolated: - extra_dist_args = {"script_args": ["--no-user-cfg"]} - else: - extra_dist_args = {} - dist_args = {'name': dist_name} # type: Dict[str, Union[str, List[str]]] - dist_args.update(extra_dist_args) - - d = Distribution(dist_args) - # Ignoring, typeshed issue reported python/typeshed/issues/2567 - d.parse_config_files() - # NOTE: Ignoring type since mypy can't find attributes on 'Command' - i = d.get_command_obj('install', create=True) # type: Any - assert i is not None - # NOTE: setting user or home has the side-effect of creating the home dir - # or user base for installations during finalize_options() - # ideally, we'd prefer a scheme class that has no side-effects. - assert not (user and prefix), "user={} prefix={}".format(user, prefix) - i.user = user or i.user - if user: - i.prefix = "" - i.prefix = prefix or i.prefix - i.home = home or i.home - i.root = root or i.root - i.finalize_options() - for key in SCHEME_KEYS: - scheme[key] = getattr(i, 'install_' + key) - - # install_lib specified in setup.cfg should install *everything* - # into there (i.e. it takes precedence over both purelib and - # platlib). Note, i.install_lib is *always* set after - # finalize_options(); we only want to override here if the user - # has explicitly requested it hence going back to the config - - # Ignoring, typeshed issue reported python/typeshed/issues/2567 - if 'install_lib' in d.get_option_dict('install'): # type: ignore - scheme.update(dict(purelib=i.install_lib, platlib=i.install_lib)) - - if running_under_virtualenv(): - scheme['headers'] = os.path.join( - sys.prefix, - 'include', - 'site', - 'python' + sys.version[:3], - dist_name, - ) - - if root is not None: - path_no_drive = os.path.splitdrive( - os.path.abspath(scheme["headers"]))[1] - scheme["headers"] = os.path.join( - root, - path_no_drive[1:], - ) - - return scheme diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/models/__init__.py b/venv2/lib/python2.7/site-packages/pip/_internal/models/__init__.py deleted file mode 100644 index 7855226..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/models/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -"""A package that contains models that represent entities. -""" diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/models/candidate.py b/venv2/lib/python2.7/site-packages/pip/_internal/models/candidate.py deleted file mode 100644 index b66c365..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/models/candidate.py +++ /dev/null @@ -1,31 +0,0 @@ -from pip._vendor.packaging.version import parse as parse_version - -from pip._internal.utils.models import KeyBasedCompareMixin -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from pip._vendor.packaging.version import _BaseVersion - from pip._internal.models.link import Link - from typing import Any - - -class InstallationCandidate(KeyBasedCompareMixin): - """Represents a potential "candidate" for installation. - """ - - def __init__(self, project, version, location): - # type: (Any, str, Link) -> None - self.project = project - self.version = parse_version(version) # type: _BaseVersion - self.location = location - - super(InstallationCandidate, self).__init__( - key=(self.project, self.version, self.location), - defining_class=InstallationCandidate - ) - - def __repr__(self): - # type: () -> str - return "".format( - self.project, self.version, self.location, - ) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/models/format_control.py b/venv2/lib/python2.7/site-packages/pip/_internal/models/format_control.py deleted file mode 100644 index 53138e4..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/models/format_control.py +++ /dev/null @@ -1,73 +0,0 @@ -from pip._vendor.packaging.utils import canonicalize_name - -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import Optional, Set, FrozenSet - - -class FormatControl(object): - """Helper for managing formats from which a package can be installed. - """ - - def __init__(self, no_binary=None, only_binary=None): - # type: (Optional[Set], Optional[Set]) -> None - if no_binary is None: - no_binary = set() - if only_binary is None: - only_binary = set() - - self.no_binary = no_binary - self.only_binary = only_binary - - def __eq__(self, other): - return self.__dict__ == other.__dict__ - - def __ne__(self, other): - return not self.__eq__(other) - - def __repr__(self): - return "{}({}, {})".format( - self.__class__.__name__, - self.no_binary, - self.only_binary - ) - - @staticmethod - def handle_mutual_excludes(value, target, other): - # type: (str, Optional[Set], Optional[Set]) -> None - new = value.split(',') - while ':all:' in new: - other.clear() - target.clear() - target.add(':all:') - del new[:new.index(':all:') + 1] - # Without a none, we want to discard everything as :all: covers it - if ':none:' not in new: - return - for name in new: - if name == ':none:': - target.clear() - continue - name = canonicalize_name(name) - other.discard(name) - target.add(name) - - def get_allowed_formats(self, canonical_name): - # type: (str) -> FrozenSet - result = {"binary", "source"} - if canonical_name in self.only_binary: - result.discard('source') - elif canonical_name in self.no_binary: - result.discard('binary') - elif ':all:' in self.only_binary: - result.discard('source') - elif ':all:' in self.no_binary: - result.discard('binary') - return frozenset(result) - - def disallow_binaries(self): - # type: () -> None - self.handle_mutual_excludes( - ':all:', self.no_binary, self.only_binary, - ) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/models/index.py b/venv2/lib/python2.7/site-packages/pip/_internal/models/index.py deleted file mode 100644 index ead1efb..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/models/index.py +++ /dev/null @@ -1,31 +0,0 @@ -from pip._vendor.six.moves.urllib import parse as urllib_parse - - -class PackageIndex(object): - """Represents a Package Index and provides easier access to endpoints - """ - - def __init__(self, url, file_storage_domain): - # type: (str, str) -> None - super(PackageIndex, self).__init__() - self.url = url - self.netloc = urllib_parse.urlsplit(url).netloc - self.simple_url = self._url_for_path('simple') - self.pypi_url = self._url_for_path('pypi') - - # This is part of a temporary hack used to block installs of PyPI - # packages which depend on external urls only necessary until PyPI can - # block such packages themselves - self.file_storage_domain = file_storage_domain - - def _url_for_path(self, path): - # type: (str) -> str - return urllib_parse.urljoin(self.url, path) - - -PyPI = PackageIndex( - 'https://pypi.org/', file_storage_domain='files.pythonhosted.org' -) -TestPyPI = PackageIndex( - 'https://test.pypi.org/', file_storage_domain='test-files.pythonhosted.org' -) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/models/link.py b/venv2/lib/python2.7/site-packages/pip/_internal/models/link.py deleted file mode 100644 index 2f42076..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/models/link.py +++ /dev/null @@ -1,163 +0,0 @@ -import posixpath -import re - -from pip._vendor.six.moves.urllib import parse as urllib_parse - -from pip._internal.download import path_to_url -from pip._internal.utils.misc import ( - WHEEL_EXTENSION, redact_password_from_url, splitext, -) -from pip._internal.utils.models import KeyBasedCompareMixin -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import Optional, Tuple, Union - from pip._internal.index import HTMLPage - - -class Link(KeyBasedCompareMixin): - """Represents a parsed link from a Package Index's simple URL - """ - - def __init__(self, url, comes_from=None, requires_python=None): - # type: (str, Optional[Union[str, HTMLPage]], Optional[str]) -> None - """ - url: - url of the resource pointed to (href of the link) - comes_from: - instance of HTMLPage where the link was found, or string. - requires_python: - String containing the `Requires-Python` metadata field, specified - in PEP 345. This may be specified by a data-requires-python - attribute in the HTML link tag, as described in PEP 503. - """ - - # url can be a UNC windows share - if url.startswith('\\\\'): - url = path_to_url(url) - - self.url = url - self.comes_from = comes_from - self.requires_python = requires_python if requires_python else None - - super(Link, self).__init__( - key=(self.url), - defining_class=Link - ) - - def __str__(self): - if self.requires_python: - rp = ' (requires-python:%s)' % self.requires_python - else: - rp = '' - if self.comes_from: - return '%s (from %s)%s' % (redact_password_from_url(self.url), - self.comes_from, rp) - else: - return redact_password_from_url(str(self.url)) - - def __repr__(self): - return '' % self - - @property - def filename(self): - # type: () -> str - _, netloc, path, _, _ = urllib_parse.urlsplit(self.url) - name = posixpath.basename(path.rstrip('/')) or netloc - name = urllib_parse.unquote(name) - assert name, ('URL %r produced no filename' % self.url) - return name - - @property - def scheme(self): - # type: () -> str - return urllib_parse.urlsplit(self.url)[0] - - @property - def netloc(self): - # type: () -> str - return urllib_parse.urlsplit(self.url)[1] - - @property - def path(self): - # type: () -> str - return urllib_parse.unquote(urllib_parse.urlsplit(self.url)[2]) - - def splitext(self): - # type: () -> Tuple[str, str] - return splitext(posixpath.basename(self.path.rstrip('/'))) - - @property - def ext(self): - # type: () -> str - return self.splitext()[1] - - @property - def url_without_fragment(self): - # type: () -> str - scheme, netloc, path, query, fragment = urllib_parse.urlsplit(self.url) - return urllib_parse.urlunsplit((scheme, netloc, path, query, None)) - - _egg_fragment_re = re.compile(r'[#&]egg=([^&]*)') - - @property - def egg_fragment(self): - # type: () -> Optional[str] - match = self._egg_fragment_re.search(self.url) - if not match: - return None - return match.group(1) - - _subdirectory_fragment_re = re.compile(r'[#&]subdirectory=([^&]*)') - - @property - def subdirectory_fragment(self): - # type: () -> Optional[str] - match = self._subdirectory_fragment_re.search(self.url) - if not match: - return None - return match.group(1) - - _hash_re = re.compile( - r'(sha1|sha224|sha384|sha256|sha512|md5)=([a-f0-9]+)' - ) - - @property - def hash(self): - # type: () -> Optional[str] - match = self._hash_re.search(self.url) - if match: - return match.group(2) - return None - - @property - def hash_name(self): - # type: () -> Optional[str] - match = self._hash_re.search(self.url) - if match: - return match.group(1) - return None - - @property - def show_url(self): - # type: () -> Optional[str] - return posixpath.basename(self.url.split('#', 1)[0].split('?', 1)[0]) - - @property - def is_wheel(self): - # type: () -> bool - return self.ext == WHEEL_EXTENSION - - @property - def is_artifact(self): - # type: () -> bool - """ - Determines if this points to an actual artifact (e.g. a tarball) or if - it points to an "abstract" thing like a path or a VCS location. - """ - from pip._internal.vcs import vcs - - if self.scheme in vcs.all_schemes: - return False - - return True diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/operations/__init__.py b/venv2/lib/python2.7/site-packages/pip/_internal/operations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/operations/check.py b/venv2/lib/python2.7/site-packages/pip/_internal/operations/check.py deleted file mode 100644 index 920df5d..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/operations/check.py +++ /dev/null @@ -1,155 +0,0 @@ -"""Validation of dependencies of packages -""" - -import logging -from collections import namedtuple - -from pip._vendor.packaging.utils import canonicalize_name -from pip._vendor.pkg_resources import RequirementParseError - -from pip._internal.operations.prepare import make_abstract_dist -from pip._internal.utils.misc import get_installed_distributions -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -logger = logging.getLogger(__name__) - -if MYPY_CHECK_RUNNING: - from pip._internal.req.req_install import InstallRequirement - from typing import ( - Any, Callable, Dict, Optional, Set, Tuple, List - ) - - # Shorthands - PackageSet = Dict[str, 'PackageDetails'] - Missing = Tuple[str, Any] - Conflicting = Tuple[str, str, Any] - - MissingDict = Dict[str, List[Missing]] - ConflictingDict = Dict[str, List[Conflicting]] - CheckResult = Tuple[MissingDict, ConflictingDict] - -PackageDetails = namedtuple('PackageDetails', ['version', 'requires']) - - -def create_package_set_from_installed(**kwargs): - # type: (**Any) -> Tuple[PackageSet, bool] - """Converts a list of distributions into a PackageSet. - """ - # Default to using all packages installed on the system - if kwargs == {}: - kwargs = {"local_only": False, "skip": ()} - - package_set = {} - problems = False - for dist in get_installed_distributions(**kwargs): - name = canonicalize_name(dist.project_name) - try: - package_set[name] = PackageDetails(dist.version, dist.requires()) - except RequirementParseError as e: - # Don't crash on broken metadata - logging.warning("Error parsing requirements for %s: %s", name, e) - problems = True - return package_set, problems - - -def check_package_set(package_set, should_ignore=None): - # type: (PackageSet, Optional[Callable[[str], bool]]) -> CheckResult - """Check if a package set is consistent - - If should_ignore is passed, it should be a callable that takes a - package name and returns a boolean. - """ - if should_ignore is None: - def should_ignore(name): - return False - - missing = dict() - conflicting = dict() - - for package_name in package_set: - # Info about dependencies of package_name - missing_deps = set() # type: Set[Missing] - conflicting_deps = set() # type: Set[Conflicting] - - if should_ignore(package_name): - continue - - for req in package_set[package_name].requires: - name = canonicalize_name(req.project_name) # type: str - - # Check if it's missing - if name not in package_set: - missed = True - if req.marker is not None: - missed = req.marker.evaluate() - if missed: - missing_deps.add((name, req)) - continue - - # Check if there's a conflict - version = package_set[name].version # type: str - if not req.specifier.contains(version, prereleases=True): - conflicting_deps.add((name, version, req)) - - if missing_deps: - missing[package_name] = sorted(missing_deps, key=str) - if conflicting_deps: - conflicting[package_name] = sorted(conflicting_deps, key=str) - - return missing, conflicting - - -def check_install_conflicts(to_install): - # type: (List[InstallRequirement]) -> Tuple[PackageSet, CheckResult] - """For checking if the dependency graph would be consistent after \ - installing given requirements - """ - # Start from the current state - package_set, _ = create_package_set_from_installed() - # Install packages - would_be_installed = _simulate_installation_of(to_install, package_set) - - # Only warn about directly-dependent packages; create a whitelist of them - whitelist = _create_whitelist(would_be_installed, package_set) - - return ( - package_set, - check_package_set( - package_set, should_ignore=lambda name: name not in whitelist - ) - ) - - -def _simulate_installation_of(to_install, package_set): - # type: (List[InstallRequirement], PackageSet) -> Set[str] - """Computes the version of packages after installing to_install. - """ - - # Keep track of packages that were installed - installed = set() - - # Modify it as installing requirement_set would (assuming no errors) - for inst_req in to_install: - dist = make_abstract_dist(inst_req).dist() - name = canonicalize_name(dist.key) - package_set[name] = PackageDetails(dist.version, dist.requires()) - - installed.add(name) - - return installed - - -def _create_whitelist(would_be_installed, package_set): - # type: (Set[str], PackageSet) -> Set[str] - packages_affected = set(would_be_installed) - - for package_name in package_set: - if package_name in packages_affected: - continue - - for req in package_set[package_name].requires: - if canonicalize_name(req.name) in packages_affected: - packages_affected.add(package_name) - break - - return packages_affected diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/operations/freeze.py b/venv2/lib/python2.7/site-packages/pip/_internal/operations/freeze.py deleted file mode 100644 index 0c4c761..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/operations/freeze.py +++ /dev/null @@ -1,247 +0,0 @@ -from __future__ import absolute_import - -import collections -import logging -import os -import re - -from pip._vendor import six -from pip._vendor.packaging.utils import canonicalize_name -from pip._vendor.pkg_resources import RequirementParseError - -from pip._internal.exceptions import BadCommand, InstallationError -from pip._internal.req.constructors import ( - install_req_from_editable, install_req_from_line, -) -from pip._internal.req.req_file import COMMENT_RE -from pip._internal.utils.misc import ( - dist_is_editable, get_installed_distributions, -) -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import ( - Iterator, Optional, List, Container, Set, Dict, Tuple, Iterable, Union - ) - from pip._internal.cache import WheelCache - from pip._vendor.pkg_resources import ( - Distribution, Requirement - ) - - RequirementInfo = Tuple[Optional[Union[str, Requirement]], bool, List[str]] - - -logger = logging.getLogger(__name__) - - -def freeze( - requirement=None, # type: Optional[List[str]] - find_links=None, # type: Optional[List[str]] - local_only=None, # type: Optional[bool] - user_only=None, # type: Optional[bool] - skip_regex=None, # type: Optional[str] - isolated=False, # type: bool - wheel_cache=None, # type: Optional[WheelCache] - exclude_editable=False, # type: bool - skip=() # type: Container[str] -): - # type: (...) -> Iterator[str] - find_links = find_links or [] - skip_match = None - - if skip_regex: - skip_match = re.compile(skip_regex).search - - for link in find_links: - yield '-f %s' % link - installations = {} # type: Dict[str, FrozenRequirement] - for dist in get_installed_distributions(local_only=local_only, - skip=(), - user_only=user_only): - try: - req = FrozenRequirement.from_dist(dist) - except RequirementParseError: - logger.warning( - "Could not parse requirement: %s", - dist.project_name - ) - continue - if exclude_editable and req.editable: - continue - installations[req.name] = req - - if requirement: - # the options that don't get turned into an InstallRequirement - # should only be emitted once, even if the same option is in multiple - # requirements files, so we need to keep track of what has been emitted - # so that we don't emit it again if it's seen again - emitted_options = set() # type: Set[str] - # keep track of which files a requirement is in so that we can - # give an accurate warning if a requirement appears multiple times. - req_files = collections.defaultdict(list) # type: Dict[str, List[str]] - for req_file_path in requirement: - with open(req_file_path) as req_file: - for line in req_file: - if (not line.strip() or - line.strip().startswith('#') or - (skip_match and skip_match(line)) or - line.startswith(( - '-r', '--requirement', - '-Z', '--always-unzip', - '-f', '--find-links', - '-i', '--index-url', - '--pre', - '--trusted-host', - '--process-dependency-links', - '--extra-index-url'))): - line = line.rstrip() - if line not in emitted_options: - emitted_options.add(line) - yield line - continue - - if line.startswith('-e') or line.startswith('--editable'): - if line.startswith('-e'): - line = line[2:].strip() - else: - line = line[len('--editable'):].strip().lstrip('=') - line_req = install_req_from_editable( - line, - isolated=isolated, - wheel_cache=wheel_cache, - ) - else: - line_req = install_req_from_line( - COMMENT_RE.sub('', line).strip(), - isolated=isolated, - wheel_cache=wheel_cache, - ) - - if not line_req.name: - logger.info( - "Skipping line in requirement file [%s] because " - "it's not clear what it would install: %s", - req_file_path, line.strip(), - ) - logger.info( - " (add #egg=PackageName to the URL to avoid" - " this warning)" - ) - elif line_req.name not in installations: - # either it's not installed, or it is installed - # but has been processed already - if not req_files[line_req.name]: - logger.warning( - "Requirement file [%s] contains %s, but " - "package %r is not installed", - req_file_path, - COMMENT_RE.sub('', line).strip(), line_req.name - ) - else: - req_files[line_req.name].append(req_file_path) - else: - yield str(installations[line_req.name]).rstrip() - del installations[line_req.name] - req_files[line_req.name].append(req_file_path) - - # Warn about requirements that were included multiple times (in a - # single requirements file or in different requirements files). - for name, files in six.iteritems(req_files): - if len(files) > 1: - logger.warning("Requirement %s included multiple times [%s]", - name, ', '.join(sorted(set(files)))) - - yield( - '## The following requirements were added by ' - 'pip freeze:' - ) - for installation in sorted( - installations.values(), key=lambda x: x.name.lower()): - if canonicalize_name(installation.name) not in skip: - yield str(installation).rstrip() - - -def get_requirement_info(dist): - # type: (Distribution) -> RequirementInfo - """ - Compute and return values (req, editable, comments) for use in - FrozenRequirement.from_dist(). - """ - if not dist_is_editable(dist): - return (None, False, []) - - location = os.path.normcase(os.path.abspath(dist.location)) - - from pip._internal.vcs import vcs, RemoteNotFoundError - vc_type = vcs.get_backend_type(location) - - if not vc_type: - req = dist.as_requirement() - logger.debug( - 'No VCS found for editable requirement {!r} in: {!r}', req, - location, - ) - comments = [ - '# Editable install with no version control ({})'.format(req) - ] - return (location, True, comments) - - try: - req = vc_type.get_src_requirement(location, dist.project_name) - except RemoteNotFoundError: - req = dist.as_requirement() - comments = [ - '# Editable {} install with no remote ({})'.format( - vc_type.__name__, req, - ) - ] - return (location, True, comments) - - except BadCommand: - logger.warning( - 'cannot determine version of editable source in %s ' - '(%s command not found in path)', - location, - vc_type.name, - ) - return (None, True, []) - - except InstallationError as exc: - logger.warning( - "Error when trying to get requirement for VCS system %s, " - "falling back to uneditable format", exc - ) - else: - if req is not None: - return (req, True, []) - - logger.warning( - 'Could not determine repository location of %s', location - ) - comments = ['## !! Could not determine repository location'] - - return (None, False, comments) - - -class FrozenRequirement(object): - def __init__(self, name, req, editable, comments=()): - # type: (str, Union[str, Requirement], bool, Iterable[str]) -> None - self.name = name - self.req = req - self.editable = editable - self.comments = comments - - @classmethod - def from_dist(cls, dist): - # type: (Distribution) -> FrozenRequirement - req, editable, comments = get_requirement_info(dist) - if req is None: - req = dist.as_requirement() - - return cls(dist.project_name, req, editable, comments=comments) - - def __str__(self): - req = self.req - if self.editable: - req = '-e %s' % req - return '\n'.join(list(self.comments) + [str(req)]) + '\n' diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/operations/prepare.py b/venv2/lib/python2.7/site-packages/pip/_internal/operations/prepare.py deleted file mode 100644 index 077a985..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/operations/prepare.py +++ /dev/null @@ -1,426 +0,0 @@ -"""Prepares a distribution for installation -""" - -import logging -import os - -from pip._vendor import pkg_resources, requests - -from pip._internal.build_env import BuildEnvironment -from pip._internal.download import ( - is_dir_url, is_file_url, is_vcs_url, unpack_url, url_to_path, -) -from pip._internal.exceptions import ( - DirectoryUrlHashUnsupported, HashUnpinned, InstallationError, - PreviousBuildDirError, VcsHashUnsupported, -) -from pip._internal.utils.compat import expanduser -from pip._internal.utils.hashes import MissingHashes -from pip._internal.utils.logging import indent_log -from pip._internal.utils.misc import display_path, normalize_path -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import Any, Optional - from pip._internal.req.req_install import InstallRequirement - from pip._internal.index import PackageFinder - from pip._internal.download import PipSession - from pip._internal.req.req_tracker import RequirementTracker - -logger = logging.getLogger(__name__) - - -def make_abstract_dist(req): - # type: (InstallRequirement) -> DistAbstraction - """Factory to make an abstract dist object. - - Preconditions: Either an editable req with a source_dir, or satisfied_by or - a wheel link, or a non-editable req with a source_dir. - - :return: A concrete DistAbstraction. - """ - if req.editable: - return IsSDist(req) - elif req.link and req.link.is_wheel: - return IsWheel(req) - else: - return IsSDist(req) - - -class DistAbstraction(object): - """Abstracts out the wheel vs non-wheel Resolver.resolve() logic. - - The requirements for anything installable are as follows: - - we must be able to determine the requirement name - (or we can't correctly handle the non-upgrade case). - - we must be able to generate a list of run-time dependencies - without installing any additional packages (or we would - have to either burn time by doing temporary isolated installs - or alternatively violate pips 'don't start installing unless - all requirements are available' rule - neither of which are - desirable). - - for packages with setup requirements, we must also be able - to determine their requirements without installing additional - packages (for the same reason as run-time dependencies) - - we must be able to create a Distribution object exposing the - above metadata. - """ - - def __init__(self, req): - # type: (InstallRequirement) -> None - self.req = req # type: InstallRequirement - - def dist(self): - # type: () -> Any - """Return a setuptools Dist object.""" - raise NotImplementedError - - def prep_for_dist(self, finder, build_isolation): - # type: (PackageFinder, bool) -> Any - """Ensure that we can get a Dist for this requirement.""" - raise NotImplementedError - - -class IsWheel(DistAbstraction): - - def dist(self): - # type: () -> pkg_resources.Distribution - return list(pkg_resources.find_distributions( - self.req.source_dir))[0] - - def prep_for_dist(self, finder, build_isolation): - # type: (PackageFinder, bool) -> Any - # FIXME:https://github.com/pypa/pip/issues/1112 - pass - - -class IsSDist(DistAbstraction): - - def dist(self): - return self.req.get_dist() - - def _raise_conflicts(self, conflicting_with, conflicting_reqs): - conflict_messages = [ - '%s is incompatible with %s' % (installed, wanted) - for installed, wanted in sorted(conflicting_reqs) - ] - raise InstallationError( - "Some build dependencies for %s conflict with %s: %s." % ( - self.req, conflicting_with, ', '.join(conflict_messages)) - ) - - def install_backend_dependencies(self, finder): - # type: (PackageFinder) -> None - """ - Install any extra build dependencies that the backend requests. - - :param finder: a PackageFinder object. - """ - req = self.req - with req.build_env: - # We need to have the env active when calling the hook. - req.spin_message = "Getting requirements to build wheel" - reqs = req.pep517_backend.get_requires_for_build_wheel() - conflicting, missing = req.build_env.check_requirements(reqs) - if conflicting: - self._raise_conflicts("the backend dependencies", conflicting) - req.build_env.install_requirements( - finder, missing, 'normal', - "Installing backend dependencies" - ) - - def prep_for_dist(self, finder, build_isolation): - # type: (PackageFinder, bool) -> None - # Prepare for building. We need to: - # 1. Load pyproject.toml (if it exists) - # 2. Set up the build environment - - self.req.load_pyproject_toml() - should_isolate = self.req.use_pep517 and build_isolation - - if should_isolate: - # Isolate in a BuildEnvironment and install the build-time - # requirements. - self.req.build_env = BuildEnvironment() - self.req.build_env.install_requirements( - finder, self.req.pyproject_requires, 'overlay', - "Installing build dependencies" - ) - conflicting, missing = self.req.build_env.check_requirements( - self.req.requirements_to_check - ) - if conflicting: - self._raise_conflicts("PEP 517/518 supported requirements", - conflicting) - if missing: - logger.warning( - "Missing build requirements in pyproject.toml for %s.", - self.req, - ) - logger.warning( - "The project does not specify a build backend, and " - "pip cannot fall back to setuptools without %s.", - " and ".join(map(repr, sorted(missing))) - ) - - # Install any extra build dependencies that the backend requests. - # This must be done in a second pass, as the pyproject.toml - # dependencies must be installed before we can call the backend. - self.install_backend_dependencies(finder=finder) - - self.req.prepare_metadata() - self.req.assert_source_matches_version() - - -class Installed(DistAbstraction): - - def dist(self): - # type: () -> pkg_resources.Distribution - return self.req.satisfied_by - - def prep_for_dist(self, finder, build_isolation): - # type: (PackageFinder, bool) -> Any - pass - - -class RequirementPreparer(object): - """Prepares a Requirement - """ - - def __init__( - self, - build_dir, # type: str - download_dir, # type: Optional[str] - src_dir, # type: str - wheel_download_dir, # type: Optional[str] - progress_bar, # type: str - build_isolation, # type: bool - req_tracker # type: RequirementTracker - ): - # type: (...) -> None - super(RequirementPreparer, self).__init__() - - self.src_dir = src_dir - self.build_dir = build_dir - self.req_tracker = req_tracker - - # Where still packed archives should be written to. If None, they are - # not saved, and are deleted immediately after unpacking. - self.download_dir = download_dir - - # Where still-packed .whl files should be written to. If None, they are - # written to the download_dir parameter. Separate to download_dir to - # permit only keeping wheel archives for pip wheel. - if wheel_download_dir: - wheel_download_dir = normalize_path(wheel_download_dir) - self.wheel_download_dir = wheel_download_dir - - # NOTE - # download_dir and wheel_download_dir overlap semantically and may - # be combined if we're willing to have non-wheel archives present in - # the wheelhouse output by 'pip wheel'. - - self.progress_bar = progress_bar - - # Is build isolation allowed? - self.build_isolation = build_isolation - - @property - def _download_should_save(self): - # type: () -> bool - # TODO: Modify to reduce indentation needed - if self.download_dir: - self.download_dir = expanduser(self.download_dir) - if os.path.exists(self.download_dir): - return True - else: - logger.critical('Could not find download directory') - raise InstallationError( - "Could not find or access download directory '%s'" - % display_path(self.download_dir)) - return False - - def prepare_linked_requirement( - self, - req, # type: InstallRequirement - session, # type: PipSession - finder, # type: PackageFinder - upgrade_allowed, # type: bool - require_hashes # type: bool - ): - # type: (...) -> DistAbstraction - """Prepare a requirement that would be obtained from req.link - """ - # TODO: Breakup into smaller functions - if req.link and req.link.scheme == 'file': - path = url_to_path(req.link.url) - logger.info('Processing %s', display_path(path)) - else: - logger.info('Collecting %s', req) - - with indent_log(): - # @@ if filesystem packages are not marked - # editable in a req, a non deterministic error - # occurs when the script attempts to unpack the - # build directory - req.ensure_has_source_dir(self.build_dir) - # If a checkout exists, it's unwise to keep going. version - # inconsistencies are logged later, but do not fail the - # installation. - # FIXME: this won't upgrade when there's an existing - # package unpacked in `req.source_dir` - # package unpacked in `req.source_dir` - if os.path.exists(os.path.join(req.source_dir, 'setup.py')): - raise PreviousBuildDirError( - "pip can't proceed with requirements '%s' due to a" - " pre-existing build directory (%s). This is " - "likely due to a previous installation that failed" - ". pip is being responsible and not assuming it " - "can delete this. Please delete it and try again." - % (req, req.source_dir) - ) - req.populate_link(finder, upgrade_allowed, require_hashes) - - # We can't hit this spot and have populate_link return None. - # req.satisfied_by is None here (because we're - # guarded) and upgrade has no impact except when satisfied_by - # is not None. - # Then inside find_requirement existing_applicable -> False - # If no new versions are found, DistributionNotFound is raised, - # otherwise a result is guaranteed. - assert req.link - link = req.link - - # Now that we have the real link, we can tell what kind of - # requirements we have and raise some more informative errors - # than otherwise. (For example, we can raise VcsHashUnsupported - # for a VCS URL rather than HashMissing.) - if require_hashes: - # We could check these first 2 conditions inside - # unpack_url and save repetition of conditions, but then - # we would report less-useful error messages for - # unhashable requirements, complaining that there's no - # hash provided. - if is_vcs_url(link): - raise VcsHashUnsupported() - elif is_file_url(link) and is_dir_url(link): - raise DirectoryUrlHashUnsupported() - if not req.original_link and not req.is_pinned: - # Unpinned packages are asking for trouble when a new - # version is uploaded. This isn't a security check, but - # it saves users a surprising hash mismatch in the - # future. - # - # file:/// URLs aren't pinnable, so don't complain - # about them not being pinned. - raise HashUnpinned() - - hashes = req.hashes(trust_internet=not require_hashes) - if require_hashes and not hashes: - # Known-good hashes are missing for this requirement, so - # shim it with a facade object that will provoke hash - # computation and then raise a HashMissing exception - # showing the user what the hash should be. - hashes = MissingHashes() - - try: - download_dir = self.download_dir - # We always delete unpacked sdists after pip ran. - autodelete_unpacked = True - if req.link.is_wheel and self.wheel_download_dir: - # when doing 'pip wheel` we download wheels to a - # dedicated dir. - download_dir = self.wheel_download_dir - if req.link.is_wheel: - if download_dir: - # When downloading, we only unpack wheels to get - # metadata. - autodelete_unpacked = True - else: - # When installing a wheel, we use the unpacked - # wheel. - autodelete_unpacked = False - unpack_url( - req.link, req.source_dir, - download_dir, autodelete_unpacked, - session=session, hashes=hashes, - progress_bar=self.progress_bar - ) - except requests.HTTPError as exc: - logger.critical( - 'Could not install requirement %s because of error %s', - req, - exc, - ) - raise InstallationError( - 'Could not install requirement %s because of HTTP ' - 'error %s for URL %s' % - (req, exc, req.link) - ) - abstract_dist = make_abstract_dist(req) - with self.req_tracker.track(req): - abstract_dist.prep_for_dist(finder, self.build_isolation) - if self._download_should_save: - # Make a .zip of the source_dir we already created. - if not req.link.is_artifact: - req.archive(self.download_dir) - return abstract_dist - - def prepare_editable_requirement( - self, - req, # type: InstallRequirement - require_hashes, # type: bool - use_user_site, # type: bool - finder # type: PackageFinder - ): - # type: (...) -> DistAbstraction - """Prepare an editable requirement - """ - assert req.editable, "cannot prepare a non-editable req as editable" - - logger.info('Obtaining %s', req) - - with indent_log(): - if require_hashes: - raise InstallationError( - 'The editable requirement %s cannot be installed when ' - 'requiring hashes, because there is no single file to ' - 'hash.' % req - ) - req.ensure_has_source_dir(self.src_dir) - req.update_editable(not self._download_should_save) - - abstract_dist = make_abstract_dist(req) - with self.req_tracker.track(req): - abstract_dist.prep_for_dist(finder, self.build_isolation) - - if self._download_should_save: - req.archive(self.download_dir) - req.check_if_exists(use_user_site) - - return abstract_dist - - def prepare_installed_requirement(self, req, require_hashes, skip_reason): - # type: (InstallRequirement, bool, Optional[str]) -> DistAbstraction - """Prepare an already-installed requirement - """ - assert req.satisfied_by, "req should have been satisfied but isn't" - assert skip_reason is not None, ( - "did not get skip reason skipped but req.satisfied_by " - "is set to %r" % (req.satisfied_by,) - ) - logger.info( - 'Requirement %s: %s (%s)', - skip_reason, req, req.satisfied_by.version - ) - with indent_log(): - if require_hashes: - logger.debug( - 'Since it is already installed, we are trusting this ' - 'package without checking its hash. To ensure a ' - 'completely repeatable environment, install into an ' - 'empty virtualenv.' - ) - abstract_dist = Installed(req) - - return abstract_dist diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/pep425tags.py b/venv2/lib/python2.7/site-packages/pip/_internal/pep425tags.py deleted file mode 100644 index 3b68f28..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/pep425tags.py +++ /dev/null @@ -1,381 +0,0 @@ -"""Generate and work with PEP 425 Compatibility Tags.""" -from __future__ import absolute_import - -import distutils.util -import logging -import platform -import re -import sys -import sysconfig -import warnings -from collections import OrderedDict - -import pip._internal.utils.glibc -from pip._internal.utils.compat import get_extension_suffixes -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import ( - Tuple, Callable, List, Optional, Union, Dict - ) - - Pep425Tag = Tuple[str, str, str] - -logger = logging.getLogger(__name__) - -_osx_arch_pat = re.compile(r'(.+)_(\d+)_(\d+)_(.+)') - - -def get_config_var(var): - # type: (str) -> Optional[str] - try: - return sysconfig.get_config_var(var) - except IOError as e: # Issue #1074 - warnings.warn("{}".format(e), RuntimeWarning) - return None - - -def get_abbr_impl(): - # type: () -> str - """Return abbreviated implementation name.""" - if hasattr(sys, 'pypy_version_info'): - pyimpl = 'pp' - elif sys.platform.startswith('java'): - pyimpl = 'jy' - elif sys.platform == 'cli': - pyimpl = 'ip' - else: - pyimpl = 'cp' - return pyimpl - - -def get_impl_ver(): - # type: () -> str - """Return implementation version.""" - impl_ver = get_config_var("py_version_nodot") - if not impl_ver or get_abbr_impl() == 'pp': - impl_ver = ''.join(map(str, get_impl_version_info())) - return impl_ver - - -def get_impl_version_info(): - # type: () -> Tuple[int, ...] - """Return sys.version_info-like tuple for use in decrementing the minor - version.""" - if get_abbr_impl() == 'pp': - # as per https://github.com/pypa/pip/issues/2882 - # attrs exist only on pypy - return (sys.version_info[0], - sys.pypy_version_info.major, # type: ignore - sys.pypy_version_info.minor) # type: ignore - else: - return sys.version_info[0], sys.version_info[1] - - -def get_impl_tag(): - # type: () -> str - """ - Returns the Tag for this specific implementation. - """ - return "{}{}".format(get_abbr_impl(), get_impl_ver()) - - -def get_flag(var, fallback, expected=True, warn=True): - # type: (str, Callable[..., bool], Union[bool, int], bool) -> bool - """Use a fallback method for determining SOABI flags if the needed config - var is unset or unavailable.""" - val = get_config_var(var) - if val is None: - if warn: - logger.debug("Config variable '%s' is unset, Python ABI tag may " - "be incorrect", var) - return fallback() - return val == expected - - -def get_abi_tag(): - # type: () -> Optional[str] - """Return the ABI tag based on SOABI (if available) or emulate SOABI - (CPython 2, PyPy).""" - soabi = get_config_var('SOABI') - impl = get_abbr_impl() - if not soabi and impl in {'cp', 'pp'} and hasattr(sys, 'maxunicode'): - d = '' - m = '' - u = '' - if get_flag('Py_DEBUG', - lambda: hasattr(sys, 'gettotalrefcount'), - warn=(impl == 'cp')): - d = 'd' - if get_flag('WITH_PYMALLOC', - lambda: impl == 'cp', - warn=(impl == 'cp')): - m = 'm' - if get_flag('Py_UNICODE_SIZE', - lambda: sys.maxunicode == 0x10ffff, - expected=4, - warn=(impl == 'cp' and - sys.version_info < (3, 3))) \ - and sys.version_info < (3, 3): - u = 'u' - abi = '%s%s%s%s%s' % (impl, get_impl_ver(), d, m, u) - elif soabi and soabi.startswith('cpython-'): - abi = 'cp' + soabi.split('-')[1] - elif soabi: - abi = soabi.replace('.', '_').replace('-', '_') - else: - abi = None - return abi - - -def _is_running_32bit(): - # type: () -> bool - return sys.maxsize == 2147483647 - - -def get_platform(): - # type: () -> str - """Return our platform name 'win32', 'linux_x86_64'""" - if sys.platform == 'darwin': - # distutils.util.get_platform() returns the release based on the value - # of MACOSX_DEPLOYMENT_TARGET on which Python was built, which may - # be significantly older than the user's current machine. - release, _, machine = platform.mac_ver() - split_ver = release.split('.') - - if machine == "x86_64" and _is_running_32bit(): - machine = "i386" - elif machine == "ppc64" and _is_running_32bit(): - machine = "ppc" - - return 'macosx_{}_{}_{}'.format(split_ver[0], split_ver[1], machine) - - # XXX remove distutils dependency - result = distutils.util.get_platform().replace('.', '_').replace('-', '_') - if result == "linux_x86_64" and _is_running_32bit(): - # 32 bit Python program (running on a 64 bit Linux): pip should only - # install and run 32 bit compiled extensions in that case. - result = "linux_i686" - - return result - - -def is_manylinux1_compatible(): - # type: () -> bool - # Only Linux, and only x86-64 / i686 - if get_platform() not in {"linux_x86_64", "linux_i686"}: - return False - - # Check for presence of _manylinux module - try: - import _manylinux - return bool(_manylinux.manylinux1_compatible) - except (ImportError, AttributeError): - # Fall through to heuristic check below - pass - - # Check glibc version. CentOS 5 uses glibc 2.5. - return pip._internal.utils.glibc.have_compatible_glibc(2, 5) - - -def is_manylinux2010_compatible(): - # type: () -> bool - # Only Linux, and only x86-64 / i686 - if get_platform() not in {"linux_x86_64", "linux_i686"}: - return False - - # Check for presence of _manylinux module - try: - import _manylinux - return bool(_manylinux.manylinux2010_compatible) - except (ImportError, AttributeError): - # Fall through to heuristic check below - pass - - # Check glibc version. CentOS 6 uses glibc 2.12. - return pip._internal.utils.glibc.have_compatible_glibc(2, 12) - - -def get_darwin_arches(major, minor, machine): - # type: (int, int, str) -> List[str] - """Return a list of supported arches (including group arches) for - the given major, minor and machine architecture of an macOS machine. - """ - arches = [] - - def _supports_arch(major, minor, arch): - # type: (int, int, str) -> bool - # Looking at the application support for macOS versions in the chart - # provided by https://en.wikipedia.org/wiki/OS_X#Versions it appears - # our timeline looks roughly like: - # - # 10.0 - Introduces ppc support. - # 10.4 - Introduces ppc64, i386, and x86_64 support, however the ppc64 - # and x86_64 support is CLI only, and cannot be used for GUI - # applications. - # 10.5 - Extends ppc64 and x86_64 support to cover GUI applications. - # 10.6 - Drops support for ppc64 - # 10.7 - Drops support for ppc - # - # Given that we do not know if we're installing a CLI or a GUI - # application, we must be conservative and assume it might be a GUI - # application and behave as if ppc64 and x86_64 support did not occur - # until 10.5. - # - # Note: The above information is taken from the "Application support" - # column in the chart not the "Processor support" since I believe - # that we care about what instruction sets an application can use - # not which processors the OS supports. - if arch == 'ppc': - return (major, minor) <= (10, 5) - if arch == 'ppc64': - return (major, minor) == (10, 5) - if arch == 'i386': - return (major, minor) >= (10, 4) - if arch == 'x86_64': - return (major, minor) >= (10, 5) - if arch in groups: - for garch in groups[arch]: - if _supports_arch(major, minor, garch): - return True - return False - - groups = OrderedDict([ - ("fat", ("i386", "ppc")), - ("intel", ("x86_64", "i386")), - ("fat64", ("x86_64", "ppc64")), - ("fat32", ("x86_64", "i386", "ppc")), - ]) # type: Dict[str, Tuple[str, ...]] - - if _supports_arch(major, minor, machine): - arches.append(machine) - - for garch in groups: - if machine in groups[garch] and _supports_arch(major, minor, garch): - arches.append(garch) - - arches.append('universal') - - return arches - - -def get_all_minor_versions_as_strings(version_info): - # type: (Tuple[int, ...]) -> List[str] - versions = [] - major = version_info[:-1] - # Support all previous minor Python versions. - for minor in range(version_info[-1], -1, -1): - versions.append(''.join(map(str, major + (minor,)))) - return versions - - -def get_supported( - versions=None, # type: Optional[List[str]] - noarch=False, # type: bool - platform=None, # type: Optional[str] - impl=None, # type: Optional[str] - abi=None # type: Optional[str] -): - # type: (...) -> List[Pep425Tag] - """Return a list of supported tags for each version specified in - `versions`. - - :param versions: a list of string versions, of the form ["33", "32"], - or None. The first version will be assumed to support our ABI. - :param platform: specify the exact platform you want valid - tags for, or None. If None, use the local system platform. - :param impl: specify the exact implementation you want valid - tags for, or None. If None, use the local interpreter impl. - :param abi: specify the exact abi you want valid - tags for, or None. If None, use the local interpreter abi. - """ - supported = [] - - # Versions must be given with respect to the preference - if versions is None: - version_info = get_impl_version_info() - versions = get_all_minor_versions_as_strings(version_info) - - impl = impl or get_abbr_impl() - - abis = [] # type: List[str] - - abi = abi or get_abi_tag() - if abi: - abis[0:0] = [abi] - - abi3s = set() - for suffix in get_extension_suffixes(): - if suffix.startswith('.abi'): - abi3s.add(suffix.split('.', 2)[1]) - - abis.extend(sorted(list(abi3s))) - - abis.append('none') - - if not noarch: - arch = platform or get_platform() - arch_prefix, arch_sep, arch_suffix = arch.partition('_') - if arch.startswith('macosx'): - # support macosx-10.6-intel on macosx-10.9-x86_64 - match = _osx_arch_pat.match(arch) - if match: - name, major, minor, actual_arch = match.groups() - tpl = '{}_{}_%i_%s'.format(name, major) - arches = [] - for m in reversed(range(int(minor) + 1)): - for a in get_darwin_arches(int(major), m, actual_arch): - arches.append(tpl % (m, a)) - else: - # arch pattern didn't match (?!) - arches = [arch] - elif arch_prefix == 'manylinux2010': - # manylinux1 wheels run on most manylinux2010 systems with the - # exception of wheels depending on ncurses. PEP 571 states - # manylinux1 wheels should be considered manylinux2010 wheels: - # https://www.python.org/dev/peps/pep-0571/#backwards-compatibility-with-manylinux1-wheels - arches = [arch, 'manylinux1' + arch_sep + arch_suffix] - elif platform is None: - arches = [] - if is_manylinux2010_compatible(): - arches.append('manylinux2010' + arch_sep + arch_suffix) - if is_manylinux1_compatible(): - arches.append('manylinux1' + arch_sep + arch_suffix) - arches.append(arch) - else: - arches = [arch] - - # Current version, current API (built specifically for our Python): - for abi in abis: - for arch in arches: - supported.append(('%s%s' % (impl, versions[0]), abi, arch)) - - # abi3 modules compatible with older version of Python - for version in versions[1:]: - # abi3 was introduced in Python 3.2 - if version in {'31', '30'}: - break - for abi in abi3s: # empty set if not Python 3 - for arch in arches: - supported.append(("%s%s" % (impl, version), abi, arch)) - - # Has binaries, does not use the Python API: - for arch in arches: - supported.append(('py%s' % (versions[0][0]), 'none', arch)) - - # No abi / arch, but requires our implementation: - supported.append(('%s%s' % (impl, versions[0]), 'none', 'any')) - # Tagged specifically as being cross-version compatible - # (with just the major version specified) - supported.append(('%s%s' % (impl, versions[0][0]), 'none', 'any')) - - # No abi / arch, generic Python - for i, version in enumerate(versions): - supported.append(('py%s' % (version,), 'none', 'any')) - if i == 0: - supported.append(('py%s' % (version[0]), 'none', 'any')) - - return supported - - -implementation_tag = get_impl_tag() diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/pyproject.py b/venv2/lib/python2.7/site-packages/pip/_internal/pyproject.py deleted file mode 100644 index 43efbed..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/pyproject.py +++ /dev/null @@ -1,171 +0,0 @@ -from __future__ import absolute_import - -import io -import os -import sys - -from pip._vendor import pytoml, six - -from pip._internal.exceptions import InstallationError -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import Any, Tuple, Optional, List - - -def _is_list_of_str(obj): - # type: (Any) -> bool - return ( - isinstance(obj, list) and - all(isinstance(item, six.string_types) for item in obj) - ) - - -def make_pyproject_path(setup_py_dir): - # type: (str) -> str - path = os.path.join(setup_py_dir, 'pyproject.toml') - - # Python2 __file__ should not be unicode - if six.PY2 and isinstance(path, six.text_type): - path = path.encode(sys.getfilesystemencoding()) - - return path - - -def load_pyproject_toml( - use_pep517, # type: Optional[bool] - pyproject_toml, # type: str - setup_py, # type: str - req_name # type: str -): - # type: (...) -> Optional[Tuple[List[str], str, List[str]]] - """Load the pyproject.toml file. - - Parameters: - use_pep517 - Has the user requested PEP 517 processing? None - means the user hasn't explicitly specified. - pyproject_toml - Location of the project's pyproject.toml file - setup_py - Location of the project's setup.py file - req_name - The name of the requirement we're processing (for - error reporting) - - Returns: - None if we should use the legacy code path, otherwise a tuple - ( - requirements from pyproject.toml, - name of PEP 517 backend, - requirements we should check are installed after setting - up the build environment - ) - """ - has_pyproject = os.path.isfile(pyproject_toml) - has_setup = os.path.isfile(setup_py) - - if has_pyproject: - with io.open(pyproject_toml, encoding="utf-8") as f: - pp_toml = pytoml.load(f) - build_system = pp_toml.get("build-system") - else: - build_system = None - - # The following cases must use PEP 517 - # We check for use_pep517 being non-None and falsey because that means - # the user explicitly requested --no-use-pep517. The value 0 as - # opposed to False can occur when the value is provided via an - # environment variable or config file option (due to the quirk of - # strtobool() returning an integer in pip's configuration code). - if has_pyproject and not has_setup: - if use_pep517 is not None and not use_pep517: - raise InstallationError( - "Disabling PEP 517 processing is invalid: " - "project does not have a setup.py" - ) - use_pep517 = True - elif build_system and "build-backend" in build_system: - if use_pep517 is not None and not use_pep517: - raise InstallationError( - "Disabling PEP 517 processing is invalid: " - "project specifies a build backend of {} " - "in pyproject.toml".format( - build_system["build-backend"] - ) - ) - use_pep517 = True - - # If we haven't worked out whether to use PEP 517 yet, - # and the user hasn't explicitly stated a preference, - # we do so if the project has a pyproject.toml file. - elif use_pep517 is None: - use_pep517 = has_pyproject - - # At this point, we know whether we're going to use PEP 517. - assert use_pep517 is not None - - # If we're using the legacy code path, there is nothing further - # for us to do here. - if not use_pep517: - return None - - if build_system is None: - # Either the user has a pyproject.toml with no build-system - # section, or the user has no pyproject.toml, but has opted in - # explicitly via --use-pep517. - # In the absence of any explicit backend specification, we - # assume the setuptools backend that most closely emulates the - # traditional direct setup.py execution, and require wheel and - # a version of setuptools that supports that backend. - - build_system = { - "requires": ["setuptools>=40.8.0", "wheel"], - "build-backend": "setuptools.build_meta:__legacy__", - } - - # If we're using PEP 517, we have build system information (either - # from pyproject.toml, or defaulted by the code above). - # Note that at this point, we do not know if the user has actually - # specified a backend, though. - assert build_system is not None - - # Ensure that the build-system section in pyproject.toml conforms - # to PEP 518. - error_template = ( - "{package} has a pyproject.toml file that does not comply " - "with PEP 518: {reason}" - ) - - # Specifying the build-system table but not the requires key is invalid - if "requires" not in build_system: - raise InstallationError( - error_template.format(package=req_name, reason=( - "it has a 'build-system' table but not " - "'build-system.requires' which is mandatory in the table" - )) - ) - - # Error out if requires is not a list of strings - requires = build_system["requires"] - if not _is_list_of_str(requires): - raise InstallationError(error_template.format( - package=req_name, - reason="'build-system.requires' is not a list of strings.", - )) - - backend = build_system.get("build-backend") - check = [] # type: List[str] - if backend is None: - # If the user didn't specify a backend, we assume they want to use - # the setuptools backend. But we can't be sure they have included - # a version of setuptools which supplies the backend, or wheel - # (which is needed by the backend) in their requirements. So we - # make a note to check that those requirements are present once - # we have set up the environment. - # This is quite a lot of work to check for a very specific case. But - # the problem is, that case is potentially quite common - projects that - # adopted PEP 518 early for the ability to specify requirements to - # execute setup.py, but never considered needing to mention the build - # tools themselves. The original PEP 518 code had a similar check (but - # implemented in a different way). - backend = "setuptools.build_meta:__legacy__" - check = ["setuptools>=40.8.0", "wheel"] - - return (requires, backend, check) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/req/__init__.py b/venv2/lib/python2.7/site-packages/pip/_internal/req/__init__.py deleted file mode 100644 index c39f63f..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/req/__init__.py +++ /dev/null @@ -1,78 +0,0 @@ -from __future__ import absolute_import - -import logging - -from .req_install import InstallRequirement -from .req_set import RequirementSet -from .req_file import parse_requirements -from pip._internal.utils.logging import indent_log -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import Any, List, Sequence - -__all__ = [ - "RequirementSet", "InstallRequirement", - "parse_requirements", "install_given_reqs", -] - -logger = logging.getLogger(__name__) - - -def install_given_reqs( - to_install, # type: List[InstallRequirement] - install_options, # type: List[str] - global_options=(), # type: Sequence[str] - *args, # type: Any - **kwargs # type: Any -): - # type: (...) -> List[InstallRequirement] - """ - Install everything in the given list. - - (to be called after having downloaded and unpacked the packages) - """ - - if to_install: - logger.info( - 'Installing collected packages: %s', - ', '.join([req.name for req in to_install]), - ) - - with indent_log(): - for requirement in to_install: - if requirement.conflicts_with: - logger.info( - 'Found existing installation: %s', - requirement.conflicts_with, - ) - with indent_log(): - uninstalled_pathset = requirement.uninstall( - auto_confirm=True - ) - try: - requirement.install( - install_options, - global_options, - *args, - **kwargs - ) - except Exception: - should_rollback = ( - requirement.conflicts_with and - not requirement.install_succeeded - ) - # if install did not succeed, rollback previous uninstall - if should_rollback: - uninstalled_pathset.rollback() - raise - else: - should_commit = ( - requirement.conflicts_with and - requirement.install_succeeded - ) - if should_commit: - uninstalled_pathset.commit() - requirement.remove_temporary_source() - - return to_install diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/req/constructors.py b/venv2/lib/python2.7/site-packages/pip/_internal/req/constructors.py deleted file mode 100644 index 0f18b6a..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/req/constructors.py +++ /dev/null @@ -1,340 +0,0 @@ -"""Backing implementation for InstallRequirement's various constructors - -The idea here is that these formed a major chunk of InstallRequirement's size -so, moving them and support code dedicated to them outside of that class -helps creates for better understandability for the rest of the code. - -These are meant to be used elsewhere within pip to create instances of -InstallRequirement. -""" - -import logging -import os -import re - -from pip._vendor.packaging.markers import Marker -from pip._vendor.packaging.requirements import InvalidRequirement, Requirement -from pip._vendor.packaging.specifiers import Specifier -from pip._vendor.pkg_resources import RequirementParseError, parse_requirements - -from pip._internal.download import ( - is_archive_file, is_url, path_to_url, url_to_path, -) -from pip._internal.exceptions import InstallationError -from pip._internal.models.index import PyPI, TestPyPI -from pip._internal.models.link import Link -from pip._internal.pyproject import make_pyproject_path -from pip._internal.req.req_install import InstallRequirement -from pip._internal.utils.misc import is_installable_dir -from pip._internal.utils.typing import MYPY_CHECK_RUNNING -from pip._internal.vcs import vcs -from pip._internal.wheel import Wheel - -if MYPY_CHECK_RUNNING: - from typing import ( - Any, Dict, Optional, Set, Tuple, Union, - ) - from pip._internal.cache import WheelCache - - -__all__ = [ - "install_req_from_editable", "install_req_from_line", - "parse_editable" -] - -logger = logging.getLogger(__name__) -operators = Specifier._operators.keys() - - -def _strip_extras(path): - # type: (str) -> Tuple[str, Optional[str]] - m = re.match(r'^(.+)(\[[^\]]+\])$', path) - extras = None - if m: - path_no_extras = m.group(1) - extras = m.group(2) - else: - path_no_extras = path - - return path_no_extras, extras - - -def parse_editable(editable_req): - # type: (str) -> Tuple[Optional[str], str, Optional[Set[str]]] - """Parses an editable requirement into: - - a requirement name - - an URL - - extras - - editable options - Accepted requirements: - svn+http://blahblah@rev#egg=Foobar[baz]&subdirectory=version_subdir - .[some_extra] - """ - - url = editable_req - - # If a file path is specified with extras, strip off the extras. - url_no_extras, extras = _strip_extras(url) - - if os.path.isdir(url_no_extras): - if not os.path.exists(os.path.join(url_no_extras, 'setup.py')): - msg = ( - 'File "setup.py" not found. Directory cannot be installed ' - 'in editable mode: {}'.format(os.path.abspath(url_no_extras)) - ) - pyproject_path = make_pyproject_path(url_no_extras) - if os.path.isfile(pyproject_path): - msg += ( - '\n(A "pyproject.toml" file was found, but editable ' - 'mode currently requires a setup.py based build.)' - ) - raise InstallationError(msg) - - # Treating it as code that has already been checked out - url_no_extras = path_to_url(url_no_extras) - - if url_no_extras.lower().startswith('file:'): - package_name = Link(url_no_extras).egg_fragment - if extras: - return ( - package_name, - url_no_extras, - Requirement("placeholder" + extras.lower()).extras, - ) - else: - return package_name, url_no_extras, None - - for version_control in vcs: - if url.lower().startswith('%s:' % version_control): - url = '%s+%s' % (version_control, url) - break - - if '+' not in url: - raise InstallationError( - '%s should either be a path to a local project or a VCS url ' - 'beginning with svn+, git+, hg+, or bzr+' % - editable_req - ) - - vc_type = url.split('+', 1)[0].lower() - - if not vcs.get_backend(vc_type): - error_message = 'For --editable=%s only ' % editable_req + \ - ', '.join([backend.name + '+URL' for backend in vcs.backends]) + \ - ' is currently supported' - raise InstallationError(error_message) - - package_name = Link(url).egg_fragment - if not package_name: - raise InstallationError( - "Could not detect requirement name for '%s', please specify one " - "with #egg=your_package_name" % editable_req - ) - return package_name, url, None - - -def deduce_helpful_msg(req): - # type: (str) -> str - """Returns helpful msg in case requirements file does not exist, - or cannot be parsed. - - :params req: Requirements file path - """ - msg = "" - if os.path.exists(req): - msg = " It does exist." - # Try to parse and check if it is a requirements file. - try: - with open(req, 'r') as fp: - # parse first line only - next(parse_requirements(fp.read())) - msg += " The argument you provided " + \ - "(%s) appears to be a" % (req) + \ - " requirements file. If that is the" + \ - " case, use the '-r' flag to install" + \ - " the packages specified within it." - except RequirementParseError: - logger.debug("Cannot parse '%s' as requirements \ - file" % (req), exc_info=True) - else: - msg += " File '%s' does not exist." % (req) - return msg - - -# ---- The actual constructors follow ---- - - -def install_req_from_editable( - editable_req, # type: str - comes_from=None, # type: Optional[str] - use_pep517=None, # type: Optional[bool] - isolated=False, # type: bool - options=None, # type: Optional[Dict[str, Any]] - wheel_cache=None, # type: Optional[WheelCache] - constraint=False # type: bool -): - # type: (...) -> InstallRequirement - name, url, extras_override = parse_editable(editable_req) - if url.startswith('file:'): - source_dir = url_to_path(url) - else: - source_dir = None - - if name is not None: - try: - req = Requirement(name) - except InvalidRequirement: - raise InstallationError("Invalid requirement: '%s'" % name) - else: - req = None - return InstallRequirement( - req, comes_from, source_dir=source_dir, - editable=True, - link=Link(url), - constraint=constraint, - use_pep517=use_pep517, - isolated=isolated, - options=options if options else {}, - wheel_cache=wheel_cache, - extras=extras_override or (), - ) - - -def install_req_from_line( - name, # type: str - comes_from=None, # type: Optional[Union[str, InstallRequirement]] - use_pep517=None, # type: Optional[bool] - isolated=False, # type: bool - options=None, # type: Optional[Dict[str, Any]] - wheel_cache=None, # type: Optional[WheelCache] - constraint=False # type: bool -): - # type: (...) -> InstallRequirement - """Creates an InstallRequirement from a name, which might be a - requirement, directory containing 'setup.py', filename, or URL. - """ - if is_url(name): - marker_sep = '; ' - else: - marker_sep = ';' - if marker_sep in name: - name, markers_as_string = name.split(marker_sep, 1) - markers_as_string = markers_as_string.strip() - if not markers_as_string: - markers = None - else: - markers = Marker(markers_as_string) - else: - markers = None - name = name.strip() - req_as_string = None - path = os.path.normpath(os.path.abspath(name)) - link = None - extras_as_string = None - - if is_url(name): - link = Link(name) - else: - p, extras_as_string = _strip_extras(path) - looks_like_dir = os.path.isdir(p) and ( - os.path.sep in name or - (os.path.altsep is not None and os.path.altsep in name) or - name.startswith('.') - ) - if looks_like_dir: - if not is_installable_dir(p): - raise InstallationError( - "Directory %r is not installable. Neither 'setup.py' " - "nor 'pyproject.toml' found." % name - ) - link = Link(path_to_url(p)) - elif is_archive_file(p): - if not os.path.isfile(p): - logger.warning( - 'Requirement %r looks like a filename, but the ' - 'file does not exist', - name - ) - link = Link(path_to_url(p)) - - # it's a local file, dir, or url - if link: - # Handle relative file URLs - if link.scheme == 'file' and re.search(r'\.\./', link.url): - link = Link( - path_to_url(os.path.normpath(os.path.abspath(link.path)))) - # wheel file - if link.is_wheel: - wheel = Wheel(link.filename) # can raise InvalidWheelFilename - req_as_string = "%s==%s" % (wheel.name, wheel.version) - else: - # set the req to the egg fragment. when it's not there, this - # will become an 'unnamed' requirement - req_as_string = link.egg_fragment - - # a requirement specifier - else: - req_as_string = name - - if extras_as_string: - extras = Requirement("placeholder" + extras_as_string.lower()).extras - else: - extras = () - if req_as_string is not None: - try: - req = Requirement(req_as_string) - except InvalidRequirement: - if os.path.sep in req_as_string: - add_msg = "It looks like a path." - add_msg += deduce_helpful_msg(req_as_string) - elif ('=' in req_as_string and - not any(op in req_as_string for op in operators)): - add_msg = "= is not a valid operator. Did you mean == ?" - else: - add_msg = "" - raise InstallationError( - "Invalid requirement: '%s'\n%s" % (req_as_string, add_msg) - ) - else: - req = None - - return InstallRequirement( - req, comes_from, link=link, markers=markers, - use_pep517=use_pep517, isolated=isolated, - options=options if options else {}, - wheel_cache=wheel_cache, - constraint=constraint, - extras=extras, - ) - - -def install_req_from_req_string( - req_string, # type: str - comes_from=None, # type: Optional[InstallRequirement] - isolated=False, # type: bool - wheel_cache=None, # type: Optional[WheelCache] - use_pep517=None # type: Optional[bool] -): - # type: (...) -> InstallRequirement - try: - req = Requirement(req_string) - except InvalidRequirement: - raise InstallationError("Invalid requirement: '%s'" % req_string) - - domains_not_allowed = [ - PyPI.file_storage_domain, - TestPyPI.file_storage_domain, - ] - if (req.url and comes_from and comes_from.link and - comes_from.link.netloc in domains_not_allowed): - # Explicitly disallow pypi packages that depend on external urls - raise InstallationError( - "Packages installed from PyPI cannot depend on packages " - "which are not also hosted on PyPI.\n" - "%s depends on %s " % (comes_from.name, req) - ) - - return InstallRequirement( - req, comes_from, isolated=isolated, wheel_cache=wheel_cache, - use_pep517=use_pep517 - ) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/req/req_file.py b/venv2/lib/python2.7/site-packages/pip/_internal/req/req_file.py deleted file mode 100644 index 270b75c..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/req/req_file.py +++ /dev/null @@ -1,383 +0,0 @@ -""" -Requirements file parsing -""" - -from __future__ import absolute_import - -import optparse -import os -import re -import shlex -import sys - -from pip._vendor.six.moves import filterfalse -from pip._vendor.six.moves.urllib import parse as urllib_parse - -from pip._internal.cli import cmdoptions -from pip._internal.download import get_file_content -from pip._internal.exceptions import RequirementsFileParseError -from pip._internal.req.constructors import ( - install_req_from_editable, install_req_from_line, -) -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import ( - Any, Callable, Iterator, List, NoReturn, Optional, Text, Tuple, - ) - from pip._internal.req import InstallRequirement - from pip._internal.cache import WheelCache - from pip._internal.index import PackageFinder - from pip._internal.download import PipSession - - ReqFileLines = Iterator[Tuple[int, Text]] - -__all__ = ['parse_requirements'] - -SCHEME_RE = re.compile(r'^(http|https|file):', re.I) -COMMENT_RE = re.compile(r'(^|\s)+#.*$') - -# Matches environment variable-style values in '${MY_VARIABLE_1}' with the -# variable name consisting of only uppercase letters, digits or the '_' -# (underscore). This follows the POSIX standard defined in IEEE Std 1003.1, -# 2013 Edition. -ENV_VAR_RE = re.compile(r'(?P\$\{(?P[A-Z0-9_]+)\})') - -SUPPORTED_OPTIONS = [ - cmdoptions.constraints, - cmdoptions.editable, - cmdoptions.requirements, - cmdoptions.no_index, - cmdoptions.index_url, - cmdoptions.find_links, - cmdoptions.extra_index_url, - cmdoptions.always_unzip, - cmdoptions.no_binary, - cmdoptions.only_binary, - cmdoptions.pre, - cmdoptions.trusted_host, - cmdoptions.require_hashes, -] # type: List[Callable[..., optparse.Option]] - -# options to be passed to requirements -SUPPORTED_OPTIONS_REQ = [ - cmdoptions.install_options, - cmdoptions.global_options, - cmdoptions.hash, -] # type: List[Callable[..., optparse.Option]] - -# the 'dest' string values -SUPPORTED_OPTIONS_REQ_DEST = [str(o().dest) for o in SUPPORTED_OPTIONS_REQ] - - -def parse_requirements( - filename, # type: str - finder=None, # type: Optional[PackageFinder] - comes_from=None, # type: Optional[str] - options=None, # type: Optional[optparse.Values] - session=None, # type: Optional[PipSession] - constraint=False, # type: bool - wheel_cache=None, # type: Optional[WheelCache] - use_pep517=None # type: Optional[bool] -): - # type: (...) -> Iterator[InstallRequirement] - """Parse a requirements file and yield InstallRequirement instances. - - :param filename: Path or url of requirements file. - :param finder: Instance of pip.index.PackageFinder. - :param comes_from: Origin description of requirements. - :param options: cli options. - :param session: Instance of pip.download.PipSession. - :param constraint: If true, parsing a constraint file rather than - requirements file. - :param wheel_cache: Instance of pip.wheel.WheelCache - :param use_pep517: Value of the --use-pep517 option. - """ - if session is None: - raise TypeError( - "parse_requirements() missing 1 required keyword argument: " - "'session'" - ) - - _, content = get_file_content( - filename, comes_from=comes_from, session=session - ) - - lines_enum = preprocess(content, options) - - for line_number, line in lines_enum: - req_iter = process_line(line, filename, line_number, finder, - comes_from, options, session, wheel_cache, - use_pep517=use_pep517, constraint=constraint) - for req in req_iter: - yield req - - -def preprocess(content, options): - # type: (Text, Optional[optparse.Values]) -> ReqFileLines - """Split, filter, and join lines, and return a line iterator - - :param content: the content of the requirements file - :param options: cli options - """ - lines_enum = enumerate(content.splitlines(), start=1) # type: ReqFileLines - lines_enum = join_lines(lines_enum) - lines_enum = ignore_comments(lines_enum) - lines_enum = skip_regex(lines_enum, options) - lines_enum = expand_env_variables(lines_enum) - return lines_enum - - -def process_line( - line, # type: Text - filename, # type: str - line_number, # type: int - finder=None, # type: Optional[PackageFinder] - comes_from=None, # type: Optional[str] - options=None, # type: Optional[optparse.Values] - session=None, # type: Optional[PipSession] - wheel_cache=None, # type: Optional[WheelCache] - use_pep517=None, # type: Optional[bool] - constraint=False # type: bool -): - # type: (...) -> Iterator[InstallRequirement] - """Process a single requirements line; This can result in creating/yielding - requirements, or updating the finder. - - For lines that contain requirements, the only options that have an effect - are from SUPPORTED_OPTIONS_REQ, and they are scoped to the - requirement. Other options from SUPPORTED_OPTIONS may be present, but are - ignored. - - For lines that do not contain requirements, the only options that have an - effect are from SUPPORTED_OPTIONS. Options from SUPPORTED_OPTIONS_REQ may - be present, but are ignored. These lines may contain multiple options - (although our docs imply only one is supported), and all our parsed and - affect the finder. - - :param constraint: If True, parsing a constraints file. - :param options: OptionParser options that we may update - """ - parser = build_parser(line) - defaults = parser.get_default_values() - defaults.index_url = None - if finder: - defaults.format_control = finder.format_control - args_str, options_str = break_args_options(line) - # Prior to 2.7.3, shlex cannot deal with unicode entries - if sys.version_info < (2, 7, 3): - # https://github.com/python/mypy/issues/1174 - options_str = options_str.encode('utf8') # type: ignore - # https://github.com/python/mypy/issues/1174 - opts, _ = parser.parse_args( - shlex.split(options_str), defaults) # type: ignore - - # preserve for the nested code path - line_comes_from = '%s %s (line %s)' % ( - '-c' if constraint else '-r', filename, line_number, - ) - - # yield a line requirement - if args_str: - isolated = options.isolated_mode if options else False - if options: - cmdoptions.check_install_build_global(options, opts) - # get the options that apply to requirements - req_options = {} - for dest in SUPPORTED_OPTIONS_REQ_DEST: - if dest in opts.__dict__ and opts.__dict__[dest]: - req_options[dest] = opts.__dict__[dest] - yield install_req_from_line( - args_str, line_comes_from, constraint=constraint, - use_pep517=use_pep517, - isolated=isolated, options=req_options, wheel_cache=wheel_cache - ) - - # yield an editable requirement - elif opts.editables: - isolated = options.isolated_mode if options else False - yield install_req_from_editable( - opts.editables[0], comes_from=line_comes_from, - use_pep517=use_pep517, - constraint=constraint, isolated=isolated, wheel_cache=wheel_cache - ) - - # parse a nested requirements file - elif opts.requirements or opts.constraints: - if opts.requirements: - req_path = opts.requirements[0] - nested_constraint = False - else: - req_path = opts.constraints[0] - nested_constraint = True - # original file is over http - if SCHEME_RE.search(filename): - # do a url join so relative paths work - req_path = urllib_parse.urljoin(filename, req_path) - # original file and nested file are paths - elif not SCHEME_RE.search(req_path): - # do a join so relative paths work - req_path = os.path.join(os.path.dirname(filename), req_path) - # TODO: Why not use `comes_from='-r {} (line {})'` here as well? - parsed_reqs = parse_requirements( - req_path, finder, comes_from, options, session, - constraint=nested_constraint, wheel_cache=wheel_cache - ) - for req in parsed_reqs: - yield req - - # percolate hash-checking option upward - elif opts.require_hashes: - options.require_hashes = opts.require_hashes - - # set finder options - elif finder: - if opts.index_url: - finder.index_urls = [opts.index_url] - if opts.no_index is True: - finder.index_urls = [] - if opts.extra_index_urls: - finder.index_urls.extend(opts.extra_index_urls) - if opts.find_links: - # FIXME: it would be nice to keep track of the source - # of the find_links: support a find-links local path - # relative to a requirements file. - value = opts.find_links[0] - req_dir = os.path.dirname(os.path.abspath(filename)) - relative_to_reqs_file = os.path.join(req_dir, value) - if os.path.exists(relative_to_reqs_file): - value = relative_to_reqs_file - finder.find_links.append(value) - if opts.pre: - finder.allow_all_prereleases = True - if opts.trusted_hosts: - finder.secure_origins.extend( - ("*", host, "*") for host in opts.trusted_hosts) - - -def break_args_options(line): - # type: (Text) -> Tuple[str, Text] - """Break up the line into an args and options string. We only want to shlex - (and then optparse) the options, not the args. args can contain markers - which are corrupted by shlex. - """ - tokens = line.split(' ') - args = [] - options = tokens[:] - for token in tokens: - if token.startswith('-') or token.startswith('--'): - break - else: - args.append(token) - options.pop(0) - return ' '.join(args), ' '.join(options) # type: ignore - - -def build_parser(line): - # type: (Text) -> optparse.OptionParser - """ - Return a parser for parsing requirement lines - """ - parser = optparse.OptionParser(add_help_option=False) - - option_factories = SUPPORTED_OPTIONS + SUPPORTED_OPTIONS_REQ - for option_factory in option_factories: - option = option_factory() - parser.add_option(option) - - # By default optparse sys.exits on parsing errors. We want to wrap - # that in our own exception. - def parser_exit(self, msg): - # type: (Any, str) -> NoReturn - # add offending line - msg = 'Invalid requirement: %s\n%s' % (line, msg) - raise RequirementsFileParseError(msg) - # NOTE: mypy disallows assigning to a method - # https://github.com/python/mypy/issues/2427 - parser.exit = parser_exit # type: ignore - - return parser - - -def join_lines(lines_enum): - # type: (ReqFileLines) -> ReqFileLines - """Joins a line ending in '\' with the previous line (except when following - comments). The joined line takes on the index of the first line. - """ - primary_line_number = None - new_line = [] # type: List[Text] - for line_number, line in lines_enum: - if not line.endswith('\\') or COMMENT_RE.match(line): - if COMMENT_RE.match(line): - # this ensures comments are always matched later - line = ' ' + line - if new_line: - new_line.append(line) - yield primary_line_number, ''.join(new_line) - new_line = [] - else: - yield line_number, line - else: - if not new_line: - primary_line_number = line_number - new_line.append(line.strip('\\')) - - # last line contains \ - if new_line: - yield primary_line_number, ''.join(new_line) - - # TODO: handle space after '\'. - - -def ignore_comments(lines_enum): - # type: (ReqFileLines) -> ReqFileLines - """ - Strips comments and filter empty lines. - """ - for line_number, line in lines_enum: - line = COMMENT_RE.sub('', line) - line = line.strip() - if line: - yield line_number, line - - -def skip_regex(lines_enum, options): - # type: (ReqFileLines, Optional[optparse.Values]) -> ReqFileLines - """ - Skip lines that match '--skip-requirements-regex' pattern - - Note: the regex pattern is only built once - """ - skip_regex = options.skip_requirements_regex if options else None - if skip_regex: - pattern = re.compile(skip_regex) - lines_enum = filterfalse(lambda e: pattern.search(e[1]), lines_enum) - return lines_enum - - -def expand_env_variables(lines_enum): - # type: (ReqFileLines) -> ReqFileLines - """Replace all environment variables that can be retrieved via `os.getenv`. - - The only allowed format for environment variables defined in the - requirement file is `${MY_VARIABLE_1}` to ensure two things: - - 1. Strings that contain a `$` aren't accidentally (partially) expanded. - 2. Ensure consistency across platforms for requirement files. - - These points are the result of a discussion on the `github pull - request #3514 `_. - - Valid characters in variable names follow the `POSIX standard - `_ and are limited - to uppercase letter, digits and the `_` (underscore). - """ - for line_number, line in lines_enum: - for env_var, var_name in ENV_VAR_RE.findall(line): - value = os.getenv(var_name) - if not value: - continue - - line = line.replace(env_var, value) - - yield line_number, line diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/req/req_install.py b/venv2/lib/python2.7/site-packages/pip/_internal/req/req_install.py deleted file mode 100644 index 25a692e..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/req/req_install.py +++ /dev/null @@ -1,1028 +0,0 @@ -from __future__ import absolute_import - -import logging -import os -import shutil -import sys -import sysconfig -import zipfile -from distutils.util import change_root - -from pip._vendor import pkg_resources, six -from pip._vendor.packaging.requirements import Requirement -from pip._vendor.packaging.utils import canonicalize_name -from pip._vendor.packaging.version import Version -from pip._vendor.packaging.version import parse as parse_version -from pip._vendor.pep517.wrappers import Pep517HookCaller - -from pip._internal import wheel -from pip._internal.build_env import NoOpBuildEnvironment -from pip._internal.exceptions import InstallationError -from pip._internal.locations import ( - PIP_DELETE_MARKER_FILENAME, running_under_virtualenv, -) -from pip._internal.models.link import Link -from pip._internal.pyproject import load_pyproject_toml, make_pyproject_path -from pip._internal.req.req_uninstall import UninstallPathSet -from pip._internal.utils.compat import native_str -from pip._internal.utils.hashes import Hashes -from pip._internal.utils.logging import indent_log -from pip._internal.utils.misc import ( - _make_build_dir, ask_path_exists, backup_dir, call_subprocess, - display_path, dist_in_site_packages, dist_in_usersite, ensure_dir, - get_installed_version, redact_password_from_url, rmtree, -) -from pip._internal.utils.packaging import get_metadata -from pip._internal.utils.setuptools_build import SETUPTOOLS_SHIM -from pip._internal.utils.temp_dir import TempDirectory -from pip._internal.utils.typing import MYPY_CHECK_RUNNING -from pip._internal.utils.ui import open_spinner -from pip._internal.vcs import vcs -from pip._internal.wheel import move_wheel_files - -if MYPY_CHECK_RUNNING: - from typing import ( - Any, Dict, Iterable, List, Mapping, Optional, Sequence, Union, - ) - from pip._internal.build_env import BuildEnvironment - from pip._internal.cache import WheelCache - from pip._internal.index import PackageFinder - from pip._vendor.pkg_resources import Distribution - from pip._vendor.packaging.specifiers import SpecifierSet - from pip._vendor.packaging.markers import Marker - - -logger = logging.getLogger(__name__) - - -class InstallRequirement(object): - """ - Represents something that may be installed later on, may have information - about where to fetch the relevant requirement and also contains logic for - installing the said requirement. - """ - - def __init__( - self, - req, # type: Optional[Requirement] - comes_from, # type: Optional[Union[str, InstallRequirement]] - source_dir=None, # type: Optional[str] - editable=False, # type: bool - link=None, # type: Optional[Link] - update=True, # type: bool - markers=None, # type: Optional[Marker] - use_pep517=None, # type: Optional[bool] - isolated=False, # type: bool - options=None, # type: Optional[Dict[str, Any]] - wheel_cache=None, # type: Optional[WheelCache] - constraint=False, # type: bool - extras=() # type: Iterable[str] - ): - # type: (...) -> None - assert req is None or isinstance(req, Requirement), req - self.req = req - self.comes_from = comes_from - self.constraint = constraint - if source_dir is not None: - self.source_dir = os.path.normpath(os.path.abspath(source_dir)) - else: - self.source_dir = None - self.editable = editable - - self._wheel_cache = wheel_cache - if link is None and req and req.url: - # PEP 508 URL requirement - link = Link(req.url) - self.link = self.original_link = link - - if extras: - self.extras = extras - elif req: - self.extras = { - pkg_resources.safe_extra(extra) for extra in req.extras - } - else: - self.extras = set() - if markers is None and req: - markers = req.marker - self.markers = markers - - self._egg_info_path = None # type: Optional[str] - # This holds the pkg_resources.Distribution object if this requirement - # is already available: - self.satisfied_by = None - # This hold the pkg_resources.Distribution object if this requirement - # conflicts with another installed distribution: - self.conflicts_with = None - # Temporary build location - self._temp_build_dir = TempDirectory(kind="req-build") - # Used to store the global directory where the _temp_build_dir should - # have been created. Cf _correct_build_location method. - self._ideal_build_dir = None # type: Optional[str] - # True if the editable should be updated: - self.update = update - # Set to True after successful installation - self.install_succeeded = None # type: Optional[bool] - # UninstallPathSet of uninstalled distribution (for possible rollback) - self.uninstalled_pathset = None - self.options = options if options else {} - # Set to True after successful preparation of this requirement - self.prepared = False - self.is_direct = False - - self.isolated = isolated - self.build_env = NoOpBuildEnvironment() # type: BuildEnvironment - - # For PEP 517, the directory where we request the project metadata - # gets stored. We need this to pass to build_wheel, so the backend - # can ensure that the wheel matches the metadata (see the PEP for - # details). - self.metadata_directory = None # type: Optional[str] - - # The static build requirements (from pyproject.toml) - self.pyproject_requires = None # type: Optional[List[str]] - - # Build requirements that we will check are available - self.requirements_to_check = [] # type: List[str] - - # The PEP 517 backend we should use to build the project - self.pep517_backend = None # type: Optional[Pep517HookCaller] - - # Are we using PEP 517 for this requirement? - # After pyproject.toml has been loaded, the only valid values are True - # and False. Before loading, None is valid (meaning "use the default"). - # Setting an explicit value before loading pyproject.toml is supported, - # but after loading this flag should be treated as read only. - self.use_pep517 = use_pep517 - - def __str__(self): - # type: () -> str - if self.req: - s = str(self.req) - if self.link: - s += ' from %s' % redact_password_from_url(self.link.url) - elif self.link: - s = redact_password_from_url(self.link.url) - else: - s = '' - if self.satisfied_by is not None: - s += ' in %s' % display_path(self.satisfied_by.location) - if self.comes_from: - if isinstance(self.comes_from, six.string_types): - comes_from = self.comes_from - else: - comes_from = self.comes_from.from_path() - if comes_from: - s += ' (from %s)' % comes_from - return s - - def __repr__(self): - # type: () -> str - return '<%s object: %s editable=%r>' % ( - self.__class__.__name__, str(self), self.editable) - - def populate_link(self, finder, upgrade, require_hashes): - # type: (PackageFinder, bool, bool) -> None - """Ensure that if a link can be found for this, that it is found. - - Note that self.link may still be None - if Upgrade is False and the - requirement is already installed. - - If require_hashes is True, don't use the wheel cache, because cached - wheels, always built locally, have different hashes than the files - downloaded from the index server and thus throw false hash mismatches. - Furthermore, cached wheels at present have undeterministic contents due - to file modification times. - """ - if self.link is None: - self.link = finder.find_requirement(self, upgrade) - if self._wheel_cache is not None and not require_hashes: - old_link = self.link - self.link = self._wheel_cache.get(self.link, self.name) - if old_link != self.link: - logger.debug('Using cached wheel link: %s', self.link) - - # Things that are valid for all kinds of requirements? - @property - def name(self): - # type: () -> Optional[str] - if self.req is None: - return None - return native_str(pkg_resources.safe_name(self.req.name)) - - @property - def specifier(self): - # type: () -> SpecifierSet - return self.req.specifier - - @property - def is_pinned(self): - # type: () -> bool - """Return whether I am pinned to an exact version. - - For example, some-package==1.2 is pinned; some-package>1.2 is not. - """ - specifiers = self.specifier - return (len(specifiers) == 1 and - next(iter(specifiers)).operator in {'==', '==='}) - - @property - def installed_version(self): - # type: () -> Optional[str] - return get_installed_version(self.name) - - def match_markers(self, extras_requested=None): - # type: (Optional[Iterable[str]]) -> bool - if not extras_requested: - # Provide an extra to safely evaluate the markers - # without matching any extra - extras_requested = ('',) - if self.markers is not None: - return any( - self.markers.evaluate({'extra': extra}) - for extra in extras_requested) - else: - return True - - @property - def has_hash_options(self): - # type: () -> bool - """Return whether any known-good hashes are specified as options. - - These activate --require-hashes mode; hashes specified as part of a - URL do not. - - """ - return bool(self.options.get('hashes', {})) - - def hashes(self, trust_internet=True): - # type: (bool) -> Hashes - """Return a hash-comparer that considers my option- and URL-based - hashes to be known-good. - - Hashes in URLs--ones embedded in the requirements file, not ones - downloaded from an index server--are almost peers with ones from - flags. They satisfy --require-hashes (whether it was implicitly or - explicitly activated) but do not activate it. md5 and sha224 are not - allowed in flags, which should nudge people toward good algos. We - always OR all hashes together, even ones from URLs. - - :param trust_internet: Whether to trust URL-based (#md5=...) hashes - downloaded from the internet, as by populate_link() - - """ - good_hashes = self.options.get('hashes', {}).copy() - link = self.link if trust_internet else self.original_link - if link and link.hash: - good_hashes.setdefault(link.hash_name, []).append(link.hash) - return Hashes(good_hashes) - - def from_path(self): - # type: () -> Optional[str] - """Format a nice indicator to show where this "comes from" - """ - if self.req is None: - return None - s = str(self.req) - if self.comes_from: - if isinstance(self.comes_from, six.string_types): - comes_from = self.comes_from - else: - comes_from = self.comes_from.from_path() - if comes_from: - s += '->' + comes_from - return s - - def build_location(self, build_dir): - # type: (str) -> Optional[str] - assert build_dir is not None - if self._temp_build_dir.path is not None: - return self._temp_build_dir.path - if self.req is None: - # for requirement via a path to a directory: the name of the - # package is not available yet so we create a temp directory - # Once run_egg_info will have run, we'll be able - # to fix it via _correct_build_location - # Some systems have /tmp as a symlink which confuses custom - # builds (such as numpy). Thus, we ensure that the real path - # is returned. - self._temp_build_dir.create() - self._ideal_build_dir = build_dir - - return self._temp_build_dir.path - if self.editable: - name = self.name.lower() - else: - name = self.name - # FIXME: Is there a better place to create the build_dir? (hg and bzr - # need this) - if not os.path.exists(build_dir): - logger.debug('Creating directory %s', build_dir) - _make_build_dir(build_dir) - return os.path.join(build_dir, name) - - def _correct_build_location(self): - # type: () -> None - """Move self._temp_build_dir to self._ideal_build_dir/self.req.name - - For some requirements (e.g. a path to a directory), the name of the - package is not available until we run egg_info, so the build_location - will return a temporary directory and store the _ideal_build_dir. - - This is only called by self.run_egg_info to fix the temporary build - directory. - """ - if self.source_dir is not None: - return - assert self.req is not None - assert self._temp_build_dir.path - assert (self._ideal_build_dir is not None and - self._ideal_build_dir.path) # type: ignore - old_location = self._temp_build_dir.path - self._temp_build_dir.path = None - - new_location = self.build_location(self._ideal_build_dir) - if os.path.exists(new_location): - raise InstallationError( - 'A package already exists in %s; please remove it to continue' - % display_path(new_location)) - logger.debug( - 'Moving package %s from %s to new location %s', - self, display_path(old_location), display_path(new_location), - ) - shutil.move(old_location, new_location) - self._temp_build_dir.path = new_location - self._ideal_build_dir = None - self.source_dir = os.path.normpath(os.path.abspath(new_location)) - self._egg_info_path = None - - # Correct the metadata directory, if it exists - if self.metadata_directory: - old_meta = self.metadata_directory - rel = os.path.relpath(old_meta, start=old_location) - new_meta = os.path.join(new_location, rel) - new_meta = os.path.normpath(os.path.abspath(new_meta)) - self.metadata_directory = new_meta - - def remove_temporary_source(self): - # type: () -> None - """Remove the source files from this requirement, if they are marked - for deletion""" - if self.source_dir and os.path.exists( - os.path.join(self.source_dir, PIP_DELETE_MARKER_FILENAME)): - logger.debug('Removing source in %s', self.source_dir) - rmtree(self.source_dir) - self.source_dir = None - self._temp_build_dir.cleanup() - self.build_env.cleanup() - - def check_if_exists(self, use_user_site): - # type: (bool) -> bool - """Find an installed distribution that satisfies or conflicts - with this requirement, and set self.satisfied_by or - self.conflicts_with appropriately. - """ - if self.req is None: - return False - try: - # get_distribution() will resolve the entire list of requirements - # anyway, and we've already determined that we need the requirement - # in question, so strip the marker so that we don't try to - # evaluate it. - no_marker = Requirement(str(self.req)) - no_marker.marker = None - self.satisfied_by = pkg_resources.get_distribution(str(no_marker)) - if self.editable and self.satisfied_by: - self.conflicts_with = self.satisfied_by - # when installing editables, nothing pre-existing should ever - # satisfy - self.satisfied_by = None - return True - except pkg_resources.DistributionNotFound: - return False - except pkg_resources.VersionConflict: - existing_dist = pkg_resources.get_distribution( - self.req.name - ) - if use_user_site: - if dist_in_usersite(existing_dist): - self.conflicts_with = existing_dist - elif (running_under_virtualenv() and - dist_in_site_packages(existing_dist)): - raise InstallationError( - "Will not install to the user site because it will " - "lack sys.path precedence to %s in %s" % - (existing_dist.project_name, existing_dist.location) - ) - else: - self.conflicts_with = existing_dist - return True - - # Things valid for wheels - @property - def is_wheel(self): - # type: () -> bool - if not self.link: - return False - return self.link.is_wheel - - def move_wheel_files( - self, - wheeldir, # type: str - root=None, # type: Optional[str] - home=None, # type: Optional[str] - prefix=None, # type: Optional[str] - warn_script_location=True, # type: bool - use_user_site=False, # type: bool - pycompile=True # type: bool - ): - # type: (...) -> None - move_wheel_files( - self.name, self.req, wheeldir, - user=use_user_site, - home=home, - root=root, - prefix=prefix, - pycompile=pycompile, - isolated=self.isolated, - warn_script_location=warn_script_location, - ) - - # Things valid for sdists - @property - def setup_py_dir(self): - # type: () -> str - return os.path.join( - self.source_dir, - self.link and self.link.subdirectory_fragment or '') - - @property - def setup_py(self): - # type: () -> str - assert self.source_dir, "No source dir for %s" % self - - setup_py = os.path.join(self.setup_py_dir, 'setup.py') - - # Python2 __file__ should not be unicode - if six.PY2 and isinstance(setup_py, six.text_type): - setup_py = setup_py.encode(sys.getfilesystemencoding()) - - return setup_py - - @property - def pyproject_toml(self): - # type: () -> str - assert self.source_dir, "No source dir for %s" % self - - return make_pyproject_path(self.setup_py_dir) - - def load_pyproject_toml(self): - # type: () -> None - """Load the pyproject.toml file. - - After calling this routine, all of the attributes related to PEP 517 - processing for this requirement have been set. In particular, the - use_pep517 attribute can be used to determine whether we should - follow the PEP 517 or legacy (setup.py) code path. - """ - pep517_data = load_pyproject_toml( - self.use_pep517, - self.pyproject_toml, - self.setup_py, - str(self) - ) - - if pep517_data is None: - self.use_pep517 = False - else: - self.use_pep517 = True - requires, backend, check = pep517_data - self.requirements_to_check = check - self.pyproject_requires = requires - self.pep517_backend = Pep517HookCaller(self.setup_py_dir, backend) - - # Use a custom function to call subprocesses - self.spin_message = "" - - def runner( - cmd, # type: List[str] - cwd=None, # type: Optional[str] - extra_environ=None # type: Optional[Mapping[str, Any]] - ): - # type: (...) -> None - with open_spinner(self.spin_message) as spinner: - call_subprocess( - cmd, - cwd=cwd, - extra_environ=extra_environ, - spinner=spinner - ) - self.spin_message = "" - - self.pep517_backend._subprocess_runner = runner - - def prepare_metadata(self): - # type: () -> None - """Ensure that project metadata is available. - - Under PEP 517, call the backend hook to prepare the metadata. - Under legacy processing, call setup.py egg-info. - """ - assert self.source_dir - - with indent_log(): - if self.use_pep517: - self.prepare_pep517_metadata() - else: - self.run_egg_info() - - if not self.req: - if isinstance(parse_version(self.metadata["Version"]), Version): - op = "==" - else: - op = "===" - self.req = Requirement( - "".join([ - self.metadata["Name"], - op, - self.metadata["Version"], - ]) - ) - self._correct_build_location() - else: - metadata_name = canonicalize_name(self.metadata["Name"]) - if canonicalize_name(self.req.name) != metadata_name: - logger.warning( - 'Generating metadata for package %s ' - 'produced metadata for project name %s. Fix your ' - '#egg=%s fragments.', - self.name, metadata_name, self.name - ) - self.req = Requirement(metadata_name) - - def prepare_pep517_metadata(self): - # type: () -> None - assert self.pep517_backend is not None - - metadata_dir = os.path.join( - self.setup_py_dir, - 'pip-wheel-metadata' - ) - ensure_dir(metadata_dir) - - with self.build_env: - # Note that Pep517HookCaller implements a fallback for - # prepare_metadata_for_build_wheel, so we don't have to - # consider the possibility that this hook doesn't exist. - backend = self.pep517_backend - self.spin_message = "Preparing wheel metadata" - distinfo_dir = backend.prepare_metadata_for_build_wheel( - metadata_dir - ) - - self.metadata_directory = os.path.join(metadata_dir, distinfo_dir) - - def run_egg_info(self): - # type: () -> None - if self.name: - logger.debug( - 'Running setup.py (path:%s) egg_info for package %s', - self.setup_py, self.name, - ) - else: - logger.debug( - 'Running setup.py (path:%s) egg_info for package from %s', - self.setup_py, self.link, - ) - script = SETUPTOOLS_SHIM % self.setup_py - base_cmd = [sys.executable, '-c', script] - if self.isolated: - base_cmd += ["--no-user-cfg"] - egg_info_cmd = base_cmd + ['egg_info'] - # We can't put the .egg-info files at the root, because then the - # source code will be mistaken for an installed egg, causing - # problems - if self.editable: - egg_base_option = [] # type: List[str] - else: - egg_info_dir = os.path.join(self.setup_py_dir, 'pip-egg-info') - ensure_dir(egg_info_dir) - egg_base_option = ['--egg-base', 'pip-egg-info'] - with self.build_env: - call_subprocess( - egg_info_cmd + egg_base_option, - cwd=self.setup_py_dir, - command_desc='python setup.py egg_info') - - @property - def egg_info_path(self): - # type: () -> str - if self._egg_info_path is None: - if self.editable: - base = self.source_dir - else: - base = os.path.join(self.setup_py_dir, 'pip-egg-info') - filenames = os.listdir(base) - if self.editable: - filenames = [] - for root, dirs, files in os.walk(base): - for dir in vcs.dirnames: - if dir in dirs: - dirs.remove(dir) - # Iterate over a copy of ``dirs``, since mutating - # a list while iterating over it can cause trouble. - # (See https://github.com/pypa/pip/pull/462.) - for dir in list(dirs): - # Don't search in anything that looks like a virtualenv - # environment - if ( - os.path.lexists( - os.path.join(root, dir, 'bin', 'python') - ) or - os.path.exists( - os.path.join( - root, dir, 'Scripts', 'Python.exe' - ) - )): - dirs.remove(dir) - # Also don't search through tests - elif dir == 'test' or dir == 'tests': - dirs.remove(dir) - filenames.extend([os.path.join(root, dir) - for dir in dirs]) - filenames = [f for f in filenames if f.endswith('.egg-info')] - - if not filenames: - raise InstallationError( - "Files/directories not found in %s" % base - ) - # if we have more than one match, we pick the toplevel one. This - # can easily be the case if there is a dist folder which contains - # an extracted tarball for testing purposes. - if len(filenames) > 1: - filenames.sort( - key=lambda x: x.count(os.path.sep) + - (os.path.altsep and x.count(os.path.altsep) or 0) - ) - self._egg_info_path = os.path.join(base, filenames[0]) - return self._egg_info_path - - @property - def metadata(self): - # type: () -> Any - if not hasattr(self, '_metadata'): - self._metadata = get_metadata(self.get_dist()) - - return self._metadata - - def get_dist(self): - # type: () -> Distribution - """Return a pkg_resources.Distribution for this requirement""" - if self.metadata_directory: - base_dir, distinfo = os.path.split(self.metadata_directory) - metadata = pkg_resources.PathMetadata( - base_dir, self.metadata_directory - ) - dist_name = os.path.splitext(distinfo)[0] - typ = pkg_resources.DistInfoDistribution - else: - egg_info = self.egg_info_path.rstrip(os.path.sep) - base_dir = os.path.dirname(egg_info) - metadata = pkg_resources.PathMetadata(base_dir, egg_info) - dist_name = os.path.splitext(os.path.basename(egg_info))[0] - # https://github.com/python/mypy/issues/1174 - typ = pkg_resources.Distribution # type: ignore - - return typ( - base_dir, - project_name=dist_name, - metadata=metadata, - ) - - def assert_source_matches_version(self): - # type: () -> None - assert self.source_dir - version = self.metadata['version'] - if self.req.specifier and version not in self.req.specifier: - logger.warning( - 'Requested %s, but installing version %s', - self, - version, - ) - else: - logger.debug( - 'Source in %s has version %s, which satisfies requirement %s', - display_path(self.source_dir), - version, - self, - ) - - # For both source distributions and editables - def ensure_has_source_dir(self, parent_dir): - # type: (str) -> str - """Ensure that a source_dir is set. - - This will create a temporary build dir if the name of the requirement - isn't known yet. - - :param parent_dir: The ideal pip parent_dir for the source_dir. - Generally src_dir for editables and build_dir for sdists. - :return: self.source_dir - """ - if self.source_dir is None: - self.source_dir = self.build_location(parent_dir) - return self.source_dir - - # For editable installations - def install_editable( - self, - install_options, # type: List[str] - global_options=(), # type: Sequence[str] - prefix=None # type: Optional[str] - ): - # type: (...) -> None - logger.info('Running setup.py develop for %s', self.name) - - if self.isolated: - global_options = list(global_options) + ["--no-user-cfg"] - - if prefix: - prefix_param = ['--prefix={}'.format(prefix)] - install_options = list(install_options) + prefix_param - - with indent_log(): - # FIXME: should we do --install-headers here too? - with self.build_env: - call_subprocess( - [ - sys.executable, - '-c', - SETUPTOOLS_SHIM % self.setup_py - ] + - list(global_options) + - ['develop', '--no-deps'] + - list(install_options), - - cwd=self.setup_py_dir, - ) - - self.install_succeeded = True - - def update_editable(self, obtain=True): - # type: (bool) -> None - if not self.link: - logger.debug( - "Cannot update repository at %s; repository location is " - "unknown", - self.source_dir, - ) - return - assert self.editable - assert self.source_dir - if self.link.scheme == 'file': - # Static paths don't get updated - return - assert '+' in self.link.url, "bad url: %r" % self.link.url - if not self.update: - return - vc_type, url = self.link.url.split('+', 1) - backend = vcs.get_backend(vc_type) - if backend: - vcs_backend = backend(self.link.url) - if obtain: - vcs_backend.obtain(self.source_dir) - else: - vcs_backend.export(self.source_dir) - else: - assert 0, ( - 'Unexpected version control type (in %s): %s' - % (self.link, vc_type)) - - # Top-level Actions - def uninstall(self, auto_confirm=False, verbose=False, - use_user_site=False): - # type: (bool, bool, bool) -> Optional[UninstallPathSet] - """ - Uninstall the distribution currently satisfying this requirement. - - Prompts before removing or modifying files unless - ``auto_confirm`` is True. - - Refuses to delete or modify files outside of ``sys.prefix`` - - thus uninstallation within a virtual environment can only - modify that virtual environment, even if the virtualenv is - linked to global site-packages. - - """ - if not self.check_if_exists(use_user_site): - logger.warning("Skipping %s as it is not installed.", self.name) - return None - dist = self.satisfied_by or self.conflicts_with - - uninstalled_pathset = UninstallPathSet.from_dist(dist) - uninstalled_pathset.remove(auto_confirm, verbose) - return uninstalled_pathset - - def _clean_zip_name(self, name, prefix): # only used by archive. - # type: (str, str) -> str - assert name.startswith(prefix + os.path.sep), ( - "name %r doesn't start with prefix %r" % (name, prefix) - ) - name = name[len(prefix) + 1:] - name = name.replace(os.path.sep, '/') - return name - - def _get_archive_name(self, path, parentdir, rootdir): - # type: (str, str, str) -> str - path = os.path.join(parentdir, path) - name = self._clean_zip_name(path, rootdir) - return self.name + '/' + name - - # TODO: Investigate if this should be kept in InstallRequirement - # Seems to be used only when VCS + downloads - def archive(self, build_dir): - # type: (str) -> None - assert self.source_dir - create_archive = True - archive_name = '%s-%s.zip' % (self.name, self.metadata["version"]) - archive_path = os.path.join(build_dir, archive_name) - if os.path.exists(archive_path): - response = ask_path_exists( - 'The file %s exists. (i)gnore, (w)ipe, (b)ackup, (a)bort ' % - display_path(archive_path), ('i', 'w', 'b', 'a')) - if response == 'i': - create_archive = False - elif response == 'w': - logger.warning('Deleting %s', display_path(archive_path)) - os.remove(archive_path) - elif response == 'b': - dest_file = backup_dir(archive_path) - logger.warning( - 'Backing up %s to %s', - display_path(archive_path), - display_path(dest_file), - ) - shutil.move(archive_path, dest_file) - elif response == 'a': - sys.exit(-1) - if create_archive: - zip = zipfile.ZipFile( - archive_path, 'w', zipfile.ZIP_DEFLATED, - allowZip64=True - ) - dir = os.path.normcase(os.path.abspath(self.setup_py_dir)) - for dirpath, dirnames, filenames in os.walk(dir): - if 'pip-egg-info' in dirnames: - dirnames.remove('pip-egg-info') - for dirname in dirnames: - dir_arcname = self._get_archive_name(dirname, - parentdir=dirpath, - rootdir=dir) - zipdir = zipfile.ZipInfo(dir_arcname + '/') - zipdir.external_attr = 0x1ED << 16 # 0o755 - zip.writestr(zipdir, '') - for filename in filenames: - if filename == PIP_DELETE_MARKER_FILENAME: - continue - file_arcname = self._get_archive_name(filename, - parentdir=dirpath, - rootdir=dir) - filename = os.path.join(dirpath, filename) - zip.write(filename, file_arcname) - zip.close() - logger.info('Saved %s', display_path(archive_path)) - - def install( - self, - install_options, # type: List[str] - global_options=None, # type: Optional[Sequence[str]] - root=None, # type: Optional[str] - home=None, # type: Optional[str] - prefix=None, # type: Optional[str] - warn_script_location=True, # type: bool - use_user_site=False, # type: bool - pycompile=True # type: bool - ): - # type: (...) -> None - global_options = global_options if global_options is not None else [] - if self.editable: - self.install_editable( - install_options, global_options, prefix=prefix, - ) - return - if self.is_wheel: - version = wheel.wheel_version(self.source_dir) - wheel.check_compatibility(version, self.name) - - self.move_wheel_files( - self.source_dir, root=root, prefix=prefix, home=home, - warn_script_location=warn_script_location, - use_user_site=use_user_site, pycompile=pycompile, - ) - self.install_succeeded = True - return - - # Extend the list of global and install options passed on to - # the setup.py call with the ones from the requirements file. - # Options specified in requirements file override those - # specified on the command line, since the last option given - # to setup.py is the one that is used. - global_options = list(global_options) + \ - self.options.get('global_options', []) - install_options = list(install_options) + \ - self.options.get('install_options', []) - - if self.isolated: - # https://github.com/python/mypy/issues/1174 - global_options = global_options + ["--no-user-cfg"] # type: ignore - - with TempDirectory(kind="record") as temp_dir: - record_filename = os.path.join(temp_dir.path, 'install-record.txt') - install_args = self.get_install_args( - global_options, record_filename, root, prefix, pycompile, - ) - msg = 'Running setup.py install for %s' % (self.name,) - with open_spinner(msg) as spinner: - with indent_log(): - with self.build_env: - call_subprocess( - install_args + install_options, - cwd=self.setup_py_dir, - spinner=spinner, - ) - - if not os.path.exists(record_filename): - logger.debug('Record file %s not found', record_filename) - return - self.install_succeeded = True - - def prepend_root(path): - # type: (str) -> str - if root is None or not os.path.isabs(path): - return path - else: - return change_root(root, path) - - with open(record_filename) as f: - for line in f: - directory = os.path.dirname(line) - if directory.endswith('.egg-info'): - egg_info_dir = prepend_root(directory) - break - else: - logger.warning( - 'Could not find .egg-info directory in install record' - ' for %s', - self, - ) - # FIXME: put the record somewhere - # FIXME: should this be an error? - return - new_lines = [] - with open(record_filename) as f: - for line in f: - filename = line.strip() - if os.path.isdir(filename): - filename += os.path.sep - new_lines.append( - os.path.relpath(prepend_root(filename), egg_info_dir) - ) - new_lines.sort() - ensure_dir(egg_info_dir) - inst_files_path = os.path.join(egg_info_dir, 'installed-files.txt') - with open(inst_files_path, 'w') as f: - f.write('\n'.join(new_lines) + '\n') - - def get_install_args( - self, - global_options, # type: Sequence[str] - record_filename, # type: str - root, # type: Optional[str] - prefix, # type: Optional[str] - pycompile # type: bool - ): - # type: (...) -> List[str] - install_args = [sys.executable, "-u"] - install_args.append('-c') - install_args.append(SETUPTOOLS_SHIM % self.setup_py) - install_args += list(global_options) + \ - ['install', '--record', record_filename] - install_args += ['--single-version-externally-managed'] - - if root is not None: - install_args += ['--root', root] - if prefix is not None: - install_args += ['--prefix', prefix] - - if pycompile: - install_args += ["--compile"] - else: - install_args += ["--no-compile"] - - if running_under_virtualenv(): - py_ver_str = 'python' + sysconfig.get_python_version() - install_args += ['--install-headers', - os.path.join(sys.prefix, 'include', 'site', - py_ver_str, self.name)] - - return install_args diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/req/req_set.py b/venv2/lib/python2.7/site-packages/pip/_internal/req/req_set.py deleted file mode 100644 index d1966a4..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/req/req_set.py +++ /dev/null @@ -1,193 +0,0 @@ -from __future__ import absolute_import - -import logging -from collections import OrderedDict - -from pip._internal.exceptions import InstallationError -from pip._internal.utils.logging import indent_log -from pip._internal.utils.typing import MYPY_CHECK_RUNNING -from pip._internal.wheel import Wheel - -if MYPY_CHECK_RUNNING: - from typing import Dict, Iterable, List, Optional, Tuple - from pip._internal.req.req_install import InstallRequirement - - -logger = logging.getLogger(__name__) - - -class RequirementSet(object): - - def __init__(self, require_hashes=False, check_supported_wheels=True): - # type: (bool, bool) -> None - """Create a RequirementSet. - """ - - self.requirements = OrderedDict() # type: Dict[str, InstallRequirement] # noqa: E501 - self.require_hashes = require_hashes - self.check_supported_wheels = check_supported_wheels - - # Mapping of alias: real_name - self.requirement_aliases = {} # type: Dict[str, str] - self.unnamed_requirements = [] # type: List[InstallRequirement] - self.successfully_downloaded = [] # type: List[InstallRequirement] - self.reqs_to_cleanup = [] # type: List[InstallRequirement] - - def __str__(self): - # type: () -> str - reqs = [req for req in self.requirements.values() - if not req.comes_from] - reqs.sort(key=lambda req: req.name.lower()) - return ' '.join([str(req.req) for req in reqs]) - - def __repr__(self): - # type: () -> str - reqs = [req for req in self.requirements.values()] - reqs.sort(key=lambda req: req.name.lower()) - reqs_str = ', '.join([str(req.req) for req in reqs]) - return ('<%s object; %d requirement(s): %s>' - % (self.__class__.__name__, len(reqs), reqs_str)) - - def add_requirement( - self, - install_req, # type: InstallRequirement - parent_req_name=None, # type: Optional[str] - extras_requested=None # type: Optional[Iterable[str]] - ): - # type: (...) -> Tuple[List[InstallRequirement], Optional[InstallRequirement]] # noqa: E501 - """Add install_req as a requirement to install. - - :param parent_req_name: The name of the requirement that needed this - added. The name is used because when multiple unnamed requirements - resolve to the same name, we could otherwise end up with dependency - links that point outside the Requirements set. parent_req must - already be added. Note that None implies that this is a user - supplied requirement, vs an inferred one. - :param extras_requested: an iterable of extras used to evaluate the - environment markers. - :return: Additional requirements to scan. That is either [] if - the requirement is not applicable, or [install_req] if the - requirement is applicable and has just been added. - """ - name = install_req.name - - # If the markers do not match, ignore this requirement. - if not install_req.match_markers(extras_requested): - logger.info( - "Ignoring %s: markers '%s' don't match your environment", - name, install_req.markers, - ) - return [], None - - # If the wheel is not supported, raise an error. - # Should check this after filtering out based on environment markers to - # allow specifying different wheels based on the environment/OS, in a - # single requirements file. - if install_req.link and install_req.link.is_wheel: - wheel = Wheel(install_req.link.filename) - if self.check_supported_wheels and not wheel.supported(): - raise InstallationError( - "%s is not a supported wheel on this platform." % - wheel.filename - ) - - # This next bit is really a sanity check. - assert install_req.is_direct == (parent_req_name is None), ( - "a direct req shouldn't have a parent and also, " - "a non direct req should have a parent" - ) - - # Unnamed requirements are scanned again and the requirement won't be - # added as a dependency until after scanning. - if not name: - # url or path requirement w/o an egg fragment - self.unnamed_requirements.append(install_req) - return [install_req], None - - try: - existing_req = self.get_requirement(name) - except KeyError: - existing_req = None - - has_conflicting_requirement = ( - parent_req_name is None and - existing_req and - not existing_req.constraint and - existing_req.extras == install_req.extras and - existing_req.req.specifier != install_req.req.specifier - ) - if has_conflicting_requirement: - raise InstallationError( - "Double requirement given: %s (already in %s, name=%r)" - % (install_req, existing_req, name) - ) - - # When no existing requirement exists, add the requirement as a - # dependency and it will be scanned again after. - if not existing_req: - self.requirements[name] = install_req - # FIXME: what about other normalizations? E.g., _ vs. -? - if name.lower() != name: - self.requirement_aliases[name.lower()] = name - # We'd want to rescan this requirements later - return [install_req], install_req - - # Assume there's no need to scan, and that we've already - # encountered this for scanning. - if install_req.constraint or not existing_req.constraint: - return [], existing_req - - does_not_satisfy_constraint = ( - install_req.link and - not ( - existing_req.link and - install_req.link.path == existing_req.link.path - ) - ) - if does_not_satisfy_constraint: - self.reqs_to_cleanup.append(install_req) - raise InstallationError( - "Could not satisfy constraints for '%s': " - "installation from path or url cannot be " - "constrained to a version" % name, - ) - # If we're now installing a constraint, mark the existing - # object for real installation. - existing_req.constraint = False - existing_req.extras = tuple(sorted( - set(existing_req.extras) | set(install_req.extras) - )) - logger.debug( - "Setting %s extras to: %s", - existing_req, existing_req.extras, - ) - # Return the existing requirement for addition to the parent and - # scanning again. - return [existing_req], existing_req - - def has_requirement(self, project_name): - # type: (str) -> bool - name = project_name.lower() - if (name in self.requirements and - not self.requirements[name].constraint or - name in self.requirement_aliases and - not self.requirements[self.requirement_aliases[name]].constraint): - return True - return False - - def get_requirement(self, project_name): - # type: (str) -> InstallRequirement - for name in project_name, project_name.lower(): - if name in self.requirements: - return self.requirements[name] - if name in self.requirement_aliases: - return self.requirements[self.requirement_aliases[name]] - raise KeyError("No project with the name %r" % project_name) - - def cleanup_files(self): - # type: () -> None - """Clean up files, remove builds.""" - logger.debug('Cleaning up...') - with indent_log(): - for req in self.reqs_to_cleanup: - req.remove_temporary_source() diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/req/req_tracker.py b/venv2/lib/python2.7/site-packages/pip/_internal/req/req_tracker.py deleted file mode 100644 index e36a3f6..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/req/req_tracker.py +++ /dev/null @@ -1,96 +0,0 @@ -from __future__ import absolute_import - -import contextlib -import errno -import hashlib -import logging -import os - -from pip._internal.utils.temp_dir import TempDirectory -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from types import TracebackType - from typing import Iterator, Optional, Set, Type - from pip._internal.req.req_install import InstallRequirement - from pip._internal.models.link import Link - -logger = logging.getLogger(__name__) - - -class RequirementTracker(object): - - def __init__(self): - # type: () -> None - self._root = os.environ.get('PIP_REQ_TRACKER') - if self._root is None: - self._temp_dir = TempDirectory(delete=False, kind='req-tracker') - self._temp_dir.create() - self._root = os.environ['PIP_REQ_TRACKER'] = self._temp_dir.path - logger.debug('Created requirements tracker %r', self._root) - else: - self._temp_dir = None - logger.debug('Re-using requirements tracker %r', self._root) - self._entries = set() # type: Set[InstallRequirement] - - def __enter__(self): - # type: () -> RequirementTracker - return self - - def __exit__( - self, - exc_type, # type: Optional[Type[BaseException]] - exc_val, # type: Optional[BaseException] - exc_tb # type: Optional[TracebackType] - ): - # type: (...) -> None - self.cleanup() - - def _entry_path(self, link): - # type: (Link) -> str - hashed = hashlib.sha224(link.url_without_fragment.encode()).hexdigest() - return os.path.join(self._root, hashed) - - def add(self, req): - # type: (InstallRequirement) -> None - link = req.link - info = str(req) - entry_path = self._entry_path(link) - try: - with open(entry_path) as fp: - # Error, these's already a build in progress. - raise LookupError('%s is already being built: %s' - % (link, fp.read())) - except IOError as e: - if e.errno != errno.ENOENT: - raise - assert req not in self._entries - with open(entry_path, 'w') as fp: - fp.write(info) - self._entries.add(req) - logger.debug('Added %s to build tracker %r', req, self._root) - - def remove(self, req): - # type: (InstallRequirement) -> None - link = req.link - self._entries.remove(req) - os.unlink(self._entry_path(link)) - logger.debug('Removed %s from build tracker %r', req, self._root) - - def cleanup(self): - # type: () -> None - for req in set(self._entries): - self.remove(req) - remove = self._temp_dir is not None - if remove: - self._temp_dir.cleanup() - logger.debug('%s build tracker %r', - 'Removed' if remove else 'Cleaned', - self._root) - - @contextlib.contextmanager - def track(self, req): - # type: (InstallRequirement) -> Iterator[None] - self.add(req) - yield - self.remove(req) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/req/req_uninstall.py b/venv2/lib/python2.7/site-packages/pip/_internal/req/req_uninstall.py deleted file mode 100644 index 733301c..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/req/req_uninstall.py +++ /dev/null @@ -1,633 +0,0 @@ -from __future__ import absolute_import - -import csv -import functools -import logging -import os -import sys -import sysconfig - -from pip._vendor import pkg_resources - -from pip._internal.exceptions import UninstallationError -from pip._internal.locations import bin_py, bin_user -from pip._internal.utils.compat import WINDOWS, cache_from_source, uses_pycache -from pip._internal.utils.logging import indent_log -from pip._internal.utils.misc import ( - FakeFile, ask, dist_in_usersite, dist_is_local, egg_link_path, is_local, - normalize_path, renames, rmtree, -) -from pip._internal.utils.temp_dir import AdjacentTempDirectory, TempDirectory -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import ( - Any, Callable, Dict, Iterable, Iterator, List, Optional, Set, Tuple, - ) - from pip._vendor.pkg_resources import Distribution - -logger = logging.getLogger(__name__) - - -def _script_names(dist, script_name, is_gui): - # type: (Distribution, str, bool) -> List[str] - """Create the fully qualified name of the files created by - {console,gui}_scripts for the given ``dist``. - Returns the list of file names - """ - if dist_in_usersite(dist): - bin_dir = bin_user - else: - bin_dir = bin_py - exe_name = os.path.join(bin_dir, script_name) - paths_to_remove = [exe_name] - if WINDOWS: - paths_to_remove.append(exe_name + '.exe') - paths_to_remove.append(exe_name + '.exe.manifest') - if is_gui: - paths_to_remove.append(exe_name + '-script.pyw') - else: - paths_to_remove.append(exe_name + '-script.py') - return paths_to_remove - - -def _unique(fn): - # type: (Callable) -> Callable[..., Iterator[Any]] - @functools.wraps(fn) - def unique(*args, **kw): - # type: (Any, Any) -> Iterator[Any] - seen = set() # type: Set[Any] - for item in fn(*args, **kw): - if item not in seen: - seen.add(item) - yield item - return unique - - -@_unique -def uninstallation_paths(dist): - # type: (Distribution) -> Iterator[str] - """ - Yield all the uninstallation paths for dist based on RECORD-without-.py[co] - - Yield paths to all the files in RECORD. For each .py file in RECORD, add - the .pyc and .pyo in the same directory. - - UninstallPathSet.add() takes care of the __pycache__ .py[co]. - """ - r = csv.reader(FakeFile(dist.get_metadata_lines('RECORD'))) - for row in r: - path = os.path.join(dist.location, row[0]) - yield path - if path.endswith('.py'): - dn, fn = os.path.split(path) - base = fn[:-3] - path = os.path.join(dn, base + '.pyc') - yield path - path = os.path.join(dn, base + '.pyo') - yield path - - -def compact(paths): - # type: (Iterable[str]) -> Set[str] - """Compact a path set to contain the minimal number of paths - necessary to contain all paths in the set. If /a/path/ and - /a/path/to/a/file.txt are both in the set, leave only the - shorter path.""" - - sep = os.path.sep - short_paths = set() # type: Set[str] - for path in sorted(paths, key=len): - should_skip = any( - path.startswith(shortpath.rstrip("*")) and - path[len(shortpath.rstrip("*").rstrip(sep))] == sep - for shortpath in short_paths - ) - if not should_skip: - short_paths.add(path) - return short_paths - - -def compress_for_rename(paths): - # type: (Iterable[str]) -> Set[str] - """Returns a set containing the paths that need to be renamed. - - This set may include directories when the original sequence of paths - included every file on disk. - """ - case_map = dict((os.path.normcase(p), p) for p in paths) - remaining = set(case_map) - unchecked = sorted(set(os.path.split(p)[0] - for p in case_map.values()), key=len) - wildcards = set() # type: Set[str] - - def norm_join(*a): - # type: (str) -> str - return os.path.normcase(os.path.join(*a)) - - for root in unchecked: - if any(os.path.normcase(root).startswith(w) - for w in wildcards): - # This directory has already been handled. - continue - - all_files = set() # type: Set[str] - all_subdirs = set() # type: Set[str] - for dirname, subdirs, files in os.walk(root): - all_subdirs.update(norm_join(root, dirname, d) - for d in subdirs) - all_files.update(norm_join(root, dirname, f) - for f in files) - # If all the files we found are in our remaining set of files to - # remove, then remove them from the latter set and add a wildcard - # for the directory. - if not (all_files - remaining): - remaining.difference_update(all_files) - wildcards.add(root + os.sep) - - return set(map(case_map.__getitem__, remaining)) | wildcards - - -def compress_for_output_listing(paths): - # type: (Iterable[str]) -> Tuple[Set[str], Set[str]] - """Returns a tuple of 2 sets of which paths to display to user - - The first set contains paths that would be deleted. Files of a package - are not added and the top-level directory of the package has a '*' added - at the end - to signify that all it's contents are removed. - - The second set contains files that would have been skipped in the above - folders. - """ - - will_remove = set(paths) - will_skip = set() - - # Determine folders and files - folders = set() - files = set() - for path in will_remove: - if path.endswith(".pyc"): - continue - if path.endswith("__init__.py") or ".dist-info" in path: - folders.add(os.path.dirname(path)) - files.add(path) - - # probably this one https://github.com/python/mypy/issues/390 - _normcased_files = set(map(os.path.normcase, files)) # type: ignore - - folders = compact(folders) - - # This walks the tree using os.walk to not miss extra folders - # that might get added. - for folder in folders: - for dirpath, _, dirfiles in os.walk(folder): - for fname in dirfiles: - if fname.endswith(".pyc"): - continue - - file_ = os.path.join(dirpath, fname) - if (os.path.isfile(file_) and - os.path.normcase(file_) not in _normcased_files): - # We are skipping this file. Add it to the set. - will_skip.add(file_) - - will_remove = files | { - os.path.join(folder, "*") for folder in folders - } - - return will_remove, will_skip - - -class StashedUninstallPathSet(object): - """A set of file rename operations to stash files while - tentatively uninstalling them.""" - def __init__(self): - # type: () -> None - # Mapping from source file root to [Adjacent]TempDirectory - # for files under that directory. - self._save_dirs = {} # type: Dict[str, TempDirectory] - # (old path, new path) tuples for each move that may need - # to be undone. - self._moves = [] # type: List[Tuple[str, str]] - - def _get_directory_stash(self, path): - # type: (str) -> str - """Stashes a directory. - - Directories are stashed adjacent to their original location if - possible, or else moved/copied into the user's temp dir.""" - - try: - save_dir = AdjacentTempDirectory(path) # type: TempDirectory - save_dir.create() - except OSError: - save_dir = TempDirectory(kind="uninstall") - save_dir.create() - self._save_dirs[os.path.normcase(path)] = save_dir - - return save_dir.path - - def _get_file_stash(self, path): - # type: (str) -> str - """Stashes a file. - - If no root has been provided, one will be created for the directory - in the user's temp directory.""" - path = os.path.normcase(path) - head, old_head = os.path.dirname(path), None - save_dir = None - - while head != old_head: - try: - save_dir = self._save_dirs[head] - break - except KeyError: - pass - head, old_head = os.path.dirname(head), head - else: - # Did not find any suitable root - head = os.path.dirname(path) - save_dir = TempDirectory(kind='uninstall') - save_dir.create() - self._save_dirs[head] = save_dir - - relpath = os.path.relpath(path, head) - if relpath and relpath != os.path.curdir: - return os.path.join(save_dir.path, relpath) - return save_dir.path - - def stash(self, path): - # type: (str) -> str - """Stashes the directory or file and returns its new location. - """ - if os.path.isdir(path): - new_path = self._get_directory_stash(path) - else: - new_path = self._get_file_stash(path) - - self._moves.append((path, new_path)) - if os.path.isdir(path) and os.path.isdir(new_path): - # If we're moving a directory, we need to - # remove the destination first or else it will be - # moved to inside the existing directory. - # We just created new_path ourselves, so it will - # be removable. - os.rmdir(new_path) - renames(path, new_path) - return new_path - - def commit(self): - # type: () -> None - """Commits the uninstall by removing stashed files.""" - for _, save_dir in self._save_dirs.items(): - save_dir.cleanup() - self._moves = [] - self._save_dirs = {} - - def rollback(self): - # type: () -> None - """Undoes the uninstall by moving stashed files back.""" - for p in self._moves: - logging.info("Moving to %s\n from %s", *p) - - for new_path, path in self._moves: - try: - logger.debug('Replacing %s from %s', new_path, path) - if os.path.isfile(new_path): - os.unlink(new_path) - elif os.path.isdir(new_path): - rmtree(new_path) - renames(path, new_path) - except OSError as ex: - logger.error("Failed to restore %s", new_path) - logger.debug("Exception: %s", ex) - - self.commit() - - @property - def can_rollback(self): - # type: () -> bool - return bool(self._moves) - - -class UninstallPathSet(object): - """A set of file paths to be removed in the uninstallation of a - requirement.""" - def __init__(self, dist): - # type: (Distribution) -> None - self.paths = set() # type: Set[str] - self._refuse = set() # type: Set[str] - self.pth = {} # type: Dict[str, UninstallPthEntries] - self.dist = dist - self._moved_paths = StashedUninstallPathSet() - - def _permitted(self, path): - # type: (str) -> bool - """ - Return True if the given path is one we are permitted to - remove/modify, False otherwise. - - """ - return is_local(path) - - def add(self, path): - # type: (str) -> None - head, tail = os.path.split(path) - - # we normalize the head to resolve parent directory symlinks, but not - # the tail, since we only want to uninstall symlinks, not their targets - path = os.path.join(normalize_path(head), os.path.normcase(tail)) - - if not os.path.exists(path): - return - if self._permitted(path): - self.paths.add(path) - else: - self._refuse.add(path) - - # __pycache__ files can show up after 'installed-files.txt' is created, - # due to imports - if os.path.splitext(path)[1] == '.py' and uses_pycache: - self.add(cache_from_source(path)) - - def add_pth(self, pth_file, entry): - # type: (str, str) -> None - pth_file = normalize_path(pth_file) - if self._permitted(pth_file): - if pth_file not in self.pth: - self.pth[pth_file] = UninstallPthEntries(pth_file) - self.pth[pth_file].add(entry) - else: - self._refuse.add(pth_file) - - def remove(self, auto_confirm=False, verbose=False): - # type: (bool, bool) -> None - """Remove paths in ``self.paths`` with confirmation (unless - ``auto_confirm`` is True).""" - - if not self.paths: - logger.info( - "Can't uninstall '%s'. No files were found to uninstall.", - self.dist.project_name, - ) - return - - dist_name_version = ( - self.dist.project_name + "-" + self.dist.version - ) - logger.info('Uninstalling %s:', dist_name_version) - - with indent_log(): - if auto_confirm or self._allowed_to_proceed(verbose): - moved = self._moved_paths - - for_rename = compress_for_rename(self.paths) - - for path in sorted(compact(for_rename)): - moved.stash(path) - logger.debug('Removing file or directory %s', path) - - for pth in self.pth.values(): - pth.remove() - - logger.info('Successfully uninstalled %s', dist_name_version) - - def _allowed_to_proceed(self, verbose): - # type: (bool) -> bool - """Display which files would be deleted and prompt for confirmation - """ - - def _display(msg, paths): - # type: (str, Iterable[str]) -> None - if not paths: - return - - logger.info(msg) - with indent_log(): - for path in sorted(compact(paths)): - logger.info(path) - - if not verbose: - will_remove, will_skip = compress_for_output_listing(self.paths) - else: - # In verbose mode, display all the files that are going to be - # deleted. - will_remove = set(self.paths) - will_skip = set() - - _display('Would remove:', will_remove) - _display('Would not remove (might be manually added):', will_skip) - _display('Would not remove (outside of prefix):', self._refuse) - if verbose: - _display('Will actually move:', compress_for_rename(self.paths)) - - return ask('Proceed (y/n)? ', ('y', 'n')) == 'y' - - def rollback(self): - # type: () -> None - """Rollback the changes previously made by remove().""" - if not self._moved_paths.can_rollback: - logger.error( - "Can't roll back %s; was not uninstalled", - self.dist.project_name, - ) - return - logger.info('Rolling back uninstall of %s', self.dist.project_name) - self._moved_paths.rollback() - for pth in self.pth.values(): - pth.rollback() - - def commit(self): - # type: () -> None - """Remove temporary save dir: rollback will no longer be possible.""" - self._moved_paths.commit() - - @classmethod - def from_dist(cls, dist): - # type: (Distribution) -> UninstallPathSet - dist_path = normalize_path(dist.location) - if not dist_is_local(dist): - logger.info( - "Not uninstalling %s at %s, outside environment %s", - dist.key, - dist_path, - sys.prefix, - ) - return cls(dist) - - if dist_path in {p for p in {sysconfig.get_path("stdlib"), - sysconfig.get_path("platstdlib")} - if p}: - logger.info( - "Not uninstalling %s at %s, as it is in the standard library.", - dist.key, - dist_path, - ) - return cls(dist) - - paths_to_remove = cls(dist) - develop_egg_link = egg_link_path(dist) - develop_egg_link_egg_info = '{}.egg-info'.format( - pkg_resources.to_filename(dist.project_name)) - egg_info_exists = dist.egg_info and os.path.exists(dist.egg_info) - # Special case for distutils installed package - distutils_egg_info = getattr(dist._provider, 'path', None) - - # Uninstall cases order do matter as in the case of 2 installs of the - # same package, pip needs to uninstall the currently detected version - if (egg_info_exists and dist.egg_info.endswith('.egg-info') and - not dist.egg_info.endswith(develop_egg_link_egg_info)): - # if dist.egg_info.endswith(develop_egg_link_egg_info), we - # are in fact in the develop_egg_link case - paths_to_remove.add(dist.egg_info) - if dist.has_metadata('installed-files.txt'): - for installed_file in dist.get_metadata( - 'installed-files.txt').splitlines(): - path = os.path.normpath( - os.path.join(dist.egg_info, installed_file) - ) - paths_to_remove.add(path) - # FIXME: need a test for this elif block - # occurs with --single-version-externally-managed/--record outside - # of pip - elif dist.has_metadata('top_level.txt'): - if dist.has_metadata('namespace_packages.txt'): - namespaces = dist.get_metadata('namespace_packages.txt') - else: - namespaces = [] - for top_level_pkg in [ - p for p - in dist.get_metadata('top_level.txt').splitlines() - if p and p not in namespaces]: - path = os.path.join(dist.location, top_level_pkg) - paths_to_remove.add(path) - paths_to_remove.add(path + '.py') - paths_to_remove.add(path + '.pyc') - paths_to_remove.add(path + '.pyo') - - elif distutils_egg_info: - raise UninstallationError( - "Cannot uninstall {!r}. It is a distutils installed project " - "and thus we cannot accurately determine which files belong " - "to it which would lead to only a partial uninstall.".format( - dist.project_name, - ) - ) - - elif dist.location.endswith('.egg'): - # package installed by easy_install - # We cannot match on dist.egg_name because it can slightly vary - # i.e. setuptools-0.6c11-py2.6.egg vs setuptools-0.6rc11-py2.6.egg - paths_to_remove.add(dist.location) - easy_install_egg = os.path.split(dist.location)[1] - easy_install_pth = os.path.join(os.path.dirname(dist.location), - 'easy-install.pth') - paths_to_remove.add_pth(easy_install_pth, './' + easy_install_egg) - - elif egg_info_exists and dist.egg_info.endswith('.dist-info'): - for path in uninstallation_paths(dist): - paths_to_remove.add(path) - - elif develop_egg_link: - # develop egg - with open(develop_egg_link, 'r') as fh: - link_pointer = os.path.normcase(fh.readline().strip()) - assert (link_pointer == dist.location), ( - 'Egg-link %s does not match installed location of %s ' - '(at %s)' % (link_pointer, dist.project_name, dist.location) - ) - paths_to_remove.add(develop_egg_link) - easy_install_pth = os.path.join(os.path.dirname(develop_egg_link), - 'easy-install.pth') - paths_to_remove.add_pth(easy_install_pth, dist.location) - - else: - logger.debug( - 'Not sure how to uninstall: %s - Check: %s', - dist, dist.location, - ) - - # find distutils scripts= scripts - if dist.has_metadata('scripts') and dist.metadata_isdir('scripts'): - for script in dist.metadata_listdir('scripts'): - if dist_in_usersite(dist): - bin_dir = bin_user - else: - bin_dir = bin_py - paths_to_remove.add(os.path.join(bin_dir, script)) - if WINDOWS: - paths_to_remove.add(os.path.join(bin_dir, script) + '.bat') - - # find console_scripts - _scripts_to_remove = [] - console_scripts = dist.get_entry_map(group='console_scripts') - for name in console_scripts.keys(): - _scripts_to_remove.extend(_script_names(dist, name, False)) - # find gui_scripts - gui_scripts = dist.get_entry_map(group='gui_scripts') - for name in gui_scripts.keys(): - _scripts_to_remove.extend(_script_names(dist, name, True)) - - for s in _scripts_to_remove: - paths_to_remove.add(s) - - return paths_to_remove - - -class UninstallPthEntries(object): - def __init__(self, pth_file): - # type: (str) -> None - if not os.path.isfile(pth_file): - raise UninstallationError( - "Cannot remove entries from nonexistent file %s" % pth_file - ) - self.file = pth_file - self.entries = set() # type: Set[str] - self._saved_lines = None # type: Optional[List[bytes]] - - def add(self, entry): - # type: (str) -> None - entry = os.path.normcase(entry) - # On Windows, os.path.normcase converts the entry to use - # backslashes. This is correct for entries that describe absolute - # paths outside of site-packages, but all the others use forward - # slashes. - if WINDOWS and not os.path.splitdrive(entry)[0]: - entry = entry.replace('\\', '/') - self.entries.add(entry) - - def remove(self): - # type: () -> None - logger.debug('Removing pth entries from %s:', self.file) - with open(self.file, 'rb') as fh: - # windows uses '\r\n' with py3k, but uses '\n' with py2.x - lines = fh.readlines() - self._saved_lines = lines - if any(b'\r\n' in line for line in lines): - endline = '\r\n' - else: - endline = '\n' - # handle missing trailing newline - if lines and not lines[-1].endswith(endline.encode("utf-8")): - lines[-1] = lines[-1] + endline.encode("utf-8") - for entry in self.entries: - try: - logger.debug('Removing entry: %s', entry) - lines.remove((entry + endline).encode("utf-8")) - except ValueError: - pass - with open(self.file, 'wb') as fh: - fh.writelines(lines) - - def rollback(self): - # type: () -> bool - if self._saved_lines is None: - logger.error( - 'Cannot roll back changes to %s, none were made', self.file - ) - return False - logger.debug('Rolling %s back to previous state', self.file) - with open(self.file, 'wb') as fh: - fh.writelines(self._saved_lines) - return True diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/resolve.py b/venv2/lib/python2.7/site-packages/pip/_internal/resolve.py deleted file mode 100644 index f49667b..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/resolve.py +++ /dev/null @@ -1,393 +0,0 @@ -"""Dependency Resolution - -The dependency resolution in pip is performed as follows: - -for top-level requirements: - a. only one spec allowed per project, regardless of conflicts or not. - otherwise a "double requirement" exception is raised - b. they override sub-dependency requirements. -for sub-dependencies - a. "first found, wins" (where the order is breadth first) -""" - -import logging -from collections import defaultdict -from itertools import chain - -from pip._internal.exceptions import ( - BestVersionAlreadyInstalled, DistributionNotFound, HashError, HashErrors, - UnsupportedPythonVersion, -) -from pip._internal.req.constructors import install_req_from_req_string -from pip._internal.utils.logging import indent_log -from pip._internal.utils.misc import dist_in_usersite, ensure_dir -from pip._internal.utils.packaging import check_dist_requires_python -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import Optional, DefaultDict, List, Set - from pip._internal.download import PipSession - from pip._internal.req.req_install import InstallRequirement - from pip._internal.index import PackageFinder - from pip._internal.req.req_set import RequirementSet - from pip._internal.operations.prepare import ( - DistAbstraction, RequirementPreparer - ) - from pip._internal.cache import WheelCache - -logger = logging.getLogger(__name__) - - -class Resolver(object): - """Resolves which packages need to be installed/uninstalled to perform \ - the requested operation without breaking the requirements of any package. - """ - - _allowed_strategies = {"eager", "only-if-needed", "to-satisfy-only"} - - def __init__( - self, - preparer, # type: RequirementPreparer - session, # type: PipSession - finder, # type: PackageFinder - wheel_cache, # type: Optional[WheelCache] - use_user_site, # type: bool - ignore_dependencies, # type: bool - ignore_installed, # type: bool - ignore_requires_python, # type: bool - force_reinstall, # type: bool - isolated, # type: bool - upgrade_strategy, # type: str - use_pep517=None # type: Optional[bool] - ): - # type: (...) -> None - super(Resolver, self).__init__() - assert upgrade_strategy in self._allowed_strategies - - self.preparer = preparer - self.finder = finder - self.session = session - - # NOTE: This would eventually be replaced with a cache that can give - # information about both sdist and wheels transparently. - self.wheel_cache = wheel_cache - - # This is set in resolve - self.require_hashes = None # type: Optional[bool] - - self.upgrade_strategy = upgrade_strategy - self.force_reinstall = force_reinstall - self.isolated = isolated - self.ignore_dependencies = ignore_dependencies - self.ignore_installed = ignore_installed - self.ignore_requires_python = ignore_requires_python - self.use_user_site = use_user_site - self.use_pep517 = use_pep517 - - self._discovered_dependencies = \ - defaultdict(list) # type: DefaultDict[str, List] - - def resolve(self, requirement_set): - # type: (RequirementSet) -> None - """Resolve what operations need to be done - - As a side-effect of this method, the packages (and their dependencies) - are downloaded, unpacked and prepared for installation. This - preparation is done by ``pip.operations.prepare``. - - Once PyPI has static dependency metadata available, it would be - possible to move the preparation to become a step separated from - dependency resolution. - """ - # make the wheelhouse - if self.preparer.wheel_download_dir: - ensure_dir(self.preparer.wheel_download_dir) - - # If any top-level requirement has a hash specified, enter - # hash-checking mode, which requires hashes from all. - root_reqs = ( - requirement_set.unnamed_requirements + - list(requirement_set.requirements.values()) - ) - self.require_hashes = ( - requirement_set.require_hashes or - any(req.has_hash_options for req in root_reqs) - ) - - # Display where finder is looking for packages - locations = self.finder.get_formatted_locations() - if locations: - logger.info(locations) - - # Actually prepare the files, and collect any exceptions. Most hash - # exceptions cannot be checked ahead of time, because - # req.populate_link() needs to be called before we can make decisions - # based on link type. - discovered_reqs = [] # type: List[InstallRequirement] - hash_errors = HashErrors() - for req in chain(root_reqs, discovered_reqs): - try: - discovered_reqs.extend( - self._resolve_one(requirement_set, req) - ) - except HashError as exc: - exc.req = req - hash_errors.append(exc) - - if hash_errors: - raise hash_errors - - def _is_upgrade_allowed(self, req): - # type: (InstallRequirement) -> bool - if self.upgrade_strategy == "to-satisfy-only": - return False - elif self.upgrade_strategy == "eager": - return True - else: - assert self.upgrade_strategy == "only-if-needed" - return req.is_direct - - def _set_req_to_reinstall(self, req): - # type: (InstallRequirement) -> None - """ - Set a requirement to be installed. - """ - # Don't uninstall the conflict if doing a user install and the - # conflict is not a user install. - if not self.use_user_site or dist_in_usersite(req.satisfied_by): - req.conflicts_with = req.satisfied_by - req.satisfied_by = None - - # XXX: Stop passing requirement_set for options - def _check_skip_installed(self, req_to_install): - # type: (InstallRequirement) -> Optional[str] - """Check if req_to_install should be skipped. - - This will check if the req is installed, and whether we should upgrade - or reinstall it, taking into account all the relevant user options. - - After calling this req_to_install will only have satisfied_by set to - None if the req_to_install is to be upgraded/reinstalled etc. Any - other value will be a dist recording the current thing installed that - satisfies the requirement. - - Note that for vcs urls and the like we can't assess skipping in this - routine - we simply identify that we need to pull the thing down, - then later on it is pulled down and introspected to assess upgrade/ - reinstalls etc. - - :return: A text reason for why it was skipped, or None. - """ - if self.ignore_installed: - return None - - req_to_install.check_if_exists(self.use_user_site) - if not req_to_install.satisfied_by: - return None - - if self.force_reinstall: - self._set_req_to_reinstall(req_to_install) - return None - - if not self._is_upgrade_allowed(req_to_install): - if self.upgrade_strategy == "only-if-needed": - return 'already satisfied, skipping upgrade' - return 'already satisfied' - - # Check for the possibility of an upgrade. For link-based - # requirements we have to pull the tree down and inspect to assess - # the version #, so it's handled way down. - if not req_to_install.link: - try: - self.finder.find_requirement(req_to_install, upgrade=True) - except BestVersionAlreadyInstalled: - # Then the best version is installed. - return 'already up-to-date' - except DistributionNotFound: - # No distribution found, so we squash the error. It will - # be raised later when we re-try later to do the install. - # Why don't we just raise here? - pass - - self._set_req_to_reinstall(req_to_install) - return None - - def _get_abstract_dist_for(self, req): - # type: (InstallRequirement) -> DistAbstraction - """Takes a InstallRequirement and returns a single AbstractDist \ - representing a prepared variant of the same. - """ - assert self.require_hashes is not None, ( - "require_hashes should have been set in Resolver.resolve()" - ) - - if req.editable: - return self.preparer.prepare_editable_requirement( - req, self.require_hashes, self.use_user_site, self.finder, - ) - - # satisfied_by is only evaluated by calling _check_skip_installed, - # so it must be None here. - assert req.satisfied_by is None - skip_reason = self._check_skip_installed(req) - - if req.satisfied_by: - return self.preparer.prepare_installed_requirement( - req, self.require_hashes, skip_reason - ) - - upgrade_allowed = self._is_upgrade_allowed(req) - abstract_dist = self.preparer.prepare_linked_requirement( - req, self.session, self.finder, upgrade_allowed, - self.require_hashes - ) - - # NOTE - # The following portion is for determining if a certain package is - # going to be re-installed/upgraded or not and reporting to the user. - # This should probably get cleaned up in a future refactor. - - # req.req is only avail after unpack for URL - # pkgs repeat check_if_exists to uninstall-on-upgrade - # (#14) - if not self.ignore_installed: - req.check_if_exists(self.use_user_site) - - if req.satisfied_by: - should_modify = ( - self.upgrade_strategy != "to-satisfy-only" or - self.force_reinstall or - self.ignore_installed or - req.link.scheme == 'file' - ) - if should_modify: - self._set_req_to_reinstall(req) - else: - logger.info( - 'Requirement already satisfied (use --upgrade to upgrade):' - ' %s', req, - ) - - return abstract_dist - - def _resolve_one( - self, - requirement_set, # type: RequirementSet - req_to_install # type: InstallRequirement - ): - # type: (...) -> List[InstallRequirement] - """Prepare a single requirements file. - - :return: A list of additional InstallRequirements to also install. - """ - # Tell user what we are doing for this requirement: - # obtain (editable), skipping, processing (local url), collecting - # (remote url or package name) - if req_to_install.constraint or req_to_install.prepared: - return [] - - req_to_install.prepared = True - - # register tmp src for cleanup in case something goes wrong - requirement_set.reqs_to_cleanup.append(req_to_install) - - abstract_dist = self._get_abstract_dist_for(req_to_install) - - # Parse and return dependencies - dist = abstract_dist.dist() - try: - check_dist_requires_python(dist) - except UnsupportedPythonVersion as err: - if self.ignore_requires_python: - logger.warning(err.args[0]) - else: - raise - - more_reqs = [] # type: List[InstallRequirement] - - def add_req(subreq, extras_requested): - sub_install_req = install_req_from_req_string( - str(subreq), - req_to_install, - isolated=self.isolated, - wheel_cache=self.wheel_cache, - use_pep517=self.use_pep517 - ) - parent_req_name = req_to_install.name - to_scan_again, add_to_parent = requirement_set.add_requirement( - sub_install_req, - parent_req_name=parent_req_name, - extras_requested=extras_requested, - ) - if parent_req_name and add_to_parent: - self._discovered_dependencies[parent_req_name].append( - add_to_parent - ) - more_reqs.extend(to_scan_again) - - with indent_log(): - # We add req_to_install before its dependencies, so that we - # can refer to it when adding dependencies. - if not requirement_set.has_requirement(req_to_install.name): - # 'unnamed' requirements will get added here - req_to_install.is_direct = True - requirement_set.add_requirement( - req_to_install, parent_req_name=None, - ) - - if not self.ignore_dependencies: - if req_to_install.extras: - logger.debug( - "Installing extra requirements: %r", - ','.join(req_to_install.extras), - ) - missing_requested = sorted( - set(req_to_install.extras) - set(dist.extras) - ) - for missing in missing_requested: - logger.warning( - '%s does not provide the extra \'%s\'', - dist, missing - ) - - available_requested = sorted( - set(dist.extras) & set(req_to_install.extras) - ) - for subreq in dist.requires(available_requested): - add_req(subreq, extras_requested=available_requested) - - if not req_to_install.editable and not req_to_install.satisfied_by: - # XXX: --no-install leads this to report 'Successfully - # downloaded' for only non-editable reqs, even though we took - # action on them. - requirement_set.successfully_downloaded.append(req_to_install) - - return more_reqs - - def get_installation_order(self, req_set): - # type: (RequirementSet) -> List[InstallRequirement] - """Create the installation order. - - The installation order is topological - requirements are installed - before the requiring thing. We break cycles at an arbitrary point, - and make no other guarantees. - """ - # The current implementation, which we may change at any point - # installs the user specified things in the order given, except when - # dependencies must come earlier to achieve topological order. - order = [] - ordered_reqs = set() # type: Set[InstallRequirement] - - def schedule(req): - if req.satisfied_by or req in ordered_reqs: - return - if req.constraint: - return - ordered_reqs.add(req) - for dep in self._discovered_dependencies[req.name]: - schedule(dep) - order.append(req) - - for install_req in req_set.requirements.values(): - schedule(install_req) - return order diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/utils/__init__.py b/venv2/lib/python2.7/site-packages/pip/_internal/utils/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/utils/appdirs.py b/venv2/lib/python2.7/site-packages/pip/_internal/utils/appdirs.py deleted file mode 100644 index fb26111..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/utils/appdirs.py +++ /dev/null @@ -1,268 +0,0 @@ -""" -This code was taken from https://github.com/ActiveState/appdirs and modified -to suit our purposes. -""" -from __future__ import absolute_import - -import os -import sys - -from pip._vendor.six import PY2, text_type - -from pip._internal.utils.compat import WINDOWS, expanduser -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import List - - -def user_cache_dir(appname): - # type: (str) -> str - r""" - Return full path to the user-specific cache dir for this application. - - "appname" is the name of application. - - Typical user cache directories are: - macOS: ~/Library/Caches/ - Unix: ~/.cache/ (XDG default) - Windows: C:\Users\\AppData\Local\\Cache - - On Windows the only suggestion in the MSDN docs is that local settings go - in the `CSIDL_LOCAL_APPDATA` directory. This is identical to the - non-roaming app data dir (the default returned by `user_data_dir`). Apps - typically put cache data somewhere *under* the given dir here. Some - examples: - ...\Mozilla\Firefox\Profiles\\Cache - ...\Acme\SuperApp\Cache\1.0 - - OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. - """ - if WINDOWS: - # Get the base path - path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA")) - - # When using Python 2, return paths as bytes on Windows like we do on - # other operating systems. See helper function docs for more details. - if PY2 and isinstance(path, text_type): - path = _win_path_to_bytes(path) - - # Add our app name and Cache directory to it - path = os.path.join(path, appname, "Cache") - elif sys.platform == "darwin": - # Get the base path - path = expanduser("~/Library/Caches") - - # Add our app name to it - path = os.path.join(path, appname) - else: - # Get the base path - path = os.getenv("XDG_CACHE_HOME", expanduser("~/.cache")) - - # Add our app name to it - path = os.path.join(path, appname) - - return path - - -def user_data_dir(appname, roaming=False): - # type: (str, bool) -> str - r""" - Return full path to the user-specific data dir for this application. - - "appname" is the name of application. - If None, just the system directory is returned. - "roaming" (boolean, default False) can be set True to use the Windows - roaming appdata directory. That means that for users on a Windows - network setup for roaming profiles, this user data will be - sync'd on login. See - - for a discussion of issues. - - Typical user data directories are: - macOS: ~/Library/Application Support/ - if it exists, else ~/.config/ - Unix: ~/.local/share/ # or in - $XDG_DATA_HOME, if defined - Win XP (not roaming): C:\Documents and Settings\\ ... - ...Application Data\ - Win XP (roaming): C:\Documents and Settings\\Local ... - ...Settings\Application Data\ - Win 7 (not roaming): C:\\Users\\AppData\Local\ - Win 7 (roaming): C:\\Users\\AppData\Roaming\ - - For Unix, we follow the XDG spec and support $XDG_DATA_HOME. - That means, by default "~/.local/share/". - """ - if WINDOWS: - const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA" - path = os.path.join(os.path.normpath(_get_win_folder(const)), appname) - elif sys.platform == "darwin": - path = os.path.join( - expanduser('~/Library/Application Support/'), - appname, - ) if os.path.isdir(os.path.join( - expanduser('~/Library/Application Support/'), - appname, - ) - ) else os.path.join( - expanduser('~/.config/'), - appname, - ) - else: - path = os.path.join( - os.getenv('XDG_DATA_HOME', expanduser("~/.local/share")), - appname, - ) - - return path - - -def user_config_dir(appname, roaming=True): - # type: (str, bool) -> str - """Return full path to the user-specific config dir for this application. - - "appname" is the name of application. - If None, just the system directory is returned. - "roaming" (boolean, default True) can be set False to not use the - Windows roaming appdata directory. That means that for users on a - Windows network setup for roaming profiles, this user data will be - sync'd on login. See - - for a discussion of issues. - - Typical user data directories are: - macOS: same as user_data_dir - Unix: ~/.config/ - Win *: same as user_data_dir - - For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME. - That means, by default "~/.config/". - """ - if WINDOWS: - path = user_data_dir(appname, roaming=roaming) - elif sys.platform == "darwin": - path = user_data_dir(appname) - else: - path = os.getenv('XDG_CONFIG_HOME', expanduser("~/.config")) - path = os.path.join(path, appname) - - return path - - -# for the discussion regarding site_config_dirs locations -# see -def site_config_dirs(appname): - # type: (str) -> List[str] - r"""Return a list of potential user-shared config dirs for this application. - - "appname" is the name of application. - - Typical user config directories are: - macOS: /Library/Application Support// - Unix: /etc or $XDG_CONFIG_DIRS[i]// for each value in - $XDG_CONFIG_DIRS - Win XP: C:\Documents and Settings\All Users\Application ... - ...Data\\ - Vista: (Fail! "C:\ProgramData" is a hidden *system* directory - on Vista.) - Win 7: Hidden, but writeable on Win 7: - C:\ProgramData\\ - """ - if WINDOWS: - path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA")) - pathlist = [os.path.join(path, appname)] - elif sys.platform == 'darwin': - pathlist = [os.path.join('/Library/Application Support', appname)] - else: - # try looking in $XDG_CONFIG_DIRS - xdg_config_dirs = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg') - if xdg_config_dirs: - pathlist = [ - os.path.join(expanduser(x), appname) - for x in xdg_config_dirs.split(os.pathsep) - ] - else: - pathlist = [] - - # always look in /etc directly as well - pathlist.append('/etc') - - return pathlist - - -# -- Windows support functions -- - -def _get_win_folder_from_registry(csidl_name): - # type: (str) -> str - """ - This is a fallback technique at best. I'm not sure if using the - registry for this guarantees us the correct answer for all CSIDL_* - names. - """ - import _winreg - - shell_folder_name = { - "CSIDL_APPDATA": "AppData", - "CSIDL_COMMON_APPDATA": "Common AppData", - "CSIDL_LOCAL_APPDATA": "Local AppData", - }[csidl_name] - - key = _winreg.OpenKey( - _winreg.HKEY_CURRENT_USER, - r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" - ) - directory, _type = _winreg.QueryValueEx(key, shell_folder_name) - return directory - - -def _get_win_folder_with_ctypes(csidl_name): - # type: (str) -> str - csidl_const = { - "CSIDL_APPDATA": 26, - "CSIDL_COMMON_APPDATA": 35, - "CSIDL_LOCAL_APPDATA": 28, - }[csidl_name] - - buf = ctypes.create_unicode_buffer(1024) - ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf) - - # Downgrade to short path name if have highbit chars. See - # . - has_high_char = False - for c in buf: - if ord(c) > 255: - has_high_char = True - break - if has_high_char: - buf2 = ctypes.create_unicode_buffer(1024) - if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024): - buf = buf2 - - return buf.value - - -if WINDOWS: - try: - import ctypes - _get_win_folder = _get_win_folder_with_ctypes - except ImportError: - _get_win_folder = _get_win_folder_from_registry - - -def _win_path_to_bytes(path): - """Encode Windows paths to bytes. Only used on Python 2. - - Motivation is to be consistent with other operating systems where paths - are also returned as bytes. This avoids problems mixing bytes and Unicode - elsewhere in the codebase. For more details and discussion see - . - - If encoding using ASCII and MBCS fails, return the original Unicode path. - """ - for encoding in ('ASCII', 'MBCS'): - try: - return path.encode(encoding) - except (UnicodeEncodeError, LookupError): - pass - return path diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/utils/compat.py b/venv2/lib/python2.7/site-packages/pip/_internal/utils/compat.py deleted file mode 100644 index 845436e..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/utils/compat.py +++ /dev/null @@ -1,264 +0,0 @@ -"""Stuff that differs in different Python versions and platform -distributions.""" -from __future__ import absolute_import, division - -import codecs -import locale -import logging -import os -import shutil -import sys - -from pip._vendor.six import text_type - -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import Tuple, Text - -try: - import ipaddress -except ImportError: - try: - from pip._vendor import ipaddress # type: ignore - except ImportError: - import ipaddr as ipaddress # type: ignore - ipaddress.ip_address = ipaddress.IPAddress # type: ignore - ipaddress.ip_network = ipaddress.IPNetwork # type: ignore - - -__all__ = [ - "ipaddress", "uses_pycache", "console_to_str", "native_str", - "get_path_uid", "stdlib_pkgs", "WINDOWS", "samefile", "get_terminal_size", - "get_extension_suffixes", -] - - -logger = logging.getLogger(__name__) - -if sys.version_info >= (3, 4): - uses_pycache = True - from importlib.util import cache_from_source -else: - import imp - - try: - cache_from_source = imp.cache_from_source # type: ignore - except AttributeError: - # does not use __pycache__ - cache_from_source = None - - uses_pycache = cache_from_source is not None - - -if sys.version_info >= (3, 5): - backslashreplace_decode = "backslashreplace" -else: - # In version 3.4 and older, backslashreplace exists - # but does not support use for decoding. - # We implement our own replace handler for this - # situation, so that we can consistently use - # backslash replacement for all versions. - def backslashreplace_decode_fn(err): - raw_bytes = (err.object[i] for i in range(err.start, err.end)) - if sys.version_info[0] == 2: - # Python 2 gave us characters - convert to numeric bytes - raw_bytes = (ord(b) for b in raw_bytes) - return u"".join(u"\\x%x" % c for c in raw_bytes), err.end - codecs.register_error( - "backslashreplace_decode", - backslashreplace_decode_fn, - ) - backslashreplace_decode = "backslashreplace_decode" - - -def console_to_str(data): - # type: (bytes) -> Text - """Return a string, safe for output, of subprocess output. - - We assume the data is in the locale preferred encoding. - If it won't decode properly, we warn the user but decode as - best we can. - - We also ensure that the output can be safely written to - standard output without encoding errors. - """ - - # First, get the encoding we assume. This is the preferred - # encoding for the locale, unless that is not found, or - # it is ASCII, in which case assume UTF-8 - encoding = locale.getpreferredencoding() - if (not encoding) or codecs.lookup(encoding).name == "ascii": - encoding = "utf-8" - - # Now try to decode the data - if we fail, warn the user and - # decode with replacement. - try: - decoded_data = data.decode(encoding) - except UnicodeDecodeError: - logger.warning( - "Subprocess output does not appear to be encoded as %s", - encoding, - ) - decoded_data = data.decode(encoding, errors=backslashreplace_decode) - - # Make sure we can print the output, by encoding it to the output - # encoding with replacement of unencodable characters, and then - # decoding again. - # We use stderr's encoding because it's less likely to be - # redirected and if we don't find an encoding we skip this - # step (on the assumption that output is wrapped by something - # that won't fail). - # The double getattr is to deal with the possibility that we're - # being called in a situation where sys.__stderr__ doesn't exist, - # or doesn't have an encoding attribute. Neither of these cases - # should occur in normal pip use, but there's no harm in checking - # in case people use pip in (unsupported) unusual situations. - output_encoding = getattr(getattr(sys, "__stderr__", None), - "encoding", None) - - if output_encoding: - output_encoded = decoded_data.encode( - output_encoding, - errors="backslashreplace" - ) - decoded_data = output_encoded.decode(output_encoding) - - return decoded_data - - -if sys.version_info >= (3,): - def native_str(s, replace=False): - # type: (str, bool) -> str - if isinstance(s, bytes): - return s.decode('utf-8', 'replace' if replace else 'strict') - return s - -else: - def native_str(s, replace=False): - # type: (str, bool) -> str - # Replace is ignored -- unicode to UTF-8 can't fail - if isinstance(s, text_type): - return s.encode('utf-8') - return s - - -def get_path_uid(path): - # type: (str) -> int - """ - Return path's uid. - - Does not follow symlinks: - https://github.com/pypa/pip/pull/935#discussion_r5307003 - - Placed this function in compat due to differences on AIX and - Jython, that should eventually go away. - - :raises OSError: When path is a symlink or can't be read. - """ - if hasattr(os, 'O_NOFOLLOW'): - fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW) - file_uid = os.fstat(fd).st_uid - os.close(fd) - else: # AIX and Jython - # WARNING: time of check vulnerability, but best we can do w/o NOFOLLOW - if not os.path.islink(path): - # older versions of Jython don't have `os.fstat` - file_uid = os.stat(path).st_uid - else: - # raise OSError for parity with os.O_NOFOLLOW above - raise OSError( - "%s is a symlink; Will not return uid for symlinks" % path - ) - return file_uid - - -if sys.version_info >= (3, 4): - from importlib.machinery import EXTENSION_SUFFIXES - - def get_extension_suffixes(): - return EXTENSION_SUFFIXES -else: - from imp import get_suffixes - - def get_extension_suffixes(): - return [suffix[0] for suffix in get_suffixes()] - - -def expanduser(path): - # type: (str) -> str - """ - Expand ~ and ~user constructions. - - Includes a workaround for https://bugs.python.org/issue14768 - """ - expanded = os.path.expanduser(path) - if path.startswith('~/') and expanded.startswith('//'): - expanded = expanded[1:] - return expanded - - -# packages in the stdlib that may have installation metadata, but should not be -# considered 'installed'. this theoretically could be determined based on -# dist.location (py27:`sysconfig.get_paths()['stdlib']`, -# py26:sysconfig.get_config_vars('LIBDEST')), but fear platform variation may -# make this ineffective, so hard-coding -stdlib_pkgs = {"python", "wsgiref", "argparse"} - - -# windows detection, covers cpython and ironpython -WINDOWS = (sys.platform.startswith("win") or - (sys.platform == 'cli' and os.name == 'nt')) - - -def samefile(file1, file2): - # type: (str, str) -> bool - """Provide an alternative for os.path.samefile on Windows/Python2""" - if hasattr(os.path, 'samefile'): - return os.path.samefile(file1, file2) - else: - path1 = os.path.normcase(os.path.abspath(file1)) - path2 = os.path.normcase(os.path.abspath(file2)) - return path1 == path2 - - -if hasattr(shutil, 'get_terminal_size'): - def get_terminal_size(): - # type: () -> Tuple[int, int] - """ - Returns a tuple (x, y) representing the width(x) and the height(y) - in characters of the terminal window. - """ - return tuple(shutil.get_terminal_size()) # type: ignore -else: - def get_terminal_size(): - # type: () -> Tuple[int, int] - """ - Returns a tuple (x, y) representing the width(x) and the height(y) - in characters of the terminal window. - """ - def ioctl_GWINSZ(fd): - try: - import fcntl - import termios - import struct - cr = struct.unpack_from( - 'hh', - fcntl.ioctl(fd, termios.TIOCGWINSZ, '12345678') - ) - except Exception: - return None - if cr == (0, 0): - return None - return cr - cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) - if not cr: - try: - fd = os.open(os.ctermid(), os.O_RDONLY) - cr = ioctl_GWINSZ(fd) - os.close(fd) - except Exception: - pass - if not cr: - cr = (os.environ.get('LINES', 25), os.environ.get('COLUMNS', 80)) - return int(cr[1]), int(cr[0]) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/utils/deprecation.py b/venv2/lib/python2.7/site-packages/pip/_internal/utils/deprecation.py deleted file mode 100644 index 8c896f8..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/utils/deprecation.py +++ /dev/null @@ -1,93 +0,0 @@ -""" -A module that implements tooling to enable easy warnings about deprecations. -""" -from __future__ import absolute_import - -import logging -import warnings - -from pip._vendor.packaging.version import parse - -from pip import __version__ as current_version -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import Any, Optional - - -DEPRECATION_MSG_PREFIX = "DEPRECATION: " - - -class PipDeprecationWarning(Warning): - pass - - -_original_showwarning = None # type: Any - - -# Warnings <-> Logging Integration -def _showwarning(message, category, filename, lineno, file=None, line=None): - if file is not None: - if _original_showwarning is not None: - _original_showwarning( - message, category, filename, lineno, file, line, - ) - elif issubclass(category, PipDeprecationWarning): - # We use a specially named logger which will handle all of the - # deprecation messages for pip. - logger = logging.getLogger("pip._internal.deprecations") - logger.warning(message) - else: - _original_showwarning( - message, category, filename, lineno, file, line, - ) - - -def install_warning_logger(): - # type: () -> None - # Enable our Deprecation Warnings - warnings.simplefilter("default", PipDeprecationWarning, append=True) - - global _original_showwarning - - if _original_showwarning is None: - _original_showwarning = warnings.showwarning - warnings.showwarning = _showwarning - - -def deprecated(reason, replacement, gone_in, issue=None): - # type: (str, Optional[str], Optional[str], Optional[int]) -> None - """Helper to deprecate existing functionality. - - reason: - Textual reason shown to the user about why this functionality has - been deprecated. - replacement: - Textual suggestion shown to the user about what alternative - functionality they can use. - gone_in: - The version of pip does this functionality should get removed in. - Raises errors if pip's current version is greater than or equal to - this. - issue: - Issue number on the tracker that would serve as a useful place for - users to find related discussion and provide feedback. - - Always pass replacement, gone_in and issue as keyword arguments for clarity - at the call site. - """ - - # Construct a nice message. - # This is purposely eagerly formatted as we want it to appear as if someone - # typed this entire message out. - message = DEPRECATION_MSG_PREFIX + reason - if replacement is not None: - message += " A possible replacement is {}.".format(replacement) - if issue is not None: - url = "https://github.com/pypa/pip/issues/" + str(issue) - message += " You can find discussion regarding this at {}.".format(url) - - # Raise as an error if it has to be removed. - if gone_in is not None and parse(current_version) >= parse(gone_in): - raise PipDeprecationWarning(message) - warnings.warn(message, category=PipDeprecationWarning, stacklevel=2) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/utils/encoding.py b/venv2/lib/python2.7/site-packages/pip/_internal/utils/encoding.py deleted file mode 100644 index 30139f2..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/utils/encoding.py +++ /dev/null @@ -1,39 +0,0 @@ -import codecs -import locale -import re -import sys - -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import List, Tuple, Text - -BOMS = [ - (codecs.BOM_UTF8, 'utf-8'), - (codecs.BOM_UTF16, 'utf-16'), - (codecs.BOM_UTF16_BE, 'utf-16-be'), - (codecs.BOM_UTF16_LE, 'utf-16-le'), - (codecs.BOM_UTF32, 'utf-32'), - (codecs.BOM_UTF32_BE, 'utf-32-be'), - (codecs.BOM_UTF32_LE, 'utf-32-le'), -] # type: List[Tuple[bytes, Text]] - -ENCODING_RE = re.compile(br'coding[:=]\s*([-\w.]+)') - - -def auto_decode(data): - # type: (bytes) -> Text - """Check a bytes string for a BOM to correctly detect the encoding - - Fallback to locale.getpreferredencoding(False) like open() on Python3""" - for bom, encoding in BOMS: - if data.startswith(bom): - return data[len(bom):].decode(encoding) - # Lets check the first two lines as in PEP263 - for line in data.split(b'\n')[:2]: - if line[0:1] == b'#' and ENCODING_RE.search(line): - encoding = ENCODING_RE.search(line).groups()[0].decode('ascii') - return data.decode(encoding) - return data.decode( - locale.getpreferredencoding(False) or sys.getdefaultencoding(), - ) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/utils/filesystem.py b/venv2/lib/python2.7/site-packages/pip/_internal/utils/filesystem.py deleted file mode 100644 index 1e6b033..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/utils/filesystem.py +++ /dev/null @@ -1,30 +0,0 @@ -import os -import os.path - -from pip._internal.utils.compat import get_path_uid - - -def check_path_owner(path): - # type: (str) -> bool - # If we don't have a way to check the effective uid of this process, then - # we'll just assume that we own the directory. - if not hasattr(os, "geteuid"): - return True - - previous = None - while path != previous: - if os.path.lexists(path): - # Check if path is writable by current user. - if os.geteuid() == 0: - # Special handling for root user in order to handle properly - # cases where users use sudo without -H flag. - try: - path_uid = get_path_uid(path) - except OSError: - return False - return path_uid == 0 - else: - return os.access(path, os.W_OK) - else: - previous, path = path, os.path.dirname(path) - return False # assume we don't own the path diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/utils/glibc.py b/venv2/lib/python2.7/site-packages/pip/_internal/utils/glibc.py deleted file mode 100644 index 5bea655..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/utils/glibc.py +++ /dev/null @@ -1,93 +0,0 @@ -from __future__ import absolute_import - -import ctypes -import re -import warnings - -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import Optional, Tuple - - -def glibc_version_string(): - # type: () -> Optional[str] - "Returns glibc version string, or None if not using glibc." - - # 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): - # type: (str, int, int) -> bool - # 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): - # type: (int, int) -> bool - version_str = glibc_version_string() # type: Optional[str] - if version_str is None: - return False - return check_glibc_version(version_str, required_major, minimum_minor) - - -# platform.libc_ver regularly returns completely nonsensical glibc -# versions. E.g. on my computer, platform says: -# -# ~$ python2.7 -c 'import platform; print(platform.libc_ver())' -# ('glibc', '2.7') -# ~$ python3.5 -c 'import platform; print(platform.libc_ver())' -# ('glibc', '2.9') -# -# But the truth is: -# -# ~$ ldd --version -# ldd (Debian GLIBC 2.22-11) 2.22 -# -# This is unfortunate, because it means that the linehaul data on libc -# versions that was generated by pip 8.1.2 and earlier is useless and -# misleading. Solution: instead of using platform, use our code that actually -# works. -def libc_ver(): - # type: () -> Tuple[str, str] - """Try to determine the glibc version - - Returns a tuple of strings (lib, version) which default to empty strings - in case the lookup fails. - """ - glibc_version = glibc_version_string() - if glibc_version is None: - return ("", "") - else: - return ("glibc", glibc_version) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/utils/hashes.py b/venv2/lib/python2.7/site-packages/pip/_internal/utils/hashes.py deleted file mode 100644 index a714206..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/utils/hashes.py +++ /dev/null @@ -1,115 +0,0 @@ -from __future__ import absolute_import - -import hashlib - -from pip._vendor.six import iteritems, iterkeys, itervalues - -from pip._internal.exceptions import ( - HashMismatch, HashMissing, InstallationError, -) -from pip._internal.utils.misc import read_chunks -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import ( - Dict, List, BinaryIO, NoReturn, Iterator - ) - from pip._vendor.six import PY3 - if PY3: - from hashlib import _Hash - else: - from hashlib import _hash as _Hash - - -# The recommended hash algo of the moment. Change this whenever the state of -# the art changes; it won't hurt backward compatibility. -FAVORITE_HASH = 'sha256' - - -# Names of hashlib algorithms allowed by the --hash option and ``pip hash`` -# Currently, those are the ones at least as collision-resistant as sha256. -STRONG_HASHES = ['sha256', 'sha384', 'sha512'] - - -class Hashes(object): - """A wrapper that builds multiple hashes at once and checks them against - known-good values - - """ - def __init__(self, hashes=None): - # type: (Dict[str, List[str]]) -> None - """ - :param hashes: A dict of algorithm names pointing to lists of allowed - hex digests - """ - self._allowed = {} if hashes is None else hashes - - def check_against_chunks(self, chunks): - # type: (Iterator[bytes]) -> None - """Check good hashes against ones built from iterable of chunks of - data. - - Raise HashMismatch if none match. - - """ - gots = {} - for hash_name in iterkeys(self._allowed): - try: - gots[hash_name] = hashlib.new(hash_name) - except (ValueError, TypeError): - raise InstallationError('Unknown hash name: %s' % hash_name) - - for chunk in chunks: - for hash in itervalues(gots): - hash.update(chunk) - - for hash_name, got in iteritems(gots): - if got.hexdigest() in self._allowed[hash_name]: - return - self._raise(gots) - - def _raise(self, gots): - # type: (Dict[str, _Hash]) -> NoReturn - raise HashMismatch(self._allowed, gots) - - def check_against_file(self, file): - # type: (BinaryIO) -> None - """Check good hashes against a file-like object - - Raise HashMismatch if none match. - - """ - return self.check_against_chunks(read_chunks(file)) - - def check_against_path(self, path): - # type: (str) -> None - with open(path, 'rb') as file: - return self.check_against_file(file) - - def __nonzero__(self): - # type: () -> bool - """Return whether I know any known-good hashes.""" - return bool(self._allowed) - - def __bool__(self): - # type: () -> bool - return self.__nonzero__() - - -class MissingHashes(Hashes): - """A workalike for Hashes used when we're missing a hash for a requirement - - It computes the actual hash of the requirement and raises a HashMissing - exception showing it to the user. - - """ - def __init__(self): - # type: () -> None - """Don't offer the ``hashes`` kwarg.""" - # Pass our favorite hash in to generate a "gotten hash". With the - # empty list, it will never match, so an error will always raise. - super(MissingHashes, self).__init__(hashes={FAVORITE_HASH: []}) - - def _raise(self, gots): - # type: (Dict[str, _Hash]) -> NoReturn - raise HashMissing(gots[FAVORITE_HASH].hexdigest()) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/utils/logging.py b/venv2/lib/python2.7/site-packages/pip/_internal/utils/logging.py deleted file mode 100644 index a28e88c..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/utils/logging.py +++ /dev/null @@ -1,371 +0,0 @@ -from __future__ import absolute_import - -import contextlib -import errno -import logging -import logging.handlers -import os -import sys -from logging import Filter - -from pip._vendor.six import PY2 - -from pip._internal.utils.compat import WINDOWS -from pip._internal.utils.deprecation import DEPRECATION_MSG_PREFIX -from pip._internal.utils.misc import ensure_dir, subprocess_logger - -try: - import threading -except ImportError: - import dummy_threading as threading # type: ignore - - -try: - from pip._vendor import colorama -# Lots of different errors can come from this, including SystemError and -# ImportError. -except Exception: - colorama = None - - -_log_state = threading.local() -_log_state.indentation = 0 - - -class BrokenStdoutLoggingError(Exception): - """ - Raised if BrokenPipeError occurs for the stdout stream while logging. - """ - pass - - -# BrokenPipeError does not exist in Python 2 and, in addition, manifests -# differently in Windows and non-Windows. -if WINDOWS: - # In Windows, a broken pipe can show up as EINVAL rather than EPIPE: - # https://bugs.python.org/issue19612 - # https://bugs.python.org/issue30418 - if PY2: - def _is_broken_pipe_error(exc_class, exc): - """See the docstring for non-Windows Python 3 below.""" - return (exc_class is IOError and - exc.errno in (errno.EINVAL, errno.EPIPE)) - else: - # In Windows, a broken pipe IOError became OSError in Python 3. - def _is_broken_pipe_error(exc_class, exc): - """See the docstring for non-Windows Python 3 below.""" - return ((exc_class is BrokenPipeError) or # noqa: F821 - (exc_class is OSError and - exc.errno in (errno.EINVAL, errno.EPIPE))) -elif PY2: - def _is_broken_pipe_error(exc_class, exc): - """See the docstring for non-Windows Python 3 below.""" - return (exc_class is IOError and exc.errno == errno.EPIPE) -else: - # Then we are in the non-Windows Python 3 case. - def _is_broken_pipe_error(exc_class, exc): - """ - Return whether an exception is a broken pipe error. - - Args: - exc_class: an exception class. - exc: an exception instance. - """ - return (exc_class is BrokenPipeError) # noqa: F821 - - -@contextlib.contextmanager -def indent_log(num=2): - """ - A context manager which will cause the log output to be indented for any - log messages emitted inside it. - """ - _log_state.indentation += num - try: - yield - finally: - _log_state.indentation -= num - - -def get_indentation(): - return getattr(_log_state, 'indentation', 0) - - -class IndentingFormatter(logging.Formatter): - def __init__(self, *args, **kwargs): - """ - A logging.Formatter that obeys the indent_log() context manager. - - :param add_timestamp: A bool indicating output lines should be prefixed - with their record's timestamp. - """ - self.add_timestamp = kwargs.pop("add_timestamp", False) - super(IndentingFormatter, self).__init__(*args, **kwargs) - - def get_message_start(self, formatted, levelno): - """ - Return the start of the formatted log message (not counting the - prefix to add to each line). - """ - if levelno < logging.WARNING: - return '' - if formatted.startswith(DEPRECATION_MSG_PREFIX): - # Then the message already has a prefix. We don't want it to - # look like "WARNING: DEPRECATION: ...." - return '' - if levelno < logging.ERROR: - return 'WARNING: ' - - return 'ERROR: ' - - def format(self, record): - """ - Calls the standard formatter, but will indent all of the log messages - by our current indentation level. - """ - formatted = super(IndentingFormatter, self).format(record) - message_start = self.get_message_start(formatted, record.levelno) - formatted = message_start + formatted - - prefix = '' - if self.add_timestamp: - prefix = self.formatTime(record, "%Y-%m-%dT%H:%M:%S ") - prefix += " " * get_indentation() - formatted = "".join([ - prefix + line - for line in formatted.splitlines(True) - ]) - return formatted - - -def _color_wrap(*colors): - def wrapped(inp): - return "".join(list(colors) + [inp, colorama.Style.RESET_ALL]) - return wrapped - - -class ColorizedStreamHandler(logging.StreamHandler): - - # Don't build up a list of colors if we don't have colorama - if colorama: - COLORS = [ - # This needs to be in order from highest logging level to lowest. - (logging.ERROR, _color_wrap(colorama.Fore.RED)), - (logging.WARNING, _color_wrap(colorama.Fore.YELLOW)), - ] - else: - COLORS = [] - - def __init__(self, stream=None, no_color=None): - logging.StreamHandler.__init__(self, stream) - self._no_color = no_color - - if WINDOWS and colorama: - self.stream = colorama.AnsiToWin32(self.stream) - - def _using_stdout(self): - """ - Return whether the handler is using sys.stdout. - """ - if WINDOWS and colorama: - # Then self.stream is an AnsiToWin32 object. - return self.stream.wrapped is sys.stdout - - return self.stream is sys.stdout - - def should_color(self): - # Don't colorize things if we do not have colorama or if told not to - if not colorama or self._no_color: - return False - - real_stream = ( - self.stream if not isinstance(self.stream, colorama.AnsiToWin32) - else self.stream.wrapped - ) - - # If the stream is a tty we should color it - if hasattr(real_stream, "isatty") and real_stream.isatty(): - return True - - # If we have an ANSI term we should color it - if os.environ.get("TERM") == "ANSI": - return True - - # If anything else we should not color it - return False - - def format(self, record): - msg = logging.StreamHandler.format(self, record) - - if self.should_color(): - for level, color in self.COLORS: - if record.levelno >= level: - msg = color(msg) - break - - return msg - - # The logging module says handleError() can be customized. - def handleError(self, record): - exc_class, exc = sys.exc_info()[:2] - # If a broken pipe occurred while calling write() or flush() on the - # stdout stream in logging's Handler.emit(), then raise our special - # exception so we can handle it in main() instead of logging the - # broken pipe error and continuing. - if (exc_class and self._using_stdout() and - _is_broken_pipe_error(exc_class, exc)): - raise BrokenStdoutLoggingError() - - return super(ColorizedStreamHandler, self).handleError(record) - - -class BetterRotatingFileHandler(logging.handlers.RotatingFileHandler): - - def _open(self): - ensure_dir(os.path.dirname(self.baseFilename)) - return logging.handlers.RotatingFileHandler._open(self) - - -class MaxLevelFilter(Filter): - - def __init__(self, level): - self.level = level - - def filter(self, record): - return record.levelno < self.level - - -class ExcludeLoggerFilter(Filter): - - """ - A logging Filter that excludes records from a logger (or its children). - """ - - def filter(self, record): - # The base Filter class allows only records from a logger (or its - # children). - return not super(ExcludeLoggerFilter, self).filter(record) - - -def setup_logging(verbosity, no_color, user_log_file): - """Configures and sets up all of the logging - - Returns the requested logging level, as its integer value. - """ - - # Determine the level to be logging at. - if verbosity >= 1: - level = "DEBUG" - elif verbosity == -1: - level = "WARNING" - elif verbosity == -2: - level = "ERROR" - elif verbosity <= -3: - level = "CRITICAL" - else: - level = "INFO" - - level_number = getattr(logging, level) - - # The "root" logger should match the "console" level *unless* we also need - # to log to a user log file. - include_user_log = user_log_file is not None - if include_user_log: - additional_log_file = user_log_file - root_level = "DEBUG" - else: - additional_log_file = "/dev/null" - root_level = level - - # Disable any logging besides WARNING unless we have DEBUG level logging - # enabled for vendored libraries. - vendored_log_level = "WARNING" if level in ["INFO", "ERROR"] else "DEBUG" - - # Shorthands for clarity - log_streams = { - "stdout": "ext://sys.stdout", - "stderr": "ext://sys.stderr", - } - handler_classes = { - "stream": "pip._internal.utils.logging.ColorizedStreamHandler", - "file": "pip._internal.utils.logging.BetterRotatingFileHandler", - } - handlers = ["console", "console_errors", "console_subprocess"] + ( - ["user_log"] if include_user_log else [] - ) - - logging.config.dictConfig({ - "version": 1, - "disable_existing_loggers": False, - "filters": { - "exclude_warnings": { - "()": "pip._internal.utils.logging.MaxLevelFilter", - "level": logging.WARNING, - }, - "restrict_to_subprocess": { - "()": "logging.Filter", - "name": subprocess_logger.name, - }, - "exclude_subprocess": { - "()": "pip._internal.utils.logging.ExcludeLoggerFilter", - "name": subprocess_logger.name, - }, - }, - "formatters": { - "indent": { - "()": IndentingFormatter, - "format": "%(message)s", - }, - "indent_with_timestamp": { - "()": IndentingFormatter, - "format": "%(message)s", - "add_timestamp": True, - }, - }, - "handlers": { - "console": { - "level": level, - "class": handler_classes["stream"], - "no_color": no_color, - "stream": log_streams["stdout"], - "filters": ["exclude_subprocess", "exclude_warnings"], - "formatter": "indent", - }, - "console_errors": { - "level": "WARNING", - "class": handler_classes["stream"], - "no_color": no_color, - "stream": log_streams["stderr"], - "filters": ["exclude_subprocess"], - "formatter": "indent", - }, - # A handler responsible for logging to the console messages - # from the "subprocessor" logger. - "console_subprocess": { - "level": level, - "class": handler_classes["stream"], - "no_color": no_color, - "stream": log_streams["stderr"], - "filters": ["restrict_to_subprocess"], - "formatter": "indent", - }, - "user_log": { - "level": "DEBUG", - "class": handler_classes["file"], - "filename": additional_log_file, - "delay": True, - "formatter": "indent_with_timestamp", - }, - }, - "root": { - "level": root_level, - "handlers": handlers, - }, - "loggers": { - "pip._vendor": { - "level": vendored_log_level - } - }, - }) - - return level_number diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/utils/misc.py b/venv2/lib/python2.7/site-packages/pip/_internal/utils/misc.py deleted file mode 100644 index ca7a529..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/utils/misc.py +++ /dev/null @@ -1,1011 +0,0 @@ -from __future__ import absolute_import - -import contextlib -import errno -import io -# we have a submodule named 'logging' which would shadow this if we used the -# regular name: -import logging as std_logging -import os -import posixpath -import re -import shutil -import stat -import subprocess -import sys -import tarfile -import zipfile -from collections import deque - -from pip._vendor import pkg_resources -# NOTE: retrying is not annotated in typeshed as on 2017-07-17, which is -# why we ignore the type on this import. -from pip._vendor.retrying import retry # type: ignore -from pip._vendor.six import PY2 -from pip._vendor.six.moves import input, shlex_quote -from pip._vendor.six.moves.urllib import parse as urllib_parse -from pip._vendor.six.moves.urllib.parse import unquote as urllib_unquote - -from pip._internal.exceptions import CommandError, InstallationError -from pip._internal.locations import ( - running_under_virtualenv, site_packages, user_site, virtualenv_no_global, - write_delete_marker_file, -) -from pip._internal.utils.compat import ( - WINDOWS, console_to_str, expanduser, stdlib_pkgs, -) -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if PY2: - from io import BytesIO as StringIO -else: - from io import StringIO - -if MYPY_CHECK_RUNNING: - from typing import ( - Optional, Tuple, Iterable, List, Match, Union, Any, Mapping, Text, - AnyStr, Container - ) - from pip._vendor.pkg_resources import Distribution - from pip._internal.models.link import Link - from pip._internal.utils.ui import SpinnerInterface - - -__all__ = ['rmtree', 'display_path', 'backup_dir', - 'ask', 'splitext', - 'format_size', 'is_installable_dir', - 'is_svn_page', 'file_contents', - 'split_leading_dir', 'has_leading_dir', - 'normalize_path', - 'renames', 'get_prog', - 'unzip_file', 'untar_file', 'unpack_file', 'call_subprocess', - 'captured_stdout', 'ensure_dir', - 'ARCHIVE_EXTENSIONS', 'SUPPORTED_EXTENSIONS', 'WHEEL_EXTENSION', - 'get_installed_version', 'remove_auth_from_url'] - - -logger = std_logging.getLogger(__name__) -subprocess_logger = std_logging.getLogger('pip.subprocessor') - -LOG_DIVIDER = '----------------------------------------' - -WHEEL_EXTENSION = '.whl' -BZ2_EXTENSIONS = ('.tar.bz2', '.tbz') -XZ_EXTENSIONS = ('.tar.xz', '.txz', '.tlz', '.tar.lz', '.tar.lzma') -ZIP_EXTENSIONS = ('.zip', WHEEL_EXTENSION) -TAR_EXTENSIONS = ('.tar.gz', '.tgz', '.tar') -ARCHIVE_EXTENSIONS = ( - ZIP_EXTENSIONS + BZ2_EXTENSIONS + TAR_EXTENSIONS + XZ_EXTENSIONS) -SUPPORTED_EXTENSIONS = ZIP_EXTENSIONS + TAR_EXTENSIONS - -try: - import bz2 # noqa - SUPPORTED_EXTENSIONS += BZ2_EXTENSIONS -except ImportError: - logger.debug('bz2 module is not available') - -try: - # Only for Python 3.3+ - import lzma # noqa - SUPPORTED_EXTENSIONS += XZ_EXTENSIONS -except ImportError: - logger.debug('lzma module is not available') - - -def ensure_dir(path): - # type: (AnyStr) -> None - """os.path.makedirs without EEXIST.""" - try: - os.makedirs(path) - except OSError as e: - if e.errno != errno.EEXIST: - raise - - -def get_prog(): - # type: () -> str - try: - prog = os.path.basename(sys.argv[0]) - if prog in ('__main__.py', '-c'): - return "%s -m pip" % sys.executable - else: - return prog - except (AttributeError, TypeError, IndexError): - pass - return 'pip' - - -# Retry every half second for up to 3 seconds -@retry(stop_max_delay=3000, wait_fixed=500) -def rmtree(dir, ignore_errors=False): - # type: (str, bool) -> None - shutil.rmtree(dir, ignore_errors=ignore_errors, - onerror=rmtree_errorhandler) - - -def rmtree_errorhandler(func, path, exc_info): - """On Windows, the files in .svn are read-only, so when rmtree() tries to - remove them, an exception is thrown. We catch that here, remove the - read-only attribute, and hopefully continue without problems.""" - # if file type currently read only - if os.stat(path).st_mode & stat.S_IREAD: - # convert to read/write - os.chmod(path, stat.S_IWRITE) - # use the original function to repeat the operation - func(path) - return - else: - raise - - -def display_path(path): - # type: (Union[str, Text]) -> str - """Gives the display value for a given path, making it relative to cwd - if possible.""" - path = os.path.normcase(os.path.abspath(path)) - if sys.version_info[0] == 2: - path = path.decode(sys.getfilesystemencoding(), 'replace') - path = path.encode(sys.getdefaultencoding(), 'replace') - if path.startswith(os.getcwd() + os.path.sep): - path = '.' + path[len(os.getcwd()):] - return path - - -def backup_dir(dir, ext='.bak'): - # type: (str, str) -> str - """Figure out the name of a directory to back up the given dir to - (adding .bak, .bak2, etc)""" - n = 1 - extension = ext - while os.path.exists(dir + extension): - n += 1 - extension = ext + str(n) - return dir + extension - - -def ask_path_exists(message, options): - # type: (str, Iterable[str]) -> str - for action in os.environ.get('PIP_EXISTS_ACTION', '').split(): - if action in options: - return action - return ask(message, options) - - -def ask(message, options): - # type: (str, Iterable[str]) -> str - """Ask the message interactively, with the given possible responses""" - while 1: - if os.environ.get('PIP_NO_INPUT'): - raise Exception( - 'No input was expected ($PIP_NO_INPUT set); question: %s' % - message - ) - response = input(message) - response = response.strip().lower() - if response not in options: - print( - 'Your response (%r) was not one of the expected responses: ' - '%s' % (response, ', '.join(options)) - ) - else: - return response - - -def format_size(bytes): - # type: (float) -> str - if bytes > 1000 * 1000: - return '%.1fMB' % (bytes / 1000.0 / 1000) - elif bytes > 10 * 1000: - return '%ikB' % (bytes / 1000) - elif bytes > 1000: - return '%.1fkB' % (bytes / 1000.0) - else: - return '%ibytes' % bytes - - -def is_installable_dir(path): - # type: (str) -> bool - """Is path is a directory containing setup.py or pyproject.toml? - """ - if not os.path.isdir(path): - return False - setup_py = os.path.join(path, 'setup.py') - if os.path.isfile(setup_py): - return True - pyproject_toml = os.path.join(path, 'pyproject.toml') - if os.path.isfile(pyproject_toml): - return True - return False - - -def is_svn_page(html): - # type: (Union[str, Text]) -> Optional[Match[Union[str, Text]]] - """ - Returns true if the page appears to be the index page of an svn repository - """ - return (re.search(r'[^<]*Revision \d+:', html) and - re.search(r'Powered by (?:<a[^>]*?>)?Subversion', html, re.I)) - - -def file_contents(filename): - # type: (str) -> Text - with open(filename, 'rb') as fp: - return fp.read().decode('utf-8') - - -def read_chunks(file, size=io.DEFAULT_BUFFER_SIZE): - """Yield pieces of data from a file-like object until EOF.""" - while True: - chunk = file.read(size) - if not chunk: - break - yield chunk - - -def split_leading_dir(path): - # type: (Union[str, Text]) -> List[Union[str, Text]] - path = path.lstrip('/').lstrip('\\') - if '/' in path and (('\\' in path and path.find('/') < path.find('\\')) or - '\\' not in path): - return path.split('/', 1) - elif '\\' in path: - return path.split('\\', 1) - else: - return [path, ''] - - -def has_leading_dir(paths): - # type: (Iterable[Union[str, Text]]) -> bool - """Returns true if all the paths have the same leading path name - (i.e., everything is in one subdirectory in an archive)""" - common_prefix = None - for path in paths: - prefix, rest = split_leading_dir(path) - if not prefix: - return False - elif common_prefix is None: - common_prefix = prefix - elif prefix != common_prefix: - return False - return True - - -def normalize_path(path, resolve_symlinks=True): - # type: (str, bool) -> str - """ - Convert a path to its canonical, case-normalized, absolute version. - - """ - path = expanduser(path) - if resolve_symlinks: - path = os.path.realpath(path) - else: - path = os.path.abspath(path) - return os.path.normcase(path) - - -def splitext(path): - # type: (str) -> Tuple[str, str] - """Like os.path.splitext, but take off .tar too""" - base, ext = posixpath.splitext(path) - if base.lower().endswith('.tar'): - ext = base[-4:] + ext - base = base[:-4] - return base, ext - - -def renames(old, new): - # type: (str, str) -> None - """Like os.renames(), but handles renaming across devices.""" - # Implementation borrowed from os.renames(). - head, tail = os.path.split(new) - if head and tail and not os.path.exists(head): - os.makedirs(head) - - shutil.move(old, new) - - head, tail = os.path.split(old) - if head and tail: - try: - os.removedirs(head) - except OSError: - pass - - -def is_local(path): - # type: (str) -> bool - """ - Return True if path is within sys.prefix, if we're running in a virtualenv. - - If we're not in a virtualenv, all paths are considered "local." - - """ - if not running_under_virtualenv(): - return True - return normalize_path(path).startswith(normalize_path(sys.prefix)) - - -def dist_is_local(dist): - # type: (Distribution) -> bool - """ - Return True if given Distribution object is installed locally - (i.e. within current virtualenv). - - Always True if we're not in a virtualenv. - - """ - return is_local(dist_location(dist)) - - -def dist_in_usersite(dist): - # type: (Distribution) -> bool - """ - Return True if given Distribution is installed in user site. - """ - norm_path = normalize_path(dist_location(dist)) - return norm_path.startswith(normalize_path(user_site)) - - -def dist_in_site_packages(dist): - # type: (Distribution) -> bool - """ - Return True if given Distribution is installed in - sysconfig.get_python_lib(). - """ - return normalize_path( - dist_location(dist) - ).startswith(normalize_path(site_packages)) - - -def dist_is_editable(dist): - # type: (Distribution) -> bool - """ - Return True if given Distribution is an editable install. - """ - for path_item in sys.path: - egg_link = os.path.join(path_item, dist.project_name + '.egg-link') - if os.path.isfile(egg_link): - return True - return False - - -def get_installed_distributions(local_only=True, - skip=stdlib_pkgs, - include_editables=True, - editables_only=False, - user_only=False): - # type: (bool, Container[str], bool, bool, bool) -> List[Distribution] - """ - Return a list of installed Distribution objects. - - If ``local_only`` is True (default), only return installations - local to the current virtualenv, if in a virtualenv. - - ``skip`` argument is an iterable of lower-case project names to - ignore; defaults to stdlib_pkgs - - If ``include_editables`` is False, don't report editables. - - If ``editables_only`` is True , only report editables. - - If ``user_only`` is True , only report installations in the user - site directory. - - """ - if local_only: - local_test = dist_is_local - else: - def local_test(d): - return True - - if include_editables: - def editable_test(d): - return True - else: - def editable_test(d): - return not dist_is_editable(d) - - if editables_only: - def editables_only_test(d): - return dist_is_editable(d) - else: - def editables_only_test(d): - return True - - if user_only: - user_test = dist_in_usersite - else: - def user_test(d): - return True - - # because of pkg_resources vendoring, mypy cannot find stub in typeshed - return [d for d in pkg_resources.working_set # type: ignore - if local_test(d) and - d.key not in skip and - editable_test(d) and - editables_only_test(d) and - user_test(d) - ] - - -def egg_link_path(dist): - # type: (Distribution) -> Optional[str] - """ - Return the path for the .egg-link file if it exists, otherwise, None. - - There's 3 scenarios: - 1) not in a virtualenv - try to find in site.USER_SITE, then site_packages - 2) in a no-global virtualenv - try to find in site_packages - 3) in a yes-global virtualenv - try to find in site_packages, then site.USER_SITE - (don't look in global location) - - For #1 and #3, there could be odd cases, where there's an egg-link in 2 - locations. - - This method will just return the first one found. - """ - sites = [] - if running_under_virtualenv(): - if virtualenv_no_global(): - sites.append(site_packages) - else: - sites.append(site_packages) - if user_site: - sites.append(user_site) - else: - if user_site: - sites.append(user_site) - sites.append(site_packages) - - for site in sites: - egglink = os.path.join(site, dist.project_name) + '.egg-link' - if os.path.isfile(egglink): - return egglink - return None - - -def dist_location(dist): - # type: (Distribution) -> str - """ - Get the site-packages location of this distribution. Generally - this is dist.location, except in the case of develop-installed - packages, where dist.location is the source code location, and we - want to know where the egg-link file is. - - """ - egg_link = egg_link_path(dist) - if egg_link: - return egg_link - return dist.location - - -def current_umask(): - """Get the current umask which involves having to set it temporarily.""" - mask = os.umask(0) - os.umask(mask) - return mask - - -def unzip_file(filename, location, flatten=True): - # type: (str, str, bool) -> None - """ - Unzip the file (with path `filename`) to the destination `location`. All - files are written based on system defaults and umask (i.e. permissions are - not preserved), except that regular file members with any execute - permissions (user, group, or world) have "chmod +x" applied after being - written. Note that for windows, any execute changes using os.chmod are - no-ops per the python docs. - """ - ensure_dir(location) - zipfp = open(filename, 'rb') - try: - zip = zipfile.ZipFile(zipfp, allowZip64=True) - leading = has_leading_dir(zip.namelist()) and flatten - for info in zip.infolist(): - name = info.filename - fn = name - if leading: - fn = split_leading_dir(name)[1] - fn = os.path.join(location, fn) - dir = os.path.dirname(fn) - if fn.endswith('/') or fn.endswith('\\'): - # A directory - ensure_dir(fn) - else: - ensure_dir(dir) - # Don't use read() to avoid allocating an arbitrarily large - # chunk of memory for the file's content - fp = zip.open(name) - try: - with open(fn, 'wb') as destfp: - shutil.copyfileobj(fp, destfp) - finally: - fp.close() - mode = info.external_attr >> 16 - # if mode and regular file and any execute permissions for - # user/group/world? - if mode and stat.S_ISREG(mode) and mode & 0o111: - # make dest file have execute for user/group/world - # (chmod +x) no-op on windows per python docs - os.chmod(fn, (0o777 - current_umask() | 0o111)) - finally: - zipfp.close() - - -def untar_file(filename, location): - # type: (str, str) -> None - """ - Untar the file (with path `filename`) to the destination `location`. - All files are written based on system defaults and umask (i.e. permissions - are not preserved), except that regular file members with any execute - permissions (user, group, or world) have "chmod +x" applied after being - written. Note that for windows, any execute changes using os.chmod are - no-ops per the python docs. - """ - ensure_dir(location) - if filename.lower().endswith('.gz') or filename.lower().endswith('.tgz'): - mode = 'r:gz' - elif filename.lower().endswith(BZ2_EXTENSIONS): - mode = 'r:bz2' - elif filename.lower().endswith(XZ_EXTENSIONS): - mode = 'r:xz' - elif filename.lower().endswith('.tar'): - mode = 'r' - else: - logger.warning( - 'Cannot determine compression type for file %s', filename, - ) - mode = 'r:*' - tar = tarfile.open(filename, mode) - try: - leading = has_leading_dir([ - member.name for member in tar.getmembers() - ]) - for member in tar.getmembers(): - fn = member.name - if leading: - # https://github.com/python/mypy/issues/1174 - fn = split_leading_dir(fn)[1] # type: ignore - path = os.path.join(location, fn) - if member.isdir(): - ensure_dir(path) - elif member.issym(): - try: - # https://github.com/python/typeshed/issues/2673 - tar._extract_member(member, path) # type: ignore - except Exception as exc: - # Some corrupt tar files seem to produce this - # (specifically bad symlinks) - logger.warning( - 'In the tar file %s the member %s is invalid: %s', - filename, member.name, exc, - ) - continue - else: - try: - fp = tar.extractfile(member) - except (KeyError, AttributeError) as exc: - # Some corrupt tar files seem to produce this - # (specifically bad symlinks) - logger.warning( - 'In the tar file %s the member %s is invalid: %s', - filename, member.name, exc, - ) - continue - ensure_dir(os.path.dirname(path)) - with open(path, 'wb') as destfp: - shutil.copyfileobj(fp, destfp) - fp.close() - # Update the timestamp (useful for cython compiled files) - # https://github.com/python/typeshed/issues/2673 - tar.utime(member, path) # type: ignore - # member have any execute permissions for user/group/world? - if member.mode & 0o111: - # make dest file have execute for user/group/world - # no-op on windows per python docs - os.chmod(path, (0o777 - current_umask() | 0o111)) - finally: - tar.close() - - -def unpack_file( - filename, # type: str - location, # type: str - content_type, # type: Optional[str] - link # type: Optional[Link] -): - # type: (...) -> None - filename = os.path.realpath(filename) - if (content_type == 'application/zip' or - filename.lower().endswith(ZIP_EXTENSIONS) or - zipfile.is_zipfile(filename)): - unzip_file( - filename, - location, - flatten=not filename.endswith('.whl') - ) - elif (content_type == 'application/x-gzip' or - tarfile.is_tarfile(filename) or - filename.lower().endswith( - TAR_EXTENSIONS + BZ2_EXTENSIONS + XZ_EXTENSIONS)): - untar_file(filename, location) - elif (content_type and content_type.startswith('text/html') and - is_svn_page(file_contents(filename))): - # We don't really care about this - from pip._internal.vcs.subversion import Subversion - Subversion('svn+' + link.url).unpack(location) - else: - # FIXME: handle? - # FIXME: magic signatures? - logger.critical( - 'Cannot unpack file %s (downloaded from %s, content-type: %s); ' - 'cannot detect archive format', - filename, location, content_type, - ) - raise InstallationError( - 'Cannot determine archive format of %s' % location - ) - - -def format_command_args(args): - # type: (List[str]) -> str - """ - Format command arguments for display. - """ - return ' '.join(shlex_quote(arg) for arg in args) - - -def call_subprocess( - cmd, # type: List[str] - show_stdout=False, # type: bool - cwd=None, # type: Optional[str] - on_returncode='raise', # type: str - extra_ok_returncodes=None, # type: Optional[Iterable[int]] - command_desc=None, # type: Optional[str] - extra_environ=None, # type: Optional[Mapping[str, Any]] - unset_environ=None, # type: Optional[Iterable[str]] - spinner=None # type: Optional[SpinnerInterface] -): - # type: (...) -> Optional[Text] - """ - Args: - show_stdout: if true, use INFO to log the subprocess's stderr and - stdout streams. Otherwise, use DEBUG. Defaults to False. - extra_ok_returncodes: an iterable of integer return codes that are - acceptable, in addition to 0. Defaults to None, which means []. - unset_environ: an iterable of environment variable names to unset - prior to calling subprocess.Popen(). - """ - if extra_ok_returncodes is None: - extra_ok_returncodes = [] - if unset_environ is None: - unset_environ = [] - # Most places in pip use show_stdout=False. What this means is-- - # - # - We connect the child's output (combined stderr and stdout) to a - # single pipe, which we read. - # - We log this output to stderr at DEBUG level as it is received. - # - If DEBUG logging isn't enabled (e.g. if --verbose logging wasn't - # requested), then we show a spinner so the user can still see the - # subprocess is in progress. - # - If the subprocess exits with an error, we log the output to stderr - # at ERROR level if it hasn't already been displayed to the console - # (e.g. if --verbose logging wasn't enabled). This way we don't log - # the output to the console twice. - # - # If show_stdout=True, then the above is still done, but with DEBUG - # replaced by INFO. - if show_stdout: - # Then log the subprocess output at INFO level. - log_subprocess = subprocess_logger.info - used_level = std_logging.INFO - else: - # Then log the subprocess output using DEBUG. This also ensures - # it will be logged to the log file (aka user_log), if enabled. - log_subprocess = subprocess_logger.debug - used_level = std_logging.DEBUG - - # Whether the subprocess will be visible in the console. - showing_subprocess = subprocess_logger.getEffectiveLevel() <= used_level - - # Only use the spinner if we're not showing the subprocess output - # and we have a spinner. - use_spinner = not showing_subprocess and spinner is not None - - if command_desc is None: - command_desc = format_command_args(cmd) - - log_subprocess("Running command %s", command_desc) - env = os.environ.copy() - if extra_environ: - env.update(extra_environ) - for name in unset_environ: - env.pop(name, None) - try: - proc = subprocess.Popen( - cmd, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, cwd=cwd, env=env, - ) - proc.stdin.close() - except Exception as exc: - subprocess_logger.critical( - "Error %s while executing command %s", exc, command_desc, - ) - raise - all_output = [] - while True: - line = console_to_str(proc.stdout.readline()) - if not line: - break - line = line.rstrip() - all_output.append(line + '\n') - - # Show the line immediately. - log_subprocess(line) - # Update the spinner. - if use_spinner: - spinner.spin() - try: - proc.wait() - finally: - if proc.stdout: - proc.stdout.close() - proc_had_error = ( - proc.returncode and proc.returncode not in extra_ok_returncodes - ) - if use_spinner: - if proc_had_error: - spinner.finish("error") - else: - spinner.finish("done") - if proc_had_error: - if on_returncode == 'raise': - if not showing_subprocess: - # Then the subprocess streams haven't been logged to the - # console yet. - subprocess_logger.error( - 'Complete output from command %s:', command_desc, - ) - # The all_output value already ends in a newline. - subprocess_logger.error(''.join(all_output) + LOG_DIVIDER) - raise InstallationError( - 'Command "%s" failed with error code %s in %s' - % (command_desc, proc.returncode, cwd)) - elif on_returncode == 'warn': - subprocess_logger.warning( - 'Command "%s" had error code %s in %s', - command_desc, proc.returncode, cwd, - ) - elif on_returncode == 'ignore': - pass - else: - raise ValueError('Invalid value: on_returncode=%s' % - repr(on_returncode)) - return ''.join(all_output) - - -def _make_build_dir(build_dir): - os.makedirs(build_dir) - write_delete_marker_file(build_dir) - - -class FakeFile(object): - """Wrap a list of lines in an object with readline() to make - ConfigParser happy.""" - def __init__(self, lines): - self._gen = (l for l in lines) - - def readline(self): - try: - try: - return next(self._gen) - except NameError: - return self._gen.next() - except StopIteration: - return '' - - def __iter__(self): - return self._gen - - -class StreamWrapper(StringIO): - - @classmethod - def from_stream(cls, orig_stream): - cls.orig_stream = orig_stream - return cls() - - # compileall.compile_dir() needs stdout.encoding to print to stdout - @property - def encoding(self): - return self.orig_stream.encoding - - -@contextlib.contextmanager -def captured_output(stream_name): - """Return a context manager used by captured_stdout/stdin/stderr - that temporarily replaces the sys stream *stream_name* with a StringIO. - - Taken from Lib/support/__init__.py in the CPython repo. - """ - orig_stdout = getattr(sys, stream_name) - setattr(sys, stream_name, StreamWrapper.from_stream(orig_stdout)) - try: - yield getattr(sys, stream_name) - finally: - setattr(sys, stream_name, orig_stdout) - - -def captured_stdout(): - """Capture the output of sys.stdout: - - with captured_stdout() as stdout: - print('hello') - self.assertEqual(stdout.getvalue(), 'hello\n') - - Taken from Lib/support/__init__.py in the CPython repo. - """ - return captured_output('stdout') - - -def captured_stderr(): - """ - See captured_stdout(). - """ - return captured_output('stderr') - - -class cached_property(object): - """A property that is only computed once per instance and then replaces - itself with an ordinary attribute. Deleting the attribute resets the - property. - - Source: https://github.com/bottlepy/bottle/blob/0.11.5/bottle.py#L175 - """ - - def __init__(self, func): - self.__doc__ = getattr(func, '__doc__') - self.func = func - - def __get__(self, obj, cls): - if obj is None: - # We're being accessed from the class itself, not from an object - return self - value = obj.__dict__[self.func.__name__] = self.func(obj) - return value - - -def get_installed_version(dist_name, working_set=None): - """Get the installed version of dist_name avoiding pkg_resources cache""" - # Create a requirement that we'll look for inside of setuptools. - req = pkg_resources.Requirement.parse(dist_name) - - if working_set is None: - # We want to avoid having this cached, so we need to construct a new - # working set each time. - working_set = pkg_resources.WorkingSet() - - # Get the installed distribution from our working set - dist = working_set.find(req) - - # Check to see if we got an installed distribution or not, if we did - # we want to return it's version. - return dist.version if dist else None - - -def consume(iterator): - """Consume an iterable at C speed.""" - deque(iterator, maxlen=0) - - -# Simulates an enum -def enum(*sequential, **named): - enums = dict(zip(sequential, range(len(sequential))), **named) - reverse = {value: key for key, value in enums.items()} - enums['reverse_mapping'] = reverse - return type('Enum', (), enums) - - -def split_auth_from_netloc(netloc): - """ - Parse out and remove the auth information from a netloc. - - Returns: (netloc, (username, password)). - """ - if '@' not in netloc: - return netloc, (None, None) - - # Split from the right because that's how urllib.parse.urlsplit() - # behaves if more than one @ is present (which can be checked using - # the password attribute of urlsplit()'s return value). - auth, netloc = netloc.rsplit('@', 1) - if ':' in auth: - # Split from the left because that's how urllib.parse.urlsplit() - # behaves if more than one : is present (which again can be checked - # using the password attribute of the return value) - user_pass = auth.split(':', 1) - else: - user_pass = auth, None - - user_pass = tuple( - None if x is None else urllib_unquote(x) for x in user_pass - ) - - return netloc, user_pass - - -def redact_netloc(netloc): - # type: (str) -> str - """ - Replace the password in a netloc with "****", if it exists. - - For example, "user:pass@example.com" returns "user:****@example.com". - """ - netloc, (user, password) = split_auth_from_netloc(netloc) - if user is None: - return netloc - password = '' if password is None else ':****' - return '{user}{password}@{netloc}'.format(user=urllib_parse.quote(user), - password=password, - netloc=netloc) - - -def _transform_url(url, transform_netloc): - purl = urllib_parse.urlsplit(url) - netloc = transform_netloc(purl.netloc) - # stripped url - url_pieces = ( - purl.scheme, netloc, purl.path, purl.query, purl.fragment - ) - surl = urllib_parse.urlunsplit(url_pieces) - return surl - - -def _get_netloc(netloc): - return split_auth_from_netloc(netloc)[0] - - -def remove_auth_from_url(url): - # type: (str) -> str - # Return a copy of url with 'username:password@' removed. - # username/pass params are passed to subversion through flags - # and are not recognized in the url. - return _transform_url(url, _get_netloc) - - -def redact_password_from_url(url): - # type: (str) -> str - """Replace the password in a given url with ****.""" - return _transform_url(url, redact_netloc) - - -def protect_pip_from_modification_on_windows(modifying_pip): - """Protection of pip.exe from modification on Windows - - On Windows, any operation modifying pip should be run as: - python -m pip ... - """ - pip_names = [ - "pip.exe", - "pip{}.exe".format(sys.version_info[0]), - "pip{}.{}.exe".format(*sys.version_info[:2]) - ] - - # See https://github.com/pypa/pip/issues/1299 for more discussion - should_show_use_python_msg = ( - modifying_pip and - WINDOWS and - os.path.basename(sys.argv[0]) in pip_names - ) - - if should_show_use_python_msg: - new_command = [ - sys.executable, "-m", "pip" - ] + sys.argv[1:] - raise CommandError( - 'To modify pip, please run the following command:\n{}' - .format(" ".join(new_command)) - ) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/utils/models.py b/venv2/lib/python2.7/site-packages/pip/_internal/utils/models.py deleted file mode 100644 index d5cb80a..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/utils/models.py +++ /dev/null @@ -1,40 +0,0 @@ -"""Utilities for defining models -""" - -import operator - - -class KeyBasedCompareMixin(object): - """Provides comparision capabilities that is based on a key - """ - - def __init__(self, key, defining_class): - self._compare_key = key - self._defining_class = defining_class - - def __hash__(self): - return hash(self._compare_key) - - def __lt__(self, other): - return self._compare(other, operator.__lt__) - - def __le__(self, other): - return self._compare(other, operator.__le__) - - def __gt__(self, other): - return self._compare(other, operator.__gt__) - - def __ge__(self, other): - return self._compare(other, operator.__ge__) - - def __eq__(self, other): - return self._compare(other, operator.__eq__) - - def __ne__(self, other): - return self._compare(other, operator.__ne__) - - def _compare(self, other, method): - if not isinstance(other, self._defining_class): - return NotImplemented - - return method(self._compare_key, other._compare_key) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/utils/outdated.py b/venv2/lib/python2.7/site-packages/pip/_internal/utils/outdated.py deleted file mode 100644 index 3b58cd5..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/utils/outdated.py +++ /dev/null @@ -1,162 +0,0 @@ -from __future__ import absolute_import - -import datetime -import json -import logging -import os.path -import sys - -from pip._vendor import lockfile, pkg_resources -from pip._vendor.packaging import version as packaging_version - -from pip._internal.index import PackageFinder -from pip._internal.utils.compat import WINDOWS -from pip._internal.utils.filesystem import check_path_owner -from pip._internal.utils.misc import ensure_dir, get_installed_version -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - import optparse - from typing import Any, Dict - from pip._internal.download import PipSession - - -SELFCHECK_DATE_FMT = "%Y-%m-%dT%H:%M:%SZ" - - -logger = logging.getLogger(__name__) - - -class SelfCheckState(object): - def __init__(self, cache_dir): - # type: (str) -> None - self.state = {} # type: Dict[str, Any] - self.statefile_path = None - - # Try to load the existing state - if cache_dir: - self.statefile_path = os.path.join(cache_dir, "selfcheck.json") - try: - with open(self.statefile_path) as statefile: - self.state = json.load(statefile)[sys.prefix] - except (IOError, ValueError, KeyError): - # Explicitly suppressing exceptions, since we don't want to - # error out if the cache file is invalid. - pass - - def save(self, pypi_version, current_time): - # type: (str, datetime.datetime) -> None - # If we do not have a path to cache in, don't bother saving. - if not self.statefile_path: - return - - # Check to make sure that we own the directory - if not check_path_owner(os.path.dirname(self.statefile_path)): - return - - # Now that we've ensured the directory is owned by this user, we'll go - # ahead and make sure that all our directories are created. - ensure_dir(os.path.dirname(self.statefile_path)) - - # Attempt to write out our version check file - with lockfile.LockFile(self.statefile_path): - if os.path.exists(self.statefile_path): - with open(self.statefile_path) as statefile: - state = json.load(statefile) - else: - state = {} - - state[sys.prefix] = { - "last_check": current_time.strftime(SELFCHECK_DATE_FMT), - "pypi_version": pypi_version, - } - - with open(self.statefile_path, "w") as statefile: - json.dump(state, statefile, sort_keys=True, - separators=(",", ":")) - - -def was_installed_by_pip(pkg): - # type: (str) -> bool - """Checks whether pkg was installed by pip - - This is used not to display the upgrade message when pip is in fact - installed by system package manager, such as dnf on Fedora. - """ - try: - dist = pkg_resources.get_distribution(pkg) - return (dist.has_metadata('INSTALLER') and - 'pip' in dist.get_metadata_lines('INSTALLER')) - except pkg_resources.DistributionNotFound: - return False - - -def pip_version_check(session, options): - # type: (PipSession, optparse.Values) -> None - """Check for an update for pip. - - Limit the frequency of checks to once per week. State is stored either in - the active virtualenv or in the user's USER_CACHE_DIR keyed off the prefix - of the pip script path. - """ - installed_version = get_installed_version("pip") - if not installed_version: - return - - pip_version = packaging_version.parse(installed_version) - pypi_version = None - - try: - state = SelfCheckState(cache_dir=options.cache_dir) - - current_time = datetime.datetime.utcnow() - # Determine if we need to refresh the state - if "last_check" in state.state and "pypi_version" in state.state: - last_check = datetime.datetime.strptime( - state.state["last_check"], - SELFCHECK_DATE_FMT - ) - if (current_time - last_check).total_seconds() < 7 * 24 * 60 * 60: - pypi_version = state.state["pypi_version"] - - # Refresh the version if we need to or just see if we need to warn - if pypi_version is None: - # Lets use PackageFinder to see what the latest pip version is - finder = PackageFinder( - find_links=options.find_links, - index_urls=[options.index_url] + options.extra_index_urls, - allow_all_prereleases=False, # Explicitly set to False - trusted_hosts=options.trusted_hosts, - session=session, - ) - candidate = finder.find_candidates("pip").get_best() - if candidate is None: - return - pypi_version = str(candidate.version) - - # save that we've performed a check - state.save(pypi_version, current_time) - - remote_version = packaging_version.parse(pypi_version) - - # Determine if our pypi_version is older - if (pip_version < remote_version and - pip_version.base_version != remote_version.base_version and - was_installed_by_pip('pip')): - # Advise "python -m pip" on Windows to avoid issues - # with overwriting pip.exe. - if WINDOWS: - pip_cmd = "python -m pip" - else: - pip_cmd = "pip" - logger.warning( - "You are using pip version %s, however version %s is " - "available.\nYou should consider upgrading via the " - "'%s install --upgrade pip' command.", - pip_version, pypi_version, pip_cmd - ) - except Exception: - logger.debug( - "There was an error checking the latest version of pip", - exc_info=True, - ) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/utils/packaging.py b/venv2/lib/python2.7/site-packages/pip/_internal/utils/packaging.py deleted file mode 100644 index 449f3fd..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/utils/packaging.py +++ /dev/null @@ -1,85 +0,0 @@ -from __future__ import absolute_import - -import logging -import sys -from email.parser import FeedParser - -from pip._vendor import pkg_resources -from pip._vendor.packaging import specifiers, version - -from pip._internal import exceptions -from pip._internal.utils.misc import display_path -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import Optional - from email.message import Message - from pip._vendor.pkg_resources import Distribution - - -logger = logging.getLogger(__name__) - - -def check_requires_python(requires_python): - # type: (Optional[str]) -> bool - """ - Check if the python version in use match the `requires_python` specifier. - - Returns `True` if the version of python in use matches the requirement. - Returns `False` if the version of python in use does not matches the - requirement. - - Raises an InvalidSpecifier if `requires_python` have an invalid format. - """ - if requires_python is None: - # The package provides no information - return True - requires_python_specifier = specifiers.SpecifierSet(requires_python) - - # We only use major.minor.micro - python_version = version.parse('.'.join(map(str, sys.version_info[:3]))) - return python_version in requires_python_specifier - - -def get_metadata(dist): - # type: (Distribution) -> Message - if (isinstance(dist, pkg_resources.DistInfoDistribution) and - dist.has_metadata('METADATA')): - metadata = dist.get_metadata('METADATA') - elif dist.has_metadata('PKG-INFO'): - metadata = dist.get_metadata('PKG-INFO') - else: - logger.warning("No metadata found in %s", display_path(dist.location)) - metadata = '' - - feed_parser = FeedParser() - feed_parser.feed(metadata) - return feed_parser.close() - - -def check_dist_requires_python(dist): - pkg_info_dict = get_metadata(dist) - requires_python = pkg_info_dict.get('Requires-Python') - try: - if not check_requires_python(requires_python): - raise exceptions.UnsupportedPythonVersion( - "%s requires Python '%s' but the running Python is %s" % ( - dist.project_name, - requires_python, - '.'.join(map(str, sys.version_info[:3])),) - ) - except specifiers.InvalidSpecifier as e: - logger.warning( - "Package %s has an invalid Requires-Python entry %s - %s", - dist.project_name, requires_python, e, - ) - return - - -def get_installer(dist): - # type: (Distribution) -> str - if dist.has_metadata('INSTALLER'): - for line in dist.get_metadata_lines('INSTALLER'): - if line.strip(): - return line.strip() - return '' diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/utils/setuptools_build.py b/venv2/lib/python2.7/site-packages/pip/_internal/utils/setuptools_build.py deleted file mode 100644 index 03973e9..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/utils/setuptools_build.py +++ /dev/null @@ -1,8 +0,0 @@ -# Shim to wrap setup.py invocation with setuptools -SETUPTOOLS_SHIM = ( - "import setuptools, tokenize;__file__=%r;" - "f=getattr(tokenize, 'open', open)(__file__);" - "code=f.read().replace('\\r\\n', '\\n');" - "f.close();" - "exec(compile(code, __file__, 'exec'))" -) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/utils/temp_dir.py b/venv2/lib/python2.7/site-packages/pip/_internal/utils/temp_dir.py deleted file mode 100644 index 2c81ad5..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/utils/temp_dir.py +++ /dev/null @@ -1,155 +0,0 @@ -from __future__ import absolute_import - -import errno -import itertools -import logging -import os.path -import tempfile - -from pip._internal.utils.misc import rmtree - -logger = logging.getLogger(__name__) - - -class TempDirectory(object): - """Helper class that owns and cleans up a temporary directory. - - This class can be used as a context manager or as an OO representation of a - temporary directory. - - Attributes: - path - Location to the created temporary directory or None - delete - Whether the directory should be deleted when exiting - (when used as a contextmanager) - - Methods: - create() - Creates a temporary directory and stores its path in the path - attribute. - cleanup() - Deletes the temporary directory and sets path attribute to None - - When used as a context manager, a temporary directory is created on - entering the context and, if the delete attribute is True, on exiting the - context the created directory is deleted. - """ - - def __init__(self, path=None, delete=None, kind="temp"): - super(TempDirectory, self).__init__() - - if path is None and delete is None: - # If we were not given an explicit directory, and we were not given - # an explicit delete option, then we'll default to deleting. - delete = True - - self.path = path - self.delete = delete - self.kind = kind - - def __repr__(self): - return "<{} {!r}>".format(self.__class__.__name__, self.path) - - def __enter__(self): - self.create() - return self - - def __exit__(self, exc, value, tb): - if self.delete: - self.cleanup() - - def create(self): - """Create a temporary directory and store its path in self.path - """ - if self.path is not None: - logger.debug( - "Skipped creation of temporary directory: {}".format(self.path) - ) - return - # We realpath here because some systems have their default tmpdir - # symlinked to another directory. This tends to confuse build - # scripts, so we canonicalize the path by traversing potential - # symlinks here. - self.path = os.path.realpath( - tempfile.mkdtemp(prefix="pip-{}-".format(self.kind)) - ) - logger.debug("Created temporary directory: {}".format(self.path)) - - def cleanup(self): - """Remove the temporary directory created and reset state - """ - if self.path is not None and os.path.exists(self.path): - rmtree(self.path) - self.path = None - - -class AdjacentTempDirectory(TempDirectory): - """Helper class that creates a temporary directory adjacent to a real one. - - Attributes: - original - The original directory to create a temp directory for. - path - After calling create() or entering, contains the full - path to the temporary directory. - delete - Whether the directory should be deleted when exiting - (when used as a contextmanager) - - """ - # The characters that may be used to name the temp directory - # We always prepend a ~ and then rotate through these until - # a usable name is found. - # pkg_resources raises a different error for .dist-info folder - # with leading '-' and invalid metadata - LEADING_CHARS = "-~.=%0123456789" - - def __init__(self, original, delete=None): - super(AdjacentTempDirectory, self).__init__(delete=delete) - self.original = original.rstrip('/\\') - - @classmethod - def _generate_names(cls, name): - """Generates a series of temporary names. - - The algorithm replaces the leading characters in the name - with ones that are valid filesystem characters, but are not - valid package names (for both Python and pip definitions of - package). - """ - for i in range(1, len(name)): - for candidate in itertools.combinations_with_replacement( - cls.LEADING_CHARS, i - 1): - new_name = '~' + ''.join(candidate) + name[i:] - if new_name != name: - yield new_name - - # If we make it this far, we will have to make a longer name - for i in range(len(cls.LEADING_CHARS)): - for candidate in itertools.combinations_with_replacement( - cls.LEADING_CHARS, i): - new_name = '~' + ''.join(candidate) + name - if new_name != name: - yield new_name - - def create(self): - root, name = os.path.split(self.original) - for candidate in self._generate_names(name): - path = os.path.join(root, candidate) - try: - os.mkdir(path) - except OSError as ex: - # Continue if the name exists already - if ex.errno != errno.EEXIST: - raise - else: - self.path = os.path.realpath(path) - break - - if not self.path: - # Final fallback on the default behavior. - self.path = os.path.realpath( - tempfile.mkdtemp(prefix="pip-{}-".format(self.kind)) - ) - logger.debug("Created temporary directory: {}".format(self.path)) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/utils/typing.py b/venv2/lib/python2.7/site-packages/pip/_internal/utils/typing.py deleted file mode 100644 index 10170ce..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/utils/typing.py +++ /dev/null @@ -1,29 +0,0 @@ -"""For neatly implementing static typing in pip. - -`mypy` - the static type analysis tool we use - uses the `typing` module, which -provides core functionality fundamental to mypy's functioning. - -Generally, `typing` would be imported at runtime and used in that fashion - -it acts as a no-op at runtime and does not have any run-time overhead by -design. - -As it turns out, `typing` is not vendorable - it uses separate sources for -Python 2/Python 3. Thus, this codebase can not expect it to be present. -To work around this, mypy allows the typing import to be behind a False-y -optional to prevent it from running at runtime and type-comments can be used -to remove the need for the types to be accessible directly during runtime. - -This module provides the False-y guard in a nicely named fashion so that a -curious maintainer can reach here to read this. - -In pip, all static-typing related imports should be guarded as follows: - - from pip._internal.utils.typing import MYPY_CHECK_RUNNING - - if MYPY_CHECK_RUNNING: - from typing import ... - -Ref: https://github.com/python/mypy/issues/3216 -""" - -MYPY_CHECK_RUNNING = False diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/utils/ui.py b/venv2/lib/python2.7/site-packages/pip/_internal/utils/ui.py deleted file mode 100644 index 0902ce7..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/utils/ui.py +++ /dev/null @@ -1,424 +0,0 @@ -from __future__ import absolute_import, division - -import contextlib -import itertools -import logging -import sys -import time -from signal import SIGINT, default_int_handler, signal - -from pip._vendor import six -from pip._vendor.progress import HIDE_CURSOR, SHOW_CURSOR -from pip._vendor.progress.bar import Bar, FillingCirclesBar, IncrementalBar -from pip._vendor.progress.spinner import Spinner - -from pip._internal.utils.compat import WINDOWS -from pip._internal.utils.logging import get_indentation -from pip._internal.utils.misc import format_size -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import Any, Iterator, IO - -try: - from pip._vendor import colorama -# Lots of different errors can come from this, including SystemError and -# ImportError. -except Exception: - colorama = None - -logger = logging.getLogger(__name__) - - -def _select_progress_class(preferred, fallback): - encoding = getattr(preferred.file, "encoding", None) - - # If we don't know what encoding this file is in, then we'll just assume - # that it doesn't support unicode and use the ASCII bar. - if not encoding: - return fallback - - # Collect all of the possible characters we want to use with the preferred - # bar. - characters = [ - getattr(preferred, "empty_fill", six.text_type()), - getattr(preferred, "fill", six.text_type()), - ] - characters += list(getattr(preferred, "phases", [])) - - # Try to decode the characters we're using for the bar using the encoding - # of the given file, if this works then we'll assume that we can use the - # fancier bar and if not we'll fall back to the plaintext bar. - try: - six.text_type().join(characters).encode(encoding) - except UnicodeEncodeError: - return fallback - else: - return preferred - - -_BaseBar = _select_progress_class(IncrementalBar, Bar) # type: Any - - -class InterruptibleMixin(object): - """ - Helper to ensure that self.finish() gets called on keyboard interrupt. - - This allows downloads to be interrupted without leaving temporary state - (like hidden cursors) behind. - - This class is similar to the progress library's existing SigIntMixin - helper, but as of version 1.2, that helper has the following problems: - - 1. It calls sys.exit(). - 2. It discards the existing SIGINT handler completely. - 3. It leaves its own handler in place even after an uninterrupted finish, - which will have unexpected delayed effects if the user triggers an - unrelated keyboard interrupt some time after a progress-displaying - download has already completed, for example. - """ - - def __init__(self, *args, **kwargs): - """ - Save the original SIGINT handler for later. - """ - super(InterruptibleMixin, self).__init__(*args, **kwargs) - - self.original_handler = signal(SIGINT, self.handle_sigint) - - # If signal() returns None, the previous handler was not installed from - # Python, and we cannot restore it. This probably should not happen, - # but if it does, we must restore something sensible instead, at least. - # The least bad option should be Python's default SIGINT handler, which - # just raises KeyboardInterrupt. - if self.original_handler is None: - self.original_handler = default_int_handler - - def finish(self): - """ - Restore the original SIGINT handler after finishing. - - This should happen regardless of whether the progress display finishes - normally, or gets interrupted. - """ - super(InterruptibleMixin, self).finish() - signal(SIGINT, self.original_handler) - - def handle_sigint(self, signum, frame): - """ - Call self.finish() before delegating to the original SIGINT handler. - - This handler should only be in place while the progress display is - active. - """ - self.finish() - self.original_handler(signum, frame) - - -class SilentBar(Bar): - - def update(self): - pass - - -class BlueEmojiBar(IncrementalBar): - - suffix = "%(percent)d%%" - bar_prefix = " " - bar_suffix = " " - phases = (u"\U0001F539", u"\U0001F537", u"\U0001F535") # type: Any - - -class DownloadProgressMixin(object): - - def __init__(self, *args, **kwargs): - super(DownloadProgressMixin, self).__init__(*args, **kwargs) - self.message = (" " * (get_indentation() + 2)) + self.message - - @property - def downloaded(self): - return format_size(self.index) - - @property - def download_speed(self): - # Avoid zero division errors... - if self.avg == 0.0: - return "..." - return format_size(1 / self.avg) + "/s" - - @property - def pretty_eta(self): - if self.eta: - return "eta %s" % self.eta_td - return "" - - def iter(self, it, n=1): - for x in it: - yield x - self.next(n) - self.finish() - - -class WindowsMixin(object): - - def __init__(self, *args, **kwargs): - # The Windows terminal does not support the hide/show cursor ANSI codes - # even with colorama. So we'll ensure that hide_cursor is False on - # Windows. - # This call needs to go before the super() call, so that hide_cursor - # is set in time. The base progress bar class writes the "hide cursor" - # code to the terminal in its init, so if we don't set this soon - # enough, we get a "hide" with no corresponding "show"... - if WINDOWS and self.hide_cursor: - self.hide_cursor = False - - super(WindowsMixin, self).__init__(*args, **kwargs) - - # Check if we are running on Windows and we have the colorama module, - # if we do then wrap our file with it. - if WINDOWS and colorama: - self.file = colorama.AnsiToWin32(self.file) - # The progress code expects to be able to call self.file.isatty() - # but the colorama.AnsiToWin32() object doesn't have that, so we'll - # add it. - self.file.isatty = lambda: self.file.wrapped.isatty() - # The progress code expects to be able to call self.file.flush() - # but the colorama.AnsiToWin32() object doesn't have that, so we'll - # add it. - self.file.flush = lambda: self.file.wrapped.flush() - - -class BaseDownloadProgressBar(WindowsMixin, InterruptibleMixin, - DownloadProgressMixin): - - file = sys.stdout - message = "%(percent)d%%" - suffix = "%(downloaded)s %(download_speed)s %(pretty_eta)s" - -# NOTE: The "type: ignore" comments on the following classes are there to -# work around https://github.com/python/typing/issues/241 - - -class DefaultDownloadProgressBar(BaseDownloadProgressBar, - _BaseBar): - pass - - -class DownloadSilentBar(BaseDownloadProgressBar, SilentBar): # type: ignore - pass - - -class DownloadIncrementalBar(BaseDownloadProgressBar, # type: ignore - IncrementalBar): - pass - - -class DownloadFillingCirclesBar(BaseDownloadProgressBar, # type: ignore - FillingCirclesBar): - pass - - -class DownloadBlueEmojiProgressBar(BaseDownloadProgressBar, # type: ignore - BlueEmojiBar): - pass - - -class DownloadProgressSpinner(WindowsMixin, InterruptibleMixin, - DownloadProgressMixin, Spinner): - - file = sys.stdout - suffix = "%(downloaded)s %(download_speed)s" - - def next_phase(self): - if not hasattr(self, "_phaser"): - self._phaser = itertools.cycle(self.phases) - return next(self._phaser) - - def update(self): - message = self.message % self - phase = self.next_phase() - suffix = self.suffix % self - line = ''.join([ - message, - " " if message else "", - phase, - " " if suffix else "", - suffix, - ]) - - self.writeln(line) - - -BAR_TYPES = { - "off": (DownloadSilentBar, DownloadSilentBar), - "on": (DefaultDownloadProgressBar, DownloadProgressSpinner), - "ascii": (DownloadIncrementalBar, DownloadProgressSpinner), - "pretty": (DownloadFillingCirclesBar, DownloadProgressSpinner), - "emoji": (DownloadBlueEmojiProgressBar, DownloadProgressSpinner) -} - - -def DownloadProgressProvider(progress_bar, max=None): - if max is None or max == 0: - return BAR_TYPES[progress_bar][1]().iter - else: - return BAR_TYPES[progress_bar][0](max=max).iter - - -################################################################ -# Generic "something is happening" spinners -# -# We don't even try using progress.spinner.Spinner here because it's actually -# simpler to reimplement from scratch than to coerce their code into doing -# what we need. -################################################################ - -@contextlib.contextmanager -def hidden_cursor(file): - # type: (IO) -> Iterator[None] - # The Windows terminal does not support the hide/show cursor ANSI codes, - # even via colorama. So don't even try. - if WINDOWS: - yield - # We don't want to clutter the output with control characters if we're - # writing to a file, or if the user is running with --quiet. - # See https://github.com/pypa/pip/issues/3418 - elif not file.isatty() or logger.getEffectiveLevel() > logging.INFO: - yield - else: - file.write(HIDE_CURSOR) - try: - yield - finally: - file.write(SHOW_CURSOR) - - -class RateLimiter(object): - def __init__(self, min_update_interval_seconds): - # type: (float) -> None - self._min_update_interval_seconds = min_update_interval_seconds - self._last_update = 0 # type: float - - def ready(self): - # type: () -> bool - now = time.time() - delta = now - self._last_update - return delta >= self._min_update_interval_seconds - - def reset(self): - # type: () -> None - self._last_update = time.time() - - -class SpinnerInterface(object): - def spin(self): - # type: () -> None - raise NotImplementedError() - - def finish(self, final_status): - # type: (str) -> None - raise NotImplementedError() - - -class InteractiveSpinner(SpinnerInterface): - def __init__(self, message, file=None, spin_chars="-\\|/", - # Empirically, 8 updates/second looks nice - min_update_interval_seconds=0.125): - self._message = message - if file is None: - file = sys.stdout - self._file = file - self._rate_limiter = RateLimiter(min_update_interval_seconds) - self._finished = False - - self._spin_cycle = itertools.cycle(spin_chars) - - self._file.write(" " * get_indentation() + self._message + " ... ") - self._width = 0 - - def _write(self, status): - assert not self._finished - # Erase what we wrote before by backspacing to the beginning, writing - # spaces to overwrite the old text, and then backspacing again - backup = "\b" * self._width - self._file.write(backup + " " * self._width + backup) - # Now we have a blank slate to add our status - self._file.write(status) - self._width = len(status) - self._file.flush() - self._rate_limiter.reset() - - def spin(self): - # type: () -> None - if self._finished: - return - if not self._rate_limiter.ready(): - return - self._write(next(self._spin_cycle)) - - def finish(self, final_status): - # type: (str) -> None - if self._finished: - return - self._write(final_status) - self._file.write("\n") - self._file.flush() - self._finished = True - - -# Used for dumb terminals, non-interactive installs (no tty), etc. -# We still print updates occasionally (once every 60 seconds by default) to -# act as a keep-alive for systems like Travis-CI that take lack-of-output as -# an indication that a task has frozen. -class NonInteractiveSpinner(SpinnerInterface): - def __init__(self, message, min_update_interval_seconds=60): - # type: (str, float) -> None - self._message = message - self._finished = False - self._rate_limiter = RateLimiter(min_update_interval_seconds) - self._update("started") - - def _update(self, status): - assert not self._finished - self._rate_limiter.reset() - logger.info("%s: %s", self._message, status) - - def spin(self): - # type: () -> None - if self._finished: - return - if not self._rate_limiter.ready(): - return - self._update("still running...") - - def finish(self, final_status): - # type: (str) -> None - if self._finished: - return - self._update("finished with status '%s'" % (final_status,)) - self._finished = True - - -@contextlib.contextmanager -def open_spinner(message): - # type: (str) -> Iterator[SpinnerInterface] - # Interactive spinner goes directly to sys.stdout rather than being routed - # through the logging system, but it acts like it has level INFO, - # i.e. it's only displayed if we're at level INFO or better. - # Non-interactive spinner goes through the logging system, so it is always - # in sync with logging configuration. - if sys.stdout.isatty() and logger.getEffectiveLevel() <= logging.INFO: - spinner = InteractiveSpinner(message) # type: SpinnerInterface - else: - spinner = NonInteractiveSpinner(message) - try: - with hidden_cursor(sys.stdout): - yield spinner - except KeyboardInterrupt: - spinner.finish("canceled") - raise - except Exception: - spinner.finish("error") - raise - else: - spinner.finish("done") diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/vcs/__init__.py b/venv2/lib/python2.7/site-packages/pip/_internal/vcs/__init__.py deleted file mode 100644 index 6fca079..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/vcs/__init__.py +++ /dev/null @@ -1,604 +0,0 @@ -"""Handles all VCS (version control) support""" -from __future__ import absolute_import - -import errno -import logging -import os -import shutil -import sys - -from pip._vendor import pkg_resources -from pip._vendor.six.moves.urllib import parse as urllib_parse - -from pip._internal.exceptions import BadCommand -from pip._internal.utils.misc import ( - ask_path_exists, backup_dir, call_subprocess, display_path, rmtree, -) -from pip._internal.utils.typing import MYPY_CHECK_RUNNING - -if MYPY_CHECK_RUNNING: - from typing import ( - Any, Dict, Iterable, List, Mapping, Optional, Text, Tuple, Type - ) - from pip._internal.utils.ui import SpinnerInterface - - AuthInfo = Tuple[Optional[str], Optional[str]] - -__all__ = ['vcs'] - - -logger = logging.getLogger(__name__) - - -def make_vcs_requirement_url(repo_url, rev, project_name, subdir=None): - """ - Return the URL for a VCS requirement. - - Args: - repo_url: the remote VCS url, with any needed VCS prefix (e.g. "git+"). - project_name: the (unescaped) project name. - """ - egg_project_name = pkg_resources.to_filename(project_name) - req = '{}@{}#egg={}'.format(repo_url, rev, egg_project_name) - if subdir: - req += '&subdirectory={}'.format(subdir) - - return req - - -class RemoteNotFoundError(Exception): - pass - - -class RevOptions(object): - - """ - Encapsulates a VCS-specific revision to install, along with any VCS - install options. - - Instances of this class should be treated as if immutable. - """ - - def __init__( - self, - vc_class, # type: Type[VersionControl] - rev=None, # type: Optional[str] - extra_args=None, # type: Optional[List[str]] - ): - # type: (...) -> None - """ - Args: - vc_class: a VersionControl subclass. - rev: the name of the revision to install. - extra_args: a list of extra options. - """ - if extra_args is None: - extra_args = [] - - self.extra_args = extra_args - self.rev = rev - self.vc_class = vc_class - - def __repr__(self): - return '<RevOptions {}: rev={!r}>'.format(self.vc_class.name, self.rev) - - @property - def arg_rev(self): - # type: () -> Optional[str] - if self.rev is None: - return self.vc_class.default_arg_rev - - return self.rev - - def to_args(self): - # type: () -> List[str] - """ - Return the VCS-specific command arguments. - """ - args = [] # type: List[str] - rev = self.arg_rev - if rev is not None: - args += self.vc_class.get_base_rev_args(rev) - args += self.extra_args - - return args - - def to_display(self): - # type: () -> str - if not self.rev: - return '' - - return ' (to revision {})'.format(self.rev) - - def make_new(self, rev): - # type: (str) -> RevOptions - """ - Make a copy of the current instance, but with a new rev. - - Args: - rev: the name of the revision for the new object. - """ - return self.vc_class.make_rev_options(rev, extra_args=self.extra_args) - - -class VcsSupport(object): - _registry = {} # type: Dict[str, Type[VersionControl]] - schemes = ['ssh', 'git', 'hg', 'bzr', 'sftp', 'svn'] - - def __init__(self): - # type: () -> None - # Register more schemes with urlparse for various version control - # systems - urllib_parse.uses_netloc.extend(self.schemes) - # Python >= 2.7.4, 3.3 doesn't have uses_fragment - if getattr(urllib_parse, 'uses_fragment', None): - urllib_parse.uses_fragment.extend(self.schemes) - super(VcsSupport, self).__init__() - - def __iter__(self): - return self._registry.__iter__() - - @property - def backends(self): - # type: () -> List[Type[VersionControl]] - return list(self._registry.values()) - - @property - def dirnames(self): - # type: () -> List[str] - return [backend.dirname for backend in self.backends] - - @property - def all_schemes(self): - # type: () -> List[str] - schemes = [] # type: List[str] - for backend in self.backends: - schemes.extend(backend.schemes) - return schemes - - def register(self, cls): - # type: (Type[VersionControl]) -> None - if not hasattr(cls, 'name'): - logger.warning('Cannot register VCS %s', cls.__name__) - return - if cls.name not in self._registry: - self._registry[cls.name] = cls - logger.debug('Registered VCS backend: %s', cls.name) - - def unregister(self, cls=None, name=None): - # type: (Optional[Type[VersionControl]], Optional[str]) -> None - if name in self._registry: - del self._registry[name] - elif cls in self._registry.values(): - del self._registry[cls.name] - else: - logger.warning('Cannot unregister because no class or name given') - - def get_backend_type(self, location): - # type: (str) -> Optional[Type[VersionControl]] - """ - Return the type of the version control backend if found at given - location, e.g. vcs.get_backend_type('/path/to/vcs/checkout') - """ - for vc_type in self._registry.values(): - if vc_type.controls_location(location): - logger.debug('Determine that %s uses VCS: %s', - location, vc_type.name) - return vc_type - return None - - def get_backend(self, name): - # type: (str) -> Optional[Type[VersionControl]] - name = name.lower() - if name in self._registry: - return self._registry[name] - return None - - -vcs = VcsSupport() - - -class VersionControl(object): - name = '' - dirname = '' - repo_name = '' - # List of supported schemes for this Version Control - schemes = () # type: Tuple[str, ...] - # Iterable of environment variable names to pass to call_subprocess(). - unset_environ = () # type: Tuple[str, ...] - default_arg_rev = None # type: Optional[str] - - @classmethod - def should_add_vcs_url_prefix(cls, remote_url): - """ - Return whether the vcs prefix (e.g. "git+") should be added to a - repository's remote url when used in a requirement. - """ - return not remote_url.lower().startswith('{}:'.format(cls.name)) - - @classmethod - def get_subdirectory(cls, repo_dir): - """ - Return the path to setup.py, relative to the repo root. - """ - return None - - @classmethod - def get_requirement_revision(cls, repo_dir): - """ - Return the revision string that should be used in a requirement. - """ - return cls.get_revision(repo_dir) - - @classmethod - def get_src_requirement(cls, repo_dir, project_name): - """ - Return the requirement string to use to redownload the files - currently at the given repository directory. - - Args: - project_name: the (unescaped) project name. - - The return value has a form similar to the following: - - {repository_url}@{revision}#egg={project_name} - """ - repo_url = cls.get_remote_url(repo_dir) - if repo_url is None: - return None - - if cls.should_add_vcs_url_prefix(repo_url): - repo_url = '{}+{}'.format(cls.name, repo_url) - - revision = cls.get_requirement_revision(repo_dir) - subdir = cls.get_subdirectory(repo_dir) - req = make_vcs_requirement_url(repo_url, revision, project_name, - subdir=subdir) - - return req - - def __init__(self, url=None, *args, **kwargs): - self.url = url - super(VersionControl, self).__init__(*args, **kwargs) - - @staticmethod - def get_base_rev_args(rev): - """ - Return the base revision arguments for a vcs command. - - Args: - rev: the name of a revision to install. Cannot be None. - """ - raise NotImplementedError - - @classmethod - def make_rev_options(cls, rev=None, extra_args=None): - # type: (Optional[str], Optional[List[str]]) -> RevOptions - """ - Return a RevOptions object. - - Args: - rev: the name of a revision to install. - extra_args: a list of extra options. - """ - return RevOptions(cls, rev, extra_args=extra_args) - - @classmethod - def _is_local_repository(cls, repo): - # type: (str) -> bool - """ - posix absolute paths start with os.path.sep, - win32 ones start with drive (like c:\\folder) - """ - drive, tail = os.path.splitdrive(repo) - return repo.startswith(os.path.sep) or bool(drive) - - def export(self, location): - """ - Export the repository at the url to the destination location - i.e. only download the files, without vcs informations - """ - raise NotImplementedError - - @classmethod - def get_netloc_and_auth(cls, netloc, scheme): - """ - Parse the repository URL's netloc, and return the new netloc to use - along with auth information. - - Args: - netloc: the original repository URL netloc. - scheme: the repository URL's scheme without the vcs prefix. - - This is mainly for the Subversion class to override, so that auth - information can be provided via the --username and --password options - instead of through the URL. For other subclasses like Git without - such an option, auth information must stay in the URL. - - Returns: (netloc, (username, password)). - """ - return netloc, (None, None) - - @classmethod - def get_url_rev_and_auth(cls, url): - # type: (str) -> Tuple[str, Optional[str], AuthInfo] - """ - Parse the repository URL to use, and return the URL, revision, - and auth info to use. - - Returns: (url, rev, (username, password)). - """ - scheme, netloc, path, query, frag = urllib_parse.urlsplit(url) - if '+' not in scheme: - raise ValueError( - "Sorry, {!r} is a malformed VCS url. " - "The format is <vcs>+<protocol>://<url>, " - "e.g. svn+http://myrepo/svn/MyApp#egg=MyApp".format(url) - ) - # Remove the vcs prefix. - scheme = scheme.split('+', 1)[1] - netloc, user_pass = cls.get_netloc_and_auth(netloc, scheme) - rev = None - if '@' in path: - path, rev = path.rsplit('@', 1) - url = urllib_parse.urlunsplit((scheme, netloc, path, query, '')) - return url, rev, user_pass - - @staticmethod - def make_rev_args(username, password): - """ - Return the RevOptions "extra arguments" to use in obtain(). - """ - return [] - - def get_url_rev_options(self, url): - # type: (str) -> Tuple[str, RevOptions] - """ - Return the URL and RevOptions object to use in obtain() and in - some cases export(), as a tuple (url, rev_options). - """ - url, rev, user_pass = self.get_url_rev_and_auth(url) - username, password = user_pass - extra_args = self.make_rev_args(username, password) - rev_options = self.make_rev_options(rev, extra_args=extra_args) - - return url, rev_options - - @staticmethod - def normalize_url(url): - # type: (str) -> str - """ - Normalize a URL for comparison by unquoting it and removing any - trailing slash. - """ - return urllib_parse.unquote(url).rstrip('/') - - @classmethod - def compare_urls(cls, url1, url2): - # type: (str, str) -> bool - """ - Compare two repo URLs for identity, ignoring incidental differences. - """ - return (cls.normalize_url(url1) == cls.normalize_url(url2)) - - @classmethod - def fetch_new(cls, dest, url, rev_options): - """ - Fetch a revision from a repository, in the case that this is the - first fetch from the repository. - - Args: - dest: the directory to fetch the repository to. - rev_options: a RevOptions object. - """ - raise NotImplementedError - - def switch(self, dest, url, rev_options): - """ - Switch the repo at ``dest`` to point to ``URL``. - - Args: - rev_options: a RevOptions object. - """ - raise NotImplementedError - - def update(self, dest, url, rev_options): - """ - Update an already-existing repo to the given ``rev_options``. - - Args: - rev_options: a RevOptions object. - """ - raise NotImplementedError - - @classmethod - def is_commit_id_equal(cls, dest, name): - """ - Return whether the id of the current commit equals the given name. - - Args: - dest: the repository directory. - name: a string name. - """ - raise NotImplementedError - - def obtain(self, dest): - # type: (str) -> None - """ - Install or update in editable mode the package represented by this - VersionControl object. - - Args: - dest: the repository directory in which to install or update. - """ - url, rev_options = self.get_url_rev_options(self.url) - - if not os.path.exists(dest): - self.fetch_new(dest, url, rev_options) - return - - rev_display = rev_options.to_display() - if self.is_repository_directory(dest): - existing_url = self.get_remote_url(dest) - if self.compare_urls(existing_url, url): - logger.debug( - '%s in %s exists, and has correct URL (%s)', - self.repo_name.title(), - display_path(dest), - url, - ) - if not self.is_commit_id_equal(dest, rev_options.rev): - logger.info( - 'Updating %s %s%s', - display_path(dest), - self.repo_name, - rev_display, - ) - self.update(dest, url, rev_options) - else: - logger.info('Skipping because already up-to-date.') - return - - logger.warning( - '%s %s in %s exists with URL %s', - self.name, - self.repo_name, - display_path(dest), - existing_url, - ) - prompt = ('(s)witch, (i)gnore, (w)ipe, (b)ackup ', - ('s', 'i', 'w', 'b')) - else: - logger.warning( - 'Directory %s already exists, and is not a %s %s.', - dest, - self.name, - self.repo_name, - ) - # https://github.com/python/mypy/issues/1174 - prompt = ('(i)gnore, (w)ipe, (b)ackup ', # type: ignore - ('i', 'w', 'b')) - - logger.warning( - 'The plan is to install the %s repository %s', - self.name, - url, - ) - response = ask_path_exists('What to do? %s' % prompt[0], prompt[1]) - - if response == 'a': - sys.exit(-1) - - if response == 'w': - logger.warning('Deleting %s', display_path(dest)) - rmtree(dest) - self.fetch_new(dest, url, rev_options) - return - - if response == 'b': - dest_dir = backup_dir(dest) - logger.warning( - 'Backing up %s to %s', display_path(dest), dest_dir, - ) - shutil.move(dest, dest_dir) - self.fetch_new(dest, url, rev_options) - return - - # Do nothing if the response is "i". - if response == 's': - logger.info( - 'Switching %s %s to %s%s', - self.repo_name, - display_path(dest), - url, - rev_display, - ) - self.switch(dest, url, rev_options) - - def unpack(self, location): - # type: (str) -> None - """ - Clean up current location and download the url repository - (and vcs infos) into location - """ - if os.path.exists(location): - rmtree(location) - self.obtain(location) - - @classmethod - def get_remote_url(cls, location): - """ - Return the url used at location - - Raises RemoteNotFoundError if the repository does not have a remote - url configured. - """ - raise NotImplementedError - - @classmethod - def get_revision(cls, location): - """ - Return the current commit id of the files at the given location. - """ - raise NotImplementedError - - @classmethod - def run_command( - cls, - cmd, # type: List[str] - show_stdout=True, # type: bool - cwd=None, # type: Optional[str] - on_returncode='raise', # type: str - extra_ok_returncodes=None, # type: Optional[Iterable[int]] - command_desc=None, # type: Optional[str] - extra_environ=None, # type: Optional[Mapping[str, Any]] - spinner=None # type: Optional[SpinnerInterface] - ): - # type: (...) -> Optional[Text] - """ - Run a VCS subcommand - This is simply a wrapper around call_subprocess that adds the VCS - command name, and checks that the VCS is available - """ - cmd = [cls.name] + cmd - try: - return call_subprocess(cmd, show_stdout, cwd, - on_returncode=on_returncode, - extra_ok_returncodes=extra_ok_returncodes, - command_desc=command_desc, - extra_environ=extra_environ, - unset_environ=cls.unset_environ, - spinner=spinner) - except OSError as e: - # errno.ENOENT = no such file or directory - # In other words, the VCS executable isn't available - if e.errno == errno.ENOENT: - raise BadCommand( - 'Cannot find command %r - do you have ' - '%r installed and in your ' - 'PATH?' % (cls.name, cls.name)) - else: - raise # re-raise exception if a different error occurred - - @classmethod - def is_repository_directory(cls, path): - # type: (str) -> bool - """ - Return whether a directory path is a repository directory. - """ - logger.debug('Checking in %s for %s (%s)...', - path, cls.dirname, cls.name) - return os.path.exists(os.path.join(path, cls.dirname)) - - @classmethod - def controls_location(cls, location): - # type: (str) -> bool - """ - Check if a location is controlled by the vcs. - It is meant to be overridden to implement smarter detection - mechanisms for specific vcs. - - This can do more than is_repository_directory() alone. For example, - the Git override checks that Git is actually available. - """ - return cls.is_repository_directory(location) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/vcs/bazaar.py b/venv2/lib/python2.7/site-packages/pip/_internal/vcs/bazaar.py deleted file mode 100644 index 3587b3d..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/vcs/bazaar.py +++ /dev/null @@ -1,103 +0,0 @@ -from __future__ import absolute_import - -import logging -import os - -from pip._vendor.six.moves.urllib import parse as urllib_parse - -from pip._internal.download import path_to_url -from pip._internal.utils.misc import display_path, rmtree -from pip._internal.vcs import VersionControl, vcs - -logger = logging.getLogger(__name__) - - -class Bazaar(VersionControl): - name = 'bzr' - dirname = '.bzr' - repo_name = 'branch' - schemes = ( - 'bzr', 'bzr+http', 'bzr+https', 'bzr+ssh', 'bzr+sftp', 'bzr+ftp', - 'bzr+lp', - ) - - def __init__(self, url=None, *args, **kwargs): - super(Bazaar, self).__init__(url, *args, **kwargs) - # This is only needed for python <2.7.5 - # Register lp but do not expose as a scheme to support bzr+lp. - if getattr(urllib_parse, 'uses_fragment', None): - urllib_parse.uses_fragment.extend(['lp']) - - @staticmethod - def get_base_rev_args(rev): - return ['-r', rev] - - def export(self, location): - """ - Export the Bazaar repository at the url to the destination location - """ - # Remove the location to make sure Bazaar can export it correctly - if os.path.exists(location): - rmtree(location) - - url, rev_options = self.get_url_rev_options(self.url) - self.run_command( - ['export', location, url] + rev_options.to_args(), - show_stdout=False, - ) - - @classmethod - def fetch_new(cls, dest, url, rev_options): - rev_display = rev_options.to_display() - logger.info( - 'Checking out %s%s to %s', - url, - rev_display, - display_path(dest), - ) - cmd_args = ['branch', '-q'] + rev_options.to_args() + [url, dest] - cls.run_command(cmd_args) - - def switch(self, dest, url, rev_options): - self.run_command(['switch', url], cwd=dest) - - def update(self, dest, url, rev_options): - cmd_args = ['pull', '-q'] + rev_options.to_args() - self.run_command(cmd_args, cwd=dest) - - @classmethod - def get_url_rev_and_auth(cls, url): - # hotfix the URL scheme after removing bzr+ from bzr+ssh:// readd it - url, rev, user_pass = super(Bazaar, cls).get_url_rev_and_auth(url) - if url.startswith('ssh://'): - url = 'bzr+' + url - return url, rev, user_pass - - @classmethod - def get_remote_url(cls, location): - urls = cls.run_command(['info'], show_stdout=False, cwd=location) - for line in urls.splitlines(): - line = line.strip() - for x in ('checkout of branch: ', - 'parent branch: '): - if line.startswith(x): - repo = line.split(x)[1] - if cls._is_local_repository(repo): - return path_to_url(repo) - return repo - return None - - @classmethod - def get_revision(cls, location): - revision = cls.run_command( - ['revno'], show_stdout=False, cwd=location, - ) - return revision.splitlines()[-1] - - @classmethod - def is_commit_id_equal(cls, dest, name): - """Always assume the versions don't match""" - return False - - -vcs.register(Bazaar) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/vcs/git.py b/venv2/lib/python2.7/site-packages/pip/_internal/vcs/git.py deleted file mode 100644 index 35ea930..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/vcs/git.py +++ /dev/null @@ -1,362 +0,0 @@ -from __future__ import absolute_import - -import logging -import os.path -import re - -from pip._vendor.packaging.version import parse as parse_version -from pip._vendor.six.moves.urllib import parse as urllib_parse -from pip._vendor.six.moves.urllib import request as urllib_request - -from pip._internal.exceptions import BadCommand -from pip._internal.utils.compat import samefile -from pip._internal.utils.misc import display_path, redact_password_from_url -from pip._internal.utils.temp_dir import TempDirectory -from pip._internal.vcs import RemoteNotFoundError, VersionControl, vcs - -urlsplit = urllib_parse.urlsplit -urlunsplit = urllib_parse.urlunsplit - - -logger = logging.getLogger(__name__) - - -HASH_REGEX = re.compile('[a-fA-F0-9]{40}') - - -def looks_like_hash(sha): - return bool(HASH_REGEX.match(sha)) - - -class Git(VersionControl): - name = 'git' - dirname = '.git' - repo_name = 'clone' - schemes = ( - 'git', 'git+http', 'git+https', 'git+ssh', 'git+git', 'git+file', - ) - # Prevent the user's environment variables from interfering with pip: - # https://github.com/pypa/pip/issues/1130 - unset_environ = ('GIT_DIR', 'GIT_WORK_TREE') - default_arg_rev = 'HEAD' - - def __init__(self, url=None, *args, **kwargs): - - # Works around an apparent Git bug - # (see https://article.gmane.org/gmane.comp.version-control.git/146500) - if url: - scheme, netloc, path, query, fragment = urlsplit(url) - if scheme.endswith('file'): - initial_slashes = path[:-len(path.lstrip('/'))] - newpath = ( - initial_slashes + - urllib_request.url2pathname(path) - .replace('\\', '/').lstrip('/') - ) - url = urlunsplit((scheme, netloc, newpath, query, fragment)) - after_plus = scheme.find('+') + 1 - url = scheme[:after_plus] + urlunsplit( - (scheme[after_plus:], netloc, newpath, query, fragment), - ) - - super(Git, self).__init__(url, *args, **kwargs) - - @staticmethod - def get_base_rev_args(rev): - return [rev] - - def get_git_version(self): - VERSION_PFX = 'git version ' - version = self.run_command(['version'], show_stdout=False) - if version.startswith(VERSION_PFX): - version = version[len(VERSION_PFX):].split()[0] - else: - version = '' - # get first 3 positions of the git version because - # on windows it is x.y.z.windows.t, and this parses as - # LegacyVersion which always smaller than a Version. - version = '.'.join(version.split('.')[:3]) - return parse_version(version) - - @classmethod - def get_current_branch(cls, location): - """ - Return the current branch, or None if HEAD isn't at a branch - (e.g. detached HEAD). - """ - # git-symbolic-ref exits with empty stdout if "HEAD" is a detached - # HEAD rather than a symbolic ref. In addition, the -q causes the - # command to exit with status code 1 instead of 128 in this case - # and to suppress the message to stderr. - args = ['symbolic-ref', '-q', 'HEAD'] - output = cls.run_command( - args, extra_ok_returncodes=(1, ), show_stdout=False, cwd=location, - ) - ref = output.strip() - - if ref.startswith('refs/heads/'): - return ref[len('refs/heads/'):] - - return None - - def export(self, location): - """Export the Git repository at the url to the destination location""" - if not location.endswith('/'): - location = location + '/' - - with TempDirectory(kind="export") as temp_dir: - self.unpack(temp_dir.path) - self.run_command( - ['checkout-index', '-a', '-f', '--prefix', location], - show_stdout=False, cwd=temp_dir.path - ) - - @classmethod - def get_revision_sha(cls, dest, rev): - """ - Return (sha_or_none, is_branch), where sha_or_none is a commit hash - if the revision names a remote branch or tag, otherwise None. - - Args: - dest: the repository directory. - rev: the revision name. - """ - # Pass rev to pre-filter the list. - output = cls.run_command(['show-ref', rev], cwd=dest, - show_stdout=False, on_returncode='ignore') - refs = {} - for line in output.strip().splitlines(): - try: - sha, ref = line.split() - except ValueError: - # Include the offending line to simplify troubleshooting if - # this error ever occurs. - raise ValueError('unexpected show-ref line: {!r}'.format(line)) - - refs[ref] = sha - - branch_ref = 'refs/remotes/origin/{}'.format(rev) - tag_ref = 'refs/tags/{}'.format(rev) - - sha = refs.get(branch_ref) - if sha is not None: - return (sha, True) - - sha = refs.get(tag_ref) - - return (sha, False) - - @classmethod - def resolve_revision(cls, dest, url, rev_options): - """ - Resolve a revision to a new RevOptions object with the SHA1 of the - branch, tag, or ref if found. - - Args: - rev_options: a RevOptions object. - """ - rev = rev_options.arg_rev - sha, is_branch = cls.get_revision_sha(dest, rev) - - if sha is not None: - rev_options = rev_options.make_new(sha) - rev_options.branch_name = rev if is_branch else None - - return rev_options - - # Do not show a warning for the common case of something that has - # the form of a Git commit hash. - if not looks_like_hash(rev): - logger.warning( - "Did not find branch or tag '%s', assuming revision or ref.", - rev, - ) - - if not rev.startswith('refs/'): - return rev_options - - # If it looks like a ref, we have to fetch it explicitly. - cls.run_command( - ['fetch', '-q', url] + rev_options.to_args(), - cwd=dest, - ) - # Change the revision to the SHA of the ref we fetched - sha = cls.get_revision(dest, rev='FETCH_HEAD') - rev_options = rev_options.make_new(sha) - - return rev_options - - @classmethod - def is_commit_id_equal(cls, dest, name): - """ - Return whether the current commit hash equals the given name. - - Args: - dest: the repository directory. - name: a string name. - """ - if not name: - # Then avoid an unnecessary subprocess call. - return False - - return cls.get_revision(dest) == name - - @classmethod - def fetch_new(cls, dest, url, rev_options): - rev_display = rev_options.to_display() - logger.info( - 'Cloning %s%s to %s', redact_password_from_url(url), - rev_display, display_path(dest), - ) - cls.run_command(['clone', '-q', url, dest]) - - if rev_options.rev: - # Then a specific revision was requested. - rev_options = cls.resolve_revision(dest, url, rev_options) - branch_name = getattr(rev_options, 'branch_name', None) - if branch_name is None: - # Only do a checkout if the current commit id doesn't match - # the requested revision. - if not cls.is_commit_id_equal(dest, rev_options.rev): - cmd_args = ['checkout', '-q'] + rev_options.to_args() - cls.run_command(cmd_args, cwd=dest) - elif cls.get_current_branch(dest) != branch_name: - # Then a specific branch was requested, and that branch - # is not yet checked out. - track_branch = 'origin/{}'.format(branch_name) - cmd_args = [ - 'checkout', '-b', branch_name, '--track', track_branch, - ] - cls.run_command(cmd_args, cwd=dest) - - #: repo may contain submodules - cls.update_submodules(dest) - - def switch(self, dest, url, rev_options): - self.run_command(['config', 'remote.origin.url', url], cwd=dest) - cmd_args = ['checkout', '-q'] + rev_options.to_args() - self.run_command(cmd_args, cwd=dest) - - self.update_submodules(dest) - - def update(self, dest, url, rev_options): - # First fetch changes from the default remote - if self.get_git_version() >= parse_version('1.9.0'): - # fetch tags in addition to everything else - self.run_command(['fetch', '-q', '--tags'], cwd=dest) - else: - self.run_command(['fetch', '-q'], cwd=dest) - # Then reset to wanted revision (maybe even origin/master) - rev_options = self.resolve_revision(dest, url, rev_options) - cmd_args = ['reset', '--hard', '-q'] + rev_options.to_args() - self.run_command(cmd_args, cwd=dest) - #: update submodules - self.update_submodules(dest) - - @classmethod - def get_remote_url(cls, location): - """ - Return URL of the first remote encountered. - - Raises RemoteNotFoundError if the repository does not have a remote - url configured. - """ - # We need to pass 1 for extra_ok_returncodes since the command - # exits with return code 1 if there are no matching lines. - stdout = cls.run_command( - ['config', '--get-regexp', r'remote\..*\.url'], - extra_ok_returncodes=(1, ), show_stdout=False, cwd=location, - ) - remotes = stdout.splitlines() - try: - found_remote = remotes[0] - except IndexError: - raise RemoteNotFoundError - - for remote in remotes: - if remote.startswith('remote.origin.url '): - found_remote = remote - break - url = found_remote.split(' ')[1] - return url.strip() - - @classmethod - def get_revision(cls, location, rev=None): - if rev is None: - rev = 'HEAD' - current_rev = cls.run_command( - ['rev-parse', rev], show_stdout=False, cwd=location, - ) - return current_rev.strip() - - @classmethod - def get_subdirectory(cls, location): - # find the repo root - git_dir = cls.run_command(['rev-parse', '--git-dir'], - show_stdout=False, cwd=location).strip() - if not os.path.isabs(git_dir): - git_dir = os.path.join(location, git_dir) - root_dir = os.path.join(git_dir, '..') - # find setup.py - orig_location = location - while not os.path.exists(os.path.join(location, 'setup.py')): - last_location = location - location = os.path.dirname(location) - if location == last_location: - # We've traversed up to the root of the filesystem without - # finding setup.py - logger.warning( - "Could not find setup.py for directory %s (tried all " - "parent directories)", - orig_location, - ) - return None - # relative path of setup.py to repo root - if samefile(root_dir, location): - return None - return os.path.relpath(location, root_dir) - - @classmethod - def get_url_rev_and_auth(cls, url): - """ - Prefixes stub URLs like 'user@hostname:user/repo.git' with 'ssh://'. - That's required because although they use SSH they sometimes don't - work with a ssh:// scheme (e.g. GitHub). But we need a scheme for - parsing. Hence we remove it again afterwards and return it as a stub. - """ - if '://' not in url: - assert 'file:' not in url - url = url.replace('git+', 'git+ssh://') - url, rev, user_pass = super(Git, cls).get_url_rev_and_auth(url) - url = url.replace('ssh://', '') - else: - url, rev, user_pass = super(Git, cls).get_url_rev_and_auth(url) - - return url, rev, user_pass - - @classmethod - def update_submodules(cls, location): - if not os.path.exists(os.path.join(location, '.gitmodules')): - return - cls.run_command( - ['submodule', 'update', '--init', '--recursive', '-q'], - cwd=location, - ) - - @classmethod - def controls_location(cls, location): - if super(Git, cls).controls_location(location): - return True - try: - r = cls.run_command(['rev-parse'], - cwd=location, - show_stdout=False, - on_returncode='ignore') - return not r - except BadCommand: - logger.debug("could not determine if %s is under git control " - "because git is not available", location) - return False - - -vcs.register(Git) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/vcs/mercurial.py b/venv2/lib/python2.7/site-packages/pip/_internal/vcs/mercurial.py deleted file mode 100644 index 81edc4a..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/vcs/mercurial.py +++ /dev/null @@ -1,105 +0,0 @@ -from __future__ import absolute_import - -import logging -import os - -from pip._vendor.six.moves import configparser - -from pip._internal.download import path_to_url -from pip._internal.utils.misc import display_path -from pip._internal.utils.temp_dir import TempDirectory -from pip._internal.vcs import VersionControl, vcs - -logger = logging.getLogger(__name__) - - -class Mercurial(VersionControl): - name = 'hg' - dirname = '.hg' - repo_name = 'clone' - schemes = ('hg', 'hg+http', 'hg+https', 'hg+ssh', 'hg+static-http') - - @staticmethod - def get_base_rev_args(rev): - return [rev] - - def export(self, location): - """Export the Hg repository at the url to the destination location""" - with TempDirectory(kind="export") as temp_dir: - self.unpack(temp_dir.path) - - self.run_command( - ['archive', location], show_stdout=False, cwd=temp_dir.path - ) - - @classmethod - def fetch_new(cls, dest, url, rev_options): - rev_display = rev_options.to_display() - logger.info( - 'Cloning hg %s%s to %s', - url, - rev_display, - display_path(dest), - ) - cls.run_command(['clone', '--noupdate', '-q', url, dest]) - cmd_args = ['update', '-q'] + rev_options.to_args() - cls.run_command(cmd_args, cwd=dest) - - def switch(self, dest, url, rev_options): - repo_config = os.path.join(dest, self.dirname, 'hgrc') - config = configparser.SafeConfigParser() - try: - config.read(repo_config) - config.set('paths', 'default', url) - with open(repo_config, 'w') as config_file: - config.write(config_file) - except (OSError, configparser.NoSectionError) as exc: - logger.warning( - 'Could not switch Mercurial repository to %s: %s', url, exc, - ) - else: - cmd_args = ['update', '-q'] + rev_options.to_args() - self.run_command(cmd_args, cwd=dest) - - def update(self, dest, url, rev_options): - self.run_command(['pull', '-q'], cwd=dest) - cmd_args = ['update', '-q'] + rev_options.to_args() - self.run_command(cmd_args, cwd=dest) - - @classmethod - def get_remote_url(cls, location): - url = cls.run_command( - ['showconfig', 'paths.default'], - show_stdout=False, cwd=location).strip() - if cls._is_local_repository(url): - url = path_to_url(url) - return url.strip() - - @classmethod - def get_revision(cls, location): - """ - Return the repository-local changeset revision number, as an integer. - """ - current_revision = cls.run_command( - ['parents', '--template={rev}'], - show_stdout=False, cwd=location).strip() - return current_revision - - @classmethod - def get_requirement_revision(cls, location): - """ - Return the changeset identification hash, as a 40-character - hexadecimal string - """ - current_rev_hash = cls.run_command( - ['parents', '--template={node}'], - show_stdout=False, cwd=location).strip() - return current_rev_hash - - @classmethod - def is_commit_id_equal(cls, dest, name): - """Always assume the versions don't match""" - return False - - -vcs.register(Mercurial) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/vcs/subversion.py b/venv2/lib/python2.7/site-packages/pip/_internal/vcs/subversion.py deleted file mode 100644 index 01bb161..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/vcs/subversion.py +++ /dev/null @@ -1,234 +0,0 @@ -from __future__ import absolute_import - -import logging -import os -import re - -from pip._internal.utils.logging import indent_log -from pip._internal.utils.misc import ( - display_path, rmtree, split_auth_from_netloc, -) -from pip._internal.utils.typing import MYPY_CHECK_RUNNING -from pip._internal.vcs import VersionControl, vcs - -_svn_xml_url_re = re.compile('url="([^"]+)"') -_svn_rev_re = re.compile(r'committed-rev="(\d+)"') -_svn_info_xml_rev_re = re.compile(r'\s*revision="(\d+)"') -_svn_info_xml_url_re = re.compile(r'<url>(.*)</url>') - - -if MYPY_CHECK_RUNNING: - from typing import Optional, Tuple - -logger = logging.getLogger(__name__) - - -class Subversion(VersionControl): - name = 'svn' - dirname = '.svn' - repo_name = 'checkout' - schemes = ('svn', 'svn+ssh', 'svn+http', 'svn+https', 'svn+svn') - - @classmethod - def should_add_vcs_url_prefix(cls, remote_url): - return True - - @staticmethod - def get_base_rev_args(rev): - return ['-r', rev] - - def get_vcs_version(self): - # type: () -> Optional[Tuple[int, ...]] - """Return the version of the currently installed Subversion client. - - :return: A tuple containing the parts of the version information or - ``None`` if the version returned from ``svn`` could not be parsed. - :raises: BadCommand: If ``svn`` is not installed. - """ - # Example versions: - # svn, version 1.10.3 (r1842928) - # compiled Feb 25 2019, 14:20:39 on x86_64-apple-darwin17.0.0 - # svn, version 1.7.14 (r1542130) - # compiled Mar 28 2018, 08:49:13 on x86_64-pc-linux-gnu - version_prefix = 'svn, version ' - version = self.run_command(['--version'], show_stdout=False) - if not version.startswith(version_prefix): - return None - - version = version[len(version_prefix):].split()[0] - version_list = version.split('.') - try: - parsed_version = tuple(map(int, version_list)) - except ValueError: - return None - - if not parsed_version: - return None - - return parsed_version - - def export(self, location): - """Export the svn repository at the url to the destination location""" - url, rev_options = self.get_url_rev_options(self.url) - - logger.info('Exporting svn repository %s to %s', url, location) - with indent_log(): - if os.path.exists(location): - # Subversion doesn't like to check out over an existing - # directory --force fixes this, but was only added in svn 1.5 - rmtree(location) - cmd_args = ['export'] + rev_options.to_args() + [url, location] - self.run_command(cmd_args, show_stdout=False) - - @classmethod - def fetch_new(cls, dest, url, rev_options): - rev_display = rev_options.to_display() - logger.info( - 'Checking out %s%s to %s', - url, - rev_display, - display_path(dest), - ) - cmd_args = ['checkout', '-q'] + rev_options.to_args() + [url, dest] - cls.run_command(cmd_args) - - def switch(self, dest, url, rev_options): - cmd_args = ['switch'] + rev_options.to_args() + [url, dest] - self.run_command(cmd_args) - - def update(self, dest, url, rev_options): - cmd_args = ['update'] + rev_options.to_args() + [dest] - self.run_command(cmd_args) - - @classmethod - def get_revision(cls, location): - """ - Return the maximum revision for all files under a given location - """ - # Note: taken from setuptools.command.egg_info - revision = 0 - - for base, dirs, files in os.walk(location): - if cls.dirname not in dirs: - dirs[:] = [] - continue # no sense walking uncontrolled subdirs - dirs.remove(cls.dirname) - entries_fn = os.path.join(base, cls.dirname, 'entries') - if not os.path.exists(entries_fn): - # FIXME: should we warn? - continue - - dirurl, localrev = cls._get_svn_url_rev(base) - - if base == location: - base = dirurl + '/' # save the root url - elif not dirurl or not dirurl.startswith(base): - dirs[:] = [] - continue # not part of the same svn tree, skip it - revision = max(revision, localrev) - return revision - - @classmethod - def get_netloc_and_auth(cls, netloc, scheme): - """ - This override allows the auth information to be passed to svn via the - --username and --password options instead of via the URL. - """ - if scheme == 'ssh': - # The --username and --password options can't be used for - # svn+ssh URLs, so keep the auth information in the URL. - return super(Subversion, cls).get_netloc_and_auth(netloc, scheme) - - return split_auth_from_netloc(netloc) - - @classmethod - def get_url_rev_and_auth(cls, url): - # hotfix the URL scheme after removing svn+ from svn+ssh:// readd it - url, rev, user_pass = super(Subversion, cls).get_url_rev_and_auth(url) - if url.startswith('ssh://'): - url = 'svn+' + url - return url, rev, user_pass - - @staticmethod - def make_rev_args(username, password): - extra_args = [] - if username: - extra_args += ['--username', username] - if password: - extra_args += ['--password', password] - - return extra_args - - @classmethod - def get_remote_url(cls, location): - # In cases where the source is in a subdirectory, not alongside - # setup.py we have to look up in the location until we find a real - # setup.py - orig_location = location - while not os.path.exists(os.path.join(location, 'setup.py')): - last_location = location - location = os.path.dirname(location) - if location == last_location: - # We've traversed up to the root of the filesystem without - # finding setup.py - logger.warning( - "Could not find setup.py for directory %s (tried all " - "parent directories)", - orig_location, - ) - return None - - return cls._get_svn_url_rev(location)[0] - - @classmethod - def _get_svn_url_rev(cls, location): - from pip._internal.exceptions import InstallationError - - entries_path = os.path.join(location, cls.dirname, 'entries') - if os.path.exists(entries_path): - with open(entries_path) as f: - data = f.read() - else: # subversion >= 1.7 does not have the 'entries' file - data = '' - - if (data.startswith('8') or - data.startswith('9') or - data.startswith('10')): - data = list(map(str.splitlines, data.split('\n\x0c\n'))) - del data[0][0] # get rid of the '8' - url = data[0][3] - revs = [int(d[9]) for d in data if len(d) > 9 and d[9]] + [0] - elif data.startswith('<?xml'): - match = _svn_xml_url_re.search(data) - if not match: - raise ValueError('Badly formatted data: %r' % data) - url = match.group(1) # get repository URL - revs = [int(m.group(1)) for m in _svn_rev_re.finditer(data)] + [0] - else: - try: - # subversion >= 1.7 - xml = cls.run_command( - ['info', '--xml', location], - show_stdout=False, - ) - url = _svn_info_xml_url_re.search(xml).group(1) - revs = [ - int(m.group(1)) for m in _svn_info_xml_rev_re.finditer(xml) - ] - except InstallationError: - url, revs = None, [] - - if revs: - rev = max(revs) - else: - rev = 0 - - return url, rev - - @classmethod - def is_commit_id_equal(cls, dest, name): - """Always assume the versions don't match""" - return False - - -vcs.register(Subversion) diff --git a/venv2/lib/python2.7/site-packages/pip/_internal/wheel.py b/venv2/lib/python2.7/site-packages/pip/_internal/wheel.py deleted file mode 100644 index 1bdbe93..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_internal/wheel.py +++ /dev/null @@ -1,1098 +0,0 @@ -""" -Support for installing and building the "wheel" binary package format. -""" -from __future__ import absolute_import - -import collections -import compileall -import csv -import hashlib -import logging -import os.path -import re -import shutil -import stat -import sys -import warnings -from base64 import urlsafe_b64encode -from email.parser import Parser - -from pip._vendor import pkg_resources -from pip._vendor.distlib.scripts import ScriptMaker -from pip._vendor.packaging.utils import canonicalize_name -from pip._vendor.six import StringIO - -from pip._internal import pep425tags -from pip._internal.download import path_to_url, unpack_url -from pip._internal.exceptions import ( - InstallationError, InvalidWheelFilename, UnsupportedWheel, -) -from pip._internal.locations import ( - PIP_DELETE_MARKER_FILENAME, distutils_scheme, -) -from pip._internal.models.link import Link -from pip._internal.utils.logging import indent_log -from pip._internal.utils.misc import ( - LOG_DIVIDER, call_subprocess, captured_stdout, ensure_dir, - format_command_args, read_chunks, -) -from pip._internal.utils.setuptools_build import SETUPTOOLS_SHIM -from pip._internal.utils.temp_dir import TempDirectory -from pip._internal.utils.typing import MYPY_CHECK_RUNNING -from pip._internal.utils.ui import open_spinner - -if MYPY_CHECK_RUNNING: - from typing import ( - Dict, List, Optional, Sequence, Mapping, Tuple, IO, Text, Any, Iterable - ) - from pip._vendor.packaging.requirements import Requirement - from pip._internal.req.req_install import InstallRequirement - from pip._internal.download import PipSession - from pip._internal.index import FormatControl, PackageFinder - from pip._internal.operations.prepare import ( - RequirementPreparer - ) - from pip._internal.cache import WheelCache - from pip._internal.pep425tags import Pep425Tag - - InstalledCSVRow = Tuple[str, ...] - - -VERSION_COMPATIBLE = (1, 0) - - -logger = logging.getLogger(__name__) - - -def normpath(src, p): - return os.path.relpath(src, p).replace(os.path.sep, '/') - - -def rehash(path, blocksize=1 << 20): - # type: (str, int) -> Tuple[str, str] - """Return (hash, length) for path using hashlib.sha256()""" - h = hashlib.sha256() - length = 0 - with open(path, 'rb') as f: - for block in read_chunks(f, size=blocksize): - length += len(block) - h.update(block) - digest = 'sha256=' + urlsafe_b64encode( - h.digest() - ).decode('latin1').rstrip('=') - # unicode/str python2 issues - return (digest, str(length)) # type: ignore - - -def open_for_csv(name, mode): - # type: (str, Text) -> IO - if sys.version_info[0] < 3: - nl = {} # type: Dict[str, Any] - bin = 'b' - else: - nl = {'newline': ''} # type: Dict[str, Any] - bin = '' - return open(name, mode + bin, **nl) - - -def replace_python_tag(wheelname, new_tag): - # type: (str, str) -> str - """Replace the Python tag in a wheel file name with a new value. - """ - parts = wheelname.split('-') - parts[-3] = new_tag - return '-'.join(parts) - - -def fix_script(path): - # type: (str) -> Optional[bool] - """Replace #!python with #!/path/to/python - Return True if file was changed.""" - # XXX RECORD hashes will need to be updated - if os.path.isfile(path): - with open(path, 'rb') as script: - firstline = script.readline() - if not firstline.startswith(b'#!python'): - return False - exename = sys.executable.encode(sys.getfilesystemencoding()) - firstline = b'#!' + exename + os.linesep.encode("ascii") - rest = script.read() - with open(path, 'wb') as script: - script.write(firstline) - script.write(rest) - return True - return None - - -dist_info_re = re.compile(r"""^(?P<namever>(?P<name>.+?)(-(?P<ver>.+?))?) - \.dist-info$""", re.VERBOSE) - - -def root_is_purelib(name, wheeldir): - # type: (str, str) -> bool - """ - Return True if the extracted wheel in wheeldir should go into purelib. - """ - name_folded = name.replace("-", "_") - for item in os.listdir(wheeldir): - match = dist_info_re.match(item) - if match and match.group('name') == name_folded: - with open(os.path.join(wheeldir, item, 'WHEEL')) as wheel: - for line in wheel: - line = line.lower().rstrip() - if line == "root-is-purelib: true": - return True - return False - - -def get_entrypoints(filename): - # type: (str) -> Tuple[Dict[str, str], Dict[str, str]] - if not os.path.exists(filename): - return {}, {} - - # This is done because you can pass a string to entry_points wrappers which - # means that they may or may not be valid INI files. The attempt here is to - # strip leading and trailing whitespace in order to make them valid INI - # files. - with open(filename) as fp: - data = StringIO() - for line in fp: - data.write(line.strip()) - data.write("\n") - data.seek(0) - - # get the entry points and then the script names - entry_points = pkg_resources.EntryPoint.parse_map(data) - console = entry_points.get('console_scripts', {}) - gui = entry_points.get('gui_scripts', {}) - - def _split_ep(s): - """get the string representation of EntryPoint, remove space and split - on '='""" - return str(s).replace(" ", "").split("=") - - # convert the EntryPoint objects into strings with module:function - console = dict(_split_ep(v) for v in console.values()) - gui = dict(_split_ep(v) for v in gui.values()) - return console, gui - - -def message_about_scripts_not_on_PATH(scripts): - # type: (Sequence[str]) -> Optional[str] - """Determine if any scripts are not on PATH and format a warning. - - Returns a warning message if one or more scripts are not on PATH, - otherwise None. - """ - if not scripts: - return None - - # Group scripts by the path they were installed in - grouped_by_dir = collections.defaultdict(set) # type: Dict[str, set] - for destfile in scripts: - parent_dir = os.path.dirname(destfile) - script_name = os.path.basename(destfile) - grouped_by_dir[parent_dir].add(script_name) - - # We don't want to warn for directories that are on PATH. - not_warn_dirs = [ - os.path.normcase(i).rstrip(os.sep) for i in - os.environ.get("PATH", "").split(os.pathsep) - ] - # If an executable sits with sys.executable, we don't warn for it. - # This covers the case of venv invocations without activating the venv. - not_warn_dirs.append(os.path.normcase(os.path.dirname(sys.executable))) - warn_for = { - parent_dir: scripts for parent_dir, scripts in grouped_by_dir.items() - if os.path.normcase(parent_dir) not in not_warn_dirs - } - if not warn_for: - return None - - # Format a message - msg_lines = [] - for parent_dir, scripts in warn_for.items(): - sorted_scripts = sorted(scripts) # type: List[str] - if len(sorted_scripts) == 1: - start_text = "script {} is".format(sorted_scripts[0]) - else: - start_text = "scripts {} are".format( - ", ".join(sorted_scripts[:-1]) + " and " + sorted_scripts[-1] - ) - - msg_lines.append( - "The {} installed in '{}' which is not on PATH." - .format(start_text, parent_dir) - ) - - last_line_fmt = ( - "Consider adding {} to PATH or, if you prefer " - "to suppress this warning, use --no-warn-script-location." - ) - if len(msg_lines) == 1: - msg_lines.append(last_line_fmt.format("this directory")) - else: - msg_lines.append(last_line_fmt.format("these directories")) - - # Returns the formatted multiline message - return "\n".join(msg_lines) - - -def sorted_outrows(outrows): - # type: (Iterable[InstalledCSVRow]) -> List[InstalledCSVRow] - """ - Return the given rows of a RECORD file in sorted order. - - Each row is a 3-tuple (path, hash, size) and corresponds to a record of - a RECORD file (see PEP 376 and PEP 427 for details). For the rows - passed to this function, the size can be an integer as an int or string, - or the empty string. - """ - # Normally, there should only be one row per path, in which case the - # second and third elements don't come into play when sorting. - # However, in cases in the wild where a path might happen to occur twice, - # we don't want the sort operation to trigger an error (but still want - # determinism). Since the third element can be an int or string, we - # coerce each element to a string to avoid a TypeError in this case. - # For additional background, see-- - # https://github.com/pypa/pip/issues/5868 - return sorted(outrows, key=lambda row: tuple(str(x) for x in row)) - - -def get_csv_rows_for_installed( - old_csv_rows, # type: Iterable[List[str]] - installed, # type: Dict[str, str] - changed, # type: set - generated, # type: List[str] - lib_dir, # type: str -): - # type: (...) -> List[InstalledCSVRow] - """ - :param installed: A map from archive RECORD path to installation RECORD - path. - """ - installed_rows = [] # type: List[InstalledCSVRow] - for row in old_csv_rows: - if len(row) > 3: - logger.warning( - 'RECORD line has more than three elements: {}'.format(row) - ) - # Make a copy because we are mutating the row. - row = list(row) - old_path = row[0] - new_path = installed.pop(old_path, old_path) - row[0] = new_path - if new_path in changed: - digest, length = rehash(new_path) - row[1] = digest - row[2] = length - installed_rows.append(tuple(row)) - for f in generated: - digest, length = rehash(f) - installed_rows.append((normpath(f, lib_dir), digest, str(length))) - for f in installed: - installed_rows.append((installed[f], '', '')) - return installed_rows - - -def move_wheel_files( - name, # type: str - req, # type: Requirement - wheeldir, # type: str - user=False, # type: bool - home=None, # type: Optional[str] - root=None, # type: Optional[str] - pycompile=True, # type: bool - scheme=None, # type: Optional[Mapping[str, str]] - isolated=False, # type: bool - prefix=None, # type: Optional[str] - warn_script_location=True # type: bool -): - # type: (...) -> None - """Install a wheel""" - # TODO: Investigate and break this up. - # TODO: Look into moving this into a dedicated class for representing an - # installation. - - if not scheme: - scheme = distutils_scheme( - name, user=user, home=home, root=root, isolated=isolated, - prefix=prefix, - ) - - if root_is_purelib(name, wheeldir): - lib_dir = scheme['purelib'] - else: - lib_dir = scheme['platlib'] - - info_dir = [] # type: List[str] - data_dirs = [] - source = wheeldir.rstrip(os.path.sep) + os.path.sep - - # Record details of the files moved - # installed = files copied from the wheel to the destination - # changed = files changed while installing (scripts #! line typically) - # generated = files newly generated during the install (script wrappers) - installed = {} # type: Dict[str, str] - changed = set() - generated = [] # type: List[str] - - # Compile all of the pyc files that we're going to be installing - if pycompile: - with captured_stdout() as stdout: - with warnings.catch_warnings(): - warnings.filterwarnings('ignore') - compileall.compile_dir(source, force=True, quiet=True) - logger.debug(stdout.getvalue()) - - def record_installed(srcfile, destfile, modified=False): - """Map archive RECORD paths to installation RECORD paths.""" - oldpath = normpath(srcfile, wheeldir) - newpath = normpath(destfile, lib_dir) - installed[oldpath] = newpath - if modified: - changed.add(destfile) - - def clobber(source, dest, is_base, fixer=None, filter=None): - ensure_dir(dest) # common for the 'include' path - - for dir, subdirs, files in os.walk(source): - basedir = dir[len(source):].lstrip(os.path.sep) - destdir = os.path.join(dest, basedir) - if is_base and basedir.split(os.path.sep, 1)[0].endswith('.data'): - continue - for s in subdirs: - destsubdir = os.path.join(dest, basedir, s) - if is_base and basedir == '' and destsubdir.endswith('.data'): - data_dirs.append(s) - continue - elif (is_base and - s.endswith('.dist-info') and - canonicalize_name(s).startswith( - canonicalize_name(req.name))): - assert not info_dir, ('Multiple .dist-info directories: ' + - destsubdir + ', ' + - ', '.join(info_dir)) - info_dir.append(destsubdir) - for f in files: - # Skip unwanted files - if filter and filter(f): - continue - srcfile = os.path.join(dir, f) - destfile = os.path.join(dest, basedir, f) - # directory creation is lazy and after the file filtering above - # to ensure we don't install empty dirs; empty dirs can't be - # uninstalled. - ensure_dir(destdir) - - # copyfile (called below) truncates the destination if it - # exists and then writes the new contents. This is fine in most - # cases, but can cause a segfault if pip has loaded a shared - # object (e.g. from pyopenssl through its vendored urllib3) - # Since the shared object is mmap'd an attempt to call a - # symbol in it will then cause a segfault. Unlinking the file - # allows writing of new contents while allowing the process to - # continue to use the old copy. - if os.path.exists(destfile): - os.unlink(destfile) - - # We use copyfile (not move, copy, or copy2) to be extra sure - # that we are not moving directories over (copyfile fails for - # directories) as well as to ensure that we are not copying - # over any metadata because we want more control over what - # metadata we actually copy over. - shutil.copyfile(srcfile, destfile) - - # Copy over the metadata for the file, currently this only - # includes the atime and mtime. - st = os.stat(srcfile) - if hasattr(os, "utime"): - os.utime(destfile, (st.st_atime, st.st_mtime)) - - # If our file is executable, then make our destination file - # executable. - if os.access(srcfile, os.X_OK): - st = os.stat(srcfile) - permissions = ( - st.st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH - ) - os.chmod(destfile, permissions) - - changed = False - if fixer: - changed = fixer(destfile) - record_installed(srcfile, destfile, changed) - - clobber(source, lib_dir, True) - - assert info_dir, "%s .dist-info directory not found" % req - - # Get the defined entry points - ep_file = os.path.join(info_dir[0], 'entry_points.txt') - console, gui = get_entrypoints(ep_file) - - def is_entrypoint_wrapper(name): - # EP, EP.exe and EP-script.py are scripts generated for - # entry point EP by setuptools - if name.lower().endswith('.exe'): - matchname = name[:-4] - elif name.lower().endswith('-script.py'): - matchname = name[:-10] - elif name.lower().endswith(".pya"): - matchname = name[:-4] - else: - matchname = name - # Ignore setuptools-generated scripts - return (matchname in console or matchname in gui) - - for datadir in data_dirs: - fixer = None - filter = None - for subdir in os.listdir(os.path.join(wheeldir, datadir)): - fixer = None - if subdir == 'scripts': - fixer = fix_script - filter = is_entrypoint_wrapper - source = os.path.join(wheeldir, datadir, subdir) - dest = scheme[subdir] - clobber(source, dest, False, fixer=fixer, filter=filter) - - maker = ScriptMaker(None, scheme['scripts']) - - # Ensure old scripts are overwritten. - # See https://github.com/pypa/pip/issues/1800 - maker.clobber = True - - # Ensure we don't generate any variants for scripts because this is almost - # never what somebody wants. - # See https://bitbucket.org/pypa/distlib/issue/35/ - maker.variants = {''} - - # This is required because otherwise distlib creates scripts that are not - # executable. - # See https://bitbucket.org/pypa/distlib/issue/32/ - maker.set_mode = True - - # Simplify the script and fix the fact that the default script swallows - # every single stack trace. - # See https://bitbucket.org/pypa/distlib/issue/34/ - # See https://bitbucket.org/pypa/distlib/issue/33/ - def _get_script_text(entry): - if entry.suffix is None: - raise InstallationError( - "Invalid script entry point: %s for req: %s - A callable " - "suffix is required. Cf https://packaging.python.org/en/" - "latest/distributing.html#console-scripts for more " - "information." % (entry, req) - ) - return maker.script_template % { - "module": entry.prefix, - "import_name": entry.suffix.split(".")[0], - "func": entry.suffix, - } - # ignore type, because mypy disallows assigning to a method, - # see https://github.com/python/mypy/issues/2427 - maker._get_script_text = _get_script_text # type: ignore - maker.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()) -""" - - # Special case pip and setuptools to generate versioned wrappers - # - # The issue is that some projects (specifically, pip and setuptools) use - # code in setup.py to create "versioned" entry points - pip2.7 on Python - # 2.7, pip3.3 on Python 3.3, etc. But these entry points are baked into - # the wheel metadata at build time, and so if the wheel is installed with - # a *different* version of Python the entry points will be wrong. The - # correct fix for this is to enhance the metadata to be able to describe - # such versioned entry points, but that won't happen till Metadata 2.0 is - # available. - # In the meantime, projects using versioned entry points will either have - # incorrect versioned entry points, or they will not be able to distribute - # "universal" wheels (i.e., they will need a wheel per Python version). - # - # Because setuptools and pip are bundled with _ensurepip and virtualenv, - # we need to use universal wheels. So, as a stopgap until Metadata 2.0, we - # override the versioned entry points in the wheel and generate the - # correct ones. This code is purely a short-term measure until Metadata 2.0 - # is available. - # - # To add the level of hack in this section of code, in order to support - # ensurepip this code will look for an ``ENSUREPIP_OPTIONS`` environment - # variable which will control which version scripts get installed. - # - # ENSUREPIP_OPTIONS=altinstall - # - Only pipX.Y and easy_install-X.Y will be generated and installed - # ENSUREPIP_OPTIONS=install - # - pipX.Y, pipX, easy_install-X.Y will be generated and installed. Note - # that this option is technically if ENSUREPIP_OPTIONS is set and is - # not altinstall - # DEFAULT - # - The default behavior is to install pip, pipX, pipX.Y, easy_install - # and easy_install-X.Y. - pip_script = console.pop('pip', None) - if pip_script: - if "ENSUREPIP_OPTIONS" not in os.environ: - spec = 'pip = ' + pip_script - generated.extend(maker.make(spec)) - - if os.environ.get("ENSUREPIP_OPTIONS", "") != "altinstall": - spec = 'pip%s = %s' % (sys.version[:1], pip_script) - generated.extend(maker.make(spec)) - - spec = 'pip%s = %s' % (sys.version[:3], pip_script) - generated.extend(maker.make(spec)) - # Delete any other versioned pip entry points - pip_ep = [k for k in console if re.match(r'pip(\d(\.\d)?)?$', k)] - for k in pip_ep: - del console[k] - easy_install_script = console.pop('easy_install', None) - if easy_install_script: - if "ENSUREPIP_OPTIONS" not in os.environ: - spec = 'easy_install = ' + easy_install_script - generated.extend(maker.make(spec)) - - spec = 'easy_install-%s = %s' % (sys.version[:3], easy_install_script) - generated.extend(maker.make(spec)) - # Delete any other versioned easy_install entry points - easy_install_ep = [ - k for k in console if re.match(r'easy_install(-\d\.\d)?$', k) - ] - for k in easy_install_ep: - del console[k] - - # Generate the console and GUI entry points specified in the wheel - if len(console) > 0: - generated_console_scripts = maker.make_multiple( - ['%s = %s' % kv for kv in console.items()] - ) - generated.extend(generated_console_scripts) - - if warn_script_location: - msg = message_about_scripts_not_on_PATH(generated_console_scripts) - if msg is not None: - logger.warning(msg) - - if len(gui) > 0: - generated.extend( - maker.make_multiple( - ['%s = %s' % kv for kv in gui.items()], - {'gui': True} - ) - ) - - # Record pip as the installer - installer = os.path.join(info_dir[0], 'INSTALLER') - temp_installer = os.path.join(info_dir[0], 'INSTALLER.pip') - with open(temp_installer, 'wb') as installer_file: - installer_file.write(b'pip\n') - shutil.move(temp_installer, installer) - generated.append(installer) - - # Record details of all files installed - record = os.path.join(info_dir[0], 'RECORD') - temp_record = os.path.join(info_dir[0], 'RECORD.pip') - with open_for_csv(record, 'r') as record_in: - with open_for_csv(temp_record, 'w+') as record_out: - reader = csv.reader(record_in) - outrows = get_csv_rows_for_installed( - reader, installed=installed, changed=changed, - generated=generated, lib_dir=lib_dir, - ) - writer = csv.writer(record_out) - # Sort to simplify testing. - for row in sorted_outrows(outrows): - writer.writerow(row) - shutil.move(temp_record, record) - - -def wheel_version(source_dir): - # type: (Optional[str]) -> Optional[Tuple[int, ...]] - """ - Return the Wheel-Version of an extracted wheel, if possible. - - Otherwise, return None if we couldn't parse / extract it. - """ - try: - dist = [d for d in pkg_resources.find_on_path(None, source_dir)][0] - - wheel_data = dist.get_metadata('WHEEL') - wheel_data = Parser().parsestr(wheel_data) - - version = wheel_data['Wheel-Version'].strip() - version = tuple(map(int, version.split('.'))) - return version - except Exception: - return None - - -def check_compatibility(version, name): - # type: (Optional[Tuple[int, ...]], str) -> None - """ - Raises errors or warns if called with an incompatible Wheel-Version. - - Pip should refuse to install a Wheel-Version that's a major series - ahead of what it's compatible with (e.g 2.0 > 1.1); and warn when - installing a version only minor version ahead (e.g 1.2 > 1.1). - - version: a 2-tuple representing a Wheel-Version (Major, Minor) - name: name of wheel or package to raise exception about - - :raises UnsupportedWheel: when an incompatible Wheel-Version is given - """ - if not version: - raise UnsupportedWheel( - "%s is in an unsupported or invalid wheel" % name - ) - if version[0] > VERSION_COMPATIBLE[0]: - raise UnsupportedWheel( - "%s's Wheel-Version (%s) is not compatible with this version " - "of pip" % (name, '.'.join(map(str, version))) - ) - elif version > VERSION_COMPATIBLE: - logger.warning( - 'Installing from a newer Wheel-Version (%s)', - '.'.join(map(str, version)), - ) - - -class Wheel(object): - """A wheel file""" - - # TODO: Maybe move the class into the models sub-package - # TODO: Maybe move the install code into this class - - wheel_file_re = re.compile( - r"""^(?P<namever>(?P<name>.+?)-(?P<ver>.*?)) - ((-(?P<build>\d[^-]*?))?-(?P<pyver>.+?)-(?P<abi>.+?)-(?P<plat>.+?) - \.whl|\.dist-info)$""", - re.VERBOSE - ) - - def __init__(self, filename): - # type: (str) -> None - """ - :raises InvalidWheelFilename: when the filename is invalid for a wheel - """ - wheel_info = self.wheel_file_re.match(filename) - if not wheel_info: - raise InvalidWheelFilename( - "%s is not a valid wheel filename." % filename - ) - self.filename = filename - self.name = wheel_info.group('name').replace('_', '-') - # we'll assume "_" means "-" due to wheel naming scheme - # (https://github.com/pypa/pip/issues/1150) - self.version = wheel_info.group('ver').replace('_', '-') - self.build_tag = wheel_info.group('build') - self.pyversions = wheel_info.group('pyver').split('.') - self.abis = wheel_info.group('abi').split('.') - self.plats = wheel_info.group('plat').split('.') - - # All the tag combinations from this file - self.file_tags = { - (x, y, z) for x in self.pyversions - for y in self.abis for z in self.plats - } - - def support_index_min(self, tags=None): - # type: (Optional[List[Pep425Tag]]) -> Optional[int] - """ - Return the lowest index that one of the wheel's file_tag combinations - achieves in the supported_tags list e.g. if there are 8 supported tags, - and one of the file tags is first in the list, then return 0. Returns - None is the wheel is not supported. - """ - if tags is None: # for mock - tags = pep425tags.get_supported() - indexes = [tags.index(c) for c in self.file_tags if c in tags] - return min(indexes) if indexes else None - - def supported(self, tags=None): - # type: (Optional[List[Pep425Tag]]) -> bool - """Is this wheel supported on this system?""" - if tags is None: # for mock - tags = pep425tags.get_supported() - return bool(set(tags).intersection(self.file_tags)) - - -def _contains_egg_info( - s, _egg_info_re=re.compile(r'([a-z0-9_.]+)-([a-z0-9_.!+-]+)', re.I)): - """Determine whether the string looks like an egg_info. - - :param s: The string to parse. E.g. foo-2.1 - """ - return bool(_egg_info_re.search(s)) - - -def should_use_ephemeral_cache( - req, # type: InstallRequirement - format_control, # type: FormatControl - autobuilding, # type: bool - cache_available # type: bool -): - # type: (...) -> Optional[bool] - """ - Return whether to build an InstallRequirement object using the - ephemeral cache. - - :param cache_available: whether a cache directory is available for the - autobuilding=True case. - - :return: True or False to build the requirement with ephem_cache=True - or False, respectively; or None not to build the requirement. - """ - if req.constraint: - return None - if req.is_wheel: - if not autobuilding: - logger.info( - 'Skipping %s, due to already being wheel.', req.name, - ) - return None - if not autobuilding: - return False - - if req.editable or not req.source_dir: - return None - - if req.link and not req.link.is_artifact: - # VCS checkout. Build wheel just for this run. - return True - - if "binary" not in format_control.get_allowed_formats( - canonicalize_name(req.name)): - logger.info( - "Skipping bdist_wheel for %s, due to binaries " - "being disabled for it.", req.name, - ) - return None - - link = req.link - base, ext = link.splitext() - if cache_available and _contains_egg_info(base): - return False - - # Otherwise, build the wheel just for this run using the ephemeral - # cache since we are either in the case of e.g. a local directory, or - # no cache directory is available to use. - return True - - -def format_command_result( - command_args, # type: List[str] - command_output, # type: str -): - # type: (...) -> str - """ - Format command information for logging. - """ - command_desc = format_command_args(command_args) - text = 'Command arguments: {}\n'.format(command_desc) - - if not command_output: - text += 'Command output: None' - elif logger.getEffectiveLevel() > logging.DEBUG: - text += 'Command output: [use --verbose to show]' - else: - if not command_output.endswith('\n'): - command_output += '\n' - text += 'Command output:\n{}{}'.format(command_output, LOG_DIVIDER) - - return text - - -def get_legacy_build_wheel_path( - names, # type: List[str] - temp_dir, # type: str - req, # type: InstallRequirement - command_args, # type: List[str] - command_output, # type: str -): - # type: (...) -> Optional[str] - """ - Return the path to the wheel in the temporary build directory. - """ - # Sort for determinism. - names = sorted(names) - if not names: - msg = ( - 'Legacy build of wheel for {!r} created no files.\n' - ).format(req.name) - msg += format_command_result(command_args, command_output) - logger.warning(msg) - return None - - if len(names) > 1: - msg = ( - 'Legacy build of wheel for {!r} created more than one file.\n' - 'Filenames (choosing first): {}\n' - ).format(req.name, names) - msg += format_command_result(command_args, command_output) - logger.warning(msg) - - return os.path.join(temp_dir, names[0]) - - -class WheelBuilder(object): - """Build wheels from a RequirementSet.""" - - def __init__( - self, - finder, # type: PackageFinder - preparer, # type: RequirementPreparer - wheel_cache, # type: WheelCache - build_options=None, # type: Optional[List[str]] - global_options=None, # type: Optional[List[str]] - no_clean=False # type: bool - ): - # type: (...) -> None - self.finder = finder - self.preparer = preparer - self.wheel_cache = wheel_cache - - self._wheel_dir = preparer.wheel_download_dir - - self.build_options = build_options or [] - self.global_options = global_options or [] - self.no_clean = no_clean - - def _build_one(self, req, output_dir, python_tag=None): - """Build one wheel. - - :return: The filename of the built wheel, or None if the build failed. - """ - # Install build deps into temporary directory (PEP 518) - with req.build_env: - return self._build_one_inside_env(req, output_dir, - python_tag=python_tag) - - def _build_one_inside_env(self, req, output_dir, python_tag=None): - with TempDirectory(kind="wheel") as temp_dir: - if req.use_pep517: - builder = self._build_one_pep517 - else: - builder = self._build_one_legacy - wheel_path = builder(req, temp_dir.path, python_tag=python_tag) - if wheel_path is not None: - wheel_name = os.path.basename(wheel_path) - dest_path = os.path.join(output_dir, wheel_name) - try: - shutil.move(wheel_path, dest_path) - logger.info('Stored in directory: %s', output_dir) - return dest_path - except Exception: - pass - # Ignore return, we can't do anything else useful. - self._clean_one(req) - return None - - def _base_setup_args(self, req): - # NOTE: Eventually, we'd want to also -S to the flags here, when we're - # isolating. Currently, it breaks Python in virtualenvs, because it - # relies on site.py to find parts of the standard library outside the - # virtualenv. - return [ - sys.executable, '-u', '-c', - SETUPTOOLS_SHIM % req.setup_py - ] + list(self.global_options) - - def _build_one_pep517(self, req, tempd, python_tag=None): - """Build one InstallRequirement using the PEP 517 build process. - - Returns path to wheel if successfully built. Otherwise, returns None. - """ - assert req.metadata_directory is not None - if self.build_options: - # PEP 517 does not support --build-options - logger.error('Cannot build wheel for %s using PEP 517 when ' - '--build-options is present' % (req.name,)) - return None - try: - req.spin_message = 'Building wheel for %s (PEP 517)' % (req.name,) - logger.debug('Destination directory: %s', tempd) - wheel_name = req.pep517_backend.build_wheel( - tempd, - metadata_directory=req.metadata_directory - ) - if python_tag: - # General PEP 517 backends don't necessarily support - # a "--python-tag" option, so we rename the wheel - # file directly. - new_name = replace_python_tag(wheel_name, python_tag) - os.rename( - os.path.join(tempd, wheel_name), - os.path.join(tempd, new_name) - ) - # Reassign to simplify the return at the end of function - wheel_name = new_name - except Exception: - logger.error('Failed building wheel for %s', req.name) - return None - return os.path.join(tempd, wheel_name) - - def _build_one_legacy(self, req, tempd, python_tag=None): - """Build one InstallRequirement using the "legacy" build process. - - Returns path to wheel if successfully built. Otherwise, returns None. - """ - base_args = self._base_setup_args(req) - - spin_message = 'Building wheel for %s (setup.py)' % (req.name,) - with open_spinner(spin_message) as spinner: - logger.debug('Destination directory: %s', tempd) - wheel_args = base_args + ['bdist_wheel', '-d', tempd] \ - + self.build_options - - if python_tag is not None: - wheel_args += ["--python-tag", python_tag] - - try: - output = call_subprocess(wheel_args, cwd=req.setup_py_dir, - spinner=spinner) - except Exception: - spinner.finish("error") - logger.error('Failed building wheel for %s', req.name) - return None - names = os.listdir(tempd) - wheel_path = get_legacy_build_wheel_path( - names=names, - temp_dir=tempd, - req=req, - command_args=wheel_args, - command_output=output, - ) - return wheel_path - - def _clean_one(self, req): - base_args = self._base_setup_args(req) - - logger.info('Running setup.py clean for %s', req.name) - clean_args = base_args + ['clean', '--all'] - try: - call_subprocess(clean_args, cwd=req.source_dir) - return True - except Exception: - logger.error('Failed cleaning build dir for %s', req.name) - return False - - def build( - self, - requirements, # type: Iterable[InstallRequirement] - session, # type: PipSession - autobuilding=False # type: bool - ): - # type: (...) -> List[InstallRequirement] - """Build wheels. - - :param unpack: If True, replace the sdist we built from with the - newly built wheel, in preparation for installation. - :return: True if all the wheels built correctly. - """ - buildset = [] - format_control = self.finder.format_control - # Whether a cache directory is available for autobuilding=True. - cache_available = bool(self._wheel_dir or self.wheel_cache.cache_dir) - - for req in requirements: - ephem_cache = should_use_ephemeral_cache( - req, format_control=format_control, autobuilding=autobuilding, - cache_available=cache_available, - ) - if ephem_cache is None: - continue - - buildset.append((req, ephem_cache)) - - if not buildset: - return [] - - # Is any wheel build not using the ephemeral cache? - if any(not ephem_cache for _, ephem_cache in buildset): - have_directory_for_build = self._wheel_dir or ( - autobuilding and self.wheel_cache.cache_dir - ) - assert have_directory_for_build - - # TODO by @pradyunsg - # Should break up this method into 2 separate methods. - - # Build the wheels. - logger.info( - 'Building wheels for collected packages: %s', - ', '.join([req.name for (req, _) in buildset]), - ) - _cache = self.wheel_cache # shorter name - with indent_log(): - build_success, build_failure = [], [] - for req, ephem in buildset: - python_tag = None - if autobuilding: - python_tag = pep425tags.implementation_tag - if ephem: - output_dir = _cache.get_ephem_path_for_link(req.link) - else: - output_dir = _cache.get_path_for_link(req.link) - try: - ensure_dir(output_dir) - except OSError as e: - logger.warning("Building wheel for %s failed: %s", - req.name, e) - build_failure.append(req) - continue - else: - output_dir = self._wheel_dir - wheel_file = self._build_one( - req, output_dir, - python_tag=python_tag, - ) - if wheel_file: - build_success.append(req) - if autobuilding: - # XXX: This is mildly duplicative with prepare_files, - # but not close enough to pull out to a single common - # method. - # The code below assumes temporary source dirs - - # prevent it doing bad things. - if req.source_dir and not os.path.exists(os.path.join( - req.source_dir, PIP_DELETE_MARKER_FILENAME)): - raise AssertionError( - "bad source dir - missing marker") - # Delete the source we built the wheel from - req.remove_temporary_source() - # set the build directory again - name is known from - # the work prepare_files did. - req.source_dir = req.build_location( - self.preparer.build_dir - ) - # Update the link for this. - req.link = Link(path_to_url(wheel_file)) - assert req.link.is_wheel - # extract the wheel into the dir - unpack_url( - req.link, req.source_dir, None, False, - session=session, - ) - else: - build_failure.append(req) - - # notify success/failure - if build_success: - logger.info( - 'Successfully built %s', - ' '.join([req.name for req in build_success]), - ) - if build_failure: - logger.info( - 'Failed to build %s', - ' '.join([req.name for req in build_failure]), - ) - # Return a list of requirements that failed to build - return build_failure diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/__init__.py deleted file mode 100644 index c1d9508..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/__init__.py +++ /dev/null @@ -1,109 +0,0 @@ -""" -pip._vendor is for vendoring dependencies of pip to prevent needing pip to -depend on something external. - -Files inside of pip._vendor should be considered immutable and should only be -updated to versions from upstream. -""" -from __future__ import absolute_import - -import glob -import os.path -import sys - -# Downstream redistributors which have debundled our dependencies should also -# patch this value to be true. This will trigger the additional patching -# to cause things like "six" to be available as pip. -DEBUNDLED = False - -# By default, look in this directory for a bunch of .whl files which we will -# add to the beginning of sys.path before attempting to import anything. This -# is done to support downstream re-distributors like Debian and Fedora who -# wish to create their own Wheels for our dependencies to aid in debundling. -WHEEL_DIR = os.path.abspath(os.path.dirname(__file__)) - - -# Define a small helper function to alias our vendored modules to the real ones -# if the vendored ones do not exist. This idea of this was taken from -# https://github.com/kennethreitz/requests/pull/2567. -def vendored(modulename): - vendored_name = "{0}.{1}".format(__name__, modulename) - - try: - __import__(modulename, globals(), locals(), level=0) - except ImportError: - # We can just silently allow import failures to pass here. If we - # got to this point it means that ``import pip._vendor.whatever`` - # failed and so did ``import whatever``. Since we're importing this - # upfront in an attempt to alias imports, not erroring here will - # just mean we get a regular import error whenever pip *actually* - # tries to import one of these modules to use it, which actually - # gives us a better error message than we would have otherwise - # gotten. - pass - else: - sys.modules[vendored_name] = sys.modules[modulename] - base, head = vendored_name.rsplit(".", 1) - setattr(sys.modules[base], head, sys.modules[modulename]) - - -# If we're operating in a debundled setup, then we want to go ahead and trigger -# the aliasing of our vendored libraries as well as looking for wheels to add -# to our sys.path. This will cause all of this code to be a no-op typically -# however downstream redistributors can enable it in a consistent way across -# all platforms. -if DEBUNDLED: - # Actually look inside of WHEEL_DIR to find .whl files and add them to the - # front of our sys.path. - sys.path[:] = glob.glob(os.path.join(WHEEL_DIR, "*.whl")) + sys.path - - # Actually alias all of our vendored dependencies. - vendored("cachecontrol") - vendored("colorama") - vendored("distlib") - vendored("distro") - vendored("html5lib") - vendored("lockfile") - vendored("six") - vendored("six.moves") - vendored("six.moves.urllib") - vendored("six.moves.urllib.parse") - vendored("packaging") - vendored("packaging.version") - vendored("packaging.specifiers") - vendored("pep517") - vendored("pkg_resources") - vendored("progress") - vendored("pytoml") - vendored("retrying") - vendored("requests") - vendored("requests.exceptions") - vendored("requests.packages") - vendored("requests.packages.urllib3") - vendored("requests.packages.urllib3._collections") - vendored("requests.packages.urllib3.connection") - vendored("requests.packages.urllib3.connectionpool") - vendored("requests.packages.urllib3.contrib") - vendored("requests.packages.urllib3.contrib.ntlmpool") - vendored("requests.packages.urllib3.contrib.pyopenssl") - vendored("requests.packages.urllib3.exceptions") - vendored("requests.packages.urllib3.fields") - vendored("requests.packages.urllib3.filepost") - vendored("requests.packages.urllib3.packages") - vendored("requests.packages.urllib3.packages.ordered_dict") - vendored("requests.packages.urllib3.packages.six") - vendored("requests.packages.urllib3.packages.ssl_match_hostname") - vendored("requests.packages.urllib3.packages.ssl_match_hostname." - "_implementation") - vendored("requests.packages.urllib3.poolmanager") - vendored("requests.packages.urllib3.request") - vendored("requests.packages.urllib3.response") - vendored("requests.packages.urllib3.util") - vendored("requests.packages.urllib3.util.connection") - vendored("requests.packages.urllib3.util.request") - vendored("requests.packages.urllib3.util.response") - vendored("requests.packages.urllib3.util.retry") - vendored("requests.packages.urllib3.util.ssl_") - vendored("requests.packages.urllib3.util.timeout") - vendored("requests.packages.urllib3.util.url") - vendored("urllib3") diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/appdirs.py b/venv2/lib/python2.7/site-packages/pip/_vendor/appdirs.py deleted file mode 100644 index 2bd3911..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/appdirs.py +++ /dev/null @@ -1,604 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# Copyright (c) 2005-2010 ActiveState Software Inc. -# Copyright (c) 2013 Eddy Petrișor - -"""Utilities for determining application-specific dirs. - -See <http://github.com/ActiveState/appdirs> for details and usage. -""" -# Dev Notes: -# - MSDN on where to store app data files: -# http://support.microsoft.com/default.aspx?scid=kb;en-us;310294#XSLTH3194121123120121120120 -# - Mac OS X: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/index.html -# - XDG spec for Un*x: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html - -__version_info__ = (1, 4, 3) -__version__ = '.'.join(map(str, __version_info__)) - - -import sys -import os - -PY3 = sys.version_info[0] == 3 - -if PY3: - unicode = str - -if sys.platform.startswith('java'): - import platform - os_name = platform.java_ver()[3][0] - if os_name.startswith('Windows'): # "Windows XP", "Windows 7", etc. - system = 'win32' - elif os_name.startswith('Mac'): # "Mac OS X", etc. - system = 'darwin' - else: # "Linux", "SunOS", "FreeBSD", etc. - # Setting this to "linux2" is not ideal, but only Windows or Mac - # are actually checked for and the rest of the module expects - # *sys.platform* style strings. - system = 'linux2' -else: - system = sys.platform - - - -def user_data_dir(appname=None, appauthor=None, version=None, roaming=False): - r"""Return full path to the user-specific data dir for this application. - - "appname" is the name of application. - If None, just the system directory is returned. - "appauthor" (only used on Windows) is the name of the - appauthor or distributing body for this application. Typically - it is the owning company name. This falls back to appname. You may - pass False to disable it. - "version" is an optional version path element to append to the - path. You might want to use this if you want multiple versions - of your app to be able to run independently. If used, this - would typically be "<major>.<minor>". - Only applied when appname is present. - "roaming" (boolean, default False) can be set True to use the Windows - roaming appdata directory. That means that for users on a Windows - network setup for roaming profiles, this user data will be - sync'd on login. See - <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> - for a discussion of issues. - - Typical user data directories are: - Mac OS X: ~/Library/Application Support/<AppName> - Unix: ~/.local/share/<AppName> # or in $XDG_DATA_HOME, if defined - Win XP (not roaming): C:\Documents and Settings\<username>\Application Data\<AppAuthor>\<AppName> - Win XP (roaming): C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName> - Win 7 (not roaming): C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName> - Win 7 (roaming): C:\Users\<username>\AppData\Roaming\<AppAuthor>\<AppName> - - For Unix, we follow the XDG spec and support $XDG_DATA_HOME. - That means, by default "~/.local/share/<AppName>". - """ - if system == "win32": - if appauthor is None: - appauthor = appname - const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA" - path = os.path.normpath(_get_win_folder(const)) - if appname: - if appauthor is not False: - path = os.path.join(path, appauthor, appname) - else: - path = os.path.join(path, appname) - elif system == 'darwin': - path = os.path.expanduser('~/Library/Application Support/') - if appname: - path = os.path.join(path, appname) - else: - path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/.local/share")) - if appname: - path = os.path.join(path, appname) - if appname and version: - path = os.path.join(path, version) - return path - - -def site_data_dir(appname=None, appauthor=None, version=None, multipath=False): - r"""Return full path to the user-shared data dir for this application. - - "appname" is the name of application. - If None, just the system directory is returned. - "appauthor" (only used on Windows) is the name of the - appauthor or distributing body for this application. Typically - it is the owning company name. This falls back to appname. You may - pass False to disable it. - "version" is an optional version path element to append to the - path. You might want to use this if you want multiple versions - of your app to be able to run independently. If used, this - would typically be "<major>.<minor>". - Only applied when appname is present. - "multipath" is an optional parameter only applicable to *nix - which indicates that the entire list of data dirs should be - returned. By default, the first item from XDG_DATA_DIRS is - returned, or '/usr/local/share/<AppName>', - if XDG_DATA_DIRS is not set - - Typical site data directories are: - Mac OS X: /Library/Application Support/<AppName> - Unix: /usr/local/share/<AppName> or /usr/share/<AppName> - Win XP: C:\Documents and Settings\All Users\Application Data\<AppAuthor>\<AppName> - Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) - Win 7: C:\ProgramData\<AppAuthor>\<AppName> # Hidden, but writeable on Win 7. - - For Unix, this is using the $XDG_DATA_DIRS[0] default. - - WARNING: Do not use this on Windows. See the Vista-Fail note above for why. - """ - if system == "win32": - if appauthor is None: - appauthor = appname - path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA")) - if appname: - if appauthor is not False: - path = os.path.join(path, appauthor, appname) - else: - path = os.path.join(path, appname) - elif system == 'darwin': - path = os.path.expanduser('/Library/Application Support') - if appname: - path = os.path.join(path, appname) - else: - # XDG default for $XDG_DATA_DIRS - # only first, if multipath is False - path = os.getenv('XDG_DATA_DIRS', - os.pathsep.join(['/usr/local/share', '/usr/share'])) - pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] - if appname: - if version: - appname = os.path.join(appname, version) - pathlist = [os.sep.join([x, appname]) for x in pathlist] - - if multipath: - path = os.pathsep.join(pathlist) - else: - path = pathlist[0] - return path - - if appname and version: - path = os.path.join(path, version) - return path - - -def user_config_dir(appname=None, appauthor=None, version=None, roaming=False): - r"""Return full path to the user-specific config dir for this application. - - "appname" is the name of application. - If None, just the system directory is returned. - "appauthor" (only used on Windows) is the name of the - appauthor or distributing body for this application. Typically - it is the owning company name. This falls back to appname. You may - pass False to disable it. - "version" is an optional version path element to append to the - path. You might want to use this if you want multiple versions - of your app to be able to run independently. If used, this - would typically be "<major>.<minor>". - Only applied when appname is present. - "roaming" (boolean, default False) can be set True to use the Windows - roaming appdata directory. That means that for users on a Windows - network setup for roaming profiles, this user data will be - sync'd on login. See - <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> - for a discussion of issues. - - Typical user config directories are: - Mac OS X: same as user_data_dir - Unix: ~/.config/<AppName> # or in $XDG_CONFIG_HOME, if defined - Win *: same as user_data_dir - - For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME. - That means, by default "~/.config/<AppName>". - """ - if system in ["win32", "darwin"]: - path = user_data_dir(appname, appauthor, None, roaming) - else: - path = os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config")) - if appname: - path = os.path.join(path, appname) - if appname and version: - path = os.path.join(path, version) - return path - - -def site_config_dir(appname=None, appauthor=None, version=None, multipath=False): - r"""Return full path to the user-shared data dir for this application. - - "appname" is the name of application. - If None, just the system directory is returned. - "appauthor" (only used on Windows) is the name of the - appauthor or distributing body for this application. Typically - it is the owning company name. This falls back to appname. You may - pass False to disable it. - "version" is an optional version path element to append to the - path. You might want to use this if you want multiple versions - of your app to be able to run independently. If used, this - would typically be "<major>.<minor>". - Only applied when appname is present. - "multipath" is an optional parameter only applicable to *nix - which indicates that the entire list of config dirs should be - returned. By default, the first item from XDG_CONFIG_DIRS is - returned, or '/etc/xdg/<AppName>', if XDG_CONFIG_DIRS is not set - - Typical site config directories are: - Mac OS X: same as site_data_dir - Unix: /etc/xdg/<AppName> or $XDG_CONFIG_DIRS[i]/<AppName> for each value in - $XDG_CONFIG_DIRS - Win *: same as site_data_dir - Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) - - For Unix, this is using the $XDG_CONFIG_DIRS[0] default, if multipath=False - - WARNING: Do not use this on Windows. See the Vista-Fail note above for why. - """ - if system in ["win32", "darwin"]: - path = site_data_dir(appname, appauthor) - if appname and version: - path = os.path.join(path, version) - else: - # XDG default for $XDG_CONFIG_DIRS - # only first, if multipath is False - path = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg') - pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] - if appname: - if version: - appname = os.path.join(appname, version) - pathlist = [os.sep.join([x, appname]) for x in pathlist] - - if multipath: - path = os.pathsep.join(pathlist) - else: - path = pathlist[0] - return path - - -def user_cache_dir(appname=None, appauthor=None, version=None, opinion=True): - r"""Return full path to the user-specific cache dir for this application. - - "appname" is the name of application. - If None, just the system directory is returned. - "appauthor" (only used on Windows) is the name of the - appauthor or distributing body for this application. Typically - it is the owning company name. This falls back to appname. You may - pass False to disable it. - "version" is an optional version path element to append to the - path. You might want to use this if you want multiple versions - of your app to be able to run independently. If used, this - would typically be "<major>.<minor>". - Only applied when appname is present. - "opinion" (boolean) can be False to disable the appending of - "Cache" to the base app data dir for Windows. See - discussion below. - - Typical user cache directories are: - Mac OS X: ~/Library/Caches/<AppName> - Unix: ~/.cache/<AppName> (XDG default) - Win XP: C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Cache - Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Cache - - On Windows the only suggestion in the MSDN docs is that local settings go in - the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming - app data dir (the default returned by `user_data_dir` above). Apps typically - put cache data somewhere *under* the given dir here. Some examples: - ...\Mozilla\Firefox\Profiles\<ProfileName>\Cache - ...\Acme\SuperApp\Cache\1.0 - OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. - This can be disabled with the `opinion=False` option. - """ - if system == "win32": - if appauthor is None: - appauthor = appname - path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA")) - if appname: - if appauthor is not False: - path = os.path.join(path, appauthor, appname) - else: - path = os.path.join(path, appname) - if opinion: - path = os.path.join(path, "Cache") - elif system == 'darwin': - path = os.path.expanduser('~/Library/Caches') - if appname: - path = os.path.join(path, appname) - else: - path = os.getenv('XDG_CACHE_HOME', os.path.expanduser('~/.cache')) - if appname: - path = os.path.join(path, appname) - if appname and version: - path = os.path.join(path, version) - return path - - -def user_state_dir(appname=None, appauthor=None, version=None, roaming=False): - r"""Return full path to the user-specific state dir for this application. - - "appname" is the name of application. - If None, just the system directory is returned. - "appauthor" (only used on Windows) is the name of the - appauthor or distributing body for this application. Typically - it is the owning company name. This falls back to appname. You may - pass False to disable it. - "version" is an optional version path element to append to the - path. You might want to use this if you want multiple versions - of your app to be able to run independently. If used, this - would typically be "<major>.<minor>". - Only applied when appname is present. - "roaming" (boolean, default False) can be set True to use the Windows - roaming appdata directory. That means that for users on a Windows - network setup for roaming profiles, this user data will be - sync'd on login. See - <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> - for a discussion of issues. - - Typical user state directories are: - Mac OS X: same as user_data_dir - Unix: ~/.local/state/<AppName> # or in $XDG_STATE_HOME, if defined - Win *: same as user_data_dir - - For Unix, we follow this Debian proposal <https://wiki.debian.org/XDGBaseDirectorySpecification#state> - to extend the XDG spec and support $XDG_STATE_HOME. - - That means, by default "~/.local/state/<AppName>". - """ - if system in ["win32", "darwin"]: - path = user_data_dir(appname, appauthor, None, roaming) - else: - path = os.getenv('XDG_STATE_HOME', os.path.expanduser("~/.local/state")) - if appname: - path = os.path.join(path, appname) - if appname and version: - path = os.path.join(path, version) - return path - - -def user_log_dir(appname=None, appauthor=None, version=None, opinion=True): - r"""Return full path to the user-specific log dir for this application. - - "appname" is the name of application. - If None, just the system directory is returned. - "appauthor" (only used on Windows) is the name of the - appauthor or distributing body for this application. Typically - it is the owning company name. This falls back to appname. You may - pass False to disable it. - "version" is an optional version path element to append to the - path. You might want to use this if you want multiple versions - of your app to be able to run independently. If used, this - would typically be "<major>.<minor>". - Only applied when appname is present. - "opinion" (boolean) can be False to disable the appending of - "Logs" to the base app data dir for Windows, and "log" to the - base cache dir for Unix. See discussion below. - - Typical user log directories are: - Mac OS X: ~/Library/Logs/<AppName> - Unix: ~/.cache/<AppName>/log # or under $XDG_CACHE_HOME if defined - Win XP: C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Logs - Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Logs - - On Windows the only suggestion in the MSDN docs is that local settings - go in the `CSIDL_LOCAL_APPDATA` directory. (Note: I'm interested in - examples of what some windows apps use for a logs dir.) - - OPINION: This function appends "Logs" to the `CSIDL_LOCAL_APPDATA` - value for Windows and appends "log" to the user cache dir for Unix. - This can be disabled with the `opinion=False` option. - """ - if system == "darwin": - path = os.path.join( - os.path.expanduser('~/Library/Logs'), - appname) - elif system == "win32": - path = user_data_dir(appname, appauthor, version) - version = False - if opinion: - path = os.path.join(path, "Logs") - else: - path = user_cache_dir(appname, appauthor, version) - version = False - if opinion: - path = os.path.join(path, "log") - if appname and version: - path = os.path.join(path, version) - return path - - -class AppDirs(object): - """Convenience wrapper for getting application dirs.""" - def __init__(self, appname=None, appauthor=None, version=None, - roaming=False, multipath=False): - self.appname = appname - self.appauthor = appauthor - self.version = version - self.roaming = roaming - self.multipath = multipath - - @property - def user_data_dir(self): - return user_data_dir(self.appname, self.appauthor, - version=self.version, roaming=self.roaming) - - @property - def site_data_dir(self): - return site_data_dir(self.appname, self.appauthor, - version=self.version, multipath=self.multipath) - - @property - def user_config_dir(self): - return user_config_dir(self.appname, self.appauthor, - version=self.version, roaming=self.roaming) - - @property - def site_config_dir(self): - return site_config_dir(self.appname, self.appauthor, - version=self.version, multipath=self.multipath) - - @property - def user_cache_dir(self): - return user_cache_dir(self.appname, self.appauthor, - version=self.version) - - @property - def user_state_dir(self): - return user_state_dir(self.appname, self.appauthor, - version=self.version) - - @property - def user_log_dir(self): - return user_log_dir(self.appname, self.appauthor, - version=self.version) - - -#---- internal support stuff - -def _get_win_folder_from_registry(csidl_name): - """This is a fallback technique at best. I'm not sure if using the - registry for this guarantees us the correct answer for all CSIDL_* - names. - """ - if PY3: - import winreg as _winreg - else: - import _winreg - - shell_folder_name = { - "CSIDL_APPDATA": "AppData", - "CSIDL_COMMON_APPDATA": "Common AppData", - "CSIDL_LOCAL_APPDATA": "Local AppData", - }[csidl_name] - - key = _winreg.OpenKey( - _winreg.HKEY_CURRENT_USER, - r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" - ) - dir, type = _winreg.QueryValueEx(key, shell_folder_name) - return dir - - -def _get_win_folder_with_pywin32(csidl_name): - from win32com.shell import shellcon, shell - dir = shell.SHGetFolderPath(0, getattr(shellcon, csidl_name), 0, 0) - # Try to make this a unicode path because SHGetFolderPath does - # not return unicode strings when there is unicode data in the - # path. - try: - dir = unicode(dir) - - # Downgrade to short path name if have highbit chars. See - # <http://bugs.activestate.com/show_bug.cgi?id=85099>. - has_high_char = False - for c in dir: - if ord(c) > 255: - has_high_char = True - break - if has_high_char: - try: - import win32api - dir = win32api.GetShortPathName(dir) - except ImportError: - pass - except UnicodeError: - pass - return dir - - -def _get_win_folder_with_ctypes(csidl_name): - import ctypes - - csidl_const = { - "CSIDL_APPDATA": 26, - "CSIDL_COMMON_APPDATA": 35, - "CSIDL_LOCAL_APPDATA": 28, - }[csidl_name] - - buf = ctypes.create_unicode_buffer(1024) - ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf) - - # Downgrade to short path name if have highbit chars. See - # <http://bugs.activestate.com/show_bug.cgi?id=85099>. - has_high_char = False - for c in buf: - if ord(c) > 255: - has_high_char = True - break - if has_high_char: - buf2 = ctypes.create_unicode_buffer(1024) - if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024): - buf = buf2 - - return buf.value - -def _get_win_folder_with_jna(csidl_name): - import array - from com.sun import jna - from com.sun.jna.platform import win32 - - buf_size = win32.WinDef.MAX_PATH * 2 - buf = array.zeros('c', buf_size) - shell = win32.Shell32.INSTANCE - shell.SHGetFolderPath(None, getattr(win32.ShlObj, csidl_name), None, win32.ShlObj.SHGFP_TYPE_CURRENT, buf) - dir = jna.Native.toString(buf.tostring()).rstrip("\0") - - # Downgrade to short path name if have highbit chars. See - # <http://bugs.activestate.com/show_bug.cgi?id=85099>. - has_high_char = False - for c in dir: - if ord(c) > 255: - has_high_char = True - break - if has_high_char: - buf = array.zeros('c', buf_size) - kernel = win32.Kernel32.INSTANCE - if kernel.GetShortPathName(dir, buf, buf_size): - dir = jna.Native.toString(buf.tostring()).rstrip("\0") - - return dir - -if system == "win32": - try: - from ctypes import windll - _get_win_folder = _get_win_folder_with_ctypes - except ImportError: - try: - import com.sun.jna - _get_win_folder = _get_win_folder_with_jna - except ImportError: - _get_win_folder = _get_win_folder_from_registry - - -#---- self test code - -if __name__ == "__main__": - appname = "MyApp" - appauthor = "MyCompany" - - props = ("user_data_dir", - "user_config_dir", - "user_cache_dir", - "user_state_dir", - "user_log_dir", - "site_data_dir", - "site_config_dir") - - print("-- app dirs %s --" % __version__) - - print("-- app dirs (with optional 'version')") - dirs = AppDirs(appname, appauthor, version="1.0") - for prop in props: - print("%s: %s" % (prop, getattr(dirs, prop))) - - print("\n-- app dirs (without optional 'version')") - dirs = AppDirs(appname, appauthor) - for prop in props: - print("%s: %s" % (prop, getattr(dirs, prop))) - - print("\n-- app dirs (without optional 'appauthor')") - dirs = AppDirs(appname) - for prop in props: - print("%s: %s" % (prop, getattr(dirs, prop))) - - print("\n-- app dirs (with disabled 'appauthor')") - dirs = AppDirs(appname, appauthor=False) - for prop in props: - print("%s: %s" % (prop, getattr(dirs, prop))) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/__init__.py deleted file mode 100644 index 8fdee66..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -"""CacheControl import Interface. - -Make it easy to import from cachecontrol without long namespaces. -""" -__author__ = "Eric Larson" -__email__ = "eric@ionrock.org" -__version__ = "0.12.5" - -from .wrapper import CacheControl -from .adapter import CacheControlAdapter -from .controller import CacheController diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/_cmd.py b/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/_cmd.py deleted file mode 100644 index f1e0ad9..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/_cmd.py +++ /dev/null @@ -1,57 +0,0 @@ -import logging - -from pip._vendor import requests - -from pip._vendor.cachecontrol.adapter import CacheControlAdapter -from pip._vendor.cachecontrol.cache import DictCache -from pip._vendor.cachecontrol.controller import logger - -from argparse import ArgumentParser - - -def setup_logging(): - logger.setLevel(logging.DEBUG) - handler = logging.StreamHandler() - logger.addHandler(handler) - - -def get_session(): - adapter = CacheControlAdapter( - DictCache(), cache_etags=True, serializer=None, heuristic=None - ) - sess = requests.Session() - sess.mount("http://", adapter) - sess.mount("https://", adapter) - - sess.cache_controller = adapter.controller - return sess - - -def get_args(): - parser = ArgumentParser() - parser.add_argument("url", help="The URL to try and cache") - return parser.parse_args() - - -def main(args=None): - args = get_args() - sess = get_session() - - # Make a request to get a response - resp = sess.get(args.url) - - # Turn on logging - setup_logging() - - # try setting the cache - sess.cache_controller.cache_response(resp.request, resp.raw) - - # Now try to get it - if sess.cache_controller.cached_request(resp.request): - print("Cached!") - else: - print("Not cached :(") - - -if __name__ == "__main__": - main() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/adapter.py b/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/adapter.py deleted file mode 100644 index 780eb28..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/adapter.py +++ /dev/null @@ -1,133 +0,0 @@ -import types -import functools -import zlib - -from pip._vendor.requests.adapters import HTTPAdapter - -from .controller import CacheController -from .cache import DictCache -from .filewrapper import CallbackFileWrapper - - -class CacheControlAdapter(HTTPAdapter): - invalidating_methods = {"PUT", "DELETE"} - - def __init__( - self, - cache=None, - cache_etags=True, - controller_class=None, - serializer=None, - heuristic=None, - cacheable_methods=None, - *args, - **kw - ): - super(CacheControlAdapter, self).__init__(*args, **kw) - self.cache = cache or DictCache() - self.heuristic = heuristic - self.cacheable_methods = cacheable_methods or ("GET",) - - controller_factory = controller_class or CacheController - self.controller = controller_factory( - self.cache, cache_etags=cache_etags, serializer=serializer - ) - - def send(self, request, cacheable_methods=None, **kw): - """ - Send a request. Use the request information to see if it - exists in the cache and cache the response if we need to and can. - """ - cacheable = cacheable_methods or self.cacheable_methods - if request.method in cacheable: - try: - cached_response = self.controller.cached_request(request) - except zlib.error: - cached_response = None - if cached_response: - return self.build_response(request, cached_response, from_cache=True) - - # check for etags and add headers if appropriate - request.headers.update(self.controller.conditional_headers(request)) - - resp = super(CacheControlAdapter, self).send(request, **kw) - - return resp - - def build_response( - self, request, response, from_cache=False, cacheable_methods=None - ): - """ - Build a response by making a request or using the cache. - - This will end up calling send and returning a potentially - cached response - """ - cacheable = cacheable_methods or self.cacheable_methods - if not from_cache and request.method in cacheable: - # Check for any heuristics that might update headers - # before trying to cache. - if self.heuristic: - response = self.heuristic.apply(response) - - # apply any expiration heuristics - if response.status == 304: - # We must have sent an ETag request. This could mean - # that we've been expired already or that we simply - # have an etag. In either case, we want to try and - # update the cache if that is the case. - cached_response = self.controller.update_cached_response( - request, response - ) - - if cached_response is not response: - from_cache = True - - # We are done with the server response, read a - # possible response body (compliant servers will - # not return one, but we cannot be 100% sure) and - # release the connection back to the pool. - response.read(decode_content=False) - response.release_conn() - - response = cached_response - - # We always cache the 301 responses - elif response.status == 301: - self.controller.cache_response(request, response) - else: - # Wrap the response file with a wrapper that will cache the - # response when the stream has been consumed. - response._fp = CallbackFileWrapper( - response._fp, - functools.partial( - self.controller.cache_response, request, response - ), - ) - if response.chunked: - super_update_chunk_length = response._update_chunk_length - - def _update_chunk_length(self): - super_update_chunk_length() - if self.chunk_left == 0: - self._fp._close() - - response._update_chunk_length = types.MethodType( - _update_chunk_length, response - ) - - resp = super(CacheControlAdapter, self).build_response(request, response) - - # See if we should invalidate the cache. - if request.method in self.invalidating_methods and resp.ok: - cache_url = self.controller.cache_url(request.url) - self.cache.delete(cache_url) - - # Give the request a from_cache attr to let people use it - resp.from_cache = from_cache - - return resp - - def close(self): - self.cache.close() - super(CacheControlAdapter, self).close() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/cache.py b/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/cache.py deleted file mode 100644 index 94e0773..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/cache.py +++ /dev/null @@ -1,39 +0,0 @@ -""" -The cache object API for implementing caches. The default is a thread -safe in-memory dictionary. -""" -from threading import Lock - - -class BaseCache(object): - - def get(self, key): - raise NotImplementedError() - - def set(self, key, value): - raise NotImplementedError() - - def delete(self, key): - raise NotImplementedError() - - def close(self): - pass - - -class DictCache(BaseCache): - - def __init__(self, init_dict=None): - self.lock = Lock() - self.data = init_dict or {} - - def get(self, key): - return self.data.get(key, None) - - def set(self, key, value): - with self.lock: - self.data.update({key: value}) - - def delete(self, key): - with self.lock: - if key in self.data: - self.data.pop(key) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/caches/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/caches/__init__.py deleted file mode 100644 index 0e1658f..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/caches/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .file_cache import FileCache # noqa -from .redis_cache import RedisCache # noqa diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py b/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py deleted file mode 100644 index 1ba0080..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py +++ /dev/null @@ -1,146 +0,0 @@ -import hashlib -import os -from textwrap import dedent - -from ..cache import BaseCache -from ..controller import CacheController - -try: - FileNotFoundError -except NameError: - # py2.X - FileNotFoundError = (IOError, OSError) - - -def _secure_open_write(filename, fmode): - # We only want to write to this file, so open it in write only mode - flags = os.O_WRONLY - - # os.O_CREAT | os.O_EXCL will fail if the file already exists, so we only - # will open *new* files. - # We specify this because we want to ensure that the mode we pass is the - # mode of the file. - flags |= os.O_CREAT | os.O_EXCL - - # Do not follow symlinks to prevent someone from making a symlink that - # we follow and insecurely open a cache file. - if hasattr(os, "O_NOFOLLOW"): - flags |= os.O_NOFOLLOW - - # On Windows we'll mark this file as binary - if hasattr(os, "O_BINARY"): - flags |= os.O_BINARY - - # Before we open our file, we want to delete any existing file that is - # there - try: - os.remove(filename) - except (IOError, OSError): - # The file must not exist already, so we can just skip ahead to opening - pass - - # Open our file, the use of os.O_CREAT | os.O_EXCL will ensure that if a - # race condition happens between the os.remove and this line, that an - # error will be raised. Because we utilize a lockfile this should only - # happen if someone is attempting to attack us. - fd = os.open(filename, flags, fmode) - try: - return os.fdopen(fd, "wb") - - except: - # An error occurred wrapping our FD in a file object - os.close(fd) - raise - - -class FileCache(BaseCache): - - def __init__( - self, - directory, - forever=False, - filemode=0o0600, - dirmode=0o0700, - use_dir_lock=None, - lock_class=None, - ): - - if use_dir_lock is not None and lock_class is not None: - raise ValueError("Cannot use use_dir_lock and lock_class together") - - try: - from pip._vendor.lockfile import LockFile - from pip._vendor.lockfile.mkdirlockfile import MkdirLockFile - except ImportError: - notice = dedent( - """ - NOTE: In order to use the FileCache you must have - lockfile installed. You can install it via pip: - pip install lockfile - """ - ) - raise ImportError(notice) - - else: - if use_dir_lock: - lock_class = MkdirLockFile - - elif lock_class is None: - lock_class = LockFile - - self.directory = directory - self.forever = forever - self.filemode = filemode - self.dirmode = dirmode - self.lock_class = lock_class - - @staticmethod - def encode(x): - return hashlib.sha224(x.encode()).hexdigest() - - def _fn(self, name): - # NOTE: This method should not change as some may depend on it. - # See: https://github.com/ionrock/cachecontrol/issues/63 - hashed = self.encode(name) - parts = list(hashed[:5]) + [hashed] - return os.path.join(self.directory, *parts) - - def get(self, key): - name = self._fn(key) - try: - with open(name, "rb") as fh: - return fh.read() - - except FileNotFoundError: - return None - - def set(self, key, value): - name = self._fn(key) - - # Make sure the directory exists - try: - os.makedirs(os.path.dirname(name), self.dirmode) - except (IOError, OSError): - pass - - with self.lock_class(name) as lock: - # Write our actual file - with _secure_open_write(lock.path, self.filemode) as fh: - fh.write(value) - - def delete(self, key): - name = self._fn(key) - if not self.forever: - try: - os.remove(name) - except FileNotFoundError: - pass - - -def url_to_file_path(url, filecache): - """Return the file cache path based on the URL. - - This does not ensure the file exists! - """ - key = CacheController.cache_url(url) - return filecache._fn(key) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py b/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py deleted file mode 100644 index ed705ce..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py +++ /dev/null @@ -1,33 +0,0 @@ -from __future__ import division - -from datetime import datetime -from pip._vendor.cachecontrol.cache import BaseCache - - -class RedisCache(BaseCache): - - def __init__(self, conn): - self.conn = conn - - def get(self, key): - return self.conn.get(key) - - def set(self, key, value, expires=None): - if not expires: - self.conn.set(key, value) - else: - expires = expires - datetime.utcnow() - self.conn.setex(key, int(expires.total_seconds()), value) - - def delete(self, key): - self.conn.delete(key) - - def clear(self): - """Helper for clearing all the keys in a database. Use with - caution!""" - for key in self.conn.keys(): - self.conn.delete(key) - - def close(self): - """Redis uses connection pooling, no need to close the connection.""" - pass diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/compat.py b/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/compat.py deleted file mode 100644 index 33b5aed..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/compat.py +++ /dev/null @@ -1,29 +0,0 @@ -try: - from urllib.parse import urljoin -except ImportError: - from urlparse import urljoin - - -try: - import cPickle as pickle -except ImportError: - import pickle - - -# Handle the case where the requests module has been patched to not have -# urllib3 bundled as part of its source. -try: - from pip._vendor.requests.packages.urllib3.response import HTTPResponse -except ImportError: - from pip._vendor.urllib3.response import HTTPResponse - -try: - from pip._vendor.requests.packages.urllib3.util import is_fp_closed -except ImportError: - from pip._vendor.urllib3.util import is_fp_closed - -# Replicate some six behaviour -try: - text_type = unicode -except NameError: - text_type = str diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/controller.py b/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/controller.py deleted file mode 100644 index 1b2b943..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/controller.py +++ /dev/null @@ -1,367 +0,0 @@ -""" -The httplib2 algorithms ported for use with requests. -""" -import logging -import re -import calendar -import time -from email.utils import parsedate_tz - -from pip._vendor.requests.structures import CaseInsensitiveDict - -from .cache import DictCache -from .serialize import Serializer - - -logger = logging.getLogger(__name__) - -URI = re.compile(r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?") - - -def parse_uri(uri): - """Parses a URI using the regex given in Appendix B of RFC 3986. - - (scheme, authority, path, query, fragment) = parse_uri(uri) - """ - groups = URI.match(uri).groups() - return (groups[1], groups[3], groups[4], groups[6], groups[8]) - - -class CacheController(object): - """An interface to see if request should cached or not. - """ - - def __init__( - self, cache=None, cache_etags=True, serializer=None, status_codes=None - ): - self.cache = cache or DictCache() - self.cache_etags = cache_etags - self.serializer = serializer or Serializer() - self.cacheable_status_codes = status_codes or (200, 203, 300, 301) - - @classmethod - def _urlnorm(cls, uri): - """Normalize the URL to create a safe key for the cache""" - (scheme, authority, path, query, fragment) = parse_uri(uri) - if not scheme or not authority: - raise Exception("Only absolute URIs are allowed. uri = %s" % uri) - - scheme = scheme.lower() - authority = authority.lower() - - if not path: - path = "/" - - # Could do syntax based normalization of the URI before - # computing the digest. See Section 6.2.2 of Std 66. - request_uri = query and "?".join([path, query]) or path - defrag_uri = scheme + "://" + authority + request_uri - - return defrag_uri - - @classmethod - def cache_url(cls, uri): - return cls._urlnorm(uri) - - def parse_cache_control(self, headers): - known_directives = { - # https://tools.ietf.org/html/rfc7234#section-5.2 - "max-age": (int, True), - "max-stale": (int, False), - "min-fresh": (int, True), - "no-cache": (None, False), - "no-store": (None, False), - "no-transform": (None, False), - "only-if-cached": (None, False), - "must-revalidate": (None, False), - "public": (None, False), - "private": (None, False), - "proxy-revalidate": (None, False), - "s-maxage": (int, True), - } - - cc_headers = headers.get("cache-control", headers.get("Cache-Control", "")) - - retval = {} - - for cc_directive in cc_headers.split(","): - if not cc_directive.strip(): - continue - - parts = cc_directive.split("=", 1) - directive = parts[0].strip() - - try: - typ, required = known_directives[directive] - except KeyError: - logger.debug("Ignoring unknown cache-control directive: %s", directive) - continue - - if not typ or not required: - retval[directive] = None - if typ: - try: - retval[directive] = typ(parts[1].strip()) - except IndexError: - if required: - logger.debug( - "Missing value for cache-control " "directive: %s", - directive, - ) - except ValueError: - logger.debug( - "Invalid value for cache-control directive " "%s, must be %s", - directive, - typ.__name__, - ) - - return retval - - def cached_request(self, request): - """ - Return a cached response if it exists in the cache, otherwise - return False. - """ - cache_url = self.cache_url(request.url) - logger.debug('Looking up "%s" in the cache', cache_url) - cc = self.parse_cache_control(request.headers) - - # Bail out if the request insists on fresh data - if "no-cache" in cc: - logger.debug('Request header has "no-cache", cache bypassed') - return False - - if "max-age" in cc and cc["max-age"] == 0: - logger.debug('Request header has "max_age" as 0, cache bypassed') - return False - - # Request allows serving from the cache, let's see if we find something - cache_data = self.cache.get(cache_url) - if cache_data is None: - logger.debug("No cache entry available") - return False - - # Check whether it can be deserialized - resp = self.serializer.loads(request, cache_data) - if not resp: - logger.warning("Cache entry deserialization failed, entry ignored") - return False - - # If we have a cached 301, return it immediately. We don't - # need to test our response for other headers b/c it is - # intrinsically "cacheable" as it is Permanent. - # See: - # https://tools.ietf.org/html/rfc7231#section-6.4.2 - # - # Client can try to refresh the value by repeating the request - # with cache busting headers as usual (ie no-cache). - if resp.status == 301: - msg = ( - 'Returning cached "301 Moved Permanently" response ' - "(ignoring date and etag information)" - ) - logger.debug(msg) - return resp - - headers = CaseInsensitiveDict(resp.headers) - if not headers or "date" not in headers: - if "etag" not in headers: - # Without date or etag, the cached response can never be used - # and should be deleted. - logger.debug("Purging cached response: no date or etag") - self.cache.delete(cache_url) - logger.debug("Ignoring cached response: no date") - return False - - now = time.time() - date = calendar.timegm(parsedate_tz(headers["date"])) - current_age = max(0, now - date) - logger.debug("Current age based on date: %i", current_age) - - # TODO: There is an assumption that the result will be a - # urllib3 response object. This may not be best since we - # could probably avoid instantiating or constructing the - # response until we know we need it. - resp_cc = self.parse_cache_control(headers) - - # determine freshness - freshness_lifetime = 0 - - # Check the max-age pragma in the cache control header - if "max-age" in resp_cc: - freshness_lifetime = resp_cc["max-age"] - logger.debug("Freshness lifetime from max-age: %i", freshness_lifetime) - - # If there isn't a max-age, check for an expires header - elif "expires" in headers: - expires = parsedate_tz(headers["expires"]) - if expires is not None: - expire_time = calendar.timegm(expires) - date - freshness_lifetime = max(0, expire_time) - logger.debug("Freshness lifetime from expires: %i", freshness_lifetime) - - # Determine if we are setting freshness limit in the - # request. Note, this overrides what was in the response. - if "max-age" in cc: - freshness_lifetime = cc["max-age"] - logger.debug( - "Freshness lifetime from request max-age: %i", freshness_lifetime - ) - - if "min-fresh" in cc: - min_fresh = cc["min-fresh"] - # adjust our current age by our min fresh - current_age += min_fresh - logger.debug("Adjusted current age from min-fresh: %i", current_age) - - # Return entry if it is fresh enough - if freshness_lifetime > current_age: - logger.debug('The response is "fresh", returning cached response') - logger.debug("%i > %i", freshness_lifetime, current_age) - return resp - - # we're not fresh. If we don't have an Etag, clear it out - if "etag" not in headers: - logger.debug('The cached response is "stale" with no etag, purging') - self.cache.delete(cache_url) - - # return the original handler - return False - - def conditional_headers(self, request): - cache_url = self.cache_url(request.url) - resp = self.serializer.loads(request, self.cache.get(cache_url)) - new_headers = {} - - if resp: - headers = CaseInsensitiveDict(resp.headers) - - if "etag" in headers: - new_headers["If-None-Match"] = headers["ETag"] - - if "last-modified" in headers: - new_headers["If-Modified-Since"] = headers["Last-Modified"] - - return new_headers - - def cache_response(self, request, response, body=None, status_codes=None): - """ - Algorithm for caching requests. - - This assumes a requests Response object. - """ - # From httplib2: Don't cache 206's since we aren't going to - # handle byte range requests - cacheable_status_codes = status_codes or self.cacheable_status_codes - if response.status not in cacheable_status_codes: - logger.debug( - "Status code %s not in %s", response.status, cacheable_status_codes - ) - return - - response_headers = CaseInsensitiveDict(response.headers) - - # If we've been given a body, our response has a Content-Length, that - # Content-Length is valid then we can check to see if the body we've - # been given matches the expected size, and if it doesn't we'll just - # skip trying to cache it. - if ( - body is not None - and "content-length" in response_headers - and response_headers["content-length"].isdigit() - and int(response_headers["content-length"]) != len(body) - ): - return - - cc_req = self.parse_cache_control(request.headers) - cc = self.parse_cache_control(response_headers) - - cache_url = self.cache_url(request.url) - logger.debug('Updating cache with response from "%s"', cache_url) - - # Delete it from the cache if we happen to have it stored there - no_store = False - if "no-store" in cc: - no_store = True - logger.debug('Response header has "no-store"') - if "no-store" in cc_req: - no_store = True - logger.debug('Request header has "no-store"') - if no_store and self.cache.get(cache_url): - logger.debug('Purging existing cache entry to honor "no-store"') - self.cache.delete(cache_url) - if no_store: - return - - # If we've been given an etag, then keep the response - if self.cache_etags and "etag" in response_headers: - logger.debug("Caching due to etag") - self.cache.set( - cache_url, self.serializer.dumps(request, response, body=body) - ) - - # Add to the cache any 301s. We do this before looking that - # the Date headers. - elif response.status == 301: - logger.debug("Caching permanant redirect") - self.cache.set(cache_url, self.serializer.dumps(request, response)) - - # Add to the cache if the response headers demand it. If there - # is no date header then we can't do anything about expiring - # the cache. - elif "date" in response_headers: - # cache when there is a max-age > 0 - if "max-age" in cc and cc["max-age"] > 0: - logger.debug("Caching b/c date exists and max-age > 0") - self.cache.set( - cache_url, self.serializer.dumps(request, response, body=body) - ) - - # If the request can expire, it means we should cache it - # in the meantime. - elif "expires" in response_headers: - if response_headers["expires"]: - logger.debug("Caching b/c of expires header") - self.cache.set( - cache_url, self.serializer.dumps(request, response, body=body) - ) - - def update_cached_response(self, request, response): - """On a 304 we will get a new set of headers that we want to - update our cached value with, assuming we have one. - - This should only ever be called when we've sent an ETag and - gotten a 304 as the response. - """ - cache_url = self.cache_url(request.url) - - cached_response = self.serializer.loads(request, self.cache.get(cache_url)) - - if not cached_response: - # we didn't have a cached response - return response - - # Lets update our headers with the headers from the new request: - # http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-4.1 - # - # The server isn't supposed to send headers that would make - # the cached body invalid. But... just in case, we'll be sure - # to strip out ones we know that might be problmatic due to - # typical assumptions. - excluded_headers = ["content-length"] - - cached_response.headers.update( - dict( - (k, v) - for k, v in response.headers.items() - if k.lower() not in excluded_headers - ) - ) - - # we want a 200 b/c we have content via the cache - cached_response.status = 200 - - # update our cache - self.cache.set(cache_url, self.serializer.dumps(request, cached_response)) - - return cached_response diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/filewrapper.py b/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/filewrapper.py deleted file mode 100644 index 30ed4c5..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/filewrapper.py +++ /dev/null @@ -1,80 +0,0 @@ -from io import BytesIO - - -class CallbackFileWrapper(object): - """ - Small wrapper around a fp object which will tee everything read into a - buffer, and when that file is closed it will execute a callback with the - contents of that buffer. - - All attributes are proxied to the underlying file object. - - This class uses members with a double underscore (__) leading prefix so as - not to accidentally shadow an attribute. - """ - - def __init__(self, fp, callback): - self.__buf = BytesIO() - self.__fp = fp - self.__callback = callback - - def __getattr__(self, name): - # The vaguaries of garbage collection means that self.__fp is - # not always set. By using __getattribute__ and the private - # name[0] allows looking up the attribute value and raising an - # AttributeError when it doesn't exist. This stop thigns from - # infinitely recursing calls to getattr in the case where - # self.__fp hasn't been set. - # - # [0] https://docs.python.org/2/reference/expressions.html#atom-identifiers - fp = self.__getattribute__("_CallbackFileWrapper__fp") - return getattr(fp, name) - - def __is_fp_closed(self): - try: - return self.__fp.fp is None - - except AttributeError: - pass - - try: - return self.__fp.closed - - except AttributeError: - pass - - # We just don't cache it then. - # TODO: Add some logging here... - return False - - def _close(self): - if self.__callback: - self.__callback(self.__buf.getvalue()) - - # We assign this to None here, because otherwise we can get into - # really tricky problems where the CPython interpreter dead locks - # because the callback is holding a reference to something which - # has a __del__ method. Setting this to None breaks the cycle - # and allows the garbage collector to do it's thing normally. - self.__callback = None - - def read(self, amt=None): - data = self.__fp.read(amt) - self.__buf.write(data) - if self.__is_fp_closed(): - self._close() - - return data - - def _safe_read(self, amt): - data = self.__fp._safe_read(amt) - if amt == 2 and data == b"\r\n": - # urllib executes this read to toss the CRLF at the end - # of the chunk. - return data - - self.__buf.write(data) - if self.__is_fp_closed(): - self._close() - - return data diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/heuristics.py b/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/heuristics.py deleted file mode 100644 index 6c0e979..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/heuristics.py +++ /dev/null @@ -1,135 +0,0 @@ -import calendar -import time - -from email.utils import formatdate, parsedate, parsedate_tz - -from datetime import datetime, timedelta - -TIME_FMT = "%a, %d %b %Y %H:%M:%S GMT" - - -def expire_after(delta, date=None): - date = date or datetime.utcnow() - return date + delta - - -def datetime_to_header(dt): - return formatdate(calendar.timegm(dt.timetuple())) - - -class BaseHeuristic(object): - - def warning(self, response): - """ - Return a valid 1xx warning header value describing the cache - adjustments. - - The response is provided too allow warnings like 113 - http://tools.ietf.org/html/rfc7234#section-5.5.4 where we need - to explicitly say response is over 24 hours old. - """ - return '110 - "Response is Stale"' - - def update_headers(self, response): - """Update the response headers with any new headers. - - NOTE: This SHOULD always include some Warning header to - signify that the response was cached by the client, not - by way of the provided headers. - """ - return {} - - def apply(self, response): - updated_headers = self.update_headers(response) - - if updated_headers: - response.headers.update(updated_headers) - warning_header_value = self.warning(response) - if warning_header_value is not None: - response.headers.update({"Warning": warning_header_value}) - - return response - - -class OneDayCache(BaseHeuristic): - """ - Cache the response by providing an expires 1 day in the - future. - """ - - def update_headers(self, response): - headers = {} - - if "expires" not in response.headers: - date = parsedate(response.headers["date"]) - expires = expire_after(timedelta(days=1), date=datetime(*date[:6])) - headers["expires"] = datetime_to_header(expires) - headers["cache-control"] = "public" - return headers - - -class ExpiresAfter(BaseHeuristic): - """ - Cache **all** requests for a defined time period. - """ - - def __init__(self, **kw): - self.delta = timedelta(**kw) - - def update_headers(self, response): - expires = expire_after(self.delta) - return {"expires": datetime_to_header(expires), "cache-control": "public"} - - def warning(self, response): - tmpl = "110 - Automatically cached for %s. Response might be stale" - return tmpl % self.delta - - -class LastModified(BaseHeuristic): - """ - If there is no Expires header already, fall back on Last-Modified - using the heuristic from - http://tools.ietf.org/html/rfc7234#section-4.2.2 - to calculate a reasonable value. - - Firefox also does something like this per - https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching_FAQ - http://lxr.mozilla.org/mozilla-release/source/netwerk/protocol/http/nsHttpResponseHead.cpp#397 - Unlike mozilla we limit this to 24-hr. - """ - cacheable_by_default_statuses = { - 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501 - } - - def update_headers(self, resp): - headers = resp.headers - - if "expires" in headers: - return {} - - if "cache-control" in headers and headers["cache-control"] != "public": - return {} - - if resp.status not in self.cacheable_by_default_statuses: - return {} - - if "date" not in headers or "last-modified" not in headers: - return {} - - date = calendar.timegm(parsedate_tz(headers["date"])) - last_modified = parsedate(headers["last-modified"]) - if date is None or last_modified is None: - return {} - - now = time.time() - current_age = max(0, now - date) - delta = date - calendar.timegm(last_modified) - freshness_lifetime = max(0, min(delta / 10, 24 * 3600)) - if freshness_lifetime <= current_age: - return {} - - expires = date + freshness_lifetime - return {"expires": time.strftime(TIME_FMT, time.gmtime(expires))} - - def warning(self, resp): - return None diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/serialize.py b/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/serialize.py deleted file mode 100644 index ec43ff2..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/serialize.py +++ /dev/null @@ -1,186 +0,0 @@ -import base64 -import io -import json -import zlib - -from pip._vendor import msgpack -from pip._vendor.requests.structures import CaseInsensitiveDict - -from .compat import HTTPResponse, pickle, text_type - - -def _b64_decode_bytes(b): - return base64.b64decode(b.encode("ascii")) - - -def _b64_decode_str(s): - return _b64_decode_bytes(s).decode("utf8") - - -class Serializer(object): - - def dumps(self, request, response, body=None): - response_headers = CaseInsensitiveDict(response.headers) - - if body is None: - body = response.read(decode_content=False) - - # NOTE: 99% sure this is dead code. I'm only leaving it - # here b/c I don't have a test yet to prove - # it. Basically, before using - # `cachecontrol.filewrapper.CallbackFileWrapper`, - # this made an effort to reset the file handle. The - # `CallbackFileWrapper` short circuits this code by - # setting the body as the content is consumed, the - # result being a `body` argument is *always* passed - # into cache_response, and in turn, - # `Serializer.dump`. - response._fp = io.BytesIO(body) - - # NOTE: This is all a bit weird, but it's really important that on - # Python 2.x these objects are unicode and not str, even when - # they contain only ascii. The problem here is that msgpack - # understands the difference between unicode and bytes and we - # have it set to differentiate between them, however Python 2 - # doesn't know the difference. Forcing these to unicode will be - # enough to have msgpack know the difference. - data = { - u"response": { - u"body": body, - u"headers": dict( - (text_type(k), text_type(v)) for k, v in response.headers.items() - ), - u"status": response.status, - u"version": response.version, - u"reason": text_type(response.reason), - u"strict": response.strict, - u"decode_content": response.decode_content, - } - } - - # Construct our vary headers - data[u"vary"] = {} - if u"vary" in response_headers: - varied_headers = response_headers[u"vary"].split(",") - for header in varied_headers: - header = text_type(header).strip() - header_value = request.headers.get(header, None) - if header_value is not None: - header_value = text_type(header_value) - data[u"vary"][header] = header_value - - return b",".join([b"cc=4", msgpack.dumps(data, use_bin_type=True)]) - - def loads(self, request, data): - # Short circuit if we've been given an empty set of data - if not data: - return - - # Determine what version of the serializer the data was serialized - # with - try: - ver, data = data.split(b",", 1) - except ValueError: - ver = b"cc=0" - - # Make sure that our "ver" is actually a version and isn't a false - # positive from a , being in the data stream. - if ver[:3] != b"cc=": - data = ver + data - ver = b"cc=0" - - # Get the version number out of the cc=N - ver = ver.split(b"=", 1)[-1].decode("ascii") - - # Dispatch to the actual load method for the given version - try: - return getattr(self, "_loads_v{}".format(ver))(request, data) - - except AttributeError: - # This is a version we don't have a loads function for, so we'll - # just treat it as a miss and return None - return - - def prepare_response(self, request, cached): - """Verify our vary headers match and construct a real urllib3 - HTTPResponse object. - """ - # Special case the '*' Vary value as it means we cannot actually - # determine if the cached response is suitable for this request. - if "*" in cached.get("vary", {}): - return - - # Ensure that the Vary headers for the cached response match our - # request - for header, value in cached.get("vary", {}).items(): - if request.headers.get(header, None) != value: - return - - body_raw = cached["response"].pop("body") - - headers = CaseInsensitiveDict(data=cached["response"]["headers"]) - if headers.get("transfer-encoding", "") == "chunked": - headers.pop("transfer-encoding") - - cached["response"]["headers"] = headers - - try: - body = io.BytesIO(body_raw) - except TypeError: - # This can happen if cachecontrol serialized to v1 format (pickle) - # using Python 2. A Python 2 str(byte string) will be unpickled as - # a Python 3 str (unicode string), which will cause the above to - # fail with: - # - # TypeError: 'str' does not support the buffer interface - body = io.BytesIO(body_raw.encode("utf8")) - - return HTTPResponse(body=body, preload_content=False, **cached["response"]) - - def _loads_v0(self, request, data): - # The original legacy cache data. This doesn't contain enough - # information to construct everything we need, so we'll treat this as - # a miss. - return - - def _loads_v1(self, request, data): - try: - cached = pickle.loads(data) - except ValueError: - return - - return self.prepare_response(request, cached) - - def _loads_v2(self, request, data): - try: - cached = json.loads(zlib.decompress(data).decode("utf8")) - except (ValueError, zlib.error): - return - - # We need to decode the items that we've base64 encoded - cached["response"]["body"] = _b64_decode_bytes(cached["response"]["body"]) - cached["response"]["headers"] = dict( - (_b64_decode_str(k), _b64_decode_str(v)) - for k, v in cached["response"]["headers"].items() - ) - cached["response"]["reason"] = _b64_decode_str(cached["response"]["reason"]) - cached["vary"] = dict( - (_b64_decode_str(k), _b64_decode_str(v) if v is not None else v) - for k, v in cached["vary"].items() - ) - - return self.prepare_response(request, cached) - - def _loads_v3(self, request, data): - # Due to Python 2 encoding issues, it's impossible to know for sure - # exactly how to load v3 entries, thus we'll treat these as a miss so - # that they get rewritten out as v4 entries. - return - - def _loads_v4(self, request, data): - try: - cached = msgpack.loads(data, encoding="utf-8") - except ValueError: - return - - return self.prepare_response(request, cached) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/wrapper.py b/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/wrapper.py deleted file mode 100644 index 265bfc8..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/cachecontrol/wrapper.py +++ /dev/null @@ -1,29 +0,0 @@ -from .adapter import CacheControlAdapter -from .cache import DictCache - - -def CacheControl( - sess, - cache=None, - cache_etags=True, - serializer=None, - heuristic=None, - controller_class=None, - adapter_class=None, - cacheable_methods=None, -): - - cache = cache or DictCache() - adapter_class = adapter_class or CacheControlAdapter - adapter = adapter_class( - cache, - cache_etags=cache_etags, - serializer=serializer, - heuristic=heuristic, - controller_class=controller_class, - cacheable_methods=cacheable_methods, - ) - sess.mount("http://", adapter) - sess.mount("https://", adapter) - - return sess diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/certifi/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/certifi/__init__.py deleted file mode 100644 index 632db8e..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/certifi/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .core import where - -__version__ = "2019.03.09" diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/certifi/__main__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/certifi/__main__.py deleted file mode 100644 index ae2aff5..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/certifi/__main__.py +++ /dev/null @@ -1,2 +0,0 @@ -from pip._vendor.certifi import where -print(where()) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/certifi/cacert.pem b/venv2/lib/python2.7/site-packages/pip/_vendor/certifi/cacert.pem deleted file mode 100644 index 84636dd..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/certifi/cacert.pem +++ /dev/null @@ -1,4658 +0,0 @@ - -# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA -# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA -# Label: "GlobalSign Root CA" -# Serial: 4835703278459707669005204 -# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a -# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c -# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99 ------BEGIN CERTIFICATE----- -MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG -A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv -b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw -MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i -YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT -aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ -jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp -xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp -1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG -snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ -U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 -9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E -BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B -AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz -yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE -38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP -AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad -DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME -HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 -# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 -# Label: "GlobalSign Root CA - R2" -# Serial: 4835703278459682885658125 -# MD5 Fingerprint: 94:14:77:7e:3e:5e:fd:8f:30:bd:41:b0:cf:e7:d0:30 -# SHA1 Fingerprint: 75:e0:ab:b6:13:85:12:27:1c:04:f8:5f:dd:de:38:e4:b7:24:2e:fe -# SHA256 Fingerprint: ca:42:dd:41:74:5f:d0:b8:1e:b9:02:36:2c:f9:d8:bf:71:9d:a1:bd:1b:1e:fc:94:6f:5b:4c:99:f4:2c:1b:9e ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 -MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL -v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 -eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq -tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd -C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa -zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB -mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH -V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n -bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG -3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs -J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO -291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS -ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd -AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 -TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== ------END CERTIFICATE----- - -# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only -# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only -# Label: "Verisign Class 3 Public Primary Certification Authority - G3" -# Serial: 206684696279472310254277870180966723415 -# MD5 Fingerprint: cd:68:b6:a7:c7:c4:ce:75:e0:1d:4f:57:44:61:92:09 -# SHA1 Fingerprint: 13:2d:0d:45:53:4b:69:97:cd:b2:d5:c3:39:e2:55:76:60:9b:5c:c6 -# SHA256 Fingerprint: eb:04:cf:5e:b1:f3:9a:fa:76:2f:2b:b1:20:f2:96:cb:a5:20:c1:b9:7d:b1:58:95:65:b8:1c:b9:a1:7b:72:44 ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b -N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t -KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu -kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm -CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ -Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu -imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te -2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe -DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC -/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p -F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt -TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== ------END CERTIFICATE----- - -# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited -# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited -# Label: "Entrust.net Premium 2048 Secure Server CA" -# Serial: 946069240 -# MD5 Fingerprint: ee:29:31:bc:32:7e:9a:e6:e8:b5:f7:51:b4:34:71:90 -# SHA1 Fingerprint: 50:30:06:09:1d:97:d4:f5:ae:39:f7:cb:e7:92:7d:7d:65:2d:34:31 -# SHA256 Fingerprint: 6d:c4:71:72:e0:1c:bc:b0:bf:62:58:0d:89:5f:e2:b8:ac:9a:d4:f8:73:80:1e:0c:10:b9:c8:37:d2:1e:b1:77 ------BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML -RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp -bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 -IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 -MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 -LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp -YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG -A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq -K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe -sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX -MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT -XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ -HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH -4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV -HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub -j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo -U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf -zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b -u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ -bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er -fF6adulZkMV8gzURZVE= ------END CERTIFICATE----- - -# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust -# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust -# Label: "Baltimore CyberTrust Root" -# Serial: 33554617 -# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4 -# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74 -# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ -RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD -VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX -DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y -ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy -VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr -mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr -IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK -mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu -XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy -dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye -jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 -BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 -DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 -9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx -jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 -Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz -ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS -R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp ------END CERTIFICATE----- - -# Issuer: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network -# Subject: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network -# Label: "AddTrust External Root" -# Serial: 1 -# MD5 Fingerprint: 1d:35:54:04:85:78:b0:3f:42:42:4d:bf:20:73:0a:3f -# SHA1 Fingerprint: 02:fa:f3:e2:91:43:54:68:60:78:57:69:4d:f5:e4:5b:68:85:18:68 -# SHA256 Fingerprint: 68:7f:a4:51:38:22:78:ff:f0:c8:b1:1f:8d:43:d5:76:67:1c:6e:b2:bc:ea:b4:13:fb:83:d9:65:d0:6d:2f:f2 ------BEGIN CERTIFICATE----- -MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs -IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 -MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux -FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h -bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v -dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt -H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 -uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX -mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX -a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN -E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 -WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD -VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 -Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU -cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx -IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN -AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH -YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 -6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC -Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX -c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a -mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= ------END CERTIFICATE----- - -# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. -# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. -# Label: "Entrust Root Certification Authority" -# Serial: 1164660820 -# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4 -# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9 -# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c ------BEGIN CERTIFICATE----- -MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC -VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 -Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW -KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl -cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw -NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw -NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy -ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV -BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo -Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 -4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 -KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI -rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi -94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB -sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi -gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo -kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE -vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA -A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t -O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua -AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP -9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ -eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m -0vdXcDazv/wor3ElhVsT/h5/WrQ8 ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Global CA O=GeoTrust Inc. -# Subject: CN=GeoTrust Global CA O=GeoTrust Inc. -# Label: "GeoTrust Global CA" -# Serial: 144470 -# MD5 Fingerprint: f7:75:ab:29:fb:51:4e:b7:77:5e:ff:05:3c:99:8e:f5 -# SHA1 Fingerprint: de:28:f4:a4:ff:e5:b9:2f:a3:c5:03:d1:a3:49:a7:f9:96:2a:82:12 -# SHA256 Fingerprint: ff:85:6a:2d:25:1d:cd:88:d3:66:56:f4:50:12:67:98:cf:ab:aa:de:40:79:9c:72:2d:e4:d2:b5:db:36:a7:3a ------BEGIN CERTIFICATE----- -MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT -MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i -YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG -EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg -R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 -9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq -fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv -iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU -1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ -bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW -MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA -ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l -uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn -Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS -tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF -PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un -hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV -5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Universal CA O=GeoTrust Inc. -# Subject: CN=GeoTrust Universal CA O=GeoTrust Inc. -# Label: "GeoTrust Universal CA" -# Serial: 1 -# MD5 Fingerprint: 92:65:58:8b:a2:1a:31:72:73:68:5c:b4:a5:7a:07:48 -# SHA1 Fingerprint: e6:21:f3:35:43:79:05:9a:4b:68:30:9d:8a:2f:74:22:15:87:ec:79 -# SHA256 Fingerprint: a0:45:9b:9f:63:b2:25:59:f5:fa:5d:4c:6d:b3:f9:f7:2f:f1:93:42:03:35:78:f0:73:bf:1d:1b:46:cb:b9:12 ------BEGIN CERTIFICATE----- -MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy -c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE -BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 -IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV -VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 -cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT -QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh -F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v -c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w -mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd -VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX -teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ -f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe -Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ -nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB -/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY -MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG -9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc -aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX -IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn -ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z -uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN -Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja -QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW -koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 -ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt -DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm -bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. -# Subject: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. -# Label: "GeoTrust Universal CA 2" -# Serial: 1 -# MD5 Fingerprint: 34:fc:b8:d0:36:db:9e:14:b3:c2:f2:db:8f:e4:94:c7 -# SHA1 Fingerprint: 37:9a:19:7b:41:85:45:35:0c:a6:03:69:f3:3c:2e:af:47:4f:20:79 -# SHA256 Fingerprint: a0:23:4f:3b:c8:52:7c:a5:62:8e:ec:81:ad:5d:69:89:5d:a5:68:0d:c9:1d:1c:b8:47:7f:33:f8:78:b9:5b:0b ------BEGIN CERTIFICATE----- -MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy -c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD -VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 -c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 -WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG -FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq -XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL -se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb -KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd -IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 -y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt -hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc -QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 -Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV -HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ -KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z -dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ -L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr -Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo -ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY -T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz -GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m -1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV -OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH -6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX -QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS ------END CERTIFICATE----- - -# Issuer: CN=AAA Certificate Services O=Comodo CA Limited -# Subject: CN=AAA Certificate Services O=Comodo CA Limited -# Label: "Comodo AAA Services root" -# Serial: 1 -# MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0 -# SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49 -# SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4 ------BEGIN CERTIFICATE----- -MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj -YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL -MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE -BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM -GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua -BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe -3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 -YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR -rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm -ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU -oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF -MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v -QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t -b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF -AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q -GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz -Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 -G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi -l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 -smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== ------END CERTIFICATE----- - -# Issuer: CN=QuoVadis Root Certification Authority O=QuoVadis Limited OU=Root Certification Authority -# Subject: CN=QuoVadis Root Certification Authority O=QuoVadis Limited OU=Root Certification Authority -# Label: "QuoVadis Root CA" -# Serial: 985026699 -# MD5 Fingerprint: 27:de:36:fe:72:b7:00:03:00:9d:f4:f0:1e:6c:04:24 -# SHA1 Fingerprint: de:3f:40:bd:50:93:d3:9b:6c:60:f6:da:bc:07:62:01:00:89:76:c9 -# SHA256 Fingerprint: a4:5e:de:3b:bb:f0:9c:8a:e1:5c:72:ef:c0:72:68:d6:93:a2:1c:99:6f:d5:1e:67:ca:07:94:60:fd:6d:88:73 ------BEGIN CERTIFICATE----- -MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC -TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz -MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw -IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR -dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp -li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D -rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ -WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug -F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU -xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC -Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv -dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw -ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl -IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh -c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy -ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh -Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI -KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T -KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq -y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p -dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD -VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL -MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk -fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 -7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R -cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y -mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW -xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK -SnQ2+Q== ------END CERTIFICATE----- - -# Issuer: CN=QuoVadis Root CA 2 O=QuoVadis Limited -# Subject: CN=QuoVadis Root CA 2 O=QuoVadis Limited -# Label: "QuoVadis Root CA 2" -# Serial: 1289 -# MD5 Fingerprint: 5e:39:7b:dd:f8:ba:ec:82:e9:ac:62:ba:0c:54:00:2b -# SHA1 Fingerprint: ca:3a:fb:cf:12:40:36:4b:44:b2:16:20:88:80:48:39:19:93:7c:f7 -# SHA256 Fingerprint: 85:a0:dd:7d:d7:20:ad:b7:ff:05:f8:3d:54:2b:20:9d:c7:ff:45:28:f7:d6:77:b1:83:89:fe:a5:e5:c4:9e:86 ------BEGIN CERTIFICATE----- -MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x -GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv -b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV -BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W -YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa -GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg -Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J -WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB -rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp -+ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1 -ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i -Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz -PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og -/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH -oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI -yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud -EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2 -A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL -MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT -ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f -BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn -g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl -fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K -WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha -B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc -hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR -TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD -mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z -ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y -4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza -8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u ------END CERTIFICATE----- - -# Issuer: CN=QuoVadis Root CA 3 O=QuoVadis Limited -# Subject: CN=QuoVadis Root CA 3 O=QuoVadis Limited -# Label: "QuoVadis Root CA 3" -# Serial: 1478 -# MD5 Fingerprint: 31:85:3c:62:94:97:63:b9:aa:fd:89:4e:af:6f:e0:cf -# SHA1 Fingerprint: 1f:49:14:f7:d8:74:95:1d:dd:ae:02:c0:be:fd:3a:2d:82:75:51:85 -# SHA256 Fingerprint: 18:f1:fc:7f:20:5d:f8:ad:dd:eb:7f:e0:07:dd:57:e3:af:37:5a:9c:4d:8d:73:54:6b:f4:f1:fe:d1:e1:8d:35 ------BEGIN CERTIFICATE----- -MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x -GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv -b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV -BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W -YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM -V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB -4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr -H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd -8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv -vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT -mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe -btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc -T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt -WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ -c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A -4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD -VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG -CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 -aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 -aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu -dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw -czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G -A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC -TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg -Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 -7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem -d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd -+LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B -4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN -t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x -DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 -k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s -zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j -Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT -mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK -4SVhM7JZG+Ju1zdXtg2pEto= ------END CERTIFICATE----- - -# Issuer: O=SECOM Trust.net OU=Security Communication RootCA1 -# Subject: O=SECOM Trust.net OU=Security Communication RootCA1 -# Label: "Security Communication Root CA" -# Serial: 0 -# MD5 Fingerprint: f1:bc:63:6a:54:e0:b5:27:f5:cd:e7:1a:e3:4d:6e:4a -# SHA1 Fingerprint: 36:b1:2b:49:f9:81:9e:d7:4c:9e:bc:38:0f:c6:56:8f:5d:ac:b2:f7 -# SHA256 Fingerprint: e7:5e:72:ed:9f:56:0e:ec:6e:b4:80:00:73:a4:3f:c3:ad:19:19:5a:39:22:82:01:78:95:97:4a:99:02:6b:6c ------BEGIN CERTIFICATE----- -MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY -MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t -dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 -WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD -VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 -9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ -DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 -Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N -QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ -xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G -A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T -AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG -kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr -Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 -Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU -JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot -RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== ------END CERTIFICATE----- - -# Issuer: CN=Sonera Class2 CA O=Sonera -# Subject: CN=Sonera Class2 CA O=Sonera -# Label: "Sonera Class 2 Root CA" -# Serial: 29 -# MD5 Fingerprint: a3:ec:75:0f:2e:88:df:fa:48:01:4e:0b:5c:48:6f:fb -# SHA1 Fingerprint: 37:f7:6d:e6:07:7c:90:c5:b1:3e:93:1a:b7:41:10:b4:f2:e4:9a:27 -# SHA256 Fingerprint: 79:08:b4:03:14:c1:38:10:0b:51:8d:07:35:80:7f:fb:fc:f8:51:8a:00:95:33:71:05:ba:38:6b:15:3d:d9:27 ------BEGIN CERTIFICATE----- -MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP -MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx -MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV -BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o -Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt -5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s -3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej -vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu -8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw -DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG -MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil -zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ -3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD -FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 -Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 -ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M ------END CERTIFICATE----- - -# Issuer: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com -# Subject: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com -# Label: "XRamp Global CA Root" -# Serial: 107108908803651509692980124233745014957 -# MD5 Fingerprint: a1:0b:44:b3:ca:10:d8:00:6e:9d:0f:d8:0f:92:0a:d1 -# SHA1 Fingerprint: b8:01:86:d1:eb:9c:86:a5:41:04:cf:30:54:f3:4c:52:b7:e5:58:c6 -# SHA256 Fingerprint: ce:cd:dc:90:50:99:d8:da:df:c5:b1:d2:09:b7:37:cb:e2:c1:8c:fb:2c:10:c0:ff:0b:cf:0d:32:86:fc:1a:a2 ------BEGIN CERTIFICATE----- -MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB -gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk -MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY -UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx -NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 -dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy -dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB -dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 -38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP -KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q -DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 -qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa -JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi -PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P -BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs -jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 -eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD -ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR -vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt -qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa -IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy -i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ -O+7ETPTsJ3xCwnR8gooJybQDJbw= ------END CERTIFICATE----- - -# Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority -# Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority -# Label: "Go Daddy Class 2 CA" -# Serial: 0 -# MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67 -# SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4 -# SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4 ------BEGIN CERTIFICATE----- -MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh -MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE -YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 -MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo -ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg -MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN -ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA -PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w -wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi -EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY -avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ -YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE -sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h -/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 -IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD -ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy -OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P -TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ -HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER -dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf -ReYNnyicsbkqWletNw+vHX/bvZ8= ------END CERTIFICATE----- - -# Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority -# Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority -# Label: "Starfield Class 2 CA" -# Serial: 0 -# MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24 -# SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a -# SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58 ------BEGIN CERTIFICATE----- -MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl -MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp -U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw -NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE -ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp -ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 -DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf -8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN -+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 -X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa -K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA -1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G -A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR -zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 -YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD -bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w -DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 -L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D -eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl -xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp -VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY -WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= ------END CERTIFICATE----- - -# Issuer: O=Government Root Certification Authority -# Subject: O=Government Root Certification Authority -# Label: "Taiwan GRCA" -# Serial: 42023070807708724159991140556527066870 -# MD5 Fingerprint: 37:85:44:53:32:45:1f:20:f0:f3:95:e1:25:c4:43:4e -# SHA1 Fingerprint: f4:8b:11:bf:de:ab:be:94:54:20:71:e6:41:de:6b:be:88:2b:40:b9 -# SHA256 Fingerprint: 76:00:29:5e:ef:e8:5b:9e:1f:d6:24:db:76:06:2a:aa:ae:59:81:8a:54:d2:77:4c:d4:c0:b2:c0:11:31:e1:b3 ------BEGIN CERTIFICATE----- -MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/ -MQswCQYDVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1ow -PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB -AJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qNw8XR -IePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1q -gQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKy -yhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts -F/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2 -jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvx -ls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FC -VGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHK -YS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoH -EgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThN -Xo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1Ud -DgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkGBGcqBwAE -MTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK -UWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ -TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyf -qzvS/3WXy6TjZwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaK -ZEk9GhiHkASfQlK3T8v+R0F2Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFE -JPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7 -hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6QzDxARvBMB1uUO07+1 -EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+HbkZ6Mm -nD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WX -udpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz -ssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDe -LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl -pYYsfPQS ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Assured ID Root CA" -# Serial: 17154717934120587862167794914071425081 -# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72 -# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43 -# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c ------BEGIN CERTIFICATE----- -MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv -b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl -cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c -JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP -mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ -wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 -VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ -AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB -AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun -pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC -dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf -fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm -NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx -H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe -+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Global Root CA" -# Serial: 10944719598952040374951832963794454346 -# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e -# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36 -# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61 ------BEGIN CERTIFICATE----- -MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD -QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB -CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 -nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt -43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P -T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 -gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR -TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw -DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr -hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg -06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF -PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls -YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk -CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= ------END CERTIFICATE----- - -# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert High Assurance EV Root CA" -# Serial: 3553400076410547919724730734378100087 -# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a -# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25 -# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j -ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL -MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 -LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug -RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm -+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW -PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM -xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB -Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 -hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg -EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA -FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec -nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z -eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF -hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 -Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe -vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep -+OkuE6N36B9K ------END CERTIFICATE----- - -# Issuer: CN=Class 2 Primary CA O=Certplus -# Subject: CN=Class 2 Primary CA O=Certplus -# Label: "Certplus Class 2 Primary CA" -# Serial: 177770208045934040241468760488327595043 -# MD5 Fingerprint: 88:2c:8c:52:b8:a2:3c:f3:f7:bb:03:ea:ae:ac:42:0b -# SHA1 Fingerprint: 74:20:74:41:72:9c:dd:92:ec:79:31:d8:23:10:8d:c2:81:92:e2:bb -# SHA256 Fingerprint: 0f:99:3c:8a:ef:97:ba:af:56:87:14:0e:d5:9a:d1:82:1b:b4:af:ac:f0:aa:9a:58:b5:d5:7a:33:8a:3a:fb:cb ------BEGIN CERTIFICATE----- -MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw -PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz -cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9 -MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz -IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ -ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR -VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL -kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd -EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas -H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0 -HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud -DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4 -QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu -Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/ -AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8 -yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR -FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA -ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB -kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 -l7+ijrRU ------END CERTIFICATE----- - -# Issuer: CN=DST Root CA X3 O=Digital Signature Trust Co. -# Subject: CN=DST Root CA X3 O=Digital Signature Trust Co. -# Label: "DST Root CA X3" -# Serial: 91299735575339953335919266965803778155 -# MD5 Fingerprint: 41:03:52:dc:0f:f7:50:1b:16:f0:02:8e:ba:6f:45:c5 -# SHA1 Fingerprint: da:c9:02:4f:54:d8:f6:df:94:93:5f:b1:73:26:38:ca:6a:d7:7c:13 -# SHA256 Fingerprint: 06:87:26:03:31:a7:24:03:d9:09:f1:05:e6:9b:cf:0d:32:e1:bd:24:93:ff:c6:d9:20:6d:11:bc:d6:77:07:39 ------BEGIN CERTIFICATE----- -MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ -MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT -DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow -PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD -Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O -rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq -OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b -xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw -7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD -aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV -HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG -SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 -ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr -AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz -R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 -JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo -Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ ------END CERTIFICATE----- - -# Issuer: CN=SwissSign Gold CA - G2 O=SwissSign AG -# Subject: CN=SwissSign Gold CA - G2 O=SwissSign AG -# Label: "SwissSign Gold CA - G2" -# Serial: 13492815561806991280 -# MD5 Fingerprint: 24:77:d9:a8:91:d1:3b:fa:88:2d:c2:ff:f8:cd:33:93 -# SHA1 Fingerprint: d8:c5:38:8a:b7:30:1b:1b:6e:d4:7a:e6:45:25:3a:6f:9f:1a:27:61 -# SHA256 Fingerprint: 62:dd:0b:e9:b9:f5:0a:16:3e:a0:f8:e7:5c:05:3b:1e:ca:57:ea:55:c8:68:8f:64:7c:68:81:f2:c8:35:7b:95 ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -# Issuer: CN=SwissSign Silver CA - G2 O=SwissSign AG -# Subject: CN=SwissSign Silver CA - G2 O=SwissSign AG -# Label: "SwissSign Silver CA - G2" -# Serial: 5700383053117599563 -# MD5 Fingerprint: e0:06:a1:c9:7d:cf:c9:fc:0d:c0:56:75:96:d8:62:13 -# SHA1 Fingerprint: 9b:aa:e5:9f:56:ee:21:cb:43:5a:be:25:93:df:a7:f0:40:d1:1d:cb -# SHA256 Fingerprint: be:6c:4d:a2:bb:b9:ba:59:b6:f3:93:97:68:37:42:46:c3:c0:05:99:3f:a9:8f:02:0d:1d:ed:be:d4:8a:81:d5 ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. -# Subject: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. -# Label: "GeoTrust Primary Certification Authority" -# Serial: 32798226551256963324313806436981982369 -# MD5 Fingerprint: 02:26:c3:01:5e:08:30:37:43:a9:d0:7d:cf:37:e6:bf -# SHA1 Fingerprint: 32:3c:11:8e:1b:f7:b8:b6:52:54:e2:e2:10:0d:d6:02:90:37:f0:96 -# SHA256 Fingerprint: 37:d5:10:06:c5:12:ea:ab:62:64:21:f1:ec:8c:92:01:3f:c5:f8:2a:e9:8e:e5:33:eb:46:19:b8:de:b4:d0:6c ------BEGIN CERTIFICATE----- -MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY -MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo -R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx -MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK -Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 -AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA -ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 -7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W -kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI -mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ -KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 -6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl -4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K -oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj -UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU -AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= ------END CERTIFICATE----- - -# Issuer: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only -# Subject: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only -# Label: "thawte Primary Root CA" -# Serial: 69529181992039203566298953787712940909 -# MD5 Fingerprint: 8c:ca:dc:0b:22:ce:f5:be:72:ac:41:1a:11:a8:d8:12 -# SHA1 Fingerprint: 91:c6:d6:ee:3e:8a:c8:63:84:e5:48:c2:99:29:5c:75:6c:81:7b:81 -# SHA256 Fingerprint: 8d:72:2f:81:a9:c1:13:c0:79:1d:f1:36:a2:96:6d:b2:6c:95:0a:97:1d:b4:6b:41:99:f4:ea:54:b7:8b:fb:9f ------BEGIN CERTIFICATE----- -MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB -qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf -Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw -MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV -BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw -NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j -LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG -A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs -W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta -3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk -6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 -Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J -NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP -r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU -DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz -YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX -xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 -/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ -LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 -jVaMaA== ------END CERTIFICATE----- - -# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only -# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only -# Label: "VeriSign Class 3 Public Primary Certification Authority - G5" -# Serial: 33037644167568058970164719475676101450 -# MD5 Fingerprint: cb:17:e4:31:67:3e:e2:09:fe:45:57:93:f3:0a:fa:1c -# SHA1 Fingerprint: 4e:b6:d5:78:49:9b:1c:cf:5f:58:1e:ad:56:be:3d:9b:67:44:a5:e5 -# SHA256 Fingerprint: 9a:cf:ab:7e:43:c8:d8:80:d0:6b:26:2a:94:de:ee:e4:b4:65:99:89:c3:d0:ca:f1:9b:af:64:05:e4:1a:b7:df ------BEGIN CERTIFICATE----- -MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB -yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW -ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW -ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp -U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y -aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 -nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex -t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz -SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG -BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ -rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ -NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E -BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH -BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy -aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv -MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE -p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y -5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK -WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ -4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N -hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq ------END CERTIFICATE----- - -# Issuer: CN=SecureTrust CA O=SecureTrust Corporation -# Subject: CN=SecureTrust CA O=SecureTrust Corporation -# Label: "SecureTrust CA" -# Serial: 17199774589125277788362757014266862032 -# MD5 Fingerprint: dc:32:c3:a7:6d:25:57:c7:68:09:9d:ea:2d:a9:a2:d1 -# SHA1 Fingerprint: 87:82:c6:c3:04:35:3b:cf:d2:96:92:d2:59:3e:7d:44:d9:34:ff:11 -# SHA256 Fingerprint: f1:c1:b5:0a:e5:a2:0d:d8:03:0e:c9:f6:bc:24:82:3d:d3:67:b5:25:57:59:b4:e7:1b:61:fc:e9:f7:37:5d:73 ------BEGIN CERTIFICATE----- -MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI -MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x -FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz -MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv -cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz -Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO -0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao -wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj -7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS -8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT -BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB -/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg -JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC -NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 -6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ -3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm -D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS -CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR -3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= ------END CERTIFICATE----- - -# Issuer: CN=Secure Global CA O=SecureTrust Corporation -# Subject: CN=Secure Global CA O=SecureTrust Corporation -# Label: "Secure Global CA" -# Serial: 9751836167731051554232119481456978597 -# MD5 Fingerprint: cf:f4:27:0d:d4:ed:dc:65:16:49:6d:3d:da:bf:6e:de -# SHA1 Fingerprint: 3a:44:73:5a:e5:81:90:1f:24:86:61:46:1e:3b:9c:c4:5f:f5:3a:1b -# SHA256 Fingerprint: 42:00:f5:04:3a:c8:59:0e:bb:52:7d:20:9e:d1:50:30:29:fb:cb:d4:1c:a1:b5:06:ec:27:f1:5a:de:7d:ac:69 ------BEGIN CERTIFICATE----- -MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK -MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x -GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx -MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg -Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ -iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa -/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ -jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI -HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 -sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w -gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw -KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG -AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L -URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO -H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm -I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY -iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc -f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW ------END CERTIFICATE----- - -# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited -# Subject: CN=COMODO Certification Authority O=COMODO CA Limited -# Label: "COMODO Certification Authority" -# Serial: 104350513648249232941998508985834464573 -# MD5 Fingerprint: 5c:48:dc:f7:42:72:ec:56:94:6d:1c:cc:71:35:80:75 -# SHA1 Fingerprint: 66:31:bf:9e:f7:4f:9e:b6:c9:d5:a6:0c:ba:6a:be:d1:f7:bd:ef:7b -# SHA256 Fingerprint: 0c:2c:d6:3d:f7:80:6f:a3:99:ed:e8:09:11:6b:57:5b:f8:79:89:f0:65:18:f9:80:8c:86:05:03:17:8b:af:66 ------BEGIN CERTIFICATE----- -MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB -gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV -BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw -MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl -YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P -RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 -UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI -2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 -Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp -+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ -DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O -nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW -/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g -PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u -QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY -SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv -IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ -RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 -zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd -BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB -ZQ== ------END CERTIFICATE----- - -# Issuer: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C. -# Subject: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C. -# Label: "Network Solutions Certificate Authority" -# Serial: 116697915152937497490437556386812487904 -# MD5 Fingerprint: d3:f3:a6:16:c0:fa:6b:1d:59:b1:2d:96:4d:0e:11:2e -# SHA1 Fingerprint: 74:f8:a3:c3:ef:e7:b3:90:06:4b:83:90:3c:21:64:60:20:e5:df:ce -# SHA256 Fingerprint: 15:f0:ba:00:a3:ac:7a:f3:ac:88:4c:07:2b:10:11:a0:77:bd:77:c0:97:f4:01:64:b2:f8:59:8a:bd:83:86:0c ------BEGIN CERTIFICATE----- -MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi -MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu -MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp -dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV -UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO -ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz -c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP -OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl -mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF -BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 -qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw -gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB -BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu -bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp -dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 -6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ -h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH -/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv -wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN -pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey ------END CERTIFICATE----- - -# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited -# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited -# Label: "COMODO ECC Certification Authority" -# Serial: 41578283867086692638256921589707938090 -# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23 -# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11 -# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7 ------BEGIN CERTIFICATE----- -MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL -MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE -BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT -IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw -MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy -ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N -T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR -FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J -cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW -BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ -BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm -fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv -GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= ------END CERTIFICATE----- - -# Issuer: CN=OISTE WISeKey Global Root GA CA O=WISeKey OU=Copyright (c) 2005/OISTE Foundation Endorsed -# Subject: CN=OISTE WISeKey Global Root GA CA O=WISeKey OU=Copyright (c) 2005/OISTE Foundation Endorsed -# Label: "OISTE WISeKey Global Root GA CA" -# Serial: 86718877871133159090080555911823548314 -# MD5 Fingerprint: bc:6c:51:33:a7:e9:d3:66:63:54:15:72:1b:21:92:93 -# SHA1 Fingerprint: 59:22:a1:e1:5a:ea:16:35:21:f8:98:39:6a:46:46:b0:44:1b:0f:a9 -# SHA256 Fingerprint: 41:c9:23:86:6a:b4:ca:d6:b7:ad:57:80:81:58:2e:02:07:97:a6:cb:df:4f:ff:78:ce:83:96:b3:89:37:d7:f5 ------BEGIN CERTIFICATE----- -MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB -ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly -aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl -ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w -NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G -A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD -VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX -SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR -VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2 -w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF -mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg -4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9 -4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw -DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw -EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx -SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2 -ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8 -vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa -hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi -Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ -/L7fCg0= ------END CERTIFICATE----- - -# Issuer: CN=Certigna O=Dhimyotis -# Subject: CN=Certigna O=Dhimyotis -# Label: "Certigna" -# Serial: 18364802974209362175 -# MD5 Fingerprint: ab:57:a6:5b:7d:42:82:19:b5:d8:58:26:28:5e:fd:ff -# SHA1 Fingerprint: b1:2e:13:63:45:86:a4:6f:1a:b2:60:68:37:58:2d:c4:ac:fd:94:97 -# SHA256 Fingerprint: e3:b6:a2:db:2e:d7:ce:48:84:2f:7a:c5:32:41:c7:b7:1d:54:14:4b:fb:40:c1:1f:3f:1d:0b:42:f5:ee:a1:2d ------BEGIN CERTIFICATE----- -MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV -BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X -DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ -BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 -QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny -gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw -zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q -130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 -JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw -DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw -ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT -AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj -AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG -9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h -bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc -fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu -HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w -t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw -WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== ------END CERTIFICATE----- - -# Issuer: CN=Deutsche Telekom Root CA 2 O=Deutsche Telekom AG OU=T-TeleSec Trust Center -# Subject: CN=Deutsche Telekom Root CA 2 O=Deutsche Telekom AG OU=T-TeleSec Trust Center -# Label: "Deutsche Telekom Root CA 2" -# Serial: 38 -# MD5 Fingerprint: 74:01:4a:91:b1:08:c4:58:ce:47:cd:f0:dd:11:53:08 -# SHA1 Fingerprint: 85:a4:08:c0:9c:19:3e:5d:51:58:7d:cd:d6:13:30:fd:8c:de:37:bf -# SHA256 Fingerprint: b6:19:1a:50:d0:c3:97:7f:7d:a9:9b:cd:aa:c8:6a:22:7d:ae:b9:67:9e:c7:0b:a3:b0:c9:d9:22:71:c1:70:d3 ------BEGIN CERTIFICATE----- -MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc -MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj -IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB -IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE -RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl -U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290 -IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU -ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC -QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr -rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S -NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc -QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH -txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP -BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC -AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp -tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa -IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl -6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+ -xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU -Cm26OWMohpLzGITY+9HPBVZkVw== ------END CERTIFICATE----- - -# Issuer: CN=Cybertrust Global Root O=Cybertrust, Inc -# Subject: CN=Cybertrust Global Root O=Cybertrust, Inc -# Label: "Cybertrust Global Root" -# Serial: 4835703278459682877484360 -# MD5 Fingerprint: 72:e4:4a:87:e3:69:40:80:77:ea:bc:e3:f4:ff:f0:e1 -# SHA1 Fingerprint: 5f:43:e5:b1:bf:f8:78:8c:ac:1c:c7:ca:4a:9a:c6:22:2b:cc:34:c6 -# SHA256 Fingerprint: 96:0a:df:00:63:e9:63:56:75:0c:29:65:dd:0a:08:67:da:0b:9c:bd:6e:77:71:4a:ea:fb:23:49:ab:39:3d:a3 ------BEGIN CERTIFICATE----- -MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG -A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh -bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE -ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS -b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5 -7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS -J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y -HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP -t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz -FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY -XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ -MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw -hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js -MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA -A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj -Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx -XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o -omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc -A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW -WL1WMRJOEcgh4LMRkWXbtKaIOM5V ------END CERTIFICATE----- - -# Issuer: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority -# Subject: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority -# Label: "ePKI Root Certification Authority" -# Serial: 28956088682735189655030529057352760477 -# MD5 Fingerprint: 1b:2e:00:ca:26:06:90:3d:ad:fe:6f:15:68:d3:6b:b3 -# SHA1 Fingerprint: 67:65:0d:f1:7e:8e:7e:5b:82:40:a4:f4:56:4b:cf:e2:3d:69:c6:f0 -# SHA256 Fingerprint: c0:a6:f4:dc:63:a2:4b:fd:cf:54:ef:2a:6a:08:2a:0a:72:de:35:80:3e:2f:f5:ff:52:7a:e5:d8:72:06:df:d5 ------BEGIN CERTIFICATE----- -MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe -MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 -ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe -Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw -IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL -SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF -AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH -SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh -ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X -DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1 -TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ -fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA -sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU -WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS -nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH -dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip -NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC -AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF -MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH -ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB -uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl -PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP -JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/ -gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2 -j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6 -5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB -o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS -/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z -Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE -W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D -hNQ+IIX3Sj0rnP0qCglN6oH4EZw= ------END CERTIFICATE----- - -# Issuer: O=certSIGN OU=certSIGN ROOT CA -# Subject: O=certSIGN OU=certSIGN ROOT CA -# Label: "certSIGN ROOT CA" -# Serial: 35210227249154 -# MD5 Fingerprint: 18:98:c0:d6:e9:3a:fc:f9:b0:f5:0c:f7:4b:01:44:17 -# SHA1 Fingerprint: fa:b7:ee:36:97:26:62:fb:2d:b0:2a:f6:bf:03:fd:e8:7c:4b:2f:9b -# SHA256 Fingerprint: ea:a9:62:c4:fa:4a:6b:af:eb:e4:15:19:6d:35:1c:cd:88:8d:4f:53:f3:fa:8a:e6:d7:c4:66:a9:4e:60:42:bb ------BEGIN CERTIFICATE----- -MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT -AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD -QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP -MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC -ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do -0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ -UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d -RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ -OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv -JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C -AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O -BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ -LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY -MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ -44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I -Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw -i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN -9u6wWk5JRFRYX0KD ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only -# Subject: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only -# Label: "GeoTrust Primary Certification Authority - G3" -# Serial: 28809105769928564313984085209975885599 -# MD5 Fingerprint: b5:e8:34:36:c9:10:44:58:48:70:6d:2e:83:d4:b8:05 -# SHA1 Fingerprint: 03:9e:ed:b8:0b:e7:a0:3c:69:53:89:3b:20:d2:d9:32:3a:4c:2a:fd -# SHA256 Fingerprint: b4:78:b8:12:25:0d:f8:78:63:5c:2a:a7:ec:7d:15:5e:aa:62:5e:e8:29:16:e2:cd:29:43:61:88:6c:d1:fb:d4 ------BEGIN CERTIFICATE----- -MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB -mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT -MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s -eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv -cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ -BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg -MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0 -BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz -+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm -hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn -5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W -JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL -DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC -huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw -HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB -AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB -zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN -kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD -AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH -SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G -spki4cErx5z481+oghLrGREt ------END CERTIFICATE----- - -# Issuer: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only -# Subject: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only -# Label: "thawte Primary Root CA - G2" -# Serial: 71758320672825410020661621085256472406 -# MD5 Fingerprint: 74:9d:ea:60:24:c4:fd:22:53:3e:cc:3a:72:d9:29:4f -# SHA1 Fingerprint: aa:db:bc:22:23:8f:c4:01:a1:27:bb:38:dd:f4:1d:db:08:9e:f0:12 -# SHA256 Fingerprint: a4:31:0d:50:af:18:a6:44:71:90:37:2a:86:af:af:8b:95:1f:fb:43:1d:83:7f:1e:56:88:b4:59:71:ed:15:57 ------BEGIN CERTIFICATE----- -MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL -MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp -IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi -BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw -MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh -d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig -YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v -dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/ -BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6 -papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E -BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K -DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3 -KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox -XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== ------END CERTIFICATE----- - -# Issuer: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only -# Subject: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only -# Label: "thawte Primary Root CA - G3" -# Serial: 127614157056681299805556476275995414779 -# MD5 Fingerprint: fb:1b:5d:43:8a:94:cd:44:c6:76:f2:43:4b:47:e7:31 -# SHA1 Fingerprint: f1:8b:53:8d:1b:e9:03:b6:a6:f0:56:43:5b:17:15:89:ca:f3:6b:f2 -# SHA256 Fingerprint: 4b:03:f4:58:07:ad:70:f2:1b:fc:2c:ae:71:c9:fd:e4:60:4c:06:4c:f5:ff:b6:86:ba:e5:db:aa:d7:fd:d3:4c ------BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB -rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf -Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw -MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV -BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa -Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl -LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u -MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl -ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm -gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8 -YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf -b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9 -9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S -zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk -OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV -HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA -2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW -oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu -t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c -KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM -m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu -MdRAGmI0Nj81Aa6sY6A= ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only -# Subject: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only -# Label: "GeoTrust Primary Certification Authority - G2" -# Serial: 80682863203381065782177908751794619243 -# MD5 Fingerprint: 01:5e:d8:6b:bd:6f:3d:8e:a1:31:f8:12:e0:98:73:6a -# SHA1 Fingerprint: 8d:17:84:d5:37:f3:03:7d:ec:70:fe:57:8b:51:9a:99:e6:10:d7:b0 -# SHA256 Fingerprint: 5e:db:7a:c4:3b:82:a0:6a:87:61:e8:d7:be:49:79:eb:f2:61:1f:7d:d7:9b:f9:1c:1c:6b:56:6a:21:9e:d7:66 ------BEGIN CERTIFICATE----- -MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL -MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj -KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2 -MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV -BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw -NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV -BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH -MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL -So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal -tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO -BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG -CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT -qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz -rD6ogRLQy7rQkgu2npaqBA+K ------END CERTIFICATE----- - -# Issuer: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only -# Subject: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only -# Label: "VeriSign Universal Root Certification Authority" -# Serial: 85209574734084581917763752644031726877 -# MD5 Fingerprint: 8e:ad:b5:01:aa:4d:81:e4:8c:1d:d1:e1:14:00:95:19 -# SHA1 Fingerprint: 36:79:ca:35:66:87:72:30:4d:30:a5:fb:87:3b:0f:a7:7b:b7:0d:54 -# SHA256 Fingerprint: 23:99:56:11:27:a5:71:25:de:8c:ef:ea:61:0d:df:2f:a0:78:b5:c8:06:7f:4e:82:82:90:bf:b8:60:e8:4b:3c ------BEGIN CERTIFICATE----- -MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB -vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W -ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe -Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX -MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0 -IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y -IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh -bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF -9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH -H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H -LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN -/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT -rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw -WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs -exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud -DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4 -sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+ -seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz -4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+ -BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR -lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3 -7M2CYfE45k+XmCpajQ== ------END CERTIFICATE----- - -# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only -# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only -# Label: "VeriSign Class 3 Public Primary Certification Authority - G4" -# Serial: 63143484348153506665311985501458640051 -# MD5 Fingerprint: 3a:52:e1:e7:fd:6f:3a:e3:6f:f3:6f:99:1b:f9:22:41 -# SHA1 Fingerprint: 22:d5:d8:df:8f:02:31:d1:8d:f7:9d:b7:cf:8a:2d:64:c9:3f:6c:3a -# SHA256 Fingerprint: 69:dd:d7:ea:90:bb:57:c9:3e:13:5d:c8:5e:a6:fc:d5:48:0b:60:32:39:bd:c4:54:fc:75:8b:2a:26:cf:7f:79 ------BEGIN CERTIFICATE----- -MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW -ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp -U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y -aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp -U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg -SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln -biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm -GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve -fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw -AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ -aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj -aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW -kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC -4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga -FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== ------END CERTIFICATE----- - -# Issuer: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services) -# Subject: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services) -# Label: "NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny" -# Serial: 80544274841616 -# MD5 Fingerprint: c5:a1:b7:ff:73:dd:d6:d7:34:32:18:df:fc:3c:ad:88 -# SHA1 Fingerprint: 06:08:3f:59:3f:15:a1:04:a0:69:a4:6b:a9:03:d0:06:b7:97:09:91 -# SHA256 Fingerprint: 6c:61:da:c3:a2:de:f0:31:50:6b:e0:36:d2:a6:fe:40:19:94:fb:d1:3d:f9:c8:d4:66:59:92:74:c4:46:ec:98 ------BEGIN CERTIFICATE----- -MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG -EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 -MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl -cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR -dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB -pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM -b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm -aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz -IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT -lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz -AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 -VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG -ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 -BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG -AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M -U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh -bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C -+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC -bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F -uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 -XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= ------END CERTIFICATE----- - -# Issuer: CN=Staat der Nederlanden Root CA - G2 O=Staat der Nederlanden -# Subject: CN=Staat der Nederlanden Root CA - G2 O=Staat der Nederlanden -# Label: "Staat der Nederlanden Root CA - G2" -# Serial: 10000012 -# MD5 Fingerprint: 7c:a5:0f:f8:5b:9a:7d:6d:30:ae:54:5a:e3:42:a2:8a -# SHA1 Fingerprint: 59:af:82:79:91:86:c7:b4:75:07:cb:cf:03:57:46:eb:04:dd:b7:16 -# SHA256 Fingerprint: 66:8c:83:94:7d:a6:3b:72:4b:ec:e1:74:3c:31:a0:e6:ae:d0:db:8e:c5:b3:1b:e3:77:bb:78:4f:91:b6:71:6f ------BEGIN CERTIFICATE----- -MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO -TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh -dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX -DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl -ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv -b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291 -qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp -uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU -Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE -pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp -5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M -UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN -GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy -5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv -6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK -eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6 -B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/ -BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov -L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV -HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG -SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS -CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen -5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897 -IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK -gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL -+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL -vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm -bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk -N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC -Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z -ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ== ------END CERTIFICATE----- - -# Issuer: CN=Hongkong Post Root CA 1 O=Hongkong Post -# Subject: CN=Hongkong Post Root CA 1 O=Hongkong Post -# Label: "Hongkong Post Root CA 1" -# Serial: 1000 -# MD5 Fingerprint: a8:0d:6f:39:78:b9:43:6d:77:42:6d:98:5a:cc:23:ca -# SHA1 Fingerprint: d6:da:a8:20:8d:09:d2:15:4d:24:b5:2f:cb:34:6e:b2:58:b2:8a:58 -# SHA256 Fingerprint: f9:e6:7d:33:6c:51:00:2a:c0:54:c6:32:02:2d:66:dd:a2:e7:e3:ff:f1:0a:d0:61:ed:31:d8:bb:b4:10:cf:b2 ------BEGIN CERTIFICATE----- -MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx -FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg -Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG -A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr -b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ -jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn -PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh -ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9 -nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h -q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED -MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC -mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3 -7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB -oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs -EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO -fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi -AmvZWg== ------END CERTIFICATE----- - -# Issuer: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. -# Subject: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. -# Label: "SecureSign RootCA11" -# Serial: 1 -# MD5 Fingerprint: b7:52:74:e2:92:b4:80:93:f2:75:e4:cc:d7:f2:ea:26 -# SHA1 Fingerprint: 3b:c4:9f:48:f8:f3:73:a0:9c:1e:bd:f8:5b:b1:c3:65:c7:d8:11:b3 -# SHA256 Fingerprint: bf:0f:ee:fb:9e:3a:58:1a:d5:f9:e9:db:75:89:98:57:43:d2:61:08:5c:4d:31:4f:6f:5d:72:59:aa:42:16:12 ------BEGIN CERTIFICATE----- -MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr -MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG -A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0 -MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp -Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD -QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz -i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8 -h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV -MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9 -UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni -8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC -h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD -VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB -AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm -KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ -X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr -QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5 -pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN -QSdJQO7e5iNEOdyhIta6A/I= ------END CERTIFICATE----- - -# Issuer: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. -# Subject: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. -# Label: "Microsec e-Szigno Root CA 2009" -# Serial: 14014712776195784473 -# MD5 Fingerprint: f8:49:f4:03:bc:44:2d:83:be:48:69:7d:29:64:fc:b1 -# SHA1 Fingerprint: 89:df:74:fe:5c:f4:0f:4a:80:f9:e3:37:7d:54:da:91:e1:01:31:8e -# SHA256 Fingerprint: 3c:5f:81:fe:a5:fa:b8:2c:64:bf:a2:ea:ec:af:cd:e8:e0:77:fc:86:20:a7:ca:e5:37:16:3d:f3:6e:db:f3:78 ------BEGIN CERTIFICATE----- -MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD -VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 -ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G -CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y -OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx -FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp -Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o -dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP -kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc -cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U -fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7 -N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC -xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1 -+rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G -A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM -Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG -SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h -mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk -ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 -tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c -2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t -HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 -# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 -# Label: "GlobalSign Root CA - R3" -# Serial: 4835703278459759426209954 -# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28 -# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad -# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b ------BEGIN CERTIFICATE----- -MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 -MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 -RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT -gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm -KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd -QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ -XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw -DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o -LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU -RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp -jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK -6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX -mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs -Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH -WD9f ------END CERTIFICATE----- - -# Issuer: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 -# Subject: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 -# Label: "Autoridad de Certificacion Firmaprofesional CIF A62634068" -# Serial: 6047274297262753887 -# MD5 Fingerprint: 73:3a:74:7a:ec:bb:a3:96:a6:c2:e4:e2:c8:9b:c0:c3 -# SHA1 Fingerprint: ae:c5:fb:3f:c8:e1:bf:c4:e5:4f:03:07:5a:9a:e8:00:b7:f7:b6:fa -# SHA256 Fingerprint: 04:04:80:28:bf:1f:28:64:d4:8f:9a:d4:d8:32:94:36:6a:82:88:56:55:3f:3b:14:30:3f:90:14:7f:5d:40:ef ------BEGIN CERTIFICATE----- -MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE -BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h -cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy -MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg -Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 -thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM -cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG -L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i -NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h -X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b -m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy -Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja -EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T -KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF -6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh -OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD -VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD -VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp -cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv -ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl -AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF -661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9 -am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1 -ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481 -PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS -3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k -SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF -3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM -ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g -StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz -Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB -jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V ------END CERTIFICATE----- - -# Issuer: CN=Izenpe.com O=IZENPE S.A. -# Subject: CN=Izenpe.com O=IZENPE S.A. -# Label: "Izenpe.com" -# Serial: 917563065490389241595536686991402621 -# MD5 Fingerprint: a6:b0:cd:85:80:da:5c:50:34:a3:39:90:2f:55:67:73 -# SHA1 Fingerprint: 2f:78:3d:25:52:18:a7:4a:65:39:71:b5:2c:a2:9c:45:15:6f:e9:19 -# SHA256 Fingerprint: 25:30:cc:8e:98:32:15:02:ba:d9:6f:9b:1f:ba:1b:09:9e:2d:29:9e:0f:45:48:bb:91:4f:36:3b:c0:d4:53:1f ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -# Issuer: CN=Chambers of Commerce Root - 2008 O=AC Camerfirma S.A. -# Subject: CN=Chambers of Commerce Root - 2008 O=AC Camerfirma S.A. -# Label: "Chambers of Commerce Root - 2008" -# Serial: 11806822484801597146 -# MD5 Fingerprint: 5e:80:9e:84:5a:0e:65:0b:17:02:f3:55:18:2a:3e:d7 -# SHA1 Fingerprint: 78:6a:74:ac:76:ab:14:7f:9c:6a:30:50:ba:9e:a8:7e:fe:9a:ce:3c -# SHA256 Fingerprint: 06:3e:4a:fa:c4:91:df:d3:32:f3:08:9b:85:42:e9:46:17:d8:93:d7:fe:94:4e:10:a7:93:7e:e2:9d:96:93:c0 ------BEGIN CERTIFICATE----- -MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD -VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 -IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 -MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJz -IG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEyMjk1MFoXDTM4MDcz -MTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj -dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw -EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp -MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G -CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW9 -28sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJq -VKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072Q -DuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR -5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfL -ZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05a -Sd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esHnFIbAURRPHsl18Tl -UlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2wsWsSaR6s -+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5 -Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj -ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAx -hduub+84Mxh2EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNV -HQ4EFgQU+SSsD7K1+HnA+mCIG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1 -+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpN -YWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t -L2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVy -ZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAt -IDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV -HSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20w -DQYJKoZIhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwW -PJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF -5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1 -glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaH -FoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2 -pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MD -xvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QG -tjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq -jktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1De -fhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg -OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZ -d0jQ ------END CERTIFICATE----- - -# Issuer: CN=Global Chambersign Root - 2008 O=AC Camerfirma S.A. -# Subject: CN=Global Chambersign Root - 2008 O=AC Camerfirma S.A. -# Label: "Global Chambersign Root - 2008" -# Serial: 14541511773111788494 -# MD5 Fingerprint: 9e:80:ff:78:01:0c:2e:c1:36:bd:fe:96:90:6e:08:f3 -# SHA1 Fingerprint: 4a:bd:ee:ec:95:0d:35:9c:89:ae:c7:52:a1:2c:5b:29:f6:d6:aa:0c -# SHA256 Fingerprint: 13:63:35:43:93:34:a7:69:80:16:a0:d3:24:de:72:28:4e:07:9d:7b:52:20:bb:8f:bd:74:78:16:ee:be:ba:ca ------BEGIN CERTIFICATE----- -MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD -VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 -IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 -MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD -aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx -MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy -cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG -A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl -BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI -hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed -KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7 -G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2 -zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4 -ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG -HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2 -Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V -yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e -beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r -6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh -wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog -zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW -BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr -ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp -ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk -cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt -YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC -CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow -KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI -hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ -UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz -X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x -fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz -a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd -Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd -SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O -AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso -M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge -v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z -09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B ------END CERTIFICATE----- - -# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. -# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. -# Label: "Go Daddy Root Certificate Authority - G2" -# Serial: 0 -# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01 -# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b -# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT -EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp -ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz -NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH -EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE -AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD -E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH -/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy -DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh -GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR -tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA -AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE -FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX -WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu -9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr -gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo -2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO -LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI -4uJEvlz36hz1 ------END CERTIFICATE----- - -# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Label: "Starfield Root Certificate Authority - G2" -# Serial: 0 -# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96 -# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e -# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5 ------BEGIN CERTIFICATE----- -MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT -HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs -ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw -MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 -b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj -aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp -Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg -nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 -HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N -Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN -dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 -HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO -BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G -CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU -sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 -4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg -8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K -pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 -mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 ------END CERTIFICATE----- - -# Issuer: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Subject: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Label: "Starfield Services Root Certificate Authority - G2" -# Serial: 0 -# MD5 Fingerprint: 17:35:74:af:7b:61:1c:eb:f4:f9:3c:e2:ee:40:f9:a2 -# SHA1 Fingerprint: 92:5a:8f:8d:2c:6d:04:e0:66:5f:59:6a:ff:22:d8:63:e8:25:6f:3f -# SHA256 Fingerprint: 56:8d:69:05:a2:c8:87:08:a4:b3:02:51:90:ed:cf:ed:b1:97:4a:60:6a:13:c6:e5:29:0f:cb:2a:e6:3e:da:b5 ------BEGIN CERTIFICATE----- -MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT -HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs -ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 -MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD -VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy -ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy -dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p -OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 -8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K -Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe -hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk -6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw -DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q -AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI -bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB -ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z -qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd -iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn -0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN -sSi6 ------END CERTIFICATE----- - -# Issuer: CN=AffirmTrust Commercial O=AffirmTrust -# Subject: CN=AffirmTrust Commercial O=AffirmTrust -# Label: "AffirmTrust Commercial" -# Serial: 8608355977964138876 -# MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7 -# SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7 -# SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7 ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL -MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP -Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr -ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL -MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 -yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr -VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ -nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG -XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj -vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt -Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g -N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC -nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= ------END CERTIFICATE----- - -# Issuer: CN=AffirmTrust Networking O=AffirmTrust -# Subject: CN=AffirmTrust Networking O=AffirmTrust -# Label: "AffirmTrust Networking" -# Serial: 8957382827206547757 -# MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f -# SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f -# SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL -MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y -YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua -kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL -QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp -6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG -yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i -QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO -tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu -QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ -Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u -olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 -x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= ------END CERTIFICATE----- - -# Issuer: CN=AffirmTrust Premium O=AffirmTrust -# Subject: CN=AffirmTrust Premium O=AffirmTrust -# Label: "AffirmTrust Premium" -# Serial: 7893706540734352110 -# MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57 -# SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27 -# SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a ------BEGIN CERTIFICATE----- -MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz -dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG -A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U -cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf -qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ -JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ -+jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS -s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 -HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 -70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG -V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S -qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S -5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia -C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX -OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE -FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ -BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 -KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg -Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B -8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ -MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc -0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ -u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF -u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH -YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 -GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO -RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e -KeC2uAloGRwYQw== ------END CERTIFICATE----- - -# Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust -# Subject: CN=AffirmTrust Premium ECC O=AffirmTrust -# Label: "AffirmTrust Premium ECC" -# Serial: 8401224907861490260 -# MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d -# SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb -# SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23 ------BEGIN CERTIFICATE----- -MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC -VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ -cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ -BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt -VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D -0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 -ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G -A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs -aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I -flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== ------END CERTIFICATE----- - -# Issuer: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority -# Subject: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority -# Label: "Certum Trusted Network CA" -# Serial: 279744 -# MD5 Fingerprint: d5:e9:81:40:c5:18:69:fc:46:2c:89:75:62:0f:aa:78 -# SHA1 Fingerprint: 07:e0:32:e0:20:b7:2c:3f:19:2f:06:28:a2:59:3a:19:a7:0f:06:9e -# SHA256 Fingerprint: 5c:58:46:8d:55:f5:8e:49:7e:74:39:82:d2:b5:00:10:b6:d1:65:37:4a:cf:83:a7:d4:a3:2d:b7:68:c4:40:8e ------BEGIN CERTIFICATE----- -MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM -MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D -ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU -cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 -WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg -Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw -IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH -UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM -TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU -BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM -kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x -AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV -HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y -sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL -I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 -J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY -VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI -03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= ------END CERTIFICATE----- - -# Issuer: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA -# Subject: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA -# Label: "TWCA Root Certification Authority" -# Serial: 1 -# MD5 Fingerprint: aa:08:8f:f6:f9:7b:b7:f2:b1:a7:1e:9b:ea:ea:bd:79 -# SHA1 Fingerprint: cf:9e:87:6d:d3:eb:fc:42:26:97:a3:b5:a3:7a:a0:76:a9:06:23:48 -# SHA256 Fingerprint: bf:d8:8f:e1:10:1c:41:ae:3e:80:1b:f8:be:56:35:0e:e9:ba:d1:a6:b9:bd:51:5e:dc:5c:6d:5b:87:11:ac:44 ------BEGIN CERTIFICATE----- -MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES -MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU -V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz -WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO -LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm -aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE -AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH -K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX -RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z -rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx -3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq -hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC -MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls -XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D -lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn -aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ -YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== ------END CERTIFICATE----- - -# Issuer: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 -# Subject: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 -# Label: "Security Communication RootCA2" -# Serial: 0 -# MD5 Fingerprint: 6c:39:7d:a4:0e:55:59:b2:3f:d6:41:b1:12:50:de:43 -# SHA1 Fingerprint: 5f:3b:8c:f2:f8:10:b3:7d:78:b4:ce:ec:19:19:c3:73:34:b9:c7:74 -# SHA256 Fingerprint: 51:3b:2c:ec:b8:10:d4:cd:e5:dd:85:39:1a:df:c6:c2:dd:60:d8:7b:b7:36:d2:b5:21:48:4a:a4:7a:0e:be:f6 ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl -MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe -U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX -DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy -dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj -YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV -OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr -zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM -VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ -hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO -ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw -awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs -OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 -DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF -coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc -okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 -t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy -1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ -SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 ------END CERTIFICATE----- - -# Issuer: CN=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority -# Subject: CN=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority -# Label: "Hellenic Academic and Research Institutions RootCA 2011" -# Serial: 0 -# MD5 Fingerprint: 73:9f:4c:4b:73:5b:79:e9:fa:ba:1c:ef:6e:cb:d5:c9 -# SHA1 Fingerprint: fe:45:65:9b:79:03:5b:98:a1:61:b5:51:2e:ac:da:58:09:48:22:4d -# SHA256 Fingerprint: bc:10:4f:15:a4:8b:e7:09:dc:a5:42:a7:e1:d4:b9:df:6f:05:45:27:e8:02:ea:a9:2d:59:54:44:25:8a:fe:71 ------BEGIN CERTIFICATE----- -MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix -RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 -dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p -YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw -NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK -EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl -cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl -c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz -dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ -fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns -bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD -75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP -FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV -HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp -5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu -b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA -A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p -6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 -TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7 -dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys -Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI -l7WdmplNsDz4SgCbZN2fOUvRJ9e4 ------END CERTIFICATE----- - -# Issuer: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 -# Subject: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 -# Label: "Actalis Authentication Root CA" -# Serial: 6271844772424770508 -# MD5 Fingerprint: 69:c1:0d:4f:07:a3:1b:c3:fe:56:3d:04:bc:11:f6:a6 -# SHA1 Fingerprint: f3:73:b3:87:06:5a:28:84:8a:f2:f3:4a:ce:19:2b:dd:c7:8e:9c:ac -# SHA256 Fingerprint: 55:92:60:84:ec:96:3a:64:b9:6e:2a:be:01:ce:0b:a8:6a:64:fb:fe:bc:c7:aa:b5:af:c1:55:b3:7f:d7:60:66 ------BEGIN CERTIFICATE----- -MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE -BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w -MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 -IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC -SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1 -ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv -UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX -4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9 -KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/ -gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb -rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ -51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F -be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe -KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F -v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn -fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7 -jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz -ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt -ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL -e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70 -jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz -WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V -SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j -pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX -X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok -fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R -K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU -ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU -LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT -LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== ------END CERTIFICATE----- - -# Issuer: O=Trustis Limited OU=Trustis FPS Root CA -# Subject: O=Trustis Limited OU=Trustis FPS Root CA -# Label: "Trustis FPS Root CA" -# Serial: 36053640375399034304724988975563710553 -# MD5 Fingerprint: 30:c9:e7:1e:6b:e6:14:eb:65:b2:16:69:20:31:67:4d -# SHA1 Fingerprint: 3b:c0:38:0b:33:c3:f6:a6:0c:86:15:22:93:d9:df:f5:4b:81:c0:04 -# SHA256 Fingerprint: c1:b4:82:99:ab:a5:20:8f:e9:63:0a:ce:55:ca:68:a0:3e:da:5a:51:9c:88:02:a0:d3:a6:73:be:8f:8e:55:7d ------BEGIN CERTIFICATE----- -MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF -MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL -ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx -MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc -MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+ -AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH -iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj -vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA -0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB -OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/ -BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E -FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01 -GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW -zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4 -1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE -f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F -jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN -ZetX2fNXlrtIzYE= ------END CERTIFICATE----- - -# Issuer: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 -# Subject: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 -# Label: "Buypass Class 2 Root CA" -# Serial: 2 -# MD5 Fingerprint: 46:a7:d2:fe:45:fb:64:5a:a8:59:90:9b:78:44:9b:29 -# SHA1 Fingerprint: 49:0a:75:74:de:87:0a:47:fe:58:ee:f6:c7:6b:eb:c6:0b:12:40:99 -# SHA256 Fingerprint: 9a:11:40:25:19:7c:5b:b9:5d:94:e6:3d:55:cd:43:79:08:47:b6:46:b2:3c:df:11:ad:a4:a0:0e:ff:15:fb:48 ------BEGIN CERTIFICATE----- -MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd -MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg -Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow -TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw -HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB -BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr -6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV -L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91 -1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx -MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ -QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB -arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr -Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi -FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS -P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN -9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP -AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz -uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h -9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s -A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t -OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo -+fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7 -KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2 -DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us -H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ -I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 -5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h -3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz -Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= ------END CERTIFICATE----- - -# Issuer: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 -# Subject: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 -# Label: "Buypass Class 3 Root CA" -# Serial: 2 -# MD5 Fingerprint: 3d:3b:18:9e:2c:64:5a:e8:d5:88:ce:0e:f9:37:c2:ec -# SHA1 Fingerprint: da:fa:f7:fa:66:84:ec:06:8f:14:50:bd:c7:c2:81:a5:bc:a9:64:57 -# SHA256 Fingerprint: ed:f7:eb:bc:a2:7a:2a:38:4d:38:7b:7d:40:10:c6:66:e2:ed:b4:84:3e:4c:29:b4:ae:1d:5b:93:32:e6:b2:4d ------BEGIN CERTIFICATE----- -MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd -MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg -Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow -TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw -HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB -BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y -ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E -N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9 -tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX -0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c -/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X -KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY -zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS -O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D -34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP -K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3 -AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv -Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj -QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV -cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS -IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2 -HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa -O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv -033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u -dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE -kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 -3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD -u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq -4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= ------END CERTIFICATE----- - -# Issuer: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center -# Subject: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center -# Label: "T-TeleSec GlobalRoot Class 3" -# Serial: 1 -# MD5 Fingerprint: ca:fb:40:a8:4e:39:92:8a:1d:fe:8e:2f:c4:27:ea:ef -# SHA1 Fingerprint: 55:a6:72:3e:cb:f2:ec:cd:c3:23:74:70:19:9d:2a:be:11:e3:81:d1 -# SHA256 Fingerprint: fd:73:da:d3:1c:64:4f:f1:b4:3b:ef:0c:cd:da:96:71:0b:9c:d9:87:5e:ca:7e:31:70:7a:f3:e9:6d:52:2b:bd ------BEGIN CERTIFICATE----- -MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx -KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd -BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl -YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 -OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy -aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 -ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN -8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ -RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 -hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 -ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM -EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj -QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 -A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy -WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ -1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 -6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT -91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml -e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p -TpPDpFQUWw== ------END CERTIFICATE----- - -# Issuer: CN=EE Certification Centre Root CA O=AS Sertifitseerimiskeskus -# Subject: CN=EE Certification Centre Root CA O=AS Sertifitseerimiskeskus -# Label: "EE Certification Centre Root CA" -# Serial: 112324828676200291871926431888494945866 -# MD5 Fingerprint: 43:5e:88:d4:7d:1a:4a:7e:fd:84:2e:52:eb:01:d4:6f -# SHA1 Fingerprint: c9:a8:b9:e7:55:80:5e:58:e3:53:77:a7:25:eb:af:c3:7b:27:cc:d7 -# SHA256 Fingerprint: 3e:84:ba:43:42:90:85:16:e7:75:73:c0:99:2f:09:79:ca:08:4e:46:85:68:1f:f1:95:cc:ba:8a:22:9b:8a:76 ------BEGIN CERTIFICATE----- -MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1 -MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1 -czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG -CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy -MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl -ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS -b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy -euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO -bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw -WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d -MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE -1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD -VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/ -zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB -BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF -BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV -v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG -E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u -uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW -iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v -GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0= ------END CERTIFICATE----- - -# Issuer: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH -# Subject: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH -# Label: "D-TRUST Root Class 3 CA 2 2009" -# Serial: 623603 -# MD5 Fingerprint: cd:e0:25:69:8d:47:ac:9c:89:35:90:f7:fd:51:3d:2f -# SHA1 Fingerprint: 58:e8:ab:b0:36:15:33:fb:80:f7:9b:1b:6d:29:d3:ff:8d:5f:00:f0 -# SHA256 Fingerprint: 49:e7:a4:42:ac:f0:ea:62:87:05:00:54:b5:25:64:b6:50:e4:f4:9e:42:e3:48:d6:aa:38:e0:39:e9:57:b1:c1 ------BEGIN CERTIFICATE----- -MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF -MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD -bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha -ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM -HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03 -UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42 -tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R -ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM -lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp -/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G -A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G -A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj -dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy -MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl -cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js -L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL -BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni -acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 -o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K -zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8 -PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y -Johw1+qRzT65ysCQblrGXnRl11z+o+I= ------END CERTIFICATE----- - -# Issuer: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH -# Subject: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH -# Label: "D-TRUST Root Class 3 CA 2 EV 2009" -# Serial: 623604 -# MD5 Fingerprint: aa:c6:43:2c:5e:2d:cd:c4:34:c0:50:4f:11:02:4f:b6 -# SHA1 Fingerprint: 96:c9:1b:0b:95:b4:10:98:42:fa:d0:d8:22:79:fe:60:fa:b9:16:83 -# SHA256 Fingerprint: ee:c5:49:6b:98:8c:e9:86:25:b9:34:09:2e:ec:29:08:be:d0:b0:f3:16:c2:d4:73:0c:84:ea:f1:f3:d3:48:81 ------BEGIN CERTIFICATE----- -MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF -MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD -bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw -NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV -BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn -ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0 -3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z -qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR -p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8 -HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw -ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea -HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw -Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh -c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E -RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt -dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku -Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp -3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 -nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF -CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na -xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX -KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 ------END CERTIFICATE----- - -# Issuer: CN=CA Disig Root R2 O=Disig a.s. -# Subject: CN=CA Disig Root R2 O=Disig a.s. -# Label: "CA Disig Root R2" -# Serial: 10572350602393338211 -# MD5 Fingerprint: 26:01:fb:d8:27:a7:17:9a:45:54:38:1a:43:01:3b:03 -# SHA1 Fingerprint: b5:61:eb:ea:a4:de:e4:25:4b:69:1a:98:a5:57:47:c2:34:c7:d9:71 -# SHA256 Fingerprint: e2:3d:4a:03:6d:7b:70:e9:f5:95:b1:42:20:79:d2:b9:1e:df:bb:1f:b6:51:a0:63:3e:aa:8a:9d:c5:f8:07:03 ------BEGIN CERTIFICATE----- -MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV -BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu -MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy -MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx -EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw -ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe -NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH -PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I -x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe -QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR -yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO -QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912 -H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ -QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD -i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs -nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1 -rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud -DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI -hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM -tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf -GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb -lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka -+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal -TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i -nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3 -gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr -G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os -zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x -L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL ------END CERTIFICATE----- - -# Issuer: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV -# Subject: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV -# Label: "ACCVRAIZ1" -# Serial: 6828503384748696800 -# MD5 Fingerprint: d0:a0:5a:ee:05:b6:09:94:21:a1:7d:f1:b2:29:82:02 -# SHA1 Fingerprint: 93:05:7a:88:15:c6:4f:ce:88:2f:fa:91:16:52:28:78:bc:53:64:17 -# SHA256 Fingerprint: 9a:6e:c0:12:e1:a7:da:9d:be:34:19:4d:47:8a:d7:c0:db:18:22:fb:07:1d:f1:29:81:49:6e:d1:04:38:41:13 ------BEGIN CERTIFICATE----- -MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE -AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw -CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ -BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND -VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb -qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY -HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo -G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA -lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr -IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/ -0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH -k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47 -4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO -m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa -cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl -uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI -KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls -ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG -AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 -VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT -VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG -CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA -cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA -QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA -7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA -cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA -QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA -czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu -aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt -aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud -DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF -BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp -D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU -JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m -AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD -vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms -tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH -7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h -I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA -h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF -d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H -pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7 ------END CERTIFICATE----- - -# Issuer: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA -# Subject: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA -# Label: "TWCA Global Root CA" -# Serial: 3262 -# MD5 Fingerprint: f9:03:7e:cf:e6:9e:3c:73:7a:2a:90:07:69:ff:2b:96 -# SHA1 Fingerprint: 9c:bb:48:53:f6:a4:f6:d3:52:a4:e8:32:52:55:60:13:f5:ad:af:65 -# SHA256 Fingerprint: 59:76:90:07:f7:68:5d:0f:cd:50:87:2f:9f:95:d5:75:5a:5b:2b:45:7d:81:f3:69:2b:61:0a:98:67:2f:0e:1b ------BEGIN CERTIFICATE----- -MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx -EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT -VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 -NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT -B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF -10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz -0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh -MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH -zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc -46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2 -yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi -laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP -oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA -BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE -qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm -4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL -1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn -LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF -H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo -RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+ -nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh -15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW -6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW -nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j -wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz -aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy -KwbQBM0= ------END CERTIFICATE----- - -# Issuer: CN=TeliaSonera Root CA v1 O=TeliaSonera -# Subject: CN=TeliaSonera Root CA v1 O=TeliaSonera -# Label: "TeliaSonera Root CA v1" -# Serial: 199041966741090107964904287217786801558 -# MD5 Fingerprint: 37:41:49:1b:18:56:9a:26:f5:ad:c2:66:fb:40:a5:4c -# SHA1 Fingerprint: 43:13:bb:96:f1:d5:86:9b:c1:4e:6a:92:f6:cf:f6:34:69:87:82:37 -# SHA256 Fingerprint: dd:69:36:fe:21:f8:f0:77:c1:23:a1:a5:21:c1:22:24:f7:22:55:b7:3e:03:a7:26:06:93:e8:a2:4b:0f:a3:89 ------BEGIN CERTIFICATE----- -MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw -NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv -b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD -VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2 -MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F -VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1 -7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X -Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+ -/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs -81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm -dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe -Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu -sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4 -pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs -slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ -arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD -VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG -9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl -dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx -0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj -TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed -Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7 -Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI -OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7 -vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW -t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn -HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx -SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= ------END CERTIFICATE----- - -# Issuer: CN=E-Tugra Certification Authority O=E-Tu\u011fra EBG Bili\u015fim Teknolojileri ve Hizmetleri A.\u015e. OU=E-Tugra Sertifikasyon Merkezi -# Subject: CN=E-Tugra Certification Authority O=E-Tu\u011fra EBG Bili\u015fim Teknolojileri ve Hizmetleri A.\u015e. OU=E-Tugra Sertifikasyon Merkezi -# Label: "E-Tugra Certification Authority" -# Serial: 7667447206703254355 -# MD5 Fingerprint: b8:a1:03:63:b0:bd:21:71:70:8a:6f:13:3a:bb:79:49 -# SHA1 Fingerprint: 51:c6:e7:08:49:06:6e:f3:92:d4:5c:a0:0d:6d:a3:62:8f:c3:52:39 -# SHA256 Fingerprint: b0:bf:d5:2b:b0:d7:d9:bd:92:bf:5d:4d:c1:3d:a2:55:c0:2c:54:2f:37:83:65:ea:89:39:11:f5:5e:55:f2:3c ------BEGIN CERTIFICATE----- -MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNV -BAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBC -aWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNV -BAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQDDB9FLVR1 -Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMwNTEyMDk0OFoXDTIz -MDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+ -BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhp -em1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN -ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4vU/kwVRHoViVF56C/UY -B4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vdhQd2h8y/L5VMzH2nPbxH -D5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5KCKpbknSF -Q9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEo -q1+gElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3D -k14opz8n8Y4e0ypQBaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcH -fC425lAcP9tDJMW/hkd5s3kc91r0E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsut -dEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gzrt48Ue7LE3wBf4QOXVGUnhMM -ti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAqjqFGOjGY5RH8 -zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn -rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUX -U8u3Zg5mTPj5dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6 -Jyr+zE7S6E5UMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5 -XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAF -Nzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAKkEh47U6YA5n+KGCR -HTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jOXKqY -GwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c -77NCR807VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3 -+GbHeJAAFS6LrVE1Uweoa2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WK -vJUawSg5TB9D0pH0clmKuVb8P7Sd2nCcdlqMQ1DujjByTd//SffGqWfZbawCEeI6 -FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEVKV0jq9BgoRJP3vQXzTLl -yb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gTDx4JnW2P -AJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpD -y4Q08ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8d -NL/+I5c30jn6PQ0GC7TbO6Orb1wdtn7os4I07QZcJA== ------END CERTIFICATE----- - -# Issuer: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center -# Subject: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center -# Label: "T-TeleSec GlobalRoot Class 2" -# Serial: 1 -# MD5 Fingerprint: 2b:9b:9e:e4:7b:6c:1f:00:72:1a:cc:c1:77:79:df:6a -# SHA1 Fingerprint: 59:0d:2d:7d:88:4f:40:2e:61:7e:a5:62:32:17:65:cf:17:d8:94:e9 -# SHA256 Fingerprint: 91:e2:f5:78:8d:58:10:eb:a7:ba:58:73:7d:e1:54:8a:8e:ca:cd:01:45:98:bc:0b:14:3e:04:1b:17:05:25:52 ------BEGIN CERTIFICATE----- -MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx -KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd -BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl -YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1 -OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy -aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 -ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd -AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC -FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi -1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq -jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ -wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj -QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/ -WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy -NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC -uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw -IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6 -g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN -9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP -BSeOE6Fuwg== ------END CERTIFICATE----- - -# Issuer: CN=Atos TrustedRoot 2011 O=Atos -# Subject: CN=Atos TrustedRoot 2011 O=Atos -# Label: "Atos TrustedRoot 2011" -# Serial: 6643877497813316402 -# MD5 Fingerprint: ae:b9:c4:32:4b:ac:7f:5d:66:cc:77:94:bb:2a:77:56 -# SHA1 Fingerprint: 2b:b1:f5:3e:55:0c:1d:c5:f1:d4:e6:b7:6a:46:4b:55:06:02:ac:21 -# SHA256 Fingerprint: f3:56:be:a2:44:b7:a9:1e:b3:5d:53:ca:9a:d7:86:4a:ce:01:8e:2d:35:d5:f8:f9:6d:df:68:a6:f4:1a:a4:74 ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE -AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG -EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM -FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC -REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp -Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM -VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ -SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ -4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L -cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi -eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV -HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG -A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 -DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j -vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP -DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc -maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D -lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv -KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed ------END CERTIFICATE----- - -# Issuer: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited -# Subject: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited -# Label: "QuoVadis Root CA 1 G3" -# Serial: 687049649626669250736271037606554624078720034195 -# MD5 Fingerprint: a4:bc:5b:3f:fe:37:9a:fa:64:f0:e2:fa:05:3d:0b:ab -# SHA1 Fingerprint: 1b:8e:ea:57:96:29:1a:c9:39:ea:b8:0a:81:1a:73:73:c0:93:79:67 -# SHA256 Fingerprint: 8a:86:6f:d1:b2:76:b5:7e:57:8e:92:1c:65:82:8a:2b:ed:58:e9:f2:f2:88:05:41:34:b7:f1:f4:bf:c9:cc:74 ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL -BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc -BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00 -MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM -aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV -wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe -rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341 -68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh -4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp -UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o -abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc -3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G -KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt -hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO -Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt -zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD -ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC -MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2 -cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN -qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5 -YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv -b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2 -8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k -NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj -ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp -q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt -nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD ------END CERTIFICATE----- - -# Issuer: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited -# Subject: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited -# Label: "QuoVadis Root CA 2 G3" -# Serial: 390156079458959257446133169266079962026824725800 -# MD5 Fingerprint: af:0c:86:6e:bf:40:2d:7f:0b:3e:12:50:ba:12:3d:06 -# SHA1 Fingerprint: 09:3c:61:f3:8b:8b:dc:7d:55:df:75:38:02:05:00:e1:25:f5:c8:36 -# SHA256 Fingerprint: 8f:e4:fb:0a:f9:3a:4d:0d:67:db:0b:eb:b2:3e:37:c7:1b:f3:25:dc:bc:dd:24:0e:a0:4d:af:58:b4:7e:18:40 ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL -BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc -BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 -MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM -aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf -qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW -n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym -c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+ -O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1 -o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j -IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq -IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz -8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh -vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l -7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG -cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD -ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 -AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC -roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga -W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n -lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE -+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV -csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd -dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg -KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM -HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4 -WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M ------END CERTIFICATE----- - -# Issuer: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited -# Subject: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited -# Label: "QuoVadis Root CA 3 G3" -# Serial: 268090761170461462463995952157327242137089239581 -# MD5 Fingerprint: df:7d:b9:ad:54:6f:68:a1:df:89:57:03:97:43:b0:d7 -# SHA1 Fingerprint: 48:12:bd:92:3c:a8:c4:39:06:e7:30:6d:27:96:e6:a4:cf:22:2e:7d -# SHA256 Fingerprint: 88:ef:81:de:20:2e:b0:18:45:2e:43:f8:64:72:5c:ea:5f:bd:1f:c2:d9:d2:05:73:07:09:c5:d8:b8:69:0f:46 ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL -BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc -BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00 -MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM -aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR -/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu -FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR -U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c -ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR -FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k -A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw -eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl -sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp -VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q -A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ -ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD -ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px -KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI -FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv -oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg -u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP -0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf -3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl -8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+ -DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN -PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ -ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0 ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Assured ID Root G2" -# Serial: 15385348160840213938643033620894905419 -# MD5 Fingerprint: 92:38:b9:f8:63:24:82:65:2c:57:33:e6:fe:81:8f:9d -# SHA1 Fingerprint: a1:4b:48:d9:43:ee:0a:0e:40:90:4f:3c:e0:a4:c0:91:93:51:5d:3f -# SHA256 Fingerprint: 7d:05:eb:b6:82:33:9f:8c:94:51:ee:09:4e:eb:fe:fa:79:53:a1:14:ed:b2:f4:49:49:45:2f:ab:7d:2f:c1:85 ------BEGIN CERTIFICATE----- -MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv -b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl -cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA -n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc -biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp -EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA -bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu -YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB -AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW -BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI -QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I -0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni -lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9 -B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv -ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo -IhNzbM8m9Yop5w== ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Assured ID Root G3" -# Serial: 15459312981008553731928384953135426796 -# MD5 Fingerprint: 7c:7f:65:31:0c:81:df:8d:ba:3e:99:e2:5c:ad:6e:fb -# SHA1 Fingerprint: f5:17:a2:4f:9a:48:c6:c9:f8:a2:00:26:9f:dc:0f:48:2c:ab:30:89 -# SHA256 Fingerprint: 7e:37:cb:8b:4c:47:09:0c:ab:36:55:1b:a6:f4:5d:b8:40:68:0f:ba:16:6a:95:2d:b1:00:71:7f:43:05:3f:c2 ------BEGIN CERTIFICATE----- -MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw -CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu -ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg -RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV -UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu -Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq -hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf -Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q -RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ -BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD -AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY -JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv -6pZjamVFkpUBtA== ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Global Root G2" -# Serial: 4293743540046975378534879503202253541 -# MD5 Fingerprint: e4:a6:8a:c8:54:ac:52:42:46:0a:fd:72:48:1b:2a:44 -# SHA1 Fingerprint: df:3c:24:f9:bf:d6:66:76:1b:26:80:73:fe:06:d1:cc:8d:4f:82:a4 -# SHA256 Fingerprint: cb:3c:cb:b7:60:31:e5:e0:13:8f:8d:d3:9a:23:f9:de:47:ff:c3:5e:43:c1:14:4c:ea:27:d4:6a:5a:b1:cb:5f ------BEGIN CERTIFICATE----- -MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH -MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI -2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx -1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ -q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz -tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ -vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP -BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV -5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY -1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 -NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG -Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 -8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe -pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl -MrY= ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Global Root G3" -# Serial: 7089244469030293291760083333884364146 -# MD5 Fingerprint: f5:5d:a4:50:a5:fb:28:7e:1e:0f:0d:cc:96:57:56:ca -# SHA1 Fingerprint: 7e:04:de:89:6a:3e:66:6d:00:e6:87:d3:3f:fa:d9:3b:e8:3d:34:9e -# SHA256 Fingerprint: 31:ad:66:48:f8:10:41:38:c7:38:f3:9e:a4:32:01:33:39:3e:3a:18:cc:02:29:6e:f9:7c:2a:c9:ef:67:31:d0 ------BEGIN CERTIFICATE----- -MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw -CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu -ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe -Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw -EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x -IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF -K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG -fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO -Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd -BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx -AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/ -oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 -sycX ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Trusted Root G4" -# Serial: 7451500558977370777930084869016614236 -# MD5 Fingerprint: 78:f2:fc:aa:60:1f:2f:b4:eb:c9:37:ba:53:2e:75:49 -# SHA1 Fingerprint: dd:fb:16:cd:49:31:c9:73:a2:03:7d:3f:c8:3a:4d:7d:77:5d:05:e4 -# SHA256 Fingerprint: 55:2f:7b:dc:f1:a7:af:9e:6c:e6:72:01:7f:4f:12:ab:f7:72:40:c7:8e:76:1a:c2:03:d1:d9:d2:0a:c8:99:88 ------BEGIN CERTIFICATE----- -MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg -RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV -UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu -Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y -ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If -xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV -ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO -DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ -jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/ -CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi -EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM -fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY -uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK -chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t -9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD -ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2 -SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd -+SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc -fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa -sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N -cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N -0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie -4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI -r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 -/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm -gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ ------END CERTIFICATE----- - -# Issuer: CN=COMODO RSA Certification Authority O=COMODO CA Limited -# Subject: CN=COMODO RSA Certification Authority O=COMODO CA Limited -# Label: "COMODO RSA Certification Authority" -# Serial: 101909084537582093308941363524873193117 -# MD5 Fingerprint: 1b:31:b0:71:40:36:cc:14:36:91:ad:c4:3e:fd:ec:18 -# SHA1 Fingerprint: af:e5:d2:44:a8:d1:19:42:30:ff:47:9f:e2:f8:97:bb:cd:7a:8c:b4 -# SHA256 Fingerprint: 52:f0:e1:c4:e5:8e:c6:29:29:1b:60:31:7f:07:46:71:b8:5d:7e:a8:0d:5b:07:27:34:63:53:4b:32:b4:02:34 ------BEGIN CERTIFICATE----- -MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB -hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV -BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5 -MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT -EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR -Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR -6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X -pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC -9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV -/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf -Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z -+pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w -qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah -SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC -u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf -Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq -crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E -FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB -/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl -wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM -4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV -2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna -FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ -CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK -boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke -jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL -S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb -QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl -0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB -NVOFBkpdn627G190 ------END CERTIFICATE----- - -# Issuer: CN=USERTrust RSA Certification Authority O=The USERTRUST Network -# Subject: CN=USERTrust RSA Certification Authority O=The USERTRUST Network -# Label: "USERTrust RSA Certification Authority" -# Serial: 2645093764781058787591871645665788717 -# MD5 Fingerprint: 1b:fe:69:d1:91:b7:19:33:a3:72:a8:0f:e1:55:e5:b5 -# SHA1 Fingerprint: 2b:8f:1b:57:33:0d:bb:a2:d0:7a:6c:51:f7:0e:e9:0d:da:b9:ad:8e -# SHA256 Fingerprint: e7:93:c9:b0:2f:d8:aa:13:e2:1c:31:22:8a:cc:b0:81:19:64:3b:74:9c:89:89:64:b1:74:6d:46:c3:d4:cb:d2 ------BEGIN CERTIFICATE----- -MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB -iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl -cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV -BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw -MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV -BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU -aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy -dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B -3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY -tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/ -Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2 -VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT -79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6 -c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT -Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l -c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee -UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE -Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd -BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G -A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF -Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO -VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3 -ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs -8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR -iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze -Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ -XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/ -qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB -VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB -L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG -jjxDah2nGN59PRbxYvnKkKj9 ------END CERTIFICATE----- - -# Issuer: CN=USERTrust ECC Certification Authority O=The USERTRUST Network -# Subject: CN=USERTrust ECC Certification Authority O=The USERTRUST Network -# Label: "USERTrust ECC Certification Authority" -# Serial: 123013823720199481456569720443997572134 -# MD5 Fingerprint: fa:68:bc:d9:b5:7f:ad:fd:c9:1d:06:83:28:cc:24:c1 -# SHA1 Fingerprint: d1:cb:ca:5d:b2:d5:2a:7f:69:3b:67:4d:e5:f0:5a:1d:0c:95:7d:f0 -# SHA256 Fingerprint: 4f:f4:60:d5:4b:9c:86:da:bf:bc:fc:57:12:e0:40:0d:2b:ed:3f:bc:4d:4f:bd:aa:86:e0:6a:dc:d2:a9:ad:7a ------BEGIN CERTIFICATE----- -MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL -MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl -eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT -JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx -MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT -Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg -VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm -aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo -I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng -o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G -A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB -zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW -RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 -# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 -# Label: "GlobalSign ECC Root CA - R4" -# Serial: 14367148294922964480859022125800977897474 -# MD5 Fingerprint: 20:f0:27:68:d1:7e:a0:9d:0e:e6:2a:ca:df:5c:89:8e -# SHA1 Fingerprint: 69:69:56:2e:40:80:f4:24:a1:e7:19:9f:14:ba:f3:ee:58:ab:6a:bb -# SHA256 Fingerprint: be:c9:49:11:c2:95:56:76:db:6c:0a:55:09:86:d7:6e:3b:a0:05:66:7c:44:2c:97:62:b4:fb:b7:73:de:22:8c ------BEGIN CERTIFICATE----- -MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk -MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH -bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX -DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD -QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ -FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw -DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F -uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX -kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs -ewv4n4Q= ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5 -# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5 -# Label: "GlobalSign ECC Root CA - R5" -# Serial: 32785792099990507226680698011560947931244 -# MD5 Fingerprint: 9f:ad:3b:1c:02:1e:8a:ba:17:74:38:81:0c:a2:bc:08 -# SHA1 Fingerprint: 1f:24:c6:30:cd:a4:18:ef:20:69:ff:ad:4f:dd:5f:46:3a:1b:69:aa -# SHA256 Fingerprint: 17:9f:bc:14:8a:3d:d0:0f:d2:4e:a1:34:58:cc:43:bf:a7:f5:9c:81:82:d7:83:a5:13:f6:eb:ec:10:0c:89:24 ------BEGIN CERTIFICATE----- -MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk -MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH -bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX -DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD -QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu -MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc -8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke -hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI -KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg -515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO -xwy8p2Fp8fc74SrL+SvzZpA3 ------END CERTIFICATE----- - -# Issuer: CN=Staat der Nederlanden Root CA - G3 O=Staat der Nederlanden -# Subject: CN=Staat der Nederlanden Root CA - G3 O=Staat der Nederlanden -# Label: "Staat der Nederlanden Root CA - G3" -# Serial: 10003001 -# MD5 Fingerprint: 0b:46:67:07:db:10:2f:19:8c:35:50:60:d1:0b:f4:37 -# SHA1 Fingerprint: d8:eb:6b:41:51:92:59:e0:f3:e7:85:00:c0:3d:b6:88:97:c9:ee:fc -# SHA256 Fingerprint: 3c:4f:b0:b9:5a:b8:b3:00:32:f4:32:b8:6f:53:5f:e1:72:c1:85:d0:fd:39:86:58:37:cf:36:18:7f:a6:f4:28 ------BEGIN CERTIFICATE----- -MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO -TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh -dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloX -DTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl -ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv -b3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4yolQP -cPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WW -IkYFsO2tx1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqX -xz8ecAgwoNzFs21v0IJyEavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFy -KJLZWyNtZrVtB0LrpjPOktvA9mxjeM3KTj215VKb8b475lRgsGYeCasH/lSJEULR -9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUurmkVLoR9BvUhTFXFkC4az -5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU51nus6+N8 -6U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7 -Ngzp07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHP -bMk7ccHViLVlvMDoFxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXt -BznaqB16nzaeErAMZRKQFWDZJkBE41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTt -XUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMBAAGjQjBAMA8GA1UdEwEB/wQF -MAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleuyjWcLhL75Lpd -INyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD -U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwp -LiniyMMB8jPqKqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8 -Ipf3YF3qKS9Ysr1YvY2WTxB1v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixp -gZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA8KCWAg8zxXHzniN9lLf9OtMJgwYh -/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b8KKaa8MFSu1BYBQw -0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0rmj1A -fsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq -4BZ+Extq1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR -1VmiiXTTn74eS9fGbbeIJG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/ -QFH1T/U67cjF68IeHRaVesd+QnGTbksVtzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM -94B7IWcnMFk= ------END CERTIFICATE----- - -# Issuer: CN=Staat der Nederlanden EV Root CA O=Staat der Nederlanden -# Subject: CN=Staat der Nederlanden EV Root CA O=Staat der Nederlanden -# Label: "Staat der Nederlanden EV Root CA" -# Serial: 10000013 -# MD5 Fingerprint: fc:06:af:7b:e8:1a:f1:9a:b4:e8:d2:70:1f:c0:f5:ba -# SHA1 Fingerprint: 76:e2:7e:c1:4f:db:82:c1:c0:a6:75:b5:05:be:3d:29:b4:ed:db:bb -# SHA256 Fingerprint: 4d:24:91:41:4c:fe:95:67:46:ec:4c:ef:a6:cf:6f:72:e2:8a:13:29:43:2f:9d:8a:90:7a:c4:cb:5d:ad:c1:5a ------BEGIN CERTIFICATE----- -MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJO -TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFh -dCBkZXIgTmVkZXJsYW5kZW4gRVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0y -MjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIg -TmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBS -b290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkkSzrS -M4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nC -UiY4iKTWO0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3d -Z//BYY1jTw+bbRcwJu+r0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46p -rfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13l -pJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gVXJrm0w912fxBmJc+qiXb -j5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr08C+eKxC -KFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS -/ZbV0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0X -cgOPvZuM5l5Tnrmd74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH -1vI4gnPah1vlPNOePqc7nvQDs/nxfRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrP -px9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB -/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwaivsnuL8wbqg7 -MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI -eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u -2dfOWBfoqSmuc0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHS -v4ilf0X8rLiltTMMgsT7B/Zq5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTC -wPTxGfARKbalGAKb12NMcIxHowNDXLldRqANb/9Zjr7dn3LDWyvfjFvO5QxGbJKy -CqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tNf1zuacpzEPuKqf2e -vTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi5Dp6 -Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIa -Gl6I6lD4WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeL -eG9QgkRQP2YGiqtDhFZKDyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8 -FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGyeUN51q1veieQA6TqJIc/2b3Z6fJfUEkc -7uzXLg== ------END CERTIFICATE----- - -# Issuer: CN=IdenTrust Commercial Root CA 1 O=IdenTrust -# Subject: CN=IdenTrust Commercial Root CA 1 O=IdenTrust -# Label: "IdenTrust Commercial Root CA 1" -# Serial: 13298821034946342390520003877796839426 -# MD5 Fingerprint: b3:3e:77:73:75:ee:a0:d3:e3:7e:49:63:49:59:bb:c7 -# SHA1 Fingerprint: df:71:7e:aa:4a:d9:4e:c9:55:84:99:60:2d:48:de:5f:bc:f0:3a:25 -# SHA256 Fingerprint: 5d:56:49:9b:e4:d2:e0:8b:cf:ca:d0:8a:3e:38:72:3d:50:50:3b:de:70:69:48:e4:2f:55:60:30:19:e5:28:ae ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK -MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu -VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw -MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw -JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT -3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU -+ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp -S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1 -bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi -T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL -vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK -Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK -dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT -c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv -l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N -iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD -ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH -6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt -LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93 -nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3 -+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK -W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT -AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq -l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG -4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ -mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A -7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H ------END CERTIFICATE----- - -# Issuer: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust -# Subject: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust -# Label: "IdenTrust Public Sector Root CA 1" -# Serial: 13298821034946342390521976156843933698 -# MD5 Fingerprint: 37:06:a5:b0:fc:89:9d:ba:f4:6b:8c:1a:64:cd:d5:ba -# SHA1 Fingerprint: ba:29:41:60:77:98:3f:f4:f3:ef:f2:31:05:3b:2e:ea:6d:4d:45:fd -# SHA256 Fingerprint: 30:d0:89:5a:9a:44:8a:26:20:91:63:55:22:d1:f5:20:10:b5:86:7a:ca:e1:2c:78:ef:95:8f:d4:f4:38:9f:2f ------BEGIN CERTIFICATE----- -MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN -MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu -VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN -MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0 -MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7 -ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy -RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS -bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF -/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R -3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw -EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy -9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V -GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ -2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV -WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD -W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ -BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN -AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj -t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV -DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9 -TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G -lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW -mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df -WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5 -+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ -tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA -GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv -8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c ------END CERTIFICATE----- - -# Issuer: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only -# Subject: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only -# Label: "Entrust Root Certification Authority - G2" -# Serial: 1246989352 -# MD5 Fingerprint: 4b:e2:c9:91:96:65:0c:f4:0e:5a:93:92:a0:0a:fe:b2 -# SHA1 Fingerprint: 8c:f4:27:fd:79:0c:3a:d1:66:06:8d:e8:1e:57:ef:bb:93:22:72:d4 -# SHA256 Fingerprint: 43:df:57:74:b0:3e:7f:ef:5f:e4:0d:93:1a:7b:ed:f1:bb:2e:6b:42:73:8c:4e:6d:38:41:10:3d:3a:a7:f3:39 ------BEGIN CERTIFICATE----- -MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC -VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50 -cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs -IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz -dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy -NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu -dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt -dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0 -aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T -RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN -cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW -wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1 -U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0 -jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP -BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN -BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/ -jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ -Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v -1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R -nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH -VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g== ------END CERTIFICATE----- - -# Issuer: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only -# Subject: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only -# Label: "Entrust Root Certification Authority - EC1" -# Serial: 51543124481930649114116133369 -# MD5 Fingerprint: b6:7e:1d:f0:58:c5:49:6c:24:3b:3d:ed:98:18:ed:bc -# SHA1 Fingerprint: 20:d8:06:40:df:9b:25:f5:12:25:3a:11:ea:f7:59:8a:eb:14:b5:47 -# SHA256 Fingerprint: 02:ed:0e:b2:8c:14:da:45:16:5c:56:67:91:70:0d:64:51:d7:fb:56:f0:b2:ab:1d:3b:8e:b0:70:e5:6e:df:f5 ------BEGIN CERTIFICATE----- -MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG -A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3 -d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu -dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq -RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy -MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD -VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 -L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g -Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi -A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt -ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH -Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O -BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC -R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX -hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G ------END CERTIFICATE----- - -# Issuer: CN=CFCA EV ROOT O=China Financial Certification Authority -# Subject: CN=CFCA EV ROOT O=China Financial Certification Authority -# Label: "CFCA EV ROOT" -# Serial: 407555286 -# MD5 Fingerprint: 74:e1:b6:ed:26:7a:7a:44:30:33:94:ab:7b:27:81:30 -# SHA1 Fingerprint: e2:b8:29:4b:55:84:ab:6b:58:c2:90:46:6c:ac:3f:b8:39:8f:84:83 -# SHA256 Fingerprint: 5c:c3:d7:8e:4e:1d:5e:45:54:7a:04:e6:87:3e:64:f9:0c:f9:53:6d:1c:cc:2e:f8:00:f3:55:c4:c5:fd:70:fd ------BEGIN CERTIFICATE----- -MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD -TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y -aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx -MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j -aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP -T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03 -sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL -TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5 -/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp -7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz -EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt -hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP -a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot -aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg -TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV -PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv -cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL -tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd -BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB -ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT -ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL -jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS -ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy -P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19 -xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d -Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN -5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe -/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z -AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ -5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su ------END CERTIFICATE----- - -# Issuer: CN=Certinomis - Root CA O=Certinomis OU=0002 433998903 -# Subject: CN=Certinomis - Root CA O=Certinomis OU=0002 433998903 -# Label: "Certinomis - Root CA" -# Serial: 1 -# MD5 Fingerprint: 14:0a:fd:8d:a8:28:b5:38:69:db:56:7e:61:22:03:3f -# SHA1 Fingerprint: 9d:70:bb:01:a5:a4:a0:18:11:2e:f7:1c:01:b9:32:c5:34:e7:88:a8 -# SHA256 Fingerprint: 2a:99:f5:bc:11:74:b7:3c:bb:1d:62:08:84:e0:1c:34:e5:1c:cb:39:78:da:12:5f:0e:33:26:88:83:bf:41:58 ------BEGIN CERTIFICATE----- -MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjET -MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAb -BgNVBAMTFENlcnRpbm9taXMgLSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMz -MTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMx -FzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRDZXJ0aW5vbWlzIC0g -Um9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQosP5L2 -fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJfl -LieY6pOod5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQV -WZUKxkd8aRi5pwP5ynapz8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDF -TKWrteoB4owuZH9kb/2jJZOLyKIOSY008B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb -5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09xRLWtwHkziOC/7aOgFLSc -CbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE6OXWk6Ri -wsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJ -wx3tFvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SG -m/lg0h9tkQPTYKbVPZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4 -F2iw4lNVYC2vPsKD2NkJK/DAZNuHi5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZng -WVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIB -BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I6tNxIqSSaHh0 -2TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF -AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/ -0KGRHCwPT5iVWVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWw -F6YSjNRieOpWauwK0kDDPAUwPk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZS -g081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAXlCOotQqSD7J6wWAsOMwaplv/8gzj -qh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJy29SWwNyhlCVCNSN -h4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9Iff/ -ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8V -btaw5BngDwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwj -Y/M50n92Uaf0yKHxDHYiI0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ -8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nMcyrDflOR1m749fPH0FFNjkulW+YZFzvW -gQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVrhkIGuUE= ------END CERTIFICATE----- - -# Issuer: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed -# Subject: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed -# Label: "OISTE WISeKey Global Root GB CA" -# Serial: 157768595616588414422159278966750757568 -# MD5 Fingerprint: a4:eb:b9:61:28:2e:b7:2f:98:b0:35:26:90:99:51:1d -# SHA1 Fingerprint: 0f:f9:40:76:18:d3:d7:6a:4b:98:f0:a8:35:9e:0c:fd:27:ac:cc:ed -# SHA256 Fingerprint: 6b:9c:08:e8:6e:b0:f7:67:cf:ad:65:cd:98:b6:21:49:e5:49:4a:67:f5:84:5e:7b:d1:ed:01:9f:27:b8:6b:d6 ------BEGIN CERTIFICATE----- -MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt -MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg -Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i -YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x -CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG -b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh -bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3 -HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx -WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX -1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk -u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P -99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r -M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB -BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh -cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5 -gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO -ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf -aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic -Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= ------END CERTIFICATE----- - -# Issuer: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A. -# Subject: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A. -# Label: "SZAFIR ROOT CA2" -# Serial: 357043034767186914217277344587386743377558296292 -# MD5 Fingerprint: 11:64:c1:89:b0:24:b1:8c:b1:07:7e:89:9e:51:9e:99 -# SHA1 Fingerprint: e2:52:fa:95:3f:ed:db:24:60:bd:6e:28:f3:9c:cc:cf:5e:b3:3f:de -# SHA256 Fingerprint: a1:33:9d:33:28:1a:0b:56:e5:57:d3:d3:2b:1c:e7:f9:36:7e:b0:94:bd:5f:a7:2a:7e:50:04:c8:de:d7:ca:fe ------BEGIN CERTIFICATE----- -MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL -BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6 -ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw -NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L -cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg -Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN -QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT -3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw -3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6 -3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5 -BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN -XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD -AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF -AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw -8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG -nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP -oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy -d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg -LvWpCz/UXeHPhJ/iGcJfitYgHuNztw== ------END CERTIFICATE----- - -# Issuer: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority -# Subject: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority -# Label: "Certum Trusted Network CA 2" -# Serial: 44979900017204383099463764357512596969 -# MD5 Fingerprint: 6d:46:9e:d9:25:6d:08:23:5b:5e:74:7d:1e:27:db:f2 -# SHA1 Fingerprint: d3:dd:48:3e:2b:bf:4c:05:e8:af:10:f5:fa:76:26:cf:d3:dc:30:92 -# SHA256 Fingerprint: b6:76:f2:ed:da:e8:77:5c:d3:6c:b0:f6:3c:d1:d4:60:39:61:f4:9e:62:65:ba:01:3a:2f:03:07:b6:d0:b8:04 ------BEGIN CERTIFICATE----- -MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB -gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu -QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG -A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz -OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ -VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3 -b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA -DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn -0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB -OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE -fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E -Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m -o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i -sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW -OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez -Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS -adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n -3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC -AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ -F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf -CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29 -XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm -djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/ -WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb -AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq -P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko -b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj -XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P -5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi -DrW5viSP ------END CERTIFICATE----- - -# Issuer: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority -# Subject: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority -# Label: "Hellenic Academic and Research Institutions RootCA 2015" -# Serial: 0 -# MD5 Fingerprint: ca:ff:e2:db:03:d9:cb:4b:e9:0f:ad:84:fd:7b:18:ce -# SHA1 Fingerprint: 01:0c:06:95:a6:98:19:14:ff:bf:5f:c6:b0:b6:95:ea:29:e9:12:a6 -# SHA256 Fingerprint: a0:40:92:9a:02:ce:53:b4:ac:f4:f2:ff:c6:98:1c:e4:49:6f:75:5e:6d:45:fe:0b:2a:69:2b:cd:52:52:3f:36 ------BEGIN CERTIFICATE----- -MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix -DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k -IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT -N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v -dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG -A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh -ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx -QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 -dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA -4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0 -AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10 -4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C -ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV -9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD -gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6 -Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq -NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko -LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc -Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV -HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd -ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I -XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI -M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot -9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V -Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea -j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh -X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ -l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf -bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4 -pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK -e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0 -vm9qp/UsQu0yrbYhnr68 ------END CERTIFICATE----- - -# Issuer: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority -# Subject: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority -# Label: "Hellenic Academic and Research Institutions ECC RootCA 2015" -# Serial: 0 -# MD5 Fingerprint: 81:e5:b4:17:eb:c2:f5:e1:4b:0d:41:7b:49:92:fe:ef -# SHA1 Fingerprint: 9f:f1:71:8d:92:d5:9a:f3:7d:74:97:b4:bc:6f:84:68:0b:ba:b6:66 -# SHA256 Fingerprint: 44:b5:45:aa:8a:25:e6:5a:73:ca:15:dc:27:fc:36:d2:4c:1c:b9:95:3a:06:65:39:b1:15:82:dc:48:7b:48:33 ------BEGIN CERTIFICATE----- -MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN -BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl -c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl -bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv -b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ -BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj -YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5 -MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0 -dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg -QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa -jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi -C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep -lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof -TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR ------END CERTIFICATE----- - -# Issuer: CN=ISRG Root X1 O=Internet Security Research Group -# Subject: CN=ISRG Root X1 O=Internet Security Research Group -# Label: "ISRG Root X1" -# Serial: 172886928669790476064670243504169061120 -# MD5 Fingerprint: 0c:d2:f9:e0:da:17:73:e9:ed:86:4d:a5:e3:70:e7:4e -# SHA1 Fingerprint: ca:bd:2a:79:a1:07:6a:31:f2:1d:25:36:35:cb:03:9d:43:29:a5:e8 -# SHA256 Fingerprint: 96:bc:ec:06:26:49:76:f3:74:60:77:9a:cf:28:c5:a7:cf:e8:a3:c0:aa:e1:1a:8f:fc:ee:05:c0:bd:df:08:c6 ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 -WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu -ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY -MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc -h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ -0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U -A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW -T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH -B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC -B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv -KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn -OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn -jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw -qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI -rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq -hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL -ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ -3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK -NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 -ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur -TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC -jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc -oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq -4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA -mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d -emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= ------END CERTIFICATE----- - -# Issuer: O=FNMT-RCM OU=AC RAIZ FNMT-RCM -# Subject: O=FNMT-RCM OU=AC RAIZ FNMT-RCM -# Label: "AC RAIZ FNMT-RCM" -# Serial: 485876308206448804701554682760554759 -# MD5 Fingerprint: e2:09:04:b4:d3:bd:d1:a0:14:fd:1a:d2:47:c4:57:1d -# SHA1 Fingerprint: ec:50:35:07:b2:15:c4:95:62:19:e2:a8:9a:5b:42:99:2c:4c:2c:20 -# SHA256 Fingerprint: eb:c5:57:0c:29:01:8c:4d:67:b1:aa:12:7b:af:12:f7:03:b4:61:1e:bc:17:b7:da:b5:57:38:94:17:9b:93:fa ------BEGIN CERTIFICATE----- -MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx -CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ -WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ -BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG -Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/ -yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf -BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz -WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF -tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z -374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC -IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL -mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7 -wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS -MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2 -ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet -UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw -AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H -YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3 -LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD -nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1 -RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM -LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf -77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N -JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm -fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp -6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp -1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B -9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok -RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv -uu8wd+RU4riEmViAqhOLUTpPSPaLtrM= ------END CERTIFICATE----- - -# Issuer: CN=Amazon Root CA 1 O=Amazon -# Subject: CN=Amazon Root CA 1 O=Amazon -# Label: "Amazon Root CA 1" -# Serial: 143266978916655856878034712317230054538369994 -# MD5 Fingerprint: 43:c6:bf:ae:ec:fe:ad:2f:18:c6:88:68:30:fc:c8:e6 -# SHA1 Fingerprint: 8d:a7:f9:65:ec:5e:fc:37:91:0f:1c:6e:59:fd:c1:cc:6a:6e:de:16 -# SHA256 Fingerprint: 8e:cd:e6:88:4f:3d:87:b1:12:5b:a3:1a:c3:fc:b1:3d:70:16:de:7f:57:cc:90:4f:e1:cb:97:c6:ae:98:19:6e ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA -A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI -U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs -N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv -o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU -5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy -rqXRfboQnoZsG4q5WTP468SQvvG5 ------END CERTIFICATE----- - -# Issuer: CN=Amazon Root CA 2 O=Amazon -# Subject: CN=Amazon Root CA 2 O=Amazon -# Label: "Amazon Root CA 2" -# Serial: 143266982885963551818349160658925006970653239 -# MD5 Fingerprint: c8:e5:8d:ce:a8:42:e2:7a:c0:2a:5c:7c:9e:26:bf:66 -# SHA1 Fingerprint: 5a:8c:ef:45:d7:a6:98:59:76:7a:8c:8b:44:96:b5:78:cf:47:4b:1a -# SHA256 Fingerprint: 1b:a5:b2:aa:8c:65:40:1a:82:96:01:18:f8:0b:ec:4f:62:30:4d:83:ce:c4:71:3a:19:c3:9c:01:1e:a4:6d:b4 ------BEGIN CERTIFICATE----- -MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK -gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ -W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg -1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K -8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r -2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me -z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR -8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj -mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz -7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6 -+XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI -0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB -Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm -UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2 -LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY -+gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS -k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl -7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm -btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl -urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+ -fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63 -n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE -76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H -9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT -4PsJYGw= ------END CERTIFICATE----- - -# Issuer: CN=Amazon Root CA 3 O=Amazon -# Subject: CN=Amazon Root CA 3 O=Amazon -# Label: "Amazon Root CA 3" -# Serial: 143266986699090766294700635381230934788665930 -# MD5 Fingerprint: a0:d4:ef:0b:f7:b5:d8:49:95:2a:ec:f5:c4:fc:81:87 -# SHA1 Fingerprint: 0d:44:dd:8c:3c:8c:1a:1a:58:75:64:81:e9:0f:2e:2a:ff:b3:d2:6e -# SHA256 Fingerprint: 18:ce:6c:fe:7b:f1:4e:60:b2:e3:47:b8:df:e8:68:cb:31:d0:2e:bb:3a:da:27:15:69:f5:03:43:b4:6d:b3:a4 ------BEGIN CERTIFICATE----- -MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5 -MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g -Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG -A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg -Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl -ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j -QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr -ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr -BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM -YyRIHN8wfdVoOw== ------END CERTIFICATE----- - -# Issuer: CN=Amazon Root CA 4 O=Amazon -# Subject: CN=Amazon Root CA 4 O=Amazon -# Label: "Amazon Root CA 4" -# Serial: 143266989758080763974105200630763877849284878 -# MD5 Fingerprint: 89:bc:27:d5:eb:17:8d:06:6a:69:d5:fd:89:47:b4:cd -# SHA1 Fingerprint: f6:10:84:07:d6:f8:bb:67:98:0c:c2:e2:44:c2:eb:ae:1c:ef:63:be -# SHA256 Fingerprint: e3:5d:28:41:9e:d0:20:25:cf:a6:90:38:cd:62:39:62:45:8d:a5:c6:95:fb:de:a3:c2:2b:0b:fb:25:89:70:92 ------BEGIN CERTIFICATE----- -MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5 -MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g -Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG -A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg -Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi -9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk -M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB -/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB -MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw -CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW -1KyLa2tJElMzrdfkviT8tQp21KW8EA== ------END CERTIFICATE----- - -# Issuer: CN=LuxTrust Global Root 2 O=LuxTrust S.A. -# Subject: CN=LuxTrust Global Root 2 O=LuxTrust S.A. -# Label: "LuxTrust Global Root 2" -# Serial: 59914338225734147123941058376788110305822489521 -# MD5 Fingerprint: b2:e1:09:00:61:af:f7:f1:91:6f:c4:ad:8d:5e:3b:7c -# SHA1 Fingerprint: 1e:0e:56:19:0a:d1:8b:25:98:b2:04:44:ff:66:8a:04:17:99:5f:3f -# SHA256 Fingerprint: 54:45:5f:71:29:c2:0b:14:47:c4:18:f9:97:16:8f:24:c5:8f:c5:02:3b:f5:da:5b:e2:eb:6e:1d:d8:90:2e:d5 ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -# Issuer: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM -# Subject: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM -# Label: "TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1" -# Serial: 1 -# MD5 Fingerprint: dc:00:81:dc:69:2f:3e:2f:b0:3b:f6:3d:5a:91:8e:49 -# SHA1 Fingerprint: 31:43:64:9b:ec:ce:27:ec:ed:3a:3f:0b:8f:0d:e4:e8:91:dd:ee:ca -# SHA256 Fingerprint: 46:ed:c3:68:90:46:d5:3a:45:3f:b3:10:4a:b8:0d:ca:ec:65:8b:26:60:ea:16:29:dd:7e:86:79:90:64:87:16 ------BEGIN CERTIFICATE----- -MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx -GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp -bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w -KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0 -BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy -dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG -EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll -IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU -QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT -TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg -LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7 -a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr -LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr -N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X -YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/ -iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f -AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH -V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL -BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh -AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf -IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4 -lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c -8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf -lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= ------END CERTIFICATE----- - -# Issuer: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD. -# Subject: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD. -# Label: "GDCA TrustAUTH R5 ROOT" -# Serial: 9009899650740120186 -# MD5 Fingerprint: 63:cc:d9:3d:34:35:5c:6f:53:a3:e2:08:70:48:1f:b4 -# SHA1 Fingerprint: 0f:36:38:5b:81:1a:25:c3:9b:31:4e:83:ca:e9:34:66:70:cc:74:b4 -# SHA256 Fingerprint: bf:ff:8f:d0:44:33:48:7d:6a:8a:a6:0c:1a:29:76:7a:9f:c2:bb:b0:5e:42:0f:71:3a:13:b9:92:89:1d:38:93 ------BEGIN CERTIFICATE----- -MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE -BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ -IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0 -MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV -BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w -HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF -AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj -Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj -TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u -KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj -qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm -MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12 -ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP -zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk -L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC -jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA -HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC -AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB -/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg -p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm -DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5 -COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry -L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf -JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg -IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io -2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV -09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ -XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq -T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe -MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== ------END CERTIFICATE----- - -# Issuer: CN=TrustCor RootCert CA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority -# Subject: CN=TrustCor RootCert CA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority -# Label: "TrustCor RootCert CA-1" -# Serial: 15752444095811006489 -# MD5 Fingerprint: 6e:85:f1:dc:1a:00:d3:22:d5:b2:b2:ac:6b:37:05:45 -# SHA1 Fingerprint: ff:bd:cd:e7:82:c8:43:5e:3c:6f:26:86:5c:ca:a8:3a:45:5b:c3:0a -# SHA256 Fingerprint: d4:0e:9c:86:cd:8f:e4:68:c1:77:69:59:f4:9e:a7:74:fa:54:86:84:b6:c4:06:f3:90:92:61:f4:dc:e2:57:5c ------BEGIN CERTIFICATE----- -MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYD -VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk -MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U -cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29y -IFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkxMjMxMTcyMzE2WjCB -pDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFuYW1h -IENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUG -A1UECwweVHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZU -cnVzdENvciBSb290Q2VydCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEAv463leLCJhJrMxnHQFgKq1mqjQCj/IDHUHuO1CAmujIS2CNUSSUQIpid -RtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4pQa81QBeCQryJ3pS/C3V -seq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0JEsq1pme -9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CV -EY4hgLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorW -hnAbJN7+KIor0Gqw/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/ -DeOxCbeKyKsZn3MzUOcwHwYDVR0jBBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcw -DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD -ggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5mDo4Nvu7Zp5I -/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf -ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZ -yonnMlo2HD6CqFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djts -L1Ac59v2Z3kf9YKVmgenFK+P3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdN -zl/HHk484IkzlQsPpTLWPFp5LBk= ------END CERTIFICATE----- - -# Issuer: CN=TrustCor RootCert CA-2 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority -# Subject: CN=TrustCor RootCert CA-2 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority -# Label: "TrustCor RootCert CA-2" -# Serial: 2711694510199101698 -# MD5 Fingerprint: a2:e1:f8:18:0b:ba:45:d5:c7:41:2a:bb:37:52:45:64 -# SHA1 Fingerprint: b8:be:6d:cb:56:f1:55:b9:63:d4:12:ca:4e:06:34:c7:94:b2:1c:c0 -# SHA256 Fingerprint: 07:53:e9:40:37:8c:1b:d5:e3:83:6e:39:5d:ae:a5:cb:83:9e:50:46:f1:bd:0e:ae:19:51:cf:10:fe:c7:c9:65 ------BEGIN CERTIFICATE----- -MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNV -BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw -IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy -dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEfMB0GA1UEAwwWVHJ1c3RDb3Ig -Um9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEyMzExNzI2MzlaMIGk -MQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEg -Q2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYD -VQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRy -dXN0Q29yIFJvb3RDZXJ0IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQCnIG7CKqJiJJWQdsg4foDSq8GbZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+ -QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9NkRvRUqdw6VC0xK5mC8tkq -1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1oYxOdqHp -2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nK -DOObXUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hape -az6LMvYHL1cEksr1/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF -3wP+TfSvPd9cW436cOGlfifHhi5qjxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88 -oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQPeSghYA2FFn3XVDjxklb9tTNM -g9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+CtgrKAmrhQhJ8Z3 -mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh -8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAd -BgNVHQ4EFgQU2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6U -nrybPZx9mCAZ5YwwYrIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw -DQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/hOsh80QA9z+LqBrWyOrsGS2h60COX -dKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnpkpfbsEZC89NiqpX+ -MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv2wnL -/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RX -CI/hOWB3S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYa -ZH9bDTMJBzN7Bj8RpFxwPIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW -2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dvDDqPys/cA8GiCcjl/YBeyGBCARsaU1q7 -N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYURpFHmygk71dSTlxCnKr3 -Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANExdqtvArB -As8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp -5KeXRKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu -1uwJ ------END CERTIFICATE----- - -# Issuer: CN=TrustCor ECA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority -# Subject: CN=TrustCor ECA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority -# Label: "TrustCor ECA-1" -# Serial: 9548242946988625984 -# MD5 Fingerprint: 27:92:23:1d:0a:f5:40:7c:e9:e6:6b:9d:d8:f5:e7:6c -# SHA1 Fingerprint: 58:d1:df:95:95:67:6b:63:c0:f0:5b:1c:17:4d:8b:84:0b:c8:78:bd -# SHA256 Fingerprint: 5a:88:5d:b1:9c:01:d9:12:c5:75:93:88:93:8c:af:bb:df:03:1a:b2:d4:8e:91:ee:15:58:9b:42:97:1d:03:9c ------BEGIN CERTIFICATE----- -MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYD -VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk -MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U -cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFzAVBgNVBAMMDlRydXN0Q29y -IEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3MjgwN1owgZwxCzAJBgNV -BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw -IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy -dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3Ig -RUNBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb -3w9U73NjKYKtR8aja+3+XzP4Q1HpGjORMRegdMTUpwHmspI+ap3tDvl0mEDTPwOA -BoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23xFUfJ3zSCNV2HykVh0A5 -3ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmcp0yJF4Ou -owReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/ -wZ0+fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZF -ZtS6mFjBAgMBAAGjYzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAf -BgNVHSMEGDAWgBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/ -MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEABT41XBVwm8nHc2Fv -civUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u/ukZMjgDfxT2 -AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F -hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50 -soIipX1TH0XsJ5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BI -WJZpTdwHjFGTot+fDz2LYLSCjaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1Wi -tJ/X5g== ------END CERTIFICATE----- - -# Issuer: CN=SSL.com Root Certification Authority RSA O=SSL Corporation -# Subject: CN=SSL.com Root Certification Authority RSA O=SSL Corporation -# Label: "SSL.com Root Certification Authority RSA" -# Serial: 8875640296558310041 -# MD5 Fingerprint: 86:69:12:c0:70:f1:ec:ac:ac:c2:d5:bc:a5:5b:a1:29 -# SHA1 Fingerprint: b7:ab:33:08:d1:ea:44:77:ba:14:80:12:5a:6f:bd:a9:36:49:0c:bb -# SHA256 Fingerprint: 85:66:6a:56:2e:e0:be:5c:e9:25:c1:d8:89:0a:6f:76:a8:7e:c1:6d:4d:7d:5f:29:ea:74:19:cf:20:12:3b:69 ------BEGIN CERTIFICATE----- -MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE -BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK -DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz -OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv -dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv -bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN -AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R -xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX -qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC -C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3 -6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh -/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF -YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E -JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc -US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8 -ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm -+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi -M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV -HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G -A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV -cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc -Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs -PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/ -q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0 -cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr -a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I -H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y -K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu -nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf -oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY -Ic2wBlX7Jz9TkHCpBB5XJ7k= ------END CERTIFICATE----- - -# Issuer: CN=SSL.com Root Certification Authority ECC O=SSL Corporation -# Subject: CN=SSL.com Root Certification Authority ECC O=SSL Corporation -# Label: "SSL.com Root Certification Authority ECC" -# Serial: 8495723813297216424 -# MD5 Fingerprint: 2e:da:e4:39:7f:9c:8f:37:d1:70:9f:26:17:51:3a:8e -# SHA1 Fingerprint: c3:19:7c:39:24:e6:54:af:1b:c4:ab:20:95:7a:e2:c3:0e:13:02:6a -# SHA256 Fingerprint: 34:17:bb:06:cc:60:07:da:1b:96:1c:92:0b:8a:b4:ce:3f:ad:82:0e:4a:a3:0b:9a:cb:c4:a7:4e:bd:ce:bc:65 ------BEGIN CERTIFICATE----- -MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC -VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T -U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0 -aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz -WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0 -b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS -b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB -BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI -7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg -CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud -EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD -VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T -kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+ -gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl ------END CERTIFICATE----- - -# Issuer: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation -# Subject: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation -# Label: "SSL.com EV Root Certification Authority RSA R2" -# Serial: 6248227494352943350 -# MD5 Fingerprint: e1:1e:31:58:1a:ae:54:53:02:f6:17:6a:11:7b:4d:95 -# SHA1 Fingerprint: 74:3a:f0:52:9b:d0:32:a0:f4:4a:83:cd:d4:ba:a9:7b:7c:2e:c4:9a -# SHA256 Fingerprint: 2e:7b:f1:6c:c2:24:85:a7:bb:e2:aa:86:96:75:07:61:b0:ae:39:be:3b:2f:e9:d0:cc:6d:4e:f7:34:91:42:5c ------BEGIN CERTIFICATE----- -MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV -BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE -CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy -dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy -MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G -A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD -DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq -M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf -OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa -4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9 -HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR -aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA -b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ -Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV -PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO -pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu -UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY -MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV -HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4 -9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW -s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5 -Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg -cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM -79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz -/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt -ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm -Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK -QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ -w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi -S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07 -mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== ------END CERTIFICATE----- - -# Issuer: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation -# Subject: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation -# Label: "SSL.com EV Root Certification Authority ECC" -# Serial: 3182246526754555285 -# MD5 Fingerprint: 59:53:22:65:83:42:01:54:c0:ce:42:b9:5a:7c:f2:90 -# SHA1 Fingerprint: 4c:dd:51:a3:d1:f5:20:32:14:b0:c6:c5:32:23:03:91:c7:46:42:6d -# SHA256 Fingerprint: 22:a2:c1:f7:bd:ed:70:4c:c1:e7:01:b5:f4:08:c3:10:88:0f:e9:56:b5:de:2a:4a:44:f9:9c:87:3a:25:a7:c8 ------BEGIN CERTIFICATE----- -MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC -VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T -U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx -NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv -dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv -bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49 -AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA -VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku -WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP -MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX -5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ -ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg -h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6 -# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6 -# Label: "GlobalSign Root CA - R6" -# Serial: 1417766617973444989252670301619537 -# MD5 Fingerprint: 4f:dd:07:e4:d4:22:64:39:1e:0c:37:42:ea:d1:c6:ae -# SHA1 Fingerprint: 80:94:64:0e:b5:a7:a1:ca:11:9c:1f:dd:d5:9f:81:02:63:a7:fb:d1 -# SHA256 Fingerprint: 2c:ab:ea:fe:37:d0:6c:a2:2a:ba:73:91:c0:03:3d:25:98:29:52:c4:53:64:73:49:76:3a:3a:b5:ad:6c:cf:69 ------BEGIN CERTIFICATE----- -MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg -MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh -bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx -MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET -MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ -KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI -xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k -ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD -aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw -LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw -1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX -k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2 -SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h -bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n -WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY -rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce -MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD -AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu -bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN -nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt -Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61 -55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj -vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf -cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz -oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp -nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs -pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v -JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R -8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4 -5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= ------END CERTIFICATE----- - -# Issuer: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed -# Subject: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed -# Label: "OISTE WISeKey Global Root GC CA" -# Serial: 44084345621038548146064804565436152554 -# MD5 Fingerprint: a9:d6:b9:2d:2f:93:64:f8:a5:69:ca:91:e9:68:07:23 -# SHA1 Fingerprint: e0:11:84:5e:34:de:be:88:81:b9:9c:f6:16:26:d1:96:1f:c3:b9:31 -# SHA256 Fingerprint: 85:60:f9:1c:36:24:da:ba:95:70:b5:fe:a0:db:e3:6f:f1:1a:83:23:be:94:86:85:4f:b3:f3:4a:55:71:19:8d ------BEGIN CERTIFICATE----- -MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw -CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91 -bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg -Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ -BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu -ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS -b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni -eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W -p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E -BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T -rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV -57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg -Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 ------END CERTIFICATE----- - -# Issuer: CN=GTS Root R1 O=Google Trust Services LLC -# Subject: CN=GTS Root R1 O=Google Trust Services LLC -# Label: "GTS Root R1" -# Serial: 146587175971765017618439757810265552097 -# MD5 Fingerprint: 82:1a:ef:d4:d2:4a:f2:9f:e2:3d:97:06:14:70:72:85 -# SHA1 Fingerprint: e1:c9:50:e6:ef:22:f8:4c:56:45:72:8b:92:20:60:d7:d5:a7:a3:e8 -# SHA256 Fingerprint: 2a:57:54:71:e3:13:40:bc:21:58:1c:bd:2c:f1:3e:15:84:63:20:3e:ce:94:bc:f9:d3:cc:19:6b:f0:9a:54:72 ------BEGIN CERTIFICATE----- -MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBH -MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM -QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy -MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl -cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM -f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vX -mX7wCl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7 -zUjwTcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0P -fyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtc -vfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4 -Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUsp -zBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOO -Rc92wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYW -k70paDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+ -DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgF -lQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV -HQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBADiW -Cu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1 -d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6Z -XPYfcX3v73svfuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZR -gyFmxhE+885H7pwoHyXa/6xmld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3 -d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9bgsiG1eGZbYwE8na6SfZu6W0eX6Dv -J4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq4BjFbkerQUIpm/Zg -DdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWErtXvM -+SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyy -F62ARPBopY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9 -SQ98POyDGCBDTtWTurQ0sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdws -E3PYJ/HQcu51OyLemGhmW/HGY0dVHLqlCFF1pkgl ------END CERTIFICATE----- - -# Issuer: CN=GTS Root R2 O=Google Trust Services LLC -# Subject: CN=GTS Root R2 O=Google Trust Services LLC -# Label: "GTS Root R2" -# Serial: 146587176055767053814479386953112547951 -# MD5 Fingerprint: 44:ed:9a:0e:a4:09:3b:00:f2:ae:4c:a3:c6:61:b0:8b -# SHA1 Fingerprint: d2:73:96:2a:2a:5e:39:9f:73:3f:e1:c7:1e:64:3f:03:38:34:fc:4d -# SHA256 Fingerprint: c4:5d:7b:b0:8e:6d:67:e6:2e:42:35:11:0b:56:4e:5f:78:fd:92:ef:05:8c:84:0a:ea:4e:64:55:d7:58:5c:60 ------BEGIN CERTIFICATE----- -MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBH -MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM -QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy -MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl -cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv -CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3Kg -GjSY6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9Bu -XvAuMC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOd -re7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXu -PuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1 -mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K -8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqj -x5RWIr9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsR -nTKaG73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0 -kzCqgc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9Ok -twIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV -HQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBALZp -8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT -vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiT -z9D2PGcDFWEJ+YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiA -pJiS4wGWAqoC7o87xdFtCjMwc3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvb -pxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3DaWsYDQvTtN6LwG1BUSw7YhN4ZKJmB -R64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5rn/WkhLx3+WuXrD5R -RaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56GtmwfuNmsk -0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC -5AwiWVIQ7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiF -izoHCBy69Y9Vmhh1fuXsgWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLn -yOd/xCxgXS/Dr55FBcOEArf9LAhST4Ldo/DUhgkC ------END CERTIFICATE----- - -# Issuer: CN=GTS Root R3 O=Google Trust Services LLC -# Subject: CN=GTS Root R3 O=Google Trust Services LLC -# Label: "GTS Root R3" -# Serial: 146587176140553309517047991083707763997 -# MD5 Fingerprint: 1a:79:5b:6b:04:52:9c:5d:c7:74:33:1b:25:9a:f9:25 -# SHA1 Fingerprint: 30:d4:24:6f:07:ff:db:91:89:8a:0b:e9:49:66:11:eb:8c:5e:46:e5 -# SHA256 Fingerprint: 15:d5:b8:77:46:19:ea:7d:54:ce:1c:a6:d0:b0:c4:03:e0:37:a9:17:f1:31:e8:a0:4e:1e:6b:7a:71:ba:bc:e5 ------BEGIN CERTIFICATE----- -MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQsw -CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU -MBIGA1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw -MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp -Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQA -IgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout -736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2A -DDL24CejQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud -DgQWBBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFuk -fCPAlaUs3L6JbyO5o91lAFJekazInXJ0glMLfalAvWhgxeG4VDvBNhcl2MG9AjEA -njWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOaKaqW04MjyaR7YbPMAuhd ------END CERTIFICATE----- - -# Issuer: CN=GTS Root R4 O=Google Trust Services LLC -# Subject: CN=GTS Root R4 O=Google Trust Services LLC -# Label: "GTS Root R4" -# Serial: 146587176229350439916519468929765261721 -# MD5 Fingerprint: 5d:b6:6a:c4:60:17:24:6a:1a:99:a8:4b:ee:5e:b4:26 -# SHA1 Fingerprint: 2a:1d:60:27:d9:4a:b1:0a:1c:4d:91:5c:cd:33:a0:cb:3e:2d:54:cb -# SHA256 Fingerprint: 71:cc:a5:39:1f:9e:79:4b:04:80:25:30:b3:63:e1:21:da:8a:30:43:bb:26:66:2f:ea:4d:ca:7f:c9:51:a4:bd ------BEGIN CERTIFICATE----- -MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQsw -CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU -MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw -MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp -Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQA -IgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu -hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/l -xKvRHYqjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud -DgQWBBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0 -CMRw3J5QdCHojXohw0+WbhXRIjVhLfoIN+4Zba3bssx9BzT1YBkstTTZbyACMANx -sbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11xzPKwTdb+mciUqXWi4w== ------END CERTIFICATE----- - -# Issuer: CN=UCA Global G2 Root O=UniTrust -# Subject: CN=UCA Global G2 Root O=UniTrust -# Label: "UCA Global G2 Root" -# Serial: 124779693093741543919145257850076631279 -# MD5 Fingerprint: 80:fe:f0:c4:4a:f0:5c:62:32:9f:1c:ba:78:a9:50:f8 -# SHA1 Fingerprint: 28:f9:78:16:19:7a:ff:18:25:18:aa:44:fe:c1:a0:ce:5c:b6:4c:8a -# SHA256 Fingerprint: 9b:ea:11:c9:76:fe:01:47:64:c1:be:56:a6:f9:14:b5:a5:60:31:7a:bd:99:88:39:33:82:e5:16:1a:a0:49:3c ------BEGIN CERTIFICATE----- -MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9 -MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH -bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x -CzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEds -b2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeYr -b3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmToni9 -kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzm -VHqUwCoV8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/R -VogvGjqNO7uCEeBHANBSh6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDc -C/Vkw85DvG1xudLeJ1uK6NjGruFZfc8oLTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIj -tm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/R+zvWr9LesGtOxdQXGLY -D0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBeKW4bHAyv -j5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6Dl -NaBa4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6 -iIis7nCs+dwp4wwcOxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznP -O6Q0ibd5Ei9Hxeepl2n8pndntd978XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/ -BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIHEjMz15DD/pQwIX4wV -ZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo5sOASD0Ee/oj -L3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 -1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl -1qnN3e92mI0ADs0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oU -b3n09tDh05S60FdRvScFDcH9yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LV -PtateJLbXDzz2K36uGt/xDYotgIVilQsnLAXc47QN6MUPJiVAAwpBVueSUmxX8fj -y88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHojhJi6IjMtX9Gl8Cb -EGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZkbxqg -DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI -+Vg7RE+xygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGy -YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX -UB+K+wb1whnw0A== ------END CERTIFICATE----- - -# Issuer: CN=UCA Extended Validation Root O=UniTrust -# Subject: CN=UCA Extended Validation Root O=UniTrust -# Label: "UCA Extended Validation Root" -# Serial: 106100277556486529736699587978573607008 -# MD5 Fingerprint: a1:f3:5f:43:c6:34:9b:da:bf:8c:7e:05:53:ad:96:e2 -# SHA1 Fingerprint: a3:a1:b0:6f:24:61:23:4a:e3:36:a5:c2:37:fc:a6:ff:dd:f0:d7:3a -# SHA256 Fingerprint: d4:3a:f9:b3:54:73:75:5c:96:84:fc:06:d7:d8:cb:70:ee:5c:28:e7:73:fb:29:4e:b4:1e:e7:17:22:92:4d:24 ------BEGIN CERTIFICATE----- -MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH -MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF -eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx -MDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNV -BAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrsiWog -D4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvS -sPGP2KxFRv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aop -O2z6+I9tTcg1367r3CTueUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dk -sHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR59mzLC52LqGj3n5qiAno8geK+LLNEOfi -c0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH0mK1lTnj8/FtDw5lhIpj -VMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KRel7sFsLz -KuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/ -TuDvB0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41G -sx2VYVdWf6/wFlthWG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs -1+lvK9JKBZP8nm9rZ/+I8U6laUpSNwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQD -fwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS3H5aBZ8eNJr34RQwDwYDVR0T -AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBADaN -l8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR -ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQ -VBcZEhrxH9cMaVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5 -c6sq1WnIeJEmMX3ixzDx/BR4dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp -4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb+7lsq+KePRXBOy5nAliRn+/4Qh8s -t2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOWF3sGPjLtx7dCvHaj -2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwiGpWO -vpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2C -xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx -cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM -fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax ------END CERTIFICATE----- - -# Issuer: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036 -# Subject: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036 -# Label: "Certigna Root CA" -# Serial: 269714418870597844693661054334862075617 -# MD5 Fingerprint: 0e:5c:30:62:27:eb:5b:bc:d7:ae:62:ba:e9:d5:df:77 -# SHA1 Fingerprint: 2d:0d:52:14:ff:9e:ad:99:24:01:74:20:47:6e:6c:85:27:27:f5:43 -# SHA256 Fingerprint: d4:8d:3d:23:ee:db:50:a4:59:e5:51:97:60:1c:27:77:4b:9d:7b:18:c9:4d:5a:05:95:11:a1:02:50:b9:31:68 ------BEGIN CERTIFICATE----- -MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw -WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw -MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x -MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD -VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX -BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw -ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO -ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M -CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu -I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm -TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh -C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf -ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz -IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT -Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k -JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5 -hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB -GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE -FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of -1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov -L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo -dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr -aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq -hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L -6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG -HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6 -0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB -lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi -o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1 -gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v -faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63 -Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh -jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw -3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= ------END CERTIFICATE----- - -# Issuer: CN=emSign Root CA - G1 O=eMudhra Technologies Limited OU=emSign PKI -# Subject: CN=emSign Root CA - G1 O=eMudhra Technologies Limited OU=emSign PKI -# Label: "emSign Root CA - G1" -# Serial: 235931866688319308814040 -# MD5 Fingerprint: 9c:42:84:57:dd:cb:0b:a7:2e:95:ad:b6:f3:da:bc:ac -# SHA1 Fingerprint: 8a:c7:ad:8f:73:ac:4e:c1:b5:75:4d:a5:40:f4:fc:cf:7c:b5:8e:8c -# SHA256 Fingerprint: 40:f6:af:03:46:a9:9a:a1:cd:1d:55:5a:4e:9c:ce:62:c7:f9:63:46:03:ee:40:66:15:83:3d:c8:c8:d0:03:67 ------BEGIN CERTIFICATE----- -MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYD -VQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBU -ZWNobm9sb2dpZXMgTGltaXRlZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBH -MTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgxODMwMDBaMGcxCzAJBgNVBAYTAklO -MRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVkaHJhIFRlY2hub2xv -Z2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQz -f2N4aLTNLnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO -8oG0x5ZOrRkVUkr+PHB1cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aq -d7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHWDV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhM -tTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ6DqS0hdW5TUaQBw+jSzt -Od9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrHhQIDAQAB -o0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQD -AgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31x -PaOfG1vR2vjTnGs2vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjM -wiI/aTvFthUvozXGaCocV685743QNcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6d -GNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q+Mri/Tm3R7nrft8EI6/6nAYH -6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeihU80Bv2noWgby -RQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx -iN66zB+Afko= ------END CERTIFICATE----- - -# Issuer: CN=emSign ECC Root CA - G3 O=eMudhra Technologies Limited OU=emSign PKI -# Subject: CN=emSign ECC Root CA - G3 O=eMudhra Technologies Limited OU=emSign PKI -# Label: "emSign ECC Root CA - G3" -# Serial: 287880440101571086945156 -# MD5 Fingerprint: ce:0b:72:d1:9f:88:8e:d0:50:03:e8:e3:b8:8b:67:40 -# SHA1 Fingerprint: 30:43:fa:4f:f2:57:dc:a0:c3:80:ee:2e:58:ea:78:b2:3f:e6:bb:c1 -# SHA256 Fingerprint: 86:a1:ec:ba:08:9c:4a:8d:3b:be:27:34:c6:12:ba:34:1d:81:3e:04:3c:f9:e8:a8:62:cd:5c:57:a3:6b:be:6b ------BEGIN CERTIFICATE----- -MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG -EwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNo -bm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g -RzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4MTgzMDAwWjBrMQswCQYDVQQGEwJJ -TjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9s -b2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMw -djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0 -WXTsuwYc58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xyS -fvalY8L1X44uT6EYGQIrMgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuB -zhccLikenEhjQjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggq -hkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+DCBeQyh+KTOgNG3qxrdWB -CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD -+JbNR6iC8hZVdyR+EhCVBCyj ------END CERTIFICATE----- - -# Issuer: CN=emSign Root CA - C1 O=eMudhra Inc OU=emSign PKI -# Subject: CN=emSign Root CA - C1 O=eMudhra Inc OU=emSign PKI -# Label: "emSign Root CA - C1" -# Serial: 825510296613316004955058 -# MD5 Fingerprint: d8:e3:5d:01:21:fa:78:5a:b0:df:ba:d2:ee:2a:5f:68 -# SHA1 Fingerprint: e7:2e:f1:df:fc:b2:09:28:cf:5d:d4:d5:67:37:b1:51:cb:86:4f:01 -# SHA256 Fingerprint: 12:56:09:aa:30:1d:a0:a2:49:b9:7a:82:39:cb:6a:34:21:6f:44:dc:ac:9f:39:54:b1:42:92:f2:e8:c8:60:8f ------BEGIN CERTIFICATE----- -MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkG -A1UEBhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEg -SW5jMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAw -MFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln -biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNpZ24gUm9v -dCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+upufGZ -BczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZ -HdPIWoU/Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH -3DspVpNqs8FqOp099cGXOFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvH -GPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4VI5b2P/AgNBbeCsbEBEV5f6f9vtKppa+c -xSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleoomslMuoaJuvimUnzYnu3Yy1 -aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+XJGFehiq -TbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL -BQADggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87 -/kOXSTKZEhVb3xEp/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4 -kqNPEjE2NuLe/gDEo2APJ62gsIq1NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrG -YQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9wC68AivTxEDkigcxHpvOJpkT -+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQBmIMMMAVSKeo -WXzhriKi4gp6D/piq1JM4fHfyr6DDUI= ------END CERTIFICATE----- - -# Issuer: CN=emSign ECC Root CA - C3 O=eMudhra Inc OU=emSign PKI -# Subject: CN=emSign ECC Root CA - C3 O=eMudhra Inc OU=emSign PKI -# Label: "emSign ECC Root CA - C3" -# Serial: 582948710642506000014504 -# MD5 Fingerprint: 3e:53:b3:a3:81:ee:d7:10:f8:d3:b0:1d:17:92:f5:d5 -# SHA1 Fingerprint: b6:af:43:c2:9b:81:53:7d:f6:ef:6b:c3:1f:1f:60:15:0c:ee:48:66 -# SHA256 Fingerprint: bc:4d:80:9b:15:18:9d:78:db:3e:1d:8c:f4:f9:72:6a:79:5d:a1:64:3c:a5:f1:35:8e:1d:db:0e:dc:0d:7e:b3 ------BEGIN CERTIFICATE----- -MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQG -EwJVUzETMBEGA1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMx -IDAeBgNVBAMTF2VtU2lnbiBFQ0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAw -MFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln -biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQDExdlbVNpZ24gRUND -IFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd6bci -MK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4Ojavti -sIGJAnB9SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0O -BBYEFPtaSNCAIEDyqOkAB2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB -Af8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQC02C8Cif22TGK6Q04ThHK1rt0c -3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwUZOR8loMRnLDRWmFLpg9J -0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== ------END CERTIFICATE----- - -# Issuer: CN=Hongkong Post Root CA 3 O=Hongkong Post -# Subject: CN=Hongkong Post Root CA 3 O=Hongkong Post -# Label: "Hongkong Post Root CA 3" -# Serial: 46170865288971385588281144162979347873371282084 -# MD5 Fingerprint: 11:fc:9f:bd:73:30:02:8a:fd:3f:f3:58:b9:cb:20:f0 -# SHA1 Fingerprint: 58:a2:d0:ec:20:52:81:5b:c1:f3:f8:64:02:24:4e:c2:8e:02:4b:02 -# SHA256 Fingerprint: 5a:2f:c0:3f:0c:83:b0:90:bb:fa:40:60:4b:09:88:44:6c:76:36:18:3d:f9:84:6e:17:10:1a:44:7f:b8:ef:d6 ------BEGIN CERTIFICATE----- -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 -mpv0 ------END CERTIFICATE----- diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/certifi/core.py b/venv2/lib/python2.7/site-packages/pip/_vendor/certifi/core.py deleted file mode 100644 index 7271acf..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/certifi/core.py +++ /dev/null @@ -1,15 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -certifi.py -~~~~~~~~~~ - -This module returns the installation location of cacert.pem. -""" -import os - - -def where(): - f = os.path.dirname(__file__) - - return os.path.join(f, 'cacert.pem') diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/__init__.py deleted file mode 100644 index 0f9f820..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/__init__.py +++ /dev/null @@ -1,39 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - - -from .compat import PY2, PY3 -from .universaldetector import UniversalDetector -from .version import __version__, VERSION - - -def detect(byte_str): - """ - Detect the encoding of the given byte string. - - :param byte_str: The byte sequence to examine. - :type byte_str: ``bytes`` or ``bytearray`` - """ - if not isinstance(byte_str, bytearray): - if not isinstance(byte_str, bytes): - raise TypeError('Expected object of type bytes or bytearray, got: ' - '{0}'.format(type(byte_str))) - else: - byte_str = bytearray(byte_str) - detector = UniversalDetector() - detector.feed(byte_str) - return detector.close() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/big5freq.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/big5freq.py deleted file mode 100644 index 38f3251..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/big5freq.py +++ /dev/null @@ -1,386 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -# Big5 frequency table -# by Taiwan's Mandarin Promotion Council -# <http://www.edu.tw:81/mandr/> -# -# 128 --> 0.42261 -# 256 --> 0.57851 -# 512 --> 0.74851 -# 1024 --> 0.89384 -# 2048 --> 0.97583 -# -# Ideal Distribution Ratio = 0.74851/(1-0.74851) =2.98 -# Random Distribution Ration = 512/(5401-512)=0.105 -# -# Typical Distribution Ratio about 25% of Ideal one, still much higher than RDR - -BIG5_TYPICAL_DISTRIBUTION_RATIO = 0.75 - -#Char to FreqOrder table -BIG5_TABLE_SIZE = 5376 - -BIG5_CHAR_TO_FREQ_ORDER = ( - 1,1801,1506, 255,1431, 198, 9, 82, 6,5008, 177, 202,3681,1256,2821, 110, # 16 -3814, 33,3274, 261, 76, 44,2114, 16,2946,2187,1176, 659,3971, 26,3451,2653, # 32 -1198,3972,3350,4202, 410,2215, 302, 590, 361,1964, 8, 204, 58,4510,5009,1932, # 48 - 63,5010,5011, 317,1614, 75, 222, 159,4203,2417,1480,5012,3555,3091, 224,2822, # 64 -3682, 3, 10,3973,1471, 29,2787,1135,2866,1940, 873, 130,3275,1123, 312,5013, # 80 -4511,2052, 507, 252, 682,5014, 142,1915, 124, 206,2947, 34,3556,3204, 64, 604, # 96 -5015,2501,1977,1978, 155,1991, 645, 641,1606,5016,3452, 337, 72, 406,5017, 80, # 112 - 630, 238,3205,1509, 263, 939,1092,2654, 756,1440,1094,3453, 449, 69,2987, 591, # 128 - 179,2096, 471, 115,2035,1844, 60, 50,2988, 134, 806,1869, 734,2036,3454, 180, # 144 - 995,1607, 156, 537,2907, 688,5018, 319,1305, 779,2145, 514,2379, 298,4512, 359, # 160 -2502, 90,2716,1338, 663, 11, 906,1099,2553, 20,2441, 182, 532,1716,5019, 732, # 176 -1376,4204,1311,1420,3206, 25,2317,1056, 113, 399, 382,1950, 242,3455,2474, 529, # 192 -3276, 475,1447,3683,5020, 117, 21, 656, 810,1297,2300,2334,3557,5021, 126,4205, # 208 - 706, 456, 150, 613,4513, 71,1118,2037,4206, 145,3092, 85, 835, 486,2115,1246, # 224 -1426, 428, 727,1285,1015, 800, 106, 623, 303,1281,5022,2128,2359, 347,3815, 221, # 240 -3558,3135,5023,1956,1153,4207, 83, 296,1199,3093, 192, 624, 93,5024, 822,1898, # 256 -2823,3136, 795,2065, 991,1554,1542,1592, 27, 43,2867, 859, 139,1456, 860,4514, # 272 - 437, 712,3974, 164,2397,3137, 695, 211,3037,2097, 195,3975,1608,3559,3560,3684, # 288 -3976, 234, 811,2989,2098,3977,2233,1441,3561,1615,2380, 668,2077,1638, 305, 228, # 304 -1664,4515, 467, 415,5025, 262,2099,1593, 239, 108, 300, 200,1033, 512,1247,2078, # 320 -5026,5027,2176,3207,3685,2682, 593, 845,1062,3277, 88,1723,2038,3978,1951, 212, # 336 - 266, 152, 149, 468,1899,4208,4516, 77, 187,5028,3038, 37, 5,2990,5029,3979, # 352 -5030,5031, 39,2524,4517,2908,3208,2079, 55, 148, 74,4518, 545, 483,1474,1029, # 368 -1665, 217,1870,1531,3138,1104,2655,4209, 24, 172,3562, 900,3980,3563,3564,4519, # 384 - 32,1408,2824,1312, 329, 487,2360,2251,2717, 784,2683, 4,3039,3351,1427,1789, # 400 - 188, 109, 499,5032,3686,1717,1790, 888,1217,3040,4520,5033,3565,5034,3352,1520, # 416 -3687,3981, 196,1034, 775,5035,5036, 929,1816, 249, 439, 38,5037,1063,5038, 794, # 432 -3982,1435,2301, 46, 178,3278,2066,5039,2381,5040, 214,1709,4521, 804, 35, 707, # 448 - 324,3688,1601,2554, 140, 459,4210,5041,5042,1365, 839, 272, 978,2262,2580,3456, # 464 -2129,1363,3689,1423, 697, 100,3094, 48, 70,1231, 495,3139,2196,5043,1294,5044, # 480 -2080, 462, 586,1042,3279, 853, 256, 988, 185,2382,3457,1698, 434,1084,5045,3458, # 496 - 314,2625,2788,4522,2335,2336, 569,2285, 637,1817,2525, 757,1162,1879,1616,3459, # 512 - 287,1577,2116, 768,4523,1671,2868,3566,2526,1321,3816, 909,2418,5046,4211, 933, # 528 -3817,4212,2053,2361,1222,4524, 765,2419,1322, 786,4525,5047,1920,1462,1677,2909, # 544 -1699,5048,4526,1424,2442,3140,3690,2600,3353,1775,1941,3460,3983,4213, 309,1369, # 560 -1130,2825, 364,2234,1653,1299,3984,3567,3985,3986,2656, 525,1085,3041, 902,2001, # 576 -1475, 964,4527, 421,1845,1415,1057,2286, 940,1364,3141, 376,4528,4529,1381, 7, # 592 -2527, 983,2383, 336,1710,2684,1846, 321,3461, 559,1131,3042,2752,1809,1132,1313, # 608 - 265,1481,1858,5049, 352,1203,2826,3280, 167,1089, 420,2827, 776, 792,1724,3568, # 624 -4214,2443,3281,5050,4215,5051, 446, 229, 333,2753, 901,3818,1200,1557,4530,2657, # 640 -1921, 395,2754,2685,3819,4216,1836, 125, 916,3209,2626,4531,5052,5053,3820,5054, # 656 -5055,5056,4532,3142,3691,1133,2555,1757,3462,1510,2318,1409,3569,5057,2146, 438, # 672 -2601,2910,2384,3354,1068, 958,3043, 461, 311,2869,2686,4217,1916,3210,4218,1979, # 688 - 383, 750,2755,2627,4219, 274, 539, 385,1278,1442,5058,1154,1965, 384, 561, 210, # 704 - 98,1295,2556,3570,5059,1711,2420,1482,3463,3987,2911,1257, 129,5060,3821, 642, # 720 - 523,2789,2790,2658,5061, 141,2235,1333, 68, 176, 441, 876, 907,4220, 603,2602, # 736 - 710, 171,3464, 404, 549, 18,3143,2398,1410,3692,1666,5062,3571,4533,2912,4534, # 752 -5063,2991, 368,5064, 146, 366, 99, 871,3693,1543, 748, 807,1586,1185, 22,2263, # 768 - 379,3822,3211,5065,3212, 505,1942,2628,1992,1382,2319,5066, 380,2362, 218, 702, # 784 -1818,1248,3465,3044,3572,3355,3282,5067,2992,3694, 930,3283,3823,5068, 59,5069, # 800 - 585, 601,4221, 497,3466,1112,1314,4535,1802,5070,1223,1472,2177,5071, 749,1837, # 816 - 690,1900,3824,1773,3988,1476, 429,1043,1791,2236,2117, 917,4222, 447,1086,1629, # 832 -5072, 556,5073,5074,2021,1654, 844,1090, 105, 550, 966,1758,2828,1008,1783, 686, # 848 -1095,5075,2287, 793,1602,5076,3573,2603,4536,4223,2948,2302,4537,3825, 980,2503, # 864 - 544, 353, 527,4538, 908,2687,2913,5077, 381,2629,1943,1348,5078,1341,1252, 560, # 880 -3095,5079,3467,2870,5080,2054, 973, 886,2081, 143,4539,5081,5082, 157,3989, 496, # 896 -4224, 57, 840, 540,2039,4540,4541,3468,2118,1445, 970,2264,1748,1966,2082,4225, # 912 -3144,1234,1776,3284,2829,3695, 773,1206,2130,1066,2040,1326,3990,1738,1725,4226, # 928 - 279,3145, 51,1544,2604, 423,1578,2131,2067, 173,4542,1880,5083,5084,1583, 264, # 944 - 610,3696,4543,2444, 280, 154,5085,5086,5087,1739, 338,1282,3096, 693,2871,1411, # 960 -1074,3826,2445,5088,4544,5089,5090,1240, 952,2399,5091,2914,1538,2688, 685,1483, # 976 -4227,2475,1436, 953,4228,2055,4545, 671,2400, 79,4229,2446,3285, 608, 567,2689, # 992 -3469,4230,4231,1691, 393,1261,1792,2401,5092,4546,5093,5094,5095,5096,1383,1672, # 1008 -3827,3213,1464, 522,1119, 661,1150, 216, 675,4547,3991,1432,3574, 609,4548,2690, # 1024 -2402,5097,5098,5099,4232,3045, 0,5100,2476, 315, 231,2447, 301,3356,4549,2385, # 1040 -5101, 233,4233,3697,1819,4550,4551,5102, 96,1777,1315,2083,5103, 257,5104,1810, # 1056 -3698,2718,1139,1820,4234,2022,1124,2164,2791,1778,2659,5105,3097, 363,1655,3214, # 1072 -5106,2993,5107,5108,5109,3992,1567,3993, 718, 103,3215, 849,1443, 341,3357,2949, # 1088 -1484,5110,1712, 127, 67, 339,4235,2403, 679,1412, 821,5111,5112, 834, 738, 351, # 1104 -2994,2147, 846, 235,1497,1881, 418,1993,3828,2719, 186,1100,2148,2756,3575,1545, # 1120 -1355,2950,2872,1377, 583,3994,4236,2581,2995,5113,1298,3699,1078,2557,3700,2363, # 1136 - 78,3829,3830, 267,1289,2100,2002,1594,4237, 348, 369,1274,2197,2178,1838,4552, # 1152 -1821,2830,3701,2757,2288,2003,4553,2951,2758, 144,3358, 882,4554,3995,2759,3470, # 1168 -4555,2915,5114,4238,1726, 320,5115,3996,3046, 788,2996,5116,2831,1774,1327,2873, # 1184 -3997,2832,5117,1306,4556,2004,1700,3831,3576,2364,2660, 787,2023, 506, 824,3702, # 1200 - 534, 323,4557,1044,3359,2024,1901, 946,3471,5118,1779,1500,1678,5119,1882,4558, # 1216 - 165, 243,4559,3703,2528, 123, 683,4239, 764,4560, 36,3998,1793, 589,2916, 816, # 1232 - 626,1667,3047,2237,1639,1555,1622,3832,3999,5120,4000,2874,1370,1228,1933, 891, # 1248 -2084,2917, 304,4240,5121, 292,2997,2720,3577, 691,2101,4241,1115,4561, 118, 662, # 1264 -5122, 611,1156, 854,2386,1316,2875, 2, 386, 515,2918,5123,5124,3286, 868,2238, # 1280 -1486, 855,2661, 785,2216,3048,5125,1040,3216,3578,5126,3146, 448,5127,1525,5128, # 1296 -2165,4562,5129,3833,5130,4242,2833,3579,3147, 503, 818,4001,3148,1568, 814, 676, # 1312 -1444, 306,1749,5131,3834,1416,1030, 197,1428, 805,2834,1501,4563,5132,5133,5134, # 1328 -1994,5135,4564,5136,5137,2198, 13,2792,3704,2998,3149,1229,1917,5138,3835,2132, # 1344 -5139,4243,4565,2404,3580,5140,2217,1511,1727,1120,5141,5142, 646,3836,2448, 307, # 1360 -5143,5144,1595,3217,5145,5146,5147,3705,1113,1356,4002,1465,2529,2530,5148, 519, # 1376 -5149, 128,2133, 92,2289,1980,5150,4003,1512, 342,3150,2199,5151,2793,2218,1981, # 1392 -3360,4244, 290,1656,1317, 789, 827,2365,5152,3837,4566, 562, 581,4004,5153, 401, # 1408 -4567,2252, 94,4568,5154,1399,2794,5155,1463,2025,4569,3218,1944,5156, 828,1105, # 1424 -4245,1262,1394,5157,4246, 605,4570,5158,1784,2876,5159,2835, 819,2102, 578,2200, # 1440 -2952,5160,1502, 436,3287,4247,3288,2836,4005,2919,3472,3473,5161,2721,2320,5162, # 1456 -5163,2337,2068, 23,4571, 193, 826,3838,2103, 699,1630,4248,3098, 390,1794,1064, # 1472 -3581,5164,1579,3099,3100,1400,5165,4249,1839,1640,2877,5166,4572,4573, 137,4250, # 1488 - 598,3101,1967, 780, 104, 974,2953,5167, 278, 899, 253, 402, 572, 504, 493,1339, # 1504 -5168,4006,1275,4574,2582,2558,5169,3706,3049,3102,2253, 565,1334,2722, 863, 41, # 1520 -5170,5171,4575,5172,1657,2338, 19, 463,2760,4251, 606,5173,2999,3289,1087,2085, # 1536 -1323,2662,3000,5174,1631,1623,1750,4252,2691,5175,2878, 791,2723,2663,2339, 232, # 1552 -2421,5176,3001,1498,5177,2664,2630, 755,1366,3707,3290,3151,2026,1609, 119,1918, # 1568 -3474, 862,1026,4253,5178,4007,3839,4576,4008,4577,2265,1952,2477,5179,1125, 817, # 1584 -4254,4255,4009,1513,1766,2041,1487,4256,3050,3291,2837,3840,3152,5180,5181,1507, # 1600 -5182,2692, 733, 40,1632,1106,2879, 345,4257, 841,2531, 230,4578,3002,1847,3292, # 1616 -3475,5183,1263, 986,3476,5184, 735, 879, 254,1137, 857, 622,1300,1180,1388,1562, # 1632 -4010,4011,2954, 967,2761,2665,1349, 592,2134,1692,3361,3003,1995,4258,1679,4012, # 1648 -1902,2188,5185, 739,3708,2724,1296,1290,5186,4259,2201,2202,1922,1563,2605,2559, # 1664 -1871,2762,3004,5187, 435,5188, 343,1108, 596, 17,1751,4579,2239,3477,3709,5189, # 1680 -4580, 294,3582,2955,1693, 477, 979, 281,2042,3583, 643,2043,3710,2631,2795,2266, # 1696 -1031,2340,2135,2303,3584,4581, 367,1249,2560,5190,3585,5191,4582,1283,3362,2005, # 1712 - 240,1762,3363,4583,4584, 836,1069,3153, 474,5192,2149,2532, 268,3586,5193,3219, # 1728 -1521,1284,5194,1658,1546,4260,5195,3587,3588,5196,4261,3364,2693,1685,4262, 961, # 1744 -1673,2632, 190,2006,2203,3841,4585,4586,5197, 570,2504,3711,1490,5198,4587,2633, # 1760 -3293,1957,4588, 584,1514, 396,1045,1945,5199,4589,1968,2449,5200,5201,4590,4013, # 1776 - 619,5202,3154,3294, 215,2007,2796,2561,3220,4591,3221,4592, 763,4263,3842,4593, # 1792 -5203,5204,1958,1767,2956,3365,3712,1174, 452,1477,4594,3366,3155,5205,2838,1253, # 1808 -2387,2189,1091,2290,4264, 492,5206, 638,1169,1825,2136,1752,4014, 648, 926,1021, # 1824 -1324,4595, 520,4596, 997, 847,1007, 892,4597,3843,2267,1872,3713,2405,1785,4598, # 1840 -1953,2957,3103,3222,1728,4265,2044,3714,4599,2008,1701,3156,1551, 30,2268,4266, # 1856 -5207,2027,4600,3589,5208, 501,5209,4267, 594,3478,2166,1822,3590,3479,3591,3223, # 1872 - 829,2839,4268,5210,1680,3157,1225,4269,5211,3295,4601,4270,3158,2341,5212,4602, # 1888 -4271,5213,4015,4016,5214,1848,2388,2606,3367,5215,4603, 374,4017, 652,4272,4273, # 1904 - 375,1140, 798,5216,5217,5218,2366,4604,2269, 546,1659, 138,3051,2450,4605,5219, # 1920 -2254, 612,1849, 910, 796,3844,1740,1371, 825,3845,3846,5220,2920,2562,5221, 692, # 1936 - 444,3052,2634, 801,4606,4274,5222,1491, 244,1053,3053,4275,4276, 340,5223,4018, # 1952 -1041,3005, 293,1168, 87,1357,5224,1539, 959,5225,2240, 721, 694,4277,3847, 219, # 1968 -1478, 644,1417,3368,2666,1413,1401,1335,1389,4019,5226,5227,3006,2367,3159,1826, # 1984 - 730,1515, 184,2840, 66,4607,5228,1660,2958, 246,3369, 378,1457, 226,3480, 975, # 2000 -4020,2959,1264,3592, 674, 696,5229, 163,5230,1141,2422,2167, 713,3593,3370,4608, # 2016 -4021,5231,5232,1186, 15,5233,1079,1070,5234,1522,3224,3594, 276,1050,2725, 758, # 2032 -1126, 653,2960,3296,5235,2342, 889,3595,4022,3104,3007, 903,1250,4609,4023,3481, # 2048 -3596,1342,1681,1718, 766,3297, 286, 89,2961,3715,5236,1713,5237,2607,3371,3008, # 2064 -5238,2962,2219,3225,2880,5239,4610,2505,2533, 181, 387,1075,4024, 731,2190,3372, # 2080 -5240,3298, 310, 313,3482,2304, 770,4278, 54,3054, 189,4611,3105,3848,4025,5241, # 2096 -1230,1617,1850, 355,3597,4279,4612,3373, 111,4280,3716,1350,3160,3483,3055,4281, # 2112 -2150,3299,3598,5242,2797,4026,4027,3009, 722,2009,5243,1071, 247,1207,2343,2478, # 2128 -1378,4613,2010, 864,1437,1214,4614, 373,3849,1142,2220, 667,4615, 442,2763,2563, # 2144 -3850,4028,1969,4282,3300,1840, 837, 170,1107, 934,1336,1883,5244,5245,2119,4283, # 2160 -2841, 743,1569,5246,4616,4284, 582,2389,1418,3484,5247,1803,5248, 357,1395,1729, # 2176 -3717,3301,2423,1564,2241,5249,3106,3851,1633,4617,1114,2086,4285,1532,5250, 482, # 2192 -2451,4618,5251,5252,1492, 833,1466,5253,2726,3599,1641,2842,5254,1526,1272,3718, # 2208 -4286,1686,1795, 416,2564,1903,1954,1804,5255,3852,2798,3853,1159,2321,5256,2881, # 2224 -4619,1610,1584,3056,2424,2764, 443,3302,1163,3161,5257,5258,4029,5259,4287,2506, # 2240 -3057,4620,4030,3162,2104,1647,3600,2011,1873,4288,5260,4289, 431,3485,5261, 250, # 2256 - 97, 81,4290,5262,1648,1851,1558, 160, 848,5263, 866, 740,1694,5264,2204,2843, # 2272 -3226,4291,4621,3719,1687, 950,2479, 426, 469,3227,3720,3721,4031,5265,5266,1188, # 2288 - 424,1996, 861,3601,4292,3854,2205,2694, 168,1235,3602,4293,5267,2087,1674,4622, # 2304 -3374,3303, 220,2565,1009,5268,3855, 670,3010, 332,1208, 717,5269,5270,3603,2452, # 2320 -4032,3375,5271, 513,5272,1209,2882,3376,3163,4623,1080,5273,5274,5275,5276,2534, # 2336 -3722,3604, 815,1587,4033,4034,5277,3605,3486,3856,1254,4624,1328,3058,1390,4035, # 2352 -1741,4036,3857,4037,5278, 236,3858,2453,3304,5279,5280,3723,3859,1273,3860,4625, # 2368 -5281, 308,5282,4626, 245,4627,1852,2480,1307,2583, 430, 715,2137,2454,5283, 270, # 2384 - 199,2883,4038,5284,3606,2727,1753, 761,1754, 725,1661,1841,4628,3487,3724,5285, # 2400 -5286, 587, 14,3305, 227,2608, 326, 480,2270, 943,2765,3607, 291, 650,1884,5287, # 2416 -1702,1226, 102,1547, 62,3488, 904,4629,3489,1164,4294,5288,5289,1224,1548,2766, # 2432 - 391, 498,1493,5290,1386,1419,5291,2056,1177,4630, 813, 880,1081,2368, 566,1145, # 2448 -4631,2291,1001,1035,2566,2609,2242, 394,1286,5292,5293,2069,5294, 86,1494,1730, # 2464 -4039, 491,1588, 745, 897,2963, 843,3377,4040,2767,2884,3306,1768, 998,2221,2070, # 2480 - 397,1827,1195,1970,3725,3011,3378, 284,5295,3861,2507,2138,2120,1904,5296,4041, # 2496 -2151,4042,4295,1036,3490,1905, 114,2567,4296, 209,1527,5297,5298,2964,2844,2635, # 2512 -2390,2728,3164, 812,2568,5299,3307,5300,1559, 737,1885,3726,1210, 885, 28,2695, # 2528 -3608,3862,5301,4297,1004,1780,4632,5302, 346,1982,2222,2696,4633,3863,1742, 797, # 2544 -1642,4043,1934,1072,1384,2152, 896,4044,3308,3727,3228,2885,3609,5303,2569,1959, # 2560 -4634,2455,1786,5304,5305,5306,4045,4298,1005,1308,3728,4299,2729,4635,4636,1528, # 2576 -2610, 161,1178,4300,1983, 987,4637,1101,4301, 631,4046,1157,3229,2425,1343,1241, # 2592 -1016,2243,2570, 372, 877,2344,2508,1160, 555,1935, 911,4047,5307, 466,1170, 169, # 2608 -1051,2921,2697,3729,2481,3012,1182,2012,2571,1251,2636,5308, 992,2345,3491,1540, # 2624 -2730,1201,2071,2406,1997,2482,5309,4638, 528,1923,2191,1503,1874,1570,2369,3379, # 2640 -3309,5310, 557,1073,5311,1828,3492,2088,2271,3165,3059,3107, 767,3108,2799,4639, # 2656 -1006,4302,4640,2346,1267,2179,3730,3230, 778,4048,3231,2731,1597,2667,5312,4641, # 2672 -5313,3493,5314,5315,5316,3310,2698,1433,3311, 131, 95,1504,4049, 723,4303,3166, # 2688 -1842,3610,2768,2192,4050,2028,2105,3731,5317,3013,4051,1218,5318,3380,3232,4052, # 2704 -4304,2584, 248,1634,3864, 912,5319,2845,3732,3060,3865, 654, 53,5320,3014,5321, # 2720 -1688,4642, 777,3494,1032,4053,1425,5322, 191, 820,2121,2846, 971,4643, 931,3233, # 2736 - 135, 664, 783,3866,1998, 772,2922,1936,4054,3867,4644,2923,3234, 282,2732, 640, # 2752 -1372,3495,1127, 922, 325,3381,5323,5324, 711,2045,5325,5326,4055,2223,2800,1937, # 2768 -4056,3382,2224,2255,3868,2305,5327,4645,3869,1258,3312,4057,3235,2139,2965,4058, # 2784 -4059,5328,2225, 258,3236,4646, 101,1227,5329,3313,1755,5330,1391,3314,5331,2924, # 2800 -2057, 893,5332,5333,5334,1402,4305,2347,5335,5336,3237,3611,5337,5338, 878,1325, # 2816 -1781,2801,4647, 259,1385,2585, 744,1183,2272,4648,5339,4060,2509,5340, 684,1024, # 2832 -4306,5341, 472,3612,3496,1165,3315,4061,4062, 322,2153, 881, 455,1695,1152,1340, # 2848 - 660, 554,2154,4649,1058,4650,4307, 830,1065,3383,4063,4651,1924,5342,1703,1919, # 2864 -5343, 932,2273, 122,5344,4652, 947, 677,5345,3870,2637, 297,1906,1925,2274,4653, # 2880 -2322,3316,5346,5347,4308,5348,4309, 84,4310, 112, 989,5349, 547,1059,4064, 701, # 2896 -3613,1019,5350,4311,5351,3497, 942, 639, 457,2306,2456, 993,2966, 407, 851, 494, # 2912 -4654,3384, 927,5352,1237,5353,2426,3385, 573,4312, 680, 921,2925,1279,1875, 285, # 2928 - 790,1448,1984, 719,2168,5354,5355,4655,4065,4066,1649,5356,1541, 563,5357,1077, # 2944 -5358,3386,3061,3498, 511,3015,4067,4068,3733,4069,1268,2572,3387,3238,4656,4657, # 2960 -5359, 535,1048,1276,1189,2926,2029,3167,1438,1373,2847,2967,1134,2013,5360,4313, # 2976 -1238,2586,3109,1259,5361, 700,5362,2968,3168,3734,4314,5363,4315,1146,1876,1907, # 2992 -4658,2611,4070, 781,2427, 132,1589, 203, 147, 273,2802,2407, 898,1787,2155,4071, # 3008 -4072,5364,3871,2803,5365,5366,4659,4660,5367,3239,5368,1635,3872, 965,5369,1805, # 3024 -2699,1516,3614,1121,1082,1329,3317,4073,1449,3873, 65,1128,2848,2927,2769,1590, # 3040 -3874,5370,5371, 12,2668, 45, 976,2587,3169,4661, 517,2535,1013,1037,3240,5372, # 3056 -3875,2849,5373,3876,5374,3499,5375,2612, 614,1999,2323,3877,3110,2733,2638,5376, # 3072 -2588,4316, 599,1269,5377,1811,3735,5378,2700,3111, 759,1060, 489,1806,3388,3318, # 3088 -1358,5379,5380,2391,1387,1215,2639,2256, 490,5381,5382,4317,1759,2392,2348,5383, # 3104 -4662,3878,1908,4074,2640,1807,3241,4663,3500,3319,2770,2349, 874,5384,5385,3501, # 3120 -3736,1859, 91,2928,3737,3062,3879,4664,5386,3170,4075,2669,5387,3502,1202,1403, # 3136 -3880,2969,2536,1517,2510,4665,3503,2511,5388,4666,5389,2701,1886,1495,1731,4076, # 3152 -2370,4667,5390,2030,5391,5392,4077,2702,1216, 237,2589,4318,2324,4078,3881,4668, # 3168 -4669,2703,3615,3504, 445,4670,5393,5394,5395,5396,2771, 61,4079,3738,1823,4080, # 3184 -5397, 687,2046, 935, 925, 405,2670, 703,1096,1860,2734,4671,4081,1877,1367,2704, # 3200 -3389, 918,2106,1782,2483, 334,3320,1611,1093,4672, 564,3171,3505,3739,3390, 945, # 3216 -2641,2058,4673,5398,1926, 872,4319,5399,3506,2705,3112, 349,4320,3740,4082,4674, # 3232 -3882,4321,3741,2156,4083,4675,4676,4322,4677,2408,2047, 782,4084, 400, 251,4323, # 3248 -1624,5400,5401, 277,3742, 299,1265, 476,1191,3883,2122,4324,4325,1109, 205,5402, # 3264 -2590,1000,2157,3616,1861,5403,5404,5405,4678,5406,4679,2573, 107,2484,2158,4085, # 3280 -3507,3172,5407,1533, 541,1301, 158, 753,4326,2886,3617,5408,1696, 370,1088,4327, # 3296 -4680,3618, 579, 327, 440, 162,2244, 269,1938,1374,3508, 968,3063, 56,1396,3113, # 3312 -2107,3321,3391,5409,1927,2159,4681,3016,5410,3619,5411,5412,3743,4682,2485,5413, # 3328 -2804,5414,1650,4683,5415,2613,5416,5417,4086,2671,3392,1149,3393,4087,3884,4088, # 3344 -5418,1076, 49,5419, 951,3242,3322,3323, 450,2850, 920,5420,1812,2805,2371,4328, # 3360 -1909,1138,2372,3885,3509,5421,3243,4684,1910,1147,1518,2428,4685,3886,5422,4686, # 3376 -2393,2614, 260,1796,3244,5423,5424,3887,3324, 708,5425,3620,1704,5426,3621,1351, # 3392 -1618,3394,3017,1887, 944,4329,3395,4330,3064,3396,4331,5427,3744, 422, 413,1714, # 3408 -3325, 500,2059,2350,4332,2486,5428,1344,1911, 954,5429,1668,5430,5431,4089,2409, # 3424 -4333,3622,3888,4334,5432,2307,1318,2512,3114, 133,3115,2887,4687, 629, 31,2851, # 3440 -2706,3889,4688, 850, 949,4689,4090,2970,1732,2089,4335,1496,1853,5433,4091, 620, # 3456 -3245, 981,1242,3745,3397,1619,3746,1643,3326,2140,2457,1971,1719,3510,2169,5434, # 3472 -3246,5435,5436,3398,1829,5437,1277,4690,1565,2048,5438,1636,3623,3116,5439, 869, # 3488 -2852, 655,3890,3891,3117,4092,3018,3892,1310,3624,4691,5440,5441,5442,1733, 558, # 3504 -4692,3747, 335,1549,3065,1756,4336,3748,1946,3511,1830,1291,1192, 470,2735,2108, # 3520 -2806, 913,1054,4093,5443,1027,5444,3066,4094,4693, 982,2672,3399,3173,3512,3247, # 3536 -3248,1947,2807,5445, 571,4694,5446,1831,5447,3625,2591,1523,2429,5448,2090, 984, # 3552 -4695,3749,1960,5449,3750, 852, 923,2808,3513,3751, 969,1519, 999,2049,2325,1705, # 3568 -5450,3118, 615,1662, 151, 597,4095,2410,2326,1049, 275,4696,3752,4337, 568,3753, # 3584 -3626,2487,4338,3754,5451,2430,2275, 409,3249,5452,1566,2888,3514,1002, 769,2853, # 3600 - 194,2091,3174,3755,2226,3327,4339, 628,1505,5453,5454,1763,2180,3019,4096, 521, # 3616 -1161,2592,1788,2206,2411,4697,4097,1625,4340,4341, 412, 42,3119, 464,5455,2642, # 3632 -4698,3400,1760,1571,2889,3515,2537,1219,2207,3893,2643,2141,2373,4699,4700,3328, # 3648 -1651,3401,3627,5456,5457,3628,2488,3516,5458,3756,5459,5460,2276,2092, 460,5461, # 3664 -4701,5462,3020, 962, 588,3629, 289,3250,2644,1116, 52,5463,3067,1797,5464,5465, # 3680 -5466,1467,5467,1598,1143,3757,4342,1985,1734,1067,4702,1280,3402, 465,4703,1572, # 3696 - 510,5468,1928,2245,1813,1644,3630,5469,4704,3758,5470,5471,2673,1573,1534,5472, # 3712 -5473, 536,1808,1761,3517,3894,3175,2645,5474,5475,5476,4705,3518,2929,1912,2809, # 3728 -5477,3329,1122, 377,3251,5478, 360,5479,5480,4343,1529, 551,5481,2060,3759,1769, # 3744 -2431,5482,2930,4344,3330,3120,2327,2109,2031,4706,1404, 136,1468,1479, 672,1171, # 3760 -3252,2308, 271,3176,5483,2772,5484,2050, 678,2736, 865,1948,4707,5485,2014,4098, # 3776 -2971,5486,2737,2227,1397,3068,3760,4708,4709,1735,2931,3403,3631,5487,3895, 509, # 3792 -2854,2458,2890,3896,5488,5489,3177,3178,4710,4345,2538,4711,2309,1166,1010, 552, # 3808 - 681,1888,5490,5491,2972,2973,4099,1287,1596,1862,3179, 358, 453, 736, 175, 478, # 3824 -1117, 905,1167,1097,5492,1854,1530,5493,1706,5494,2181,3519,2292,3761,3520,3632, # 3840 -4346,2093,4347,5495,3404,1193,2489,4348,1458,2193,2208,1863,1889,1421,3331,2932, # 3856 -3069,2182,3521, 595,2123,5496,4100,5497,5498,4349,1707,2646, 223,3762,1359, 751, # 3872 -3121, 183,3522,5499,2810,3021, 419,2374, 633, 704,3897,2394, 241,5500,5501,5502, # 3888 - 838,3022,3763,2277,2773,2459,3898,1939,2051,4101,1309,3122,2246,1181,5503,1136, # 3904 -2209,3899,2375,1446,4350,2310,4712,5504,5505,4351,1055,2615, 484,3764,5506,4102, # 3920 - 625,4352,2278,3405,1499,4353,4103,5507,4104,4354,3253,2279,2280,3523,5508,5509, # 3936 -2774, 808,2616,3765,3406,4105,4355,3123,2539, 526,3407,3900,4356, 955,5510,1620, # 3952 -4357,2647,2432,5511,1429,3766,1669,1832, 994, 928,5512,3633,1260,5513,5514,5515, # 3968 -1949,2293, 741,2933,1626,4358,2738,2460, 867,1184, 362,3408,1392,5516,5517,4106, # 3984 -4359,1770,1736,3254,2934,4713,4714,1929,2707,1459,1158,5518,3070,3409,2891,1292, # 4000 -1930,2513,2855,3767,1986,1187,2072,2015,2617,4360,5519,2574,2514,2170,3768,2490, # 4016 -3332,5520,3769,4715,5521,5522, 666,1003,3023,1022,3634,4361,5523,4716,1814,2257, # 4032 - 574,3901,1603, 295,1535, 705,3902,4362, 283, 858, 417,5524,5525,3255,4717,4718, # 4048 -3071,1220,1890,1046,2281,2461,4107,1393,1599, 689,2575, 388,4363,5526,2491, 802, # 4064 -5527,2811,3903,2061,1405,2258,5528,4719,3904,2110,1052,1345,3256,1585,5529, 809, # 4080 -5530,5531,5532, 575,2739,3524, 956,1552,1469,1144,2328,5533,2329,1560,2462,3635, # 4096 -3257,4108, 616,2210,4364,3180,2183,2294,5534,1833,5535,3525,4720,5536,1319,3770, # 4112 -3771,1211,3636,1023,3258,1293,2812,5537,5538,5539,3905, 607,2311,3906, 762,2892, # 4128 -1439,4365,1360,4721,1485,3072,5540,4722,1038,4366,1450,2062,2648,4367,1379,4723, # 4144 -2593,5541,5542,4368,1352,1414,2330,2935,1172,5543,5544,3907,3908,4724,1798,1451, # 4160 -5545,5546,5547,5548,2936,4109,4110,2492,2351, 411,4111,4112,3637,3333,3124,4725, # 4176 -1561,2674,1452,4113,1375,5549,5550, 47,2974, 316,5551,1406,1591,2937,3181,5552, # 4192 -1025,2142,3125,3182, 354,2740, 884,2228,4369,2412, 508,3772, 726,3638, 996,2433, # 4208 -3639, 729,5553, 392,2194,1453,4114,4726,3773,5554,5555,2463,3640,2618,1675,2813, # 4224 - 919,2352,2975,2353,1270,4727,4115, 73,5556,5557, 647,5558,3259,2856,2259,1550, # 4240 -1346,3024,5559,1332, 883,3526,5560,5561,5562,5563,3334,2775,5564,1212, 831,1347, # 4256 -4370,4728,2331,3909,1864,3073, 720,3910,4729,4730,3911,5565,4371,5566,5567,4731, # 4272 -5568,5569,1799,4732,3774,2619,4733,3641,1645,2376,4734,5570,2938, 669,2211,2675, # 4288 -2434,5571,2893,5572,5573,1028,3260,5574,4372,2413,5575,2260,1353,5576,5577,4735, # 4304 -3183, 518,5578,4116,5579,4373,1961,5580,2143,4374,5581,5582,3025,2354,2355,3912, # 4320 - 516,1834,1454,4117,2708,4375,4736,2229,2620,1972,1129,3642,5583,2776,5584,2976, # 4336 -1422, 577,1470,3026,1524,3410,5585,5586, 432,4376,3074,3527,5587,2594,1455,2515, # 4352 -2230,1973,1175,5588,1020,2741,4118,3528,4737,5589,2742,5590,1743,1361,3075,3529, # 4368 -2649,4119,4377,4738,2295, 895, 924,4378,2171, 331,2247,3076, 166,1627,3077,1098, # 4384 -5591,1232,2894,2231,3411,4739, 657, 403,1196,2377, 542,3775,3412,1600,4379,3530, # 4400 -5592,4740,2777,3261, 576, 530,1362,4741,4742,2540,2676,3776,4120,5593, 842,3913, # 4416 -5594,2814,2032,1014,4121, 213,2709,3413, 665, 621,4380,5595,3777,2939,2435,5596, # 4432 -2436,3335,3643,3414,4743,4381,2541,4382,4744,3644,1682,4383,3531,1380,5597, 724, # 4448 -2282, 600,1670,5598,1337,1233,4745,3126,2248,5599,1621,4746,5600, 651,4384,5601, # 4464 -1612,4385,2621,5602,2857,5603,2743,2312,3078,5604, 716,2464,3079, 174,1255,2710, # 4480 -4122,3645, 548,1320,1398, 728,4123,1574,5605,1891,1197,3080,4124,5606,3081,3082, # 4496 -3778,3646,3779, 747,5607, 635,4386,4747,5608,5609,5610,4387,5611,5612,4748,5613, # 4512 -3415,4749,2437, 451,5614,3780,2542,2073,4388,2744,4389,4125,5615,1764,4750,5616, # 4528 -4390, 350,4751,2283,2395,2493,5617,4391,4126,2249,1434,4127, 488,4752, 458,4392, # 4544 -4128,3781, 771,1330,2396,3914,2576,3184,2160,2414,1553,2677,3185,4393,5618,2494, # 4560 -2895,2622,1720,2711,4394,3416,4753,5619,2543,4395,5620,3262,4396,2778,5621,2016, # 4576 -2745,5622,1155,1017,3782,3915,5623,3336,2313, 201,1865,4397,1430,5624,4129,5625, # 4592 -5626,5627,5628,5629,4398,1604,5630, 414,1866, 371,2595,4754,4755,3532,2017,3127, # 4608 -4756,1708, 960,4399, 887, 389,2172,1536,1663,1721,5631,2232,4130,2356,2940,1580, # 4624 -5632,5633,1744,4757,2544,4758,4759,5634,4760,5635,2074,5636,4761,3647,3417,2896, # 4640 -4400,5637,4401,2650,3418,2815, 673,2712,2465, 709,3533,4131,3648,4402,5638,1148, # 4656 - 502, 634,5639,5640,1204,4762,3649,1575,4763,2623,3783,5641,3784,3128, 948,3263, # 4672 - 121,1745,3916,1110,5642,4403,3083,2516,3027,4132,3785,1151,1771,3917,1488,4133, # 4688 -1987,5643,2438,3534,5644,5645,2094,5646,4404,3918,1213,1407,2816, 531,2746,2545, # 4704 -3264,1011,1537,4764,2779,4405,3129,1061,5647,3786,3787,1867,2897,5648,2018, 120, # 4720 -4406,4407,2063,3650,3265,2314,3919,2678,3419,1955,4765,4134,5649,3535,1047,2713, # 4736 -1266,5650,1368,4766,2858, 649,3420,3920,2546,2747,1102,2859,2679,5651,5652,2000, # 4752 -5653,1111,3651,2977,5654,2495,3921,3652,2817,1855,3421,3788,5655,5656,3422,2415, # 4768 -2898,3337,3266,3653,5657,2577,5658,3654,2818,4135,1460, 856,5659,3655,5660,2899, # 4784 -2978,5661,2900,3922,5662,4408, 632,2517, 875,3923,1697,3924,2296,5663,5664,4767, # 4800 -3028,1239, 580,4768,4409,5665, 914, 936,2075,1190,4136,1039,2124,5666,5667,5668, # 4816 -5669,3423,1473,5670,1354,4410,3925,4769,2173,3084,4137, 915,3338,4411,4412,3339, # 4832 -1605,1835,5671,2748, 398,3656,4413,3926,4138, 328,1913,2860,4139,3927,1331,4414, # 4848 -3029, 937,4415,5672,3657,4140,4141,3424,2161,4770,3425, 524, 742, 538,3085,1012, # 4864 -5673,5674,3928,2466,5675, 658,1103, 225,3929,5676,5677,4771,5678,4772,5679,3267, # 4880 -1243,5680,4142, 963,2250,4773,5681,2714,3658,3186,5682,5683,2596,2332,5684,4774, # 4896 -5685,5686,5687,3536, 957,3426,2547,2033,1931,2941,2467, 870,2019,3659,1746,2780, # 4912 -2781,2439,2468,5688,3930,5689,3789,3130,3790,3537,3427,3791,5690,1179,3086,5691, # 4928 -3187,2378,4416,3792,2548,3188,3131,2749,4143,5692,3428,1556,2549,2297, 977,2901, # 4944 -2034,4144,1205,3429,5693,1765,3430,3189,2125,1271, 714,1689,4775,3538,5694,2333, # 4960 -3931, 533,4417,3660,2184, 617,5695,2469,3340,3539,2315,5696,5697,3190,5698,5699, # 4976 -3932,1988, 618, 427,2651,3540,3431,5700,5701,1244,1690,5702,2819,4418,4776,5703, # 4992 -3541,4777,5704,2284,1576, 473,3661,4419,3432, 972,5705,3662,5706,3087,5707,5708, # 5008 -4778,4779,5709,3793,4145,4146,5710, 153,4780, 356,5711,1892,2902,4420,2144, 408, # 5024 - 803,2357,5712,3933,5713,4421,1646,2578,2518,4781,4782,3934,5714,3935,4422,5715, # 5040 -2416,3433, 752,5716,5717,1962,3341,2979,5718, 746,3030,2470,4783,4423,3794, 698, # 5056 -4784,1893,4424,3663,2550,4785,3664,3936,5719,3191,3434,5720,1824,1302,4147,2715, # 5072 -3937,1974,4425,5721,4426,3192, 823,1303,1288,1236,2861,3542,4148,3435, 774,3938, # 5088 -5722,1581,4786,1304,2862,3939,4787,5723,2440,2162,1083,3268,4427,4149,4428, 344, # 5104 -1173, 288,2316, 454,1683,5724,5725,1461,4788,4150,2597,5726,5727,4789, 985, 894, # 5120 -5728,3436,3193,5729,1914,2942,3795,1989,5730,2111,1975,5731,4151,5732,2579,1194, # 5136 - 425,5733,4790,3194,1245,3796,4429,5734,5735,2863,5736, 636,4791,1856,3940, 760, # 5152 -1800,5737,4430,2212,1508,4792,4152,1894,1684,2298,5738,5739,4793,4431,4432,2213, # 5168 - 479,5740,5741, 832,5742,4153,2496,5743,2980,2497,3797, 990,3132, 627,1815,2652, # 5184 -4433,1582,4434,2126,2112,3543,4794,5744, 799,4435,3195,5745,4795,2113,1737,3031, # 5200 -1018, 543, 754,4436,3342,1676,4796,4797,4154,4798,1489,5746,3544,5747,2624,2903, # 5216 -4155,5748,5749,2981,5750,5751,5752,5753,3196,4799,4800,2185,1722,5754,3269,3270, # 5232 -1843,3665,1715, 481, 365,1976,1857,5755,5756,1963,2498,4801,5757,2127,3666,3271, # 5248 - 433,1895,2064,2076,5758, 602,2750,5759,5760,5761,5762,5763,3032,1628,3437,5764, # 5264 -3197,4802,4156,2904,4803,2519,5765,2551,2782,5766,5767,5768,3343,4804,2905,5769, # 5280 -4805,5770,2864,4806,4807,1221,2982,4157,2520,5771,5772,5773,1868,1990,5774,5775, # 5296 -5776,1896,5777,5778,4808,1897,4158, 318,5779,2095,4159,4437,5780,5781, 485,5782, # 5312 - 938,3941, 553,2680, 116,5783,3942,3667,5784,3545,2681,2783,3438,3344,2820,5785, # 5328 -3668,2943,4160,1747,2944,2983,5786,5787, 207,5788,4809,5789,4810,2521,5790,3033, # 5344 - 890,3669,3943,5791,1878,3798,3439,5792,2186,2358,3440,1652,5793,5794,5795, 941, # 5360 -2299, 208,3546,4161,2020, 330,4438,3944,2906,2499,3799,4439,4811,5796,5797,5798, # 5376 -) - diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/big5prober.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/big5prober.py deleted file mode 100644 index 98f9970..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/big5prober.py +++ /dev/null @@ -1,47 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .mbcharsetprober import MultiByteCharSetProber -from .codingstatemachine import CodingStateMachine -from .chardistribution import Big5DistributionAnalysis -from .mbcssm import BIG5_SM_MODEL - - -class Big5Prober(MultiByteCharSetProber): - def __init__(self): - super(Big5Prober, self).__init__() - self.coding_sm = CodingStateMachine(BIG5_SM_MODEL) - self.distribution_analyzer = Big5DistributionAnalysis() - self.reset() - - @property - def charset_name(self): - return "Big5" - - @property - def language(self): - return "Chinese" diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/chardistribution.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/chardistribution.py deleted file mode 100644 index c0395f4..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/chardistribution.py +++ /dev/null @@ -1,233 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .euctwfreq import (EUCTW_CHAR_TO_FREQ_ORDER, EUCTW_TABLE_SIZE, - EUCTW_TYPICAL_DISTRIBUTION_RATIO) -from .euckrfreq import (EUCKR_CHAR_TO_FREQ_ORDER, EUCKR_TABLE_SIZE, - EUCKR_TYPICAL_DISTRIBUTION_RATIO) -from .gb2312freq import (GB2312_CHAR_TO_FREQ_ORDER, GB2312_TABLE_SIZE, - GB2312_TYPICAL_DISTRIBUTION_RATIO) -from .big5freq import (BIG5_CHAR_TO_FREQ_ORDER, BIG5_TABLE_SIZE, - BIG5_TYPICAL_DISTRIBUTION_RATIO) -from .jisfreq import (JIS_CHAR_TO_FREQ_ORDER, JIS_TABLE_SIZE, - JIS_TYPICAL_DISTRIBUTION_RATIO) - - -class CharDistributionAnalysis(object): - ENOUGH_DATA_THRESHOLD = 1024 - SURE_YES = 0.99 - SURE_NO = 0.01 - MINIMUM_DATA_THRESHOLD = 3 - - def __init__(self): - # Mapping table to get frequency order from char order (get from - # GetOrder()) - self._char_to_freq_order = None - self._table_size = None # Size of above table - # This is a constant value which varies from language to language, - # used in calculating confidence. See - # http://www.mozilla.org/projects/intl/UniversalCharsetDetection.html - # for further detail. - self.typical_distribution_ratio = None - self._done = None - self._total_chars = None - self._freq_chars = None - self.reset() - - def reset(self): - """reset analyser, clear any state""" - # If this flag is set to True, detection is done and conclusion has - # been made - self._done = False - self._total_chars = 0 # Total characters encountered - # The number of characters whose frequency order is less than 512 - self._freq_chars = 0 - - def feed(self, char, char_len): - """feed a character with known length""" - if char_len == 2: - # we only care about 2-bytes character in our distribution analysis - order = self.get_order(char) - else: - order = -1 - if order >= 0: - self._total_chars += 1 - # order is valid - if order < self._table_size: - if 512 > self._char_to_freq_order[order]: - self._freq_chars += 1 - - def get_confidence(self): - """return confidence based on existing data""" - # if we didn't receive any character in our consideration range, - # return negative answer - if self._total_chars <= 0 or self._freq_chars <= self.MINIMUM_DATA_THRESHOLD: - return self.SURE_NO - - if self._total_chars != self._freq_chars: - r = (self._freq_chars / ((self._total_chars - self._freq_chars) - * self.typical_distribution_ratio)) - if r < self.SURE_YES: - return r - - # normalize confidence (we don't want to be 100% sure) - return self.SURE_YES - - def got_enough_data(self): - # It is not necessary to receive all data to draw conclusion. - # For charset detection, certain amount of data is enough - return self._total_chars > self.ENOUGH_DATA_THRESHOLD - - def get_order(self, byte_str): - # We do not handle characters based on the original encoding string, - # but convert this encoding string to a number, here called order. - # This allows multiple encodings of a language to share one frequency - # table. - return -1 - - -class EUCTWDistributionAnalysis(CharDistributionAnalysis): - def __init__(self): - super(EUCTWDistributionAnalysis, self).__init__() - self._char_to_freq_order = EUCTW_CHAR_TO_FREQ_ORDER - self._table_size = EUCTW_TABLE_SIZE - self.typical_distribution_ratio = EUCTW_TYPICAL_DISTRIBUTION_RATIO - - def get_order(self, byte_str): - # for euc-TW encoding, we are interested - # first byte range: 0xc4 -- 0xfe - # second byte range: 0xa1 -- 0xfe - # no validation needed here. State machine has done that - first_char = byte_str[0] - if first_char >= 0xC4: - return 94 * (first_char - 0xC4) + byte_str[1] - 0xA1 - else: - return -1 - - -class EUCKRDistributionAnalysis(CharDistributionAnalysis): - def __init__(self): - super(EUCKRDistributionAnalysis, self).__init__() - self._char_to_freq_order = EUCKR_CHAR_TO_FREQ_ORDER - self._table_size = EUCKR_TABLE_SIZE - self.typical_distribution_ratio = EUCKR_TYPICAL_DISTRIBUTION_RATIO - - def get_order(self, byte_str): - # for euc-KR encoding, we are interested - # first byte range: 0xb0 -- 0xfe - # second byte range: 0xa1 -- 0xfe - # no validation needed here. State machine has done that - first_char = byte_str[0] - if first_char >= 0xB0: - return 94 * (first_char - 0xB0) + byte_str[1] - 0xA1 - else: - return -1 - - -class GB2312DistributionAnalysis(CharDistributionAnalysis): - def __init__(self): - super(GB2312DistributionAnalysis, self).__init__() - self._char_to_freq_order = GB2312_CHAR_TO_FREQ_ORDER - self._table_size = GB2312_TABLE_SIZE - self.typical_distribution_ratio = GB2312_TYPICAL_DISTRIBUTION_RATIO - - def get_order(self, byte_str): - # for GB2312 encoding, we are interested - # first byte range: 0xb0 -- 0xfe - # second byte range: 0xa1 -- 0xfe - # no validation needed here. State machine has done that - first_char, second_char = byte_str[0], byte_str[1] - if (first_char >= 0xB0) and (second_char >= 0xA1): - return 94 * (first_char - 0xB0) + second_char - 0xA1 - else: - return -1 - - -class Big5DistributionAnalysis(CharDistributionAnalysis): - def __init__(self): - super(Big5DistributionAnalysis, self).__init__() - self._char_to_freq_order = BIG5_CHAR_TO_FREQ_ORDER - self._table_size = BIG5_TABLE_SIZE - self.typical_distribution_ratio = BIG5_TYPICAL_DISTRIBUTION_RATIO - - def get_order(self, byte_str): - # for big5 encoding, we are interested - # first byte range: 0xa4 -- 0xfe - # second byte range: 0x40 -- 0x7e , 0xa1 -- 0xfe - # no validation needed here. State machine has done that - first_char, second_char = byte_str[0], byte_str[1] - if first_char >= 0xA4: - if second_char >= 0xA1: - return 157 * (first_char - 0xA4) + second_char - 0xA1 + 63 - else: - return 157 * (first_char - 0xA4) + second_char - 0x40 - else: - return -1 - - -class SJISDistributionAnalysis(CharDistributionAnalysis): - def __init__(self): - super(SJISDistributionAnalysis, self).__init__() - self._char_to_freq_order = JIS_CHAR_TO_FREQ_ORDER - self._table_size = JIS_TABLE_SIZE - self.typical_distribution_ratio = JIS_TYPICAL_DISTRIBUTION_RATIO - - def get_order(self, byte_str): - # for sjis encoding, we are interested - # first byte range: 0x81 -- 0x9f , 0xe0 -- 0xfe - # second byte range: 0x40 -- 0x7e, 0x81 -- oxfe - # no validation needed here. State machine has done that - first_char, second_char = byte_str[0], byte_str[1] - if (first_char >= 0x81) and (first_char <= 0x9F): - order = 188 * (first_char - 0x81) - elif (first_char >= 0xE0) and (first_char <= 0xEF): - order = 188 * (first_char - 0xE0 + 31) - else: - return -1 - order = order + second_char - 0x40 - if second_char > 0x7F: - order = -1 - return order - - -class EUCJPDistributionAnalysis(CharDistributionAnalysis): - def __init__(self): - super(EUCJPDistributionAnalysis, self).__init__() - self._char_to_freq_order = JIS_CHAR_TO_FREQ_ORDER - self._table_size = JIS_TABLE_SIZE - self.typical_distribution_ratio = JIS_TYPICAL_DISTRIBUTION_RATIO - - def get_order(self, byte_str): - # for euc-JP encoding, we are interested - # first byte range: 0xa0 -- 0xfe - # second byte range: 0xa1 -- 0xfe - # no validation needed here. State machine has done that - char = byte_str[0] - if char >= 0xA0: - return 94 * (char - 0xA1) + byte_str[1] - 0xa1 - else: - return -1 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/charsetgroupprober.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/charsetgroupprober.py deleted file mode 100644 index 8b3738e..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/charsetgroupprober.py +++ /dev/null @@ -1,106 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .enums import ProbingState -from .charsetprober import CharSetProber - - -class CharSetGroupProber(CharSetProber): - def __init__(self, lang_filter=None): - super(CharSetGroupProber, self).__init__(lang_filter=lang_filter) - self._active_num = 0 - self.probers = [] - self._best_guess_prober = None - - def reset(self): - super(CharSetGroupProber, self).reset() - self._active_num = 0 - for prober in self.probers: - if prober: - prober.reset() - prober.active = True - self._active_num += 1 - self._best_guess_prober = None - - @property - def charset_name(self): - if not self._best_guess_prober: - self.get_confidence() - if not self._best_guess_prober: - return None - return self._best_guess_prober.charset_name - - @property - def language(self): - if not self._best_guess_prober: - self.get_confidence() - if not self._best_guess_prober: - return None - return self._best_guess_prober.language - - def feed(self, byte_str): - for prober in self.probers: - if not prober: - continue - if not prober.active: - continue - state = prober.feed(byte_str) - if not state: - continue - if state == ProbingState.FOUND_IT: - self._best_guess_prober = prober - return self.state - elif state == ProbingState.NOT_ME: - prober.active = False - self._active_num -= 1 - if self._active_num <= 0: - self._state = ProbingState.NOT_ME - return self.state - return self.state - - def get_confidence(self): - state = self.state - if state == ProbingState.FOUND_IT: - return 0.99 - elif state == ProbingState.NOT_ME: - return 0.01 - best_conf = 0.0 - self._best_guess_prober = None - for prober in self.probers: - if not prober: - continue - if not prober.active: - self.logger.debug('%s not active', prober.charset_name) - continue - conf = prober.get_confidence() - self.logger.debug('%s %s confidence = %s', prober.charset_name, prober.language, conf) - if best_conf < conf: - best_conf = conf - self._best_guess_prober = prober - if not self._best_guess_prober: - return 0.0 - return best_conf diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/charsetprober.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/charsetprober.py deleted file mode 100644 index eac4e59..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/charsetprober.py +++ /dev/null @@ -1,145 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Universal charset detector code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 2001 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# Shy Shalom - original C code -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -import logging -import re - -from .enums import ProbingState - - -class CharSetProber(object): - - SHORTCUT_THRESHOLD = 0.95 - - def __init__(self, lang_filter=None): - self._state = None - self.lang_filter = lang_filter - self.logger = logging.getLogger(__name__) - - def reset(self): - self._state = ProbingState.DETECTING - - @property - def charset_name(self): - return None - - def feed(self, buf): - pass - - @property - def state(self): - return self._state - - def get_confidence(self): - return 0.0 - - @staticmethod - def filter_high_byte_only(buf): - buf = re.sub(b'([\x00-\x7F])+', b' ', buf) - return buf - - @staticmethod - def filter_international_words(buf): - """ - We define three types of bytes: - alphabet: english alphabets [a-zA-Z] - international: international characters [\x80-\xFF] - marker: everything else [^a-zA-Z\x80-\xFF] - - The input buffer can be thought to contain a series of words delimited - by markers. This function works to filter all words that contain at - least one international character. All contiguous sequences of markers - are replaced by a single space ascii character. - - This filter applies to all scripts which do not use English characters. - """ - filtered = bytearray() - - # This regex expression filters out only words that have at-least one - # international character. The word may include one marker character at - # the end. - words = re.findall(b'[a-zA-Z]*[\x80-\xFF]+[a-zA-Z]*[^a-zA-Z\x80-\xFF]?', - buf) - - for word in words: - filtered.extend(word[:-1]) - - # If the last character in the word is a marker, replace it with a - # space as markers shouldn't affect our analysis (they are used - # similarly across all languages and may thus have similar - # frequencies). - last_char = word[-1:] - if not last_char.isalpha() and last_char < b'\x80': - last_char = b' ' - filtered.extend(last_char) - - return filtered - - @staticmethod - def filter_with_english_letters(buf): - """ - Returns a copy of ``buf`` that retains only the sequences of English - alphabet and high byte characters that are not between <> characters. - Also retains English alphabet and high byte characters immediately - before occurrences of >. - - This filter can be applied to all scripts which contain both English - characters and extended ASCII characters, but is currently only used by - ``Latin1Prober``. - """ - filtered = bytearray() - in_tag = False - prev = 0 - - for curr in range(len(buf)): - # Slice here to get bytes instead of an int with Python 3 - buf_char = buf[curr:curr + 1] - # Check if we're coming out of or entering an HTML tag - if buf_char == b'>': - in_tag = False - elif buf_char == b'<': - in_tag = True - - # If current character is not extended-ASCII and not alphabetic... - if buf_char < b'\x80' and not buf_char.isalpha(): - # ...and we're not in a tag - if curr > prev and not in_tag: - # Keep everything after last non-extended-ASCII, - # non-alphabetic character - filtered.extend(buf[prev:curr]) - # Output a space to delimit stretch we kept - filtered.extend(b' ') - prev = curr + 1 - - # If we're not in a tag... - if not in_tag: - # Keep everything after last non-extended-ASCII, non-alphabetic - # character - filtered.extend(buf[prev:]) - - return filtered diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/cli/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/cli/__init__.py deleted file mode 100644 index 8b13789..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/cli/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/cli/chardetect.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/cli/chardetect.py deleted file mode 100644 index c61136b..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/cli/chardetect.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python -""" -Script which takes one or more file paths and reports on their detected -encodings - -Example:: - - % chardetect somefile someotherfile - somefile: windows-1252 with confidence 0.5 - someotherfile: ascii with confidence 1.0 - -If no paths are provided, it takes its input from stdin. - -""" - -from __future__ import absolute_import, print_function, unicode_literals - -import argparse -import sys - -from pip._vendor.chardet import __version__ -from pip._vendor.chardet.compat import PY2 -from pip._vendor.chardet.universaldetector import UniversalDetector - - -def description_of(lines, name='stdin'): - """ - Return a string describing the probable encoding of a file or - list of strings. - - :param lines: The lines to get the encoding of. - :type lines: Iterable of bytes - :param name: Name of file or collection of lines - :type name: str - """ - u = UniversalDetector() - for line in lines: - line = bytearray(line) - u.feed(line) - # shortcut out of the loop to save reading further - particularly useful if we read a BOM. - if u.done: - break - u.close() - result = u.result - if PY2: - name = name.decode(sys.getfilesystemencoding(), 'ignore') - if result['encoding']: - return '{0}: {1} with confidence {2}'.format(name, result['encoding'], - result['confidence']) - else: - return '{0}: no result'.format(name) - - -def main(argv=None): - """ - Handles command line arguments and gets things started. - - :param argv: List of arguments, as if specified on the command-line. - If None, ``sys.argv[1:]`` is used instead. - :type argv: list of str - """ - # Get command line arguments - parser = argparse.ArgumentParser( - description="Takes one or more file paths and reports their detected \ - encodings") - parser.add_argument('input', - help='File whose encoding we would like to determine. \ - (default: stdin)', - type=argparse.FileType('rb'), nargs='*', - default=[sys.stdin if PY2 else sys.stdin.buffer]) - parser.add_argument('--version', action='version', - version='%(prog)s {0}'.format(__version__)) - args = parser.parse_args(argv) - - for f in args.input: - if f.isatty(): - print("You are running chardetect interactively. Press " + - "CTRL-D twice at the start of a blank line to signal the " + - "end of your input. If you want help, run chardetect " + - "--help\n", file=sys.stderr) - print(description_of(f, f.name)) - - -if __name__ == '__main__': - main() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/codingstatemachine.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/codingstatemachine.py deleted file mode 100644 index 68fba44..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/codingstatemachine.py +++ /dev/null @@ -1,88 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is mozilla.org code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -import logging - -from .enums import MachineState - - -class CodingStateMachine(object): - """ - A state machine to verify a byte sequence for a particular encoding. For - each byte the detector receives, it will feed that byte to every active - state machine available, one byte at a time. The state machine changes its - state based on its previous state and the byte it receives. There are 3 - states in a state machine that are of interest to an auto-detector: - - START state: This is the state to start with, or a legal byte sequence - (i.e. a valid code point) for character has been identified. - - ME state: This indicates that the state machine identified a byte sequence - that is specific to the charset it is designed for and that - there is no other possible encoding which can contain this byte - sequence. This will to lead to an immediate positive answer for - the detector. - - ERROR state: This indicates the state machine identified an illegal byte - sequence for that encoding. This will lead to an immediate - negative answer for this encoding. Detector will exclude this - encoding from consideration from here on. - """ - def __init__(self, sm): - self._model = sm - self._curr_byte_pos = 0 - self._curr_char_len = 0 - self._curr_state = None - self.logger = logging.getLogger(__name__) - self.reset() - - def reset(self): - self._curr_state = MachineState.START - - def next_state(self, c): - # for each byte we get its class - # if it is first byte, we also get byte length - byte_class = self._model['class_table'][c] - if self._curr_state == MachineState.START: - self._curr_byte_pos = 0 - self._curr_char_len = self._model['char_len_table'][byte_class] - # from byte's class and state_table, we get its next state - curr_state = (self._curr_state * self._model['class_factor'] - + byte_class) - self._curr_state = self._model['state_table'][curr_state] - self._curr_byte_pos += 1 - return self._curr_state - - def get_current_charlen(self): - return self._curr_char_len - - def get_coding_state_machine(self): - return self._model['name'] - - @property - def language(self): - return self._model['language'] diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/compat.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/compat.py deleted file mode 100644 index ddd7468..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/compat.py +++ /dev/null @@ -1,34 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# Contributor(s): -# Dan Blanchard -# Ian Cordasco -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -import sys - - -if sys.version_info < (3, 0): - PY2 = True - PY3 = False - base_str = (str, unicode) - text_type = unicode -else: - PY2 = False - PY3 = True - base_str = (bytes, str) - text_type = str diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/cp949prober.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/cp949prober.py deleted file mode 100644 index efd793a..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/cp949prober.py +++ /dev/null @@ -1,49 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is mozilla.org code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .chardistribution import EUCKRDistributionAnalysis -from .codingstatemachine import CodingStateMachine -from .mbcharsetprober import MultiByteCharSetProber -from .mbcssm import CP949_SM_MODEL - - -class CP949Prober(MultiByteCharSetProber): - def __init__(self): - super(CP949Prober, self).__init__() - self.coding_sm = CodingStateMachine(CP949_SM_MODEL) - # NOTE: CP949 is a superset of EUC-KR, so the distribution should be - # not different. - self.distribution_analyzer = EUCKRDistributionAnalysis() - self.reset() - - @property - def charset_name(self): - return "CP949" - - @property - def language(self): - return "Korean" diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/enums.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/enums.py deleted file mode 100644 index 0451207..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/enums.py +++ /dev/null @@ -1,76 +0,0 @@ -""" -All of the Enums that are used throughout the chardet package. - -:author: Dan Blanchard (dan.blanchard@gmail.com) -""" - - -class InputState(object): - """ - This enum represents the different states a universal detector can be in. - """ - PURE_ASCII = 0 - ESC_ASCII = 1 - HIGH_BYTE = 2 - - -class LanguageFilter(object): - """ - This enum represents the different language filters we can apply to a - ``UniversalDetector``. - """ - CHINESE_SIMPLIFIED = 0x01 - CHINESE_TRADITIONAL = 0x02 - JAPANESE = 0x04 - KOREAN = 0x08 - NON_CJK = 0x10 - ALL = 0x1F - CHINESE = CHINESE_SIMPLIFIED | CHINESE_TRADITIONAL - CJK = CHINESE | JAPANESE | KOREAN - - -class ProbingState(object): - """ - This enum represents the different states a prober can be in. - """ - DETECTING = 0 - FOUND_IT = 1 - NOT_ME = 2 - - -class MachineState(object): - """ - This enum represents the different states a state machine can be in. - """ - START = 0 - ERROR = 1 - ITS_ME = 2 - - -class SequenceLikelihood(object): - """ - This enum represents the likelihood of a character following the previous one. - """ - NEGATIVE = 0 - UNLIKELY = 1 - LIKELY = 2 - POSITIVE = 3 - - @classmethod - def get_num_categories(cls): - """:returns: The number of likelihood categories in the enum.""" - return 4 - - -class CharacterCategory(object): - """ - This enum represents the different categories language models for - ``SingleByteCharsetProber`` put characters into. - - Anything less than CONTROL is considered a letter. - """ - UNDEFINED = 255 - LINE_BREAK = 254 - SYMBOL = 253 - DIGIT = 252 - CONTROL = 251 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/escprober.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/escprober.py deleted file mode 100644 index c70493f..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/escprober.py +++ /dev/null @@ -1,101 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is mozilla.org code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .charsetprober import CharSetProber -from .codingstatemachine import CodingStateMachine -from .enums import LanguageFilter, ProbingState, MachineState -from .escsm import (HZ_SM_MODEL, ISO2022CN_SM_MODEL, ISO2022JP_SM_MODEL, - ISO2022KR_SM_MODEL) - - -class EscCharSetProber(CharSetProber): - """ - This CharSetProber uses a "code scheme" approach for detecting encodings, - whereby easily recognizable escape or shift sequences are relied on to - identify these encodings. - """ - - def __init__(self, lang_filter=None): - super(EscCharSetProber, self).__init__(lang_filter=lang_filter) - self.coding_sm = [] - if self.lang_filter & LanguageFilter.CHINESE_SIMPLIFIED: - self.coding_sm.append(CodingStateMachine(HZ_SM_MODEL)) - self.coding_sm.append(CodingStateMachine(ISO2022CN_SM_MODEL)) - if self.lang_filter & LanguageFilter.JAPANESE: - self.coding_sm.append(CodingStateMachine(ISO2022JP_SM_MODEL)) - if self.lang_filter & LanguageFilter.KOREAN: - self.coding_sm.append(CodingStateMachine(ISO2022KR_SM_MODEL)) - self.active_sm_count = None - self._detected_charset = None - self._detected_language = None - self._state = None - self.reset() - - def reset(self): - super(EscCharSetProber, self).reset() - for coding_sm in self.coding_sm: - if not coding_sm: - continue - coding_sm.active = True - coding_sm.reset() - self.active_sm_count = len(self.coding_sm) - self._detected_charset = None - self._detected_language = None - - @property - def charset_name(self): - return self._detected_charset - - @property - def language(self): - return self._detected_language - - def get_confidence(self): - if self._detected_charset: - return 0.99 - else: - return 0.00 - - def feed(self, byte_str): - for c in byte_str: - for coding_sm in self.coding_sm: - if not coding_sm or not coding_sm.active: - continue - coding_state = coding_sm.next_state(c) - if coding_state == MachineState.ERROR: - coding_sm.active = False - self.active_sm_count -= 1 - if self.active_sm_count <= 0: - self._state = ProbingState.NOT_ME - return self.state - elif coding_state == MachineState.ITS_ME: - self._state = ProbingState.FOUND_IT - self._detected_charset = coding_sm.get_coding_state_machine() - self._detected_language = coding_sm.language - return self.state - - return self.state diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/escsm.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/escsm.py deleted file mode 100644 index 0069523..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/escsm.py +++ /dev/null @@ -1,246 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is mozilla.org code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .enums import MachineState - -HZ_CLS = ( -1,0,0,0,0,0,0,0, # 00 - 07 -0,0,0,0,0,0,0,0, # 08 - 0f -0,0,0,0,0,0,0,0, # 10 - 17 -0,0,0,1,0,0,0,0, # 18 - 1f -0,0,0,0,0,0,0,0, # 20 - 27 -0,0,0,0,0,0,0,0, # 28 - 2f -0,0,0,0,0,0,0,0, # 30 - 37 -0,0,0,0,0,0,0,0, # 38 - 3f -0,0,0,0,0,0,0,0, # 40 - 47 -0,0,0,0,0,0,0,0, # 48 - 4f -0,0,0,0,0,0,0,0, # 50 - 57 -0,0,0,0,0,0,0,0, # 58 - 5f -0,0,0,0,0,0,0,0, # 60 - 67 -0,0,0,0,0,0,0,0, # 68 - 6f -0,0,0,0,0,0,0,0, # 70 - 77 -0,0,0,4,0,5,2,0, # 78 - 7f -1,1,1,1,1,1,1,1, # 80 - 87 -1,1,1,1,1,1,1,1, # 88 - 8f -1,1,1,1,1,1,1,1, # 90 - 97 -1,1,1,1,1,1,1,1, # 98 - 9f -1,1,1,1,1,1,1,1, # a0 - a7 -1,1,1,1,1,1,1,1, # a8 - af -1,1,1,1,1,1,1,1, # b0 - b7 -1,1,1,1,1,1,1,1, # b8 - bf -1,1,1,1,1,1,1,1, # c0 - c7 -1,1,1,1,1,1,1,1, # c8 - cf -1,1,1,1,1,1,1,1, # d0 - d7 -1,1,1,1,1,1,1,1, # d8 - df -1,1,1,1,1,1,1,1, # e0 - e7 -1,1,1,1,1,1,1,1, # e8 - ef -1,1,1,1,1,1,1,1, # f0 - f7 -1,1,1,1,1,1,1,1, # f8 - ff -) - -HZ_ST = ( -MachineState.START,MachineState.ERROR, 3,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,# 00-07 -MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 08-0f -MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START, 4,MachineState.ERROR,# 10-17 - 5,MachineState.ERROR, 6,MachineState.ERROR, 5, 5, 4,MachineState.ERROR,# 18-1f - 4,MachineState.ERROR, 4, 4, 4,MachineState.ERROR, 4,MachineState.ERROR,# 20-27 - 4,MachineState.ITS_ME,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 28-2f -) - -HZ_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0) - -HZ_SM_MODEL = {'class_table': HZ_CLS, - 'class_factor': 6, - 'state_table': HZ_ST, - 'char_len_table': HZ_CHAR_LEN_TABLE, - 'name': "HZ-GB-2312", - 'language': 'Chinese'} - -ISO2022CN_CLS = ( -2,0,0,0,0,0,0,0, # 00 - 07 -0,0,0,0,0,0,0,0, # 08 - 0f -0,0,0,0,0,0,0,0, # 10 - 17 -0,0,0,1,0,0,0,0, # 18 - 1f -0,0,0,0,0,0,0,0, # 20 - 27 -0,3,0,0,0,0,0,0, # 28 - 2f -0,0,0,0,0,0,0,0, # 30 - 37 -0,0,0,0,0,0,0,0, # 38 - 3f -0,0,0,4,0,0,0,0, # 40 - 47 -0,0,0,0,0,0,0,0, # 48 - 4f -0,0,0,0,0,0,0,0, # 50 - 57 -0,0,0,0,0,0,0,0, # 58 - 5f -0,0,0,0,0,0,0,0, # 60 - 67 -0,0,0,0,0,0,0,0, # 68 - 6f -0,0,0,0,0,0,0,0, # 70 - 77 -0,0,0,0,0,0,0,0, # 78 - 7f -2,2,2,2,2,2,2,2, # 80 - 87 -2,2,2,2,2,2,2,2, # 88 - 8f -2,2,2,2,2,2,2,2, # 90 - 97 -2,2,2,2,2,2,2,2, # 98 - 9f -2,2,2,2,2,2,2,2, # a0 - a7 -2,2,2,2,2,2,2,2, # a8 - af -2,2,2,2,2,2,2,2, # b0 - b7 -2,2,2,2,2,2,2,2, # b8 - bf -2,2,2,2,2,2,2,2, # c0 - c7 -2,2,2,2,2,2,2,2, # c8 - cf -2,2,2,2,2,2,2,2, # d0 - d7 -2,2,2,2,2,2,2,2, # d8 - df -2,2,2,2,2,2,2,2, # e0 - e7 -2,2,2,2,2,2,2,2, # e8 - ef -2,2,2,2,2,2,2,2, # f0 - f7 -2,2,2,2,2,2,2,2, # f8 - ff -) - -ISO2022CN_ST = ( -MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 00-07 -MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 08-0f -MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 10-17 -MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 4,MachineState.ERROR,# 18-1f -MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 20-27 - 5, 6,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 28-2f -MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 30-37 -MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.START,# 38-3f -) - -ISO2022CN_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0, 0, 0, 0) - -ISO2022CN_SM_MODEL = {'class_table': ISO2022CN_CLS, - 'class_factor': 9, - 'state_table': ISO2022CN_ST, - 'char_len_table': ISO2022CN_CHAR_LEN_TABLE, - 'name': "ISO-2022-CN", - 'language': 'Chinese'} - -ISO2022JP_CLS = ( -2,0,0,0,0,0,0,0, # 00 - 07 -0,0,0,0,0,0,2,2, # 08 - 0f -0,0,0,0,0,0,0,0, # 10 - 17 -0,0,0,1,0,0,0,0, # 18 - 1f -0,0,0,0,7,0,0,0, # 20 - 27 -3,0,0,0,0,0,0,0, # 28 - 2f -0,0,0,0,0,0,0,0, # 30 - 37 -0,0,0,0,0,0,0,0, # 38 - 3f -6,0,4,0,8,0,0,0, # 40 - 47 -0,9,5,0,0,0,0,0, # 48 - 4f -0,0,0,0,0,0,0,0, # 50 - 57 -0,0,0,0,0,0,0,0, # 58 - 5f -0,0,0,0,0,0,0,0, # 60 - 67 -0,0,0,0,0,0,0,0, # 68 - 6f -0,0,0,0,0,0,0,0, # 70 - 77 -0,0,0,0,0,0,0,0, # 78 - 7f -2,2,2,2,2,2,2,2, # 80 - 87 -2,2,2,2,2,2,2,2, # 88 - 8f -2,2,2,2,2,2,2,2, # 90 - 97 -2,2,2,2,2,2,2,2, # 98 - 9f -2,2,2,2,2,2,2,2, # a0 - a7 -2,2,2,2,2,2,2,2, # a8 - af -2,2,2,2,2,2,2,2, # b0 - b7 -2,2,2,2,2,2,2,2, # b8 - bf -2,2,2,2,2,2,2,2, # c0 - c7 -2,2,2,2,2,2,2,2, # c8 - cf -2,2,2,2,2,2,2,2, # d0 - d7 -2,2,2,2,2,2,2,2, # d8 - df -2,2,2,2,2,2,2,2, # e0 - e7 -2,2,2,2,2,2,2,2, # e8 - ef -2,2,2,2,2,2,2,2, # f0 - f7 -2,2,2,2,2,2,2,2, # f8 - ff -) - -ISO2022JP_ST = ( -MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 00-07 -MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 08-0f -MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 10-17 -MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,# 18-1f -MachineState.ERROR, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 4,MachineState.ERROR,MachineState.ERROR,# 20-27 -MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 6,MachineState.ITS_ME,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,# 28-2f -MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,# 30-37 -MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 38-3f -MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.START,MachineState.START,# 40-47 -) - -ISO2022JP_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - -ISO2022JP_SM_MODEL = {'class_table': ISO2022JP_CLS, - 'class_factor': 10, - 'state_table': ISO2022JP_ST, - 'char_len_table': ISO2022JP_CHAR_LEN_TABLE, - 'name': "ISO-2022-JP", - 'language': 'Japanese'} - -ISO2022KR_CLS = ( -2,0,0,0,0,0,0,0, # 00 - 07 -0,0,0,0,0,0,0,0, # 08 - 0f -0,0,0,0,0,0,0,0, # 10 - 17 -0,0,0,1,0,0,0,0, # 18 - 1f -0,0,0,0,3,0,0,0, # 20 - 27 -0,4,0,0,0,0,0,0, # 28 - 2f -0,0,0,0,0,0,0,0, # 30 - 37 -0,0,0,0,0,0,0,0, # 38 - 3f -0,0,0,5,0,0,0,0, # 40 - 47 -0,0,0,0,0,0,0,0, # 48 - 4f -0,0,0,0,0,0,0,0, # 50 - 57 -0,0,0,0,0,0,0,0, # 58 - 5f -0,0,0,0,0,0,0,0, # 60 - 67 -0,0,0,0,0,0,0,0, # 68 - 6f -0,0,0,0,0,0,0,0, # 70 - 77 -0,0,0,0,0,0,0,0, # 78 - 7f -2,2,2,2,2,2,2,2, # 80 - 87 -2,2,2,2,2,2,2,2, # 88 - 8f -2,2,2,2,2,2,2,2, # 90 - 97 -2,2,2,2,2,2,2,2, # 98 - 9f -2,2,2,2,2,2,2,2, # a0 - a7 -2,2,2,2,2,2,2,2, # a8 - af -2,2,2,2,2,2,2,2, # b0 - b7 -2,2,2,2,2,2,2,2, # b8 - bf -2,2,2,2,2,2,2,2, # c0 - c7 -2,2,2,2,2,2,2,2, # c8 - cf -2,2,2,2,2,2,2,2, # d0 - d7 -2,2,2,2,2,2,2,2, # d8 - df -2,2,2,2,2,2,2,2, # e0 - e7 -2,2,2,2,2,2,2,2, # e8 - ef -2,2,2,2,2,2,2,2, # f0 - f7 -2,2,2,2,2,2,2,2, # f8 - ff -) - -ISO2022KR_ST = ( -MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,# 00-07 -MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 08-0f -MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 4,MachineState.ERROR,MachineState.ERROR,# 10-17 -MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 18-1f -MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 20-27 -) - -ISO2022KR_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0) - -ISO2022KR_SM_MODEL = {'class_table': ISO2022KR_CLS, - 'class_factor': 6, - 'state_table': ISO2022KR_ST, - 'char_len_table': ISO2022KR_CHAR_LEN_TABLE, - 'name': "ISO-2022-KR", - 'language': 'Korean'} - - diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/eucjpprober.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/eucjpprober.py deleted file mode 100644 index 20ce8f7..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/eucjpprober.py +++ /dev/null @@ -1,92 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is mozilla.org code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .enums import ProbingState, MachineState -from .mbcharsetprober import MultiByteCharSetProber -from .codingstatemachine import CodingStateMachine -from .chardistribution import EUCJPDistributionAnalysis -from .jpcntx import EUCJPContextAnalysis -from .mbcssm import EUCJP_SM_MODEL - - -class EUCJPProber(MultiByteCharSetProber): - def __init__(self): - super(EUCJPProber, self).__init__() - self.coding_sm = CodingStateMachine(EUCJP_SM_MODEL) - self.distribution_analyzer = EUCJPDistributionAnalysis() - self.context_analyzer = EUCJPContextAnalysis() - self.reset() - - def reset(self): - super(EUCJPProber, self).reset() - self.context_analyzer.reset() - - @property - def charset_name(self): - return "EUC-JP" - - @property - def language(self): - return "Japanese" - - def feed(self, byte_str): - for i in range(len(byte_str)): - # PY3K: byte_str is a byte array, so byte_str[i] is an int, not a byte - coding_state = self.coding_sm.next_state(byte_str[i]) - if coding_state == MachineState.ERROR: - self.logger.debug('%s %s prober hit error at byte %s', - self.charset_name, self.language, i) - self._state = ProbingState.NOT_ME - break - elif coding_state == MachineState.ITS_ME: - self._state = ProbingState.FOUND_IT - break - elif coding_state == MachineState.START: - char_len = self.coding_sm.get_current_charlen() - if i == 0: - self._last_char[1] = byte_str[0] - self.context_analyzer.feed(self._last_char, char_len) - self.distribution_analyzer.feed(self._last_char, char_len) - else: - self.context_analyzer.feed(byte_str[i - 1:i + 1], - char_len) - self.distribution_analyzer.feed(byte_str[i - 1:i + 1], - char_len) - - self._last_char[0] = byte_str[-1] - - if self.state == ProbingState.DETECTING: - if (self.context_analyzer.got_enough_data() and - (self.get_confidence() > self.SHORTCUT_THRESHOLD)): - self._state = ProbingState.FOUND_IT - - return self.state - - def get_confidence(self): - context_conf = self.context_analyzer.get_confidence() - distrib_conf = self.distribution_analyzer.get_confidence() - return max(context_conf, distrib_conf) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/euckrfreq.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/euckrfreq.py deleted file mode 100644 index b68078c..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/euckrfreq.py +++ /dev/null @@ -1,195 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -# Sampling from about 20M text materials include literature and computer technology - -# 128 --> 0.79 -# 256 --> 0.92 -# 512 --> 0.986 -# 1024 --> 0.99944 -# 2048 --> 0.99999 -# -# Idea Distribution Ratio = 0.98653 / (1-0.98653) = 73.24 -# Random Distribution Ration = 512 / (2350-512) = 0.279. -# -# Typical Distribution Ratio - -EUCKR_TYPICAL_DISTRIBUTION_RATIO = 6.0 - -EUCKR_TABLE_SIZE = 2352 - -# Char to FreqOrder table , -EUCKR_CHAR_TO_FREQ_ORDER = ( - 13, 130, 120,1396, 481,1719,1720, 328, 609, 212,1721, 707, 400, 299,1722, 87, -1397,1723, 104, 536,1117,1203,1724,1267, 685,1268, 508,1725,1726,1727,1728,1398, -1399,1729,1730,1731, 141, 621, 326,1057, 368,1732, 267, 488, 20,1733,1269,1734, - 945,1400,1735, 47, 904,1270,1736,1737, 773, 248,1738, 409, 313, 786, 429,1739, - 116, 987, 813,1401, 683, 75,1204, 145,1740,1741,1742,1743, 16, 847, 667, 622, - 708,1744,1745,1746, 966, 787, 304, 129,1747, 60, 820, 123, 676,1748,1749,1750, -1751, 617,1752, 626,1753,1754,1755,1756, 653,1757,1758,1759,1760,1761,1762, 856, - 344,1763,1764,1765,1766, 89, 401, 418, 806, 905, 848,1767,1768,1769, 946,1205, - 709,1770,1118,1771, 241,1772,1773,1774,1271,1775, 569,1776, 999,1777,1778,1779, -1780, 337, 751,1058, 28, 628, 254,1781, 177, 906, 270, 349, 891,1079,1782, 19, -1783, 379,1784, 315,1785, 629, 754,1402, 559,1786, 636, 203,1206,1787, 710, 567, -1788, 935, 814,1789,1790,1207, 766, 528,1791,1792,1208,1793,1794,1795,1796,1797, -1403,1798,1799, 533,1059,1404,1405,1156,1406, 936, 884,1080,1800, 351,1801,1802, -1803,1804,1805, 801,1806,1807,1808,1119,1809,1157, 714, 474,1407,1810, 298, 899, - 885,1811,1120, 802,1158,1812, 892,1813,1814,1408, 659,1815,1816,1121,1817,1818, -1819,1820,1821,1822, 319,1823, 594, 545,1824, 815, 937,1209,1825,1826, 573,1409, -1022,1827,1210,1828,1829,1830,1831,1832,1833, 556, 722, 807,1122,1060,1834, 697, -1835, 900, 557, 715,1836,1410, 540,1411, 752,1159, 294, 597,1211, 976, 803, 770, -1412,1837,1838, 39, 794,1413, 358,1839, 371, 925,1840, 453, 661, 788, 531, 723, - 544,1023,1081, 869, 91,1841, 392, 430, 790, 602,1414, 677,1082, 457,1415,1416, -1842,1843, 475, 327,1024,1417, 795, 121,1844, 733, 403,1418,1845,1846,1847, 300, - 119, 711,1212, 627,1848,1272, 207,1849,1850, 796,1213, 382,1851, 519,1852,1083, - 893,1853,1854,1855, 367, 809, 487, 671,1856, 663,1857,1858, 956, 471, 306, 857, -1859,1860,1160,1084,1861,1862,1863,1864,1865,1061,1866,1867,1868,1869,1870,1871, - 282, 96, 574,1872, 502,1085,1873,1214,1874, 907,1875,1876, 827, 977,1419,1420, -1421, 268,1877,1422,1878,1879,1880, 308,1881, 2, 537,1882,1883,1215,1884,1885, - 127, 791,1886,1273,1423,1887, 34, 336, 404, 643,1888, 571, 654, 894, 840,1889, - 0, 886,1274, 122, 575, 260, 908, 938,1890,1275, 410, 316,1891,1892, 100,1893, -1894,1123, 48,1161,1124,1025,1895, 633, 901,1276,1896,1897, 115, 816,1898, 317, -1899, 694,1900, 909, 734,1424, 572, 866,1425, 691, 85, 524,1010, 543, 394, 841, -1901,1902,1903,1026,1904,1905,1906,1907,1908,1909, 30, 451, 651, 988, 310,1910, -1911,1426, 810,1216, 93,1912,1913,1277,1217,1914, 858, 759, 45, 58, 181, 610, - 269,1915,1916, 131,1062, 551, 443,1000, 821,1427, 957, 895,1086,1917,1918, 375, -1919, 359,1920, 687,1921, 822,1922, 293,1923,1924, 40, 662, 118, 692, 29, 939, - 887, 640, 482, 174,1925, 69,1162, 728,1428, 910,1926,1278,1218,1279, 386, 870, - 217, 854,1163, 823,1927,1928,1929,1930, 834,1931, 78,1932, 859,1933,1063,1934, -1935,1936,1937, 438,1164, 208, 595,1938,1939,1940,1941,1219,1125,1942, 280, 888, -1429,1430,1220,1431,1943,1944,1945,1946,1947,1280, 150, 510,1432,1948,1949,1950, -1951,1952,1953,1954,1011,1087,1955,1433,1043,1956, 881,1957, 614, 958,1064,1065, -1221,1958, 638,1001, 860, 967, 896,1434, 989, 492, 553,1281,1165,1959,1282,1002, -1283,1222,1960,1961,1962,1963, 36, 383, 228, 753, 247, 454,1964, 876, 678,1965, -1966,1284, 126, 464, 490, 835, 136, 672, 529, 940,1088,1435, 473,1967,1968, 467, - 50, 390, 227, 587, 279, 378, 598, 792, 968, 240, 151, 160, 849, 882,1126,1285, - 639,1044, 133, 140, 288, 360, 811, 563,1027, 561, 142, 523,1969,1970,1971, 7, - 103, 296, 439, 407, 506, 634, 990,1972,1973,1974,1975, 645,1976,1977,1978,1979, -1980,1981, 236,1982,1436,1983,1984,1089, 192, 828, 618, 518,1166, 333,1127,1985, - 818,1223,1986,1987,1988,1989,1990,1991,1992,1993, 342,1128,1286, 746, 842,1994, -1995, 560, 223,1287, 98, 8, 189, 650, 978,1288,1996,1437,1997, 17, 345, 250, - 423, 277, 234, 512, 226, 97, 289, 42, 167,1998, 201,1999,2000, 843, 836, 824, - 532, 338, 783,1090, 182, 576, 436,1438,1439, 527, 500,2001, 947, 889,2002,2003, -2004,2005, 262, 600, 314, 447,2006, 547,2007, 693, 738,1129,2008, 71,1440, 745, - 619, 688,2009, 829,2010,2011, 147,2012, 33, 948,2013,2014, 74, 224,2015, 61, - 191, 918, 399, 637,2016,1028,1130, 257, 902,2017,2018,2019,2020,2021,2022,2023, -2024,2025,2026, 837,2027,2028,2029,2030, 179, 874, 591, 52, 724, 246,2031,2032, -2033,2034,1167, 969,2035,1289, 630, 605, 911,1091,1168,2036,2037,2038,1441, 912, -2039, 623,2040,2041, 253,1169,1290,2042,1442, 146, 620, 611, 577, 433,2043,1224, - 719,1170, 959, 440, 437, 534, 84, 388, 480,1131, 159, 220, 198, 679,2044,1012, - 819,1066,1443, 113,1225, 194, 318,1003,1029,2045,2046,2047,2048,1067,2049,2050, -2051,2052,2053, 59, 913, 112,2054, 632,2055, 455, 144, 739,1291,2056, 273, 681, - 499,2057, 448,2058,2059, 760,2060,2061, 970, 384, 169, 245,1132,2062,2063, 414, -1444,2064,2065, 41, 235,2066, 157, 252, 877, 568, 919, 789, 580,2067, 725,2068, -2069,1292,2070,2071,1445,2072,1446,2073,2074, 55, 588, 66,1447, 271,1092,2075, -1226,2076, 960,1013, 372,2077,2078,2079,2080,2081,1293,2082,2083,2084,2085, 850, -2086,2087,2088,2089,2090, 186,2091,1068, 180,2092,2093,2094, 109,1227, 522, 606, -2095, 867,1448,1093, 991,1171, 926, 353,1133,2096, 581,2097,2098,2099,1294,1449, -1450,2100, 596,1172,1014,1228,2101,1451,1295,1173,1229,2102,2103,1296,1134,1452, - 949,1135,2104,2105,1094,1453,1454,1455,2106,1095,2107,2108,2109,2110,2111,2112, -2113,2114,2115,2116,2117, 804,2118,2119,1230,1231, 805,1456, 405,1136,2120,2121, -2122,2123,2124, 720, 701,1297, 992,1457, 927,1004,2125,2126,2127,2128,2129,2130, - 22, 417,2131, 303,2132, 385,2133, 971, 520, 513,2134,1174, 73,1096, 231, 274, - 962,1458, 673,2135,1459,2136, 152,1137,2137,2138,2139,2140,1005,1138,1460,1139, -2141,2142,2143,2144, 11, 374, 844,2145, 154,1232, 46,1461,2146, 838, 830, 721, -1233, 106,2147, 90, 428, 462, 578, 566,1175, 352,2148,2149, 538,1234, 124,1298, -2150,1462, 761, 565,2151, 686,2152, 649,2153, 72, 173,2154, 460, 415,2155,1463, -2156,1235, 305,2157,2158,2159,2160,2161,2162, 579,2163,2164,2165,2166,2167, 747, -2168,2169,2170,2171,1464, 669,2172,2173,2174,2175,2176,1465,2177, 23, 530, 285, -2178, 335, 729,2179, 397,2180,2181,2182,1030,2183,2184, 698,2185,2186, 325,2187, -2188, 369,2189, 799,1097,1015, 348,2190,1069, 680,2191, 851,1466,2192,2193, 10, -2194, 613, 424,2195, 979, 108, 449, 589, 27, 172, 81,1031, 80, 774, 281, 350, -1032, 525, 301, 582,1176,2196, 674,1045,2197,2198,1467, 730, 762,2199,2200,2201, -2202,1468,2203, 993,2204,2205, 266,1070, 963,1140,2206,2207,2208, 664,1098, 972, -2209,2210,2211,1177,1469,1470, 871,2212,2213,2214,2215,2216,1471,2217,2218,2219, -2220,2221,2222,2223,2224,2225,2226,2227,1472,1236,2228,2229,2230,2231,2232,2233, -2234,2235,1299,2236,2237, 200,2238, 477, 373,2239,2240, 731, 825, 777,2241,2242, -2243, 521, 486, 548,2244,2245,2246,1473,1300, 53, 549, 137, 875, 76, 158,2247, -1301,1474, 469, 396,1016, 278, 712,2248, 321, 442, 503, 767, 744, 941,1237,1178, -1475,2249, 82, 178,1141,1179, 973,2250,1302,2251, 297,2252,2253, 570,2254,2255, -2256, 18, 450, 206,2257, 290, 292,1142,2258, 511, 162, 99, 346, 164, 735,2259, -1476,1477, 4, 554, 343, 798,1099,2260,1100,2261, 43, 171,1303, 139, 215,2262, -2263, 717, 775,2264,1033, 322, 216,2265, 831,2266, 149,2267,1304,2268,2269, 702, -1238, 135, 845, 347, 309,2270, 484,2271, 878, 655, 238,1006,1478,2272, 67,2273, - 295,2274,2275, 461,2276, 478, 942, 412,2277,1034,2278,2279,2280, 265,2281, 541, -2282,2283,2284,2285,2286, 70, 852,1071,2287,2288,2289,2290, 21, 56, 509, 117, - 432,2291,2292, 331, 980, 552,1101, 148, 284, 105, 393,1180,1239, 755,2293, 187, -2294,1046,1479,2295, 340,2296, 63,1047, 230,2297,2298,1305, 763,1306, 101, 800, - 808, 494,2299,2300,2301, 903,2302, 37,1072, 14, 5,2303, 79, 675,2304, 312, -2305,2306,2307,2308,2309,1480, 6,1307,2310,2311,2312, 1, 470, 35, 24, 229, -2313, 695, 210, 86, 778, 15, 784, 592, 779, 32, 77, 855, 964,2314, 259,2315, - 501, 380,2316,2317, 83, 981, 153, 689,1308,1481,1482,1483,2318,2319, 716,1484, -2320,2321,2322,2323,2324,2325,1485,2326,2327, 128, 57, 68, 261,1048, 211, 170, -1240, 31,2328, 51, 435, 742,2329,2330,2331, 635,2332, 264, 456,2333,2334,2335, - 425,2336,1486, 143, 507, 263, 943,2337, 363, 920,1487, 256,1488,1102, 243, 601, -1489,2338,2339,2340,2341,2342,2343,2344, 861,2345,2346,2347,2348,2349,2350, 395, -2351,1490,1491, 62, 535, 166, 225,2352,2353, 668, 419,1241, 138, 604, 928,2354, -1181,2355,1492,1493,2356,2357,2358,1143,2359, 696,2360, 387, 307,1309, 682, 476, -2361,2362, 332, 12, 222, 156,2363, 232,2364, 641, 276, 656, 517,1494,1495,1035, - 416, 736,1496,2365,1017, 586,2366,2367,2368,1497,2369, 242,2370,2371,2372,1498, -2373, 965, 713,2374,2375,2376,2377, 740, 982,1499, 944,1500,1007,2378,2379,1310, -1501,2380,2381,2382, 785, 329,2383,2384,1502,2385,2386,2387, 932,2388,1503,2389, -2390,2391,2392,1242,2393,2394,2395,2396,2397, 994, 950,2398,2399,2400,2401,1504, -1311,2402,2403,2404,2405,1049, 749,2406,2407, 853, 718,1144,1312,2408,1182,1505, -2409,2410, 255, 516, 479, 564, 550, 214,1506,1507,1313, 413, 239, 444, 339,1145, -1036,1508,1509,1314,1037,1510,1315,2411,1511,2412,2413,2414, 176, 703, 497, 624, - 593, 921, 302,2415, 341, 165,1103,1512,2416,1513,2417,2418,2419, 376,2420, 700, -2421,2422,2423, 258, 768,1316,2424,1183,2425, 995, 608,2426,2427,2428,2429, 221, -2430,2431,2432,2433,2434,2435,2436,2437, 195, 323, 726, 188, 897, 983,1317, 377, - 644,1050, 879,2438, 452,2439,2440,2441,2442,2443,2444, 914,2445,2446,2447,2448, - 915, 489,2449,1514,1184,2450,2451, 515, 64, 427, 495,2452, 583,2453, 483, 485, -1038, 562, 213,1515, 748, 666,2454,2455,2456,2457, 334,2458, 780, 996,1008, 705, -1243,2459,2460,2461,2462,2463, 114,2464, 493,1146, 366, 163,1516, 961,1104,2465, - 291,2466,1318,1105,2467,1517, 365,2468, 355, 951,1244,2469,1319,2470, 631,2471, -2472, 218,1320, 364, 320, 756,1518,1519,1321,1520,1322,2473,2474,2475,2476, 997, -2477,2478,2479,2480, 665,1185,2481, 916,1521,2482,2483,2484, 584, 684,2485,2486, - 797,2487,1051,1186,2488,2489,2490,1522,2491,2492, 370,2493,1039,1187, 65,2494, - 434, 205, 463,1188,2495, 125, 812, 391, 402, 826, 699, 286, 398, 155, 781, 771, - 585,2496, 590, 505,1073,2497, 599, 244, 219, 917,1018, 952, 646,1523,2498,1323, -2499,2500, 49, 984, 354, 741,2501, 625,2502,1324,2503,1019, 190, 357, 757, 491, - 95, 782, 868,2504,2505,2506,2507,2508,2509, 134,1524,1074, 422,1525, 898,2510, - 161,2511,2512,2513,2514, 769,2515,1526,2516,2517, 411,1325,2518, 472,1527,2519, -2520,2521,2522,2523,2524, 985,2525,2526,2527,2528,2529,2530, 764,2531,1245,2532, -2533, 25, 204, 311,2534, 496,2535,1052,2536,2537,2538,2539,2540,2541,2542, 199, - 704, 504, 468, 758, 657,1528, 196, 44, 839,1246, 272, 750,2543, 765, 862,2544, -2545,1326,2546, 132, 615, 933,2547, 732,2548,2549,2550,1189,1529,2551, 283,1247, -1053, 607, 929,2552,2553,2554, 930, 183, 872, 616,1040,1147,2555,1148,1020, 441, - 249,1075,2556,2557,2558, 466, 743,2559,2560,2561, 92, 514, 426, 420, 526,2562, -2563,2564,2565,2566,2567,2568, 185,2569,2570,2571,2572, 776,1530, 658,2573, 362, -2574, 361, 922,1076, 793,2575,2576,2577,2578,2579,2580,1531, 251,2581,2582,2583, -2584,1532, 54, 612, 237,1327,2585,2586, 275, 408, 647, 111,2587,1533,1106, 465, - 3, 458, 9, 38,2588, 107, 110, 890, 209, 26, 737, 498,2589,1534,2590, 431, - 202, 88,1535, 356, 287,1107, 660,1149,2591, 381,1536, 986,1150, 445,1248,1151, - 974,2592,2593, 846,2594, 446, 953, 184,1249,1250, 727,2595, 923, 193, 883,2596, -2597,2598, 102, 324, 539, 817,2599, 421,1041,2600, 832,2601, 94, 175, 197, 406, -2602, 459,2603,2604,2605,2606,2607, 330, 555,2608,2609,2610, 706,1108, 389,2611, -2612,2613,2614, 233,2615, 833, 558, 931, 954,1251,2616,2617,1537, 546,2618,2619, -1009,2620,2621,2622,1538, 690,1328,2623, 955,2624,1539,2625,2626, 772,2627,2628, -2629,2630,2631, 924, 648, 863, 603,2632,2633, 934,1540, 864, 865,2634, 642,1042, - 670,1190,2635,2636,2637,2638, 168,2639, 652, 873, 542,1054,1541,2640,2641,2642, # 512, 256 -) - diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/euckrprober.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/euckrprober.py deleted file mode 100644 index 345a060..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/euckrprober.py +++ /dev/null @@ -1,47 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is mozilla.org code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .mbcharsetprober import MultiByteCharSetProber -from .codingstatemachine import CodingStateMachine -from .chardistribution import EUCKRDistributionAnalysis -from .mbcssm import EUCKR_SM_MODEL - - -class EUCKRProber(MultiByteCharSetProber): - def __init__(self): - super(EUCKRProber, self).__init__() - self.coding_sm = CodingStateMachine(EUCKR_SM_MODEL) - self.distribution_analyzer = EUCKRDistributionAnalysis() - self.reset() - - @property - def charset_name(self): - return "EUC-KR" - - @property - def language(self): - return "Korean" diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/euctwfreq.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/euctwfreq.py deleted file mode 100644 index ed7a995..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/euctwfreq.py +++ /dev/null @@ -1,387 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -# EUCTW frequency table -# Converted from big5 work -# by Taiwan's Mandarin Promotion Council -# <http:#www.edu.tw:81/mandr/> - -# 128 --> 0.42261 -# 256 --> 0.57851 -# 512 --> 0.74851 -# 1024 --> 0.89384 -# 2048 --> 0.97583 -# -# Idea Distribution Ratio = 0.74851/(1-0.74851) =2.98 -# Random Distribution Ration = 512/(5401-512)=0.105 -# -# Typical Distribution Ratio about 25% of Ideal one, still much higher than RDR - -EUCTW_TYPICAL_DISTRIBUTION_RATIO = 0.75 - -# Char to FreqOrder table , -EUCTW_TABLE_SIZE = 5376 - -EUCTW_CHAR_TO_FREQ_ORDER = ( - 1,1800,1506, 255,1431, 198, 9, 82, 6,7310, 177, 202,3615,1256,2808, 110, # 2742 -3735, 33,3241, 261, 76, 44,2113, 16,2931,2184,1176, 659,3868, 26,3404,2643, # 2758 -1198,3869,3313,4060, 410,2211, 302, 590, 361,1963, 8, 204, 58,4296,7311,1931, # 2774 - 63,7312,7313, 317,1614, 75, 222, 159,4061,2412,1480,7314,3500,3068, 224,2809, # 2790 -3616, 3, 10,3870,1471, 29,2774,1135,2852,1939, 873, 130,3242,1123, 312,7315, # 2806 -4297,2051, 507, 252, 682,7316, 142,1914, 124, 206,2932, 34,3501,3173, 64, 604, # 2822 -7317,2494,1976,1977, 155,1990, 645, 641,1606,7318,3405, 337, 72, 406,7319, 80, # 2838 - 630, 238,3174,1509, 263, 939,1092,2644, 756,1440,1094,3406, 449, 69,2969, 591, # 2854 - 179,2095, 471, 115,2034,1843, 60, 50,2970, 134, 806,1868, 734,2035,3407, 180, # 2870 - 995,1607, 156, 537,2893, 688,7320, 319,1305, 779,2144, 514,2374, 298,4298, 359, # 2886 -2495, 90,2707,1338, 663, 11, 906,1099,2545, 20,2436, 182, 532,1716,7321, 732, # 2902 -1376,4062,1311,1420,3175, 25,2312,1056, 113, 399, 382,1949, 242,3408,2467, 529, # 2918 -3243, 475,1447,3617,7322, 117, 21, 656, 810,1297,2295,2329,3502,7323, 126,4063, # 2934 - 706, 456, 150, 613,4299, 71,1118,2036,4064, 145,3069, 85, 835, 486,2114,1246, # 2950 -1426, 428, 727,1285,1015, 800, 106, 623, 303,1281,7324,2127,2354, 347,3736, 221, # 2966 -3503,3110,7325,1955,1153,4065, 83, 296,1199,3070, 192, 624, 93,7326, 822,1897, # 2982 -2810,3111, 795,2064, 991,1554,1542,1592, 27, 43,2853, 859, 139,1456, 860,4300, # 2998 - 437, 712,3871, 164,2392,3112, 695, 211,3017,2096, 195,3872,1608,3504,3505,3618, # 3014 -3873, 234, 811,2971,2097,3874,2229,1441,3506,1615,2375, 668,2076,1638, 305, 228, # 3030 -1664,4301, 467, 415,7327, 262,2098,1593, 239, 108, 300, 200,1033, 512,1247,2077, # 3046 -7328,7329,2173,3176,3619,2673, 593, 845,1062,3244, 88,1723,2037,3875,1950, 212, # 3062 - 266, 152, 149, 468,1898,4066,4302, 77, 187,7330,3018, 37, 5,2972,7331,3876, # 3078 -7332,7333, 39,2517,4303,2894,3177,2078, 55, 148, 74,4304, 545, 483,1474,1029, # 3094 -1665, 217,1869,1531,3113,1104,2645,4067, 24, 172,3507, 900,3877,3508,3509,4305, # 3110 - 32,1408,2811,1312, 329, 487,2355,2247,2708, 784,2674, 4,3019,3314,1427,1788, # 3126 - 188, 109, 499,7334,3620,1717,1789, 888,1217,3020,4306,7335,3510,7336,3315,1520, # 3142 -3621,3878, 196,1034, 775,7337,7338, 929,1815, 249, 439, 38,7339,1063,7340, 794, # 3158 -3879,1435,2296, 46, 178,3245,2065,7341,2376,7342, 214,1709,4307, 804, 35, 707, # 3174 - 324,3622,1601,2546, 140, 459,4068,7343,7344,1365, 839, 272, 978,2257,2572,3409, # 3190 -2128,1363,3623,1423, 697, 100,3071, 48, 70,1231, 495,3114,2193,7345,1294,7346, # 3206 -2079, 462, 586,1042,3246, 853, 256, 988, 185,2377,3410,1698, 434,1084,7347,3411, # 3222 - 314,2615,2775,4308,2330,2331, 569,2280, 637,1816,2518, 757,1162,1878,1616,3412, # 3238 - 287,1577,2115, 768,4309,1671,2854,3511,2519,1321,3737, 909,2413,7348,4069, 933, # 3254 -3738,7349,2052,2356,1222,4310, 765,2414,1322, 786,4311,7350,1919,1462,1677,2895, # 3270 -1699,7351,4312,1424,2437,3115,3624,2590,3316,1774,1940,3413,3880,4070, 309,1369, # 3286 -1130,2812, 364,2230,1653,1299,3881,3512,3882,3883,2646, 525,1085,3021, 902,2000, # 3302 -1475, 964,4313, 421,1844,1415,1057,2281, 940,1364,3116, 376,4314,4315,1381, 7, # 3318 -2520, 983,2378, 336,1710,2675,1845, 321,3414, 559,1131,3022,2742,1808,1132,1313, # 3334 - 265,1481,1857,7352, 352,1203,2813,3247, 167,1089, 420,2814, 776, 792,1724,3513, # 3350 -4071,2438,3248,7353,4072,7354, 446, 229, 333,2743, 901,3739,1200,1557,4316,2647, # 3366 -1920, 395,2744,2676,3740,4073,1835, 125, 916,3178,2616,4317,7355,7356,3741,7357, # 3382 -7358,7359,4318,3117,3625,1133,2547,1757,3415,1510,2313,1409,3514,7360,2145, 438, # 3398 -2591,2896,2379,3317,1068, 958,3023, 461, 311,2855,2677,4074,1915,3179,4075,1978, # 3414 - 383, 750,2745,2617,4076, 274, 539, 385,1278,1442,7361,1154,1964, 384, 561, 210, # 3430 - 98,1295,2548,3515,7362,1711,2415,1482,3416,3884,2897,1257, 129,7363,3742, 642, # 3446 - 523,2776,2777,2648,7364, 141,2231,1333, 68, 176, 441, 876, 907,4077, 603,2592, # 3462 - 710, 171,3417, 404, 549, 18,3118,2393,1410,3626,1666,7365,3516,4319,2898,4320, # 3478 -7366,2973, 368,7367, 146, 366, 99, 871,3627,1543, 748, 807,1586,1185, 22,2258, # 3494 - 379,3743,3180,7368,3181, 505,1941,2618,1991,1382,2314,7369, 380,2357, 218, 702, # 3510 -1817,1248,3418,3024,3517,3318,3249,7370,2974,3628, 930,3250,3744,7371, 59,7372, # 3526 - 585, 601,4078, 497,3419,1112,1314,4321,1801,7373,1223,1472,2174,7374, 749,1836, # 3542 - 690,1899,3745,1772,3885,1476, 429,1043,1790,2232,2116, 917,4079, 447,1086,1629, # 3558 -7375, 556,7376,7377,2020,1654, 844,1090, 105, 550, 966,1758,2815,1008,1782, 686, # 3574 -1095,7378,2282, 793,1602,7379,3518,2593,4322,4080,2933,2297,4323,3746, 980,2496, # 3590 - 544, 353, 527,4324, 908,2678,2899,7380, 381,2619,1942,1348,7381,1341,1252, 560, # 3606 -3072,7382,3420,2856,7383,2053, 973, 886,2080, 143,4325,7384,7385, 157,3886, 496, # 3622 -4081, 57, 840, 540,2038,4326,4327,3421,2117,1445, 970,2259,1748,1965,2081,4082, # 3638 -3119,1234,1775,3251,2816,3629, 773,1206,2129,1066,2039,1326,3887,1738,1725,4083, # 3654 - 279,3120, 51,1544,2594, 423,1578,2130,2066, 173,4328,1879,7386,7387,1583, 264, # 3670 - 610,3630,4329,2439, 280, 154,7388,7389,7390,1739, 338,1282,3073, 693,2857,1411, # 3686 -1074,3747,2440,7391,4330,7392,7393,1240, 952,2394,7394,2900,1538,2679, 685,1483, # 3702 -4084,2468,1436, 953,4085,2054,4331, 671,2395, 79,4086,2441,3252, 608, 567,2680, # 3718 -3422,4087,4088,1691, 393,1261,1791,2396,7395,4332,7396,7397,7398,7399,1383,1672, # 3734 -3748,3182,1464, 522,1119, 661,1150, 216, 675,4333,3888,1432,3519, 609,4334,2681, # 3750 -2397,7400,7401,7402,4089,3025, 0,7403,2469, 315, 231,2442, 301,3319,4335,2380, # 3766 -7404, 233,4090,3631,1818,4336,4337,7405, 96,1776,1315,2082,7406, 257,7407,1809, # 3782 -3632,2709,1139,1819,4091,2021,1124,2163,2778,1777,2649,7408,3074, 363,1655,3183, # 3798 -7409,2975,7410,7411,7412,3889,1567,3890, 718, 103,3184, 849,1443, 341,3320,2934, # 3814 -1484,7413,1712, 127, 67, 339,4092,2398, 679,1412, 821,7414,7415, 834, 738, 351, # 3830 -2976,2146, 846, 235,1497,1880, 418,1992,3749,2710, 186,1100,2147,2746,3520,1545, # 3846 -1355,2935,2858,1377, 583,3891,4093,2573,2977,7416,1298,3633,1078,2549,3634,2358, # 3862 - 78,3750,3751, 267,1289,2099,2001,1594,4094, 348, 369,1274,2194,2175,1837,4338, # 3878 -1820,2817,3635,2747,2283,2002,4339,2936,2748, 144,3321, 882,4340,3892,2749,3423, # 3894 -4341,2901,7417,4095,1726, 320,7418,3893,3026, 788,2978,7419,2818,1773,1327,2859, # 3910 -3894,2819,7420,1306,4342,2003,1700,3752,3521,2359,2650, 787,2022, 506, 824,3636, # 3926 - 534, 323,4343,1044,3322,2023,1900, 946,3424,7421,1778,1500,1678,7422,1881,4344, # 3942 - 165, 243,4345,3637,2521, 123, 683,4096, 764,4346, 36,3895,1792, 589,2902, 816, # 3958 - 626,1667,3027,2233,1639,1555,1622,3753,3896,7423,3897,2860,1370,1228,1932, 891, # 3974 -2083,2903, 304,4097,7424, 292,2979,2711,3522, 691,2100,4098,1115,4347, 118, 662, # 3990 -7425, 611,1156, 854,2381,1316,2861, 2, 386, 515,2904,7426,7427,3253, 868,2234, # 4006 -1486, 855,2651, 785,2212,3028,7428,1040,3185,3523,7429,3121, 448,7430,1525,7431, # 4022 -2164,4348,7432,3754,7433,4099,2820,3524,3122, 503, 818,3898,3123,1568, 814, 676, # 4038 -1444, 306,1749,7434,3755,1416,1030, 197,1428, 805,2821,1501,4349,7435,7436,7437, # 4054 -1993,7438,4350,7439,7440,2195, 13,2779,3638,2980,3124,1229,1916,7441,3756,2131, # 4070 -7442,4100,4351,2399,3525,7443,2213,1511,1727,1120,7444,7445, 646,3757,2443, 307, # 4086 -7446,7447,1595,3186,7448,7449,7450,3639,1113,1356,3899,1465,2522,2523,7451, 519, # 4102 -7452, 128,2132, 92,2284,1979,7453,3900,1512, 342,3125,2196,7454,2780,2214,1980, # 4118 -3323,7455, 290,1656,1317, 789, 827,2360,7456,3758,4352, 562, 581,3901,7457, 401, # 4134 -4353,2248, 94,4354,1399,2781,7458,1463,2024,4355,3187,1943,7459, 828,1105,4101, # 4150 -1262,1394,7460,4102, 605,4356,7461,1783,2862,7462,2822, 819,2101, 578,2197,2937, # 4166 -7463,1502, 436,3254,4103,3255,2823,3902,2905,3425,3426,7464,2712,2315,7465,7466, # 4182 -2332,2067, 23,4357, 193, 826,3759,2102, 699,1630,4104,3075, 390,1793,1064,3526, # 4198 -7467,1579,3076,3077,1400,7468,4105,1838,1640,2863,7469,4358,4359, 137,4106, 598, # 4214 -3078,1966, 780, 104, 974,2938,7470, 278, 899, 253, 402, 572, 504, 493,1339,7471, # 4230 -3903,1275,4360,2574,2550,7472,3640,3029,3079,2249, 565,1334,2713, 863, 41,7473, # 4246 -7474,4361,7475,1657,2333, 19, 463,2750,4107, 606,7476,2981,3256,1087,2084,1323, # 4262 -2652,2982,7477,1631,1623,1750,4108,2682,7478,2864, 791,2714,2653,2334, 232,2416, # 4278 -7479,2983,1498,7480,2654,2620, 755,1366,3641,3257,3126,2025,1609, 119,1917,3427, # 4294 - 862,1026,4109,7481,3904,3760,4362,3905,4363,2260,1951,2470,7482,1125, 817,4110, # 4310 -4111,3906,1513,1766,2040,1487,4112,3030,3258,2824,3761,3127,7483,7484,1507,7485, # 4326 -2683, 733, 40,1632,1106,2865, 345,4113, 841,2524, 230,4364,2984,1846,3259,3428, # 4342 -7486,1263, 986,3429,7487, 735, 879, 254,1137, 857, 622,1300,1180,1388,1562,3907, # 4358 -3908,2939, 967,2751,2655,1349, 592,2133,1692,3324,2985,1994,4114,1679,3909,1901, # 4374 -2185,7488, 739,3642,2715,1296,1290,7489,4115,2198,2199,1921,1563,2595,2551,1870, # 4390 -2752,2986,7490, 435,7491, 343,1108, 596, 17,1751,4365,2235,3430,3643,7492,4366, # 4406 - 294,3527,2940,1693, 477, 979, 281,2041,3528, 643,2042,3644,2621,2782,2261,1031, # 4422 -2335,2134,2298,3529,4367, 367,1249,2552,7493,3530,7494,4368,1283,3325,2004, 240, # 4438 -1762,3326,4369,4370, 836,1069,3128, 474,7495,2148,2525, 268,3531,7496,3188,1521, # 4454 -1284,7497,1658,1546,4116,7498,3532,3533,7499,4117,3327,2684,1685,4118, 961,1673, # 4470 -2622, 190,2005,2200,3762,4371,4372,7500, 570,2497,3645,1490,7501,4373,2623,3260, # 4486 -1956,4374, 584,1514, 396,1045,1944,7502,4375,1967,2444,7503,7504,4376,3910, 619, # 4502 -7505,3129,3261, 215,2006,2783,2553,3189,4377,3190,4378, 763,4119,3763,4379,7506, # 4518 -7507,1957,1767,2941,3328,3646,1174, 452,1477,4380,3329,3130,7508,2825,1253,2382, # 4534 -2186,1091,2285,4120, 492,7509, 638,1169,1824,2135,1752,3911, 648, 926,1021,1324, # 4550 -4381, 520,4382, 997, 847,1007, 892,4383,3764,2262,1871,3647,7510,2400,1784,4384, # 4566 -1952,2942,3080,3191,1728,4121,2043,3648,4385,2007,1701,3131,1551, 30,2263,4122, # 4582 -7511,2026,4386,3534,7512, 501,7513,4123, 594,3431,2165,1821,3535,3432,3536,3192, # 4598 - 829,2826,4124,7514,1680,3132,1225,4125,7515,3262,4387,4126,3133,2336,7516,4388, # 4614 -4127,7517,3912,3913,7518,1847,2383,2596,3330,7519,4389, 374,3914, 652,4128,4129, # 4630 - 375,1140, 798,7520,7521,7522,2361,4390,2264, 546,1659, 138,3031,2445,4391,7523, # 4646 -2250, 612,1848, 910, 796,3765,1740,1371, 825,3766,3767,7524,2906,2554,7525, 692, # 4662 - 444,3032,2624, 801,4392,4130,7526,1491, 244,1053,3033,4131,4132, 340,7527,3915, # 4678 -1041,2987, 293,1168, 87,1357,7528,1539, 959,7529,2236, 721, 694,4133,3768, 219, # 4694 -1478, 644,1417,3331,2656,1413,1401,1335,1389,3916,7530,7531,2988,2362,3134,1825, # 4710 - 730,1515, 184,2827, 66,4393,7532,1660,2943, 246,3332, 378,1457, 226,3433, 975, # 4726 -3917,2944,1264,3537, 674, 696,7533, 163,7534,1141,2417,2166, 713,3538,3333,4394, # 4742 -3918,7535,7536,1186, 15,7537,1079,1070,7538,1522,3193,3539, 276,1050,2716, 758, # 4758 -1126, 653,2945,3263,7539,2337, 889,3540,3919,3081,2989, 903,1250,4395,3920,3434, # 4774 -3541,1342,1681,1718, 766,3264, 286, 89,2946,3649,7540,1713,7541,2597,3334,2990, # 4790 -7542,2947,2215,3194,2866,7543,4396,2498,2526, 181, 387,1075,3921, 731,2187,3335, # 4806 -7544,3265, 310, 313,3435,2299, 770,4134, 54,3034, 189,4397,3082,3769,3922,7545, # 4822 -1230,1617,1849, 355,3542,4135,4398,3336, 111,4136,3650,1350,3135,3436,3035,4137, # 4838 -2149,3266,3543,7546,2784,3923,3924,2991, 722,2008,7547,1071, 247,1207,2338,2471, # 4854 -1378,4399,2009, 864,1437,1214,4400, 373,3770,1142,2216, 667,4401, 442,2753,2555, # 4870 -3771,3925,1968,4138,3267,1839, 837, 170,1107, 934,1336,1882,7548,7549,2118,4139, # 4886 -2828, 743,1569,7550,4402,4140, 582,2384,1418,3437,7551,1802,7552, 357,1395,1729, # 4902 -3651,3268,2418,1564,2237,7553,3083,3772,1633,4403,1114,2085,4141,1532,7554, 482, # 4918 -2446,4404,7555,7556,1492, 833,1466,7557,2717,3544,1641,2829,7558,1526,1272,3652, # 4934 -4142,1686,1794, 416,2556,1902,1953,1803,7559,3773,2785,3774,1159,2316,7560,2867, # 4950 -4405,1610,1584,3036,2419,2754, 443,3269,1163,3136,7561,7562,3926,7563,4143,2499, # 4966 -3037,4406,3927,3137,2103,1647,3545,2010,1872,4144,7564,4145, 431,3438,7565, 250, # 4982 - 97, 81,4146,7566,1648,1850,1558, 160, 848,7567, 866, 740,1694,7568,2201,2830, # 4998 -3195,4147,4407,3653,1687, 950,2472, 426, 469,3196,3654,3655,3928,7569,7570,1188, # 5014 - 424,1995, 861,3546,4148,3775,2202,2685, 168,1235,3547,4149,7571,2086,1674,4408, # 5030 -3337,3270, 220,2557,1009,7572,3776, 670,2992, 332,1208, 717,7573,7574,3548,2447, # 5046 -3929,3338,7575, 513,7576,1209,2868,3339,3138,4409,1080,7577,7578,7579,7580,2527, # 5062 -3656,3549, 815,1587,3930,3931,7581,3550,3439,3777,1254,4410,1328,3038,1390,3932, # 5078 -1741,3933,3778,3934,7582, 236,3779,2448,3271,7583,7584,3657,3780,1273,3781,4411, # 5094 -7585, 308,7586,4412, 245,4413,1851,2473,1307,2575, 430, 715,2136,2449,7587, 270, # 5110 - 199,2869,3935,7588,3551,2718,1753, 761,1754, 725,1661,1840,4414,3440,3658,7589, # 5126 -7590, 587, 14,3272, 227,2598, 326, 480,2265, 943,2755,3552, 291, 650,1883,7591, # 5142 -1702,1226, 102,1547, 62,3441, 904,4415,3442,1164,4150,7592,7593,1224,1548,2756, # 5158 - 391, 498,1493,7594,1386,1419,7595,2055,1177,4416, 813, 880,1081,2363, 566,1145, # 5174 -4417,2286,1001,1035,2558,2599,2238, 394,1286,7596,7597,2068,7598, 86,1494,1730, # 5190 -3936, 491,1588, 745, 897,2948, 843,3340,3937,2757,2870,3273,1768, 998,2217,2069, # 5206 - 397,1826,1195,1969,3659,2993,3341, 284,7599,3782,2500,2137,2119,1903,7600,3938, # 5222 -2150,3939,4151,1036,3443,1904, 114,2559,4152, 209,1527,7601,7602,2949,2831,2625, # 5238 -2385,2719,3139, 812,2560,7603,3274,7604,1559, 737,1884,3660,1210, 885, 28,2686, # 5254 -3553,3783,7605,4153,1004,1779,4418,7606, 346,1981,2218,2687,4419,3784,1742, 797, # 5270 -1642,3940,1933,1072,1384,2151, 896,3941,3275,3661,3197,2871,3554,7607,2561,1958, # 5286 -4420,2450,1785,7608,7609,7610,3942,4154,1005,1308,3662,4155,2720,4421,4422,1528, # 5302 -2600, 161,1178,4156,1982, 987,4423,1101,4157, 631,3943,1157,3198,2420,1343,1241, # 5318 -1016,2239,2562, 372, 877,2339,2501,1160, 555,1934, 911,3944,7611, 466,1170, 169, # 5334 -1051,2907,2688,3663,2474,2994,1182,2011,2563,1251,2626,7612, 992,2340,3444,1540, # 5350 -2721,1201,2070,2401,1996,2475,7613,4424, 528,1922,2188,1503,1873,1570,2364,3342, # 5366 -3276,7614, 557,1073,7615,1827,3445,2087,2266,3140,3039,3084, 767,3085,2786,4425, # 5382 -1006,4158,4426,2341,1267,2176,3664,3199, 778,3945,3200,2722,1597,2657,7616,4427, # 5398 -7617,3446,7618,7619,7620,3277,2689,1433,3278, 131, 95,1504,3946, 723,4159,3141, # 5414 -1841,3555,2758,2189,3947,2027,2104,3665,7621,2995,3948,1218,7622,3343,3201,3949, # 5430 -4160,2576, 248,1634,3785, 912,7623,2832,3666,3040,3786, 654, 53,7624,2996,7625, # 5446 -1688,4428, 777,3447,1032,3950,1425,7626, 191, 820,2120,2833, 971,4429, 931,3202, # 5462 - 135, 664, 783,3787,1997, 772,2908,1935,3951,3788,4430,2909,3203, 282,2723, 640, # 5478 -1372,3448,1127, 922, 325,3344,7627,7628, 711,2044,7629,7630,3952,2219,2787,1936, # 5494 -3953,3345,2220,2251,3789,2300,7631,4431,3790,1258,3279,3954,3204,2138,2950,3955, # 5510 -3956,7632,2221, 258,3205,4432, 101,1227,7633,3280,1755,7634,1391,3281,7635,2910, # 5526 -2056, 893,7636,7637,7638,1402,4161,2342,7639,7640,3206,3556,7641,7642, 878,1325, # 5542 -1780,2788,4433, 259,1385,2577, 744,1183,2267,4434,7643,3957,2502,7644, 684,1024, # 5558 -4162,7645, 472,3557,3449,1165,3282,3958,3959, 322,2152, 881, 455,1695,1152,1340, # 5574 - 660, 554,2153,4435,1058,4436,4163, 830,1065,3346,3960,4437,1923,7646,1703,1918, # 5590 -7647, 932,2268, 122,7648,4438, 947, 677,7649,3791,2627, 297,1905,1924,2269,4439, # 5606 -2317,3283,7650,7651,4164,7652,4165, 84,4166, 112, 989,7653, 547,1059,3961, 701, # 5622 -3558,1019,7654,4167,7655,3450, 942, 639, 457,2301,2451, 993,2951, 407, 851, 494, # 5638 -4440,3347, 927,7656,1237,7657,2421,3348, 573,4168, 680, 921,2911,1279,1874, 285, # 5654 - 790,1448,1983, 719,2167,7658,7659,4441,3962,3963,1649,7660,1541, 563,7661,1077, # 5670 -7662,3349,3041,3451, 511,2997,3964,3965,3667,3966,1268,2564,3350,3207,4442,4443, # 5686 -7663, 535,1048,1276,1189,2912,2028,3142,1438,1373,2834,2952,1134,2012,7664,4169, # 5702 -1238,2578,3086,1259,7665, 700,7666,2953,3143,3668,4170,7667,4171,1146,1875,1906, # 5718 -4444,2601,3967, 781,2422, 132,1589, 203, 147, 273,2789,2402, 898,1786,2154,3968, # 5734 -3969,7668,3792,2790,7669,7670,4445,4446,7671,3208,7672,1635,3793, 965,7673,1804, # 5750 -2690,1516,3559,1121,1082,1329,3284,3970,1449,3794, 65,1128,2835,2913,2759,1590, # 5766 -3795,7674,7675, 12,2658, 45, 976,2579,3144,4447, 517,2528,1013,1037,3209,7676, # 5782 -3796,2836,7677,3797,7678,3452,7679,2602, 614,1998,2318,3798,3087,2724,2628,7680, # 5798 -2580,4172, 599,1269,7681,1810,3669,7682,2691,3088, 759,1060, 489,1805,3351,3285, # 5814 -1358,7683,7684,2386,1387,1215,2629,2252, 490,7685,7686,4173,1759,2387,2343,7687, # 5830 -4448,3799,1907,3971,2630,1806,3210,4449,3453,3286,2760,2344, 874,7688,7689,3454, # 5846 -3670,1858, 91,2914,3671,3042,3800,4450,7690,3145,3972,2659,7691,3455,1202,1403, # 5862 -3801,2954,2529,1517,2503,4451,3456,2504,7692,4452,7693,2692,1885,1495,1731,3973, # 5878 -2365,4453,7694,2029,7695,7696,3974,2693,1216, 237,2581,4174,2319,3975,3802,4454, # 5894 -4455,2694,3560,3457, 445,4456,7697,7698,7699,7700,2761, 61,3976,3672,1822,3977, # 5910 -7701, 687,2045, 935, 925, 405,2660, 703,1096,1859,2725,4457,3978,1876,1367,2695, # 5926 -3352, 918,2105,1781,2476, 334,3287,1611,1093,4458, 564,3146,3458,3673,3353, 945, # 5942 -2631,2057,4459,7702,1925, 872,4175,7703,3459,2696,3089, 349,4176,3674,3979,4460, # 5958 -3803,4177,3675,2155,3980,4461,4462,4178,4463,2403,2046, 782,3981, 400, 251,4179, # 5974 -1624,7704,7705, 277,3676, 299,1265, 476,1191,3804,2121,4180,4181,1109, 205,7706, # 5990 -2582,1000,2156,3561,1860,7707,7708,7709,4464,7710,4465,2565, 107,2477,2157,3982, # 6006 -3460,3147,7711,1533, 541,1301, 158, 753,4182,2872,3562,7712,1696, 370,1088,4183, # 6022 -4466,3563, 579, 327, 440, 162,2240, 269,1937,1374,3461, 968,3043, 56,1396,3090, # 6038 -2106,3288,3354,7713,1926,2158,4467,2998,7714,3564,7715,7716,3677,4468,2478,7717, # 6054 -2791,7718,1650,4469,7719,2603,7720,7721,3983,2661,3355,1149,3356,3984,3805,3985, # 6070 -7722,1076, 49,7723, 951,3211,3289,3290, 450,2837, 920,7724,1811,2792,2366,4184, # 6086 -1908,1138,2367,3806,3462,7725,3212,4470,1909,1147,1518,2423,4471,3807,7726,4472, # 6102 -2388,2604, 260,1795,3213,7727,7728,3808,3291, 708,7729,3565,1704,7730,3566,1351, # 6118 -1618,3357,2999,1886, 944,4185,3358,4186,3044,3359,4187,7731,3678, 422, 413,1714, # 6134 -3292, 500,2058,2345,4188,2479,7732,1344,1910, 954,7733,1668,7734,7735,3986,2404, # 6150 -4189,3567,3809,4190,7736,2302,1318,2505,3091, 133,3092,2873,4473, 629, 31,2838, # 6166 -2697,3810,4474, 850, 949,4475,3987,2955,1732,2088,4191,1496,1852,7737,3988, 620, # 6182 -3214, 981,1242,3679,3360,1619,3680,1643,3293,2139,2452,1970,1719,3463,2168,7738, # 6198 -3215,7739,7740,3361,1828,7741,1277,4476,1565,2047,7742,1636,3568,3093,7743, 869, # 6214 -2839, 655,3811,3812,3094,3989,3000,3813,1310,3569,4477,7744,7745,7746,1733, 558, # 6230 -4478,3681, 335,1549,3045,1756,4192,3682,1945,3464,1829,1291,1192, 470,2726,2107, # 6246 -2793, 913,1054,3990,7747,1027,7748,3046,3991,4479, 982,2662,3362,3148,3465,3216, # 6262 -3217,1946,2794,7749, 571,4480,7750,1830,7751,3570,2583,1523,2424,7752,2089, 984, # 6278 -4481,3683,1959,7753,3684, 852, 923,2795,3466,3685, 969,1519, 999,2048,2320,1705, # 6294 -7754,3095, 615,1662, 151, 597,3992,2405,2321,1049, 275,4482,3686,4193, 568,3687, # 6310 -3571,2480,4194,3688,7755,2425,2270, 409,3218,7756,1566,2874,3467,1002, 769,2840, # 6326 - 194,2090,3149,3689,2222,3294,4195, 628,1505,7757,7758,1763,2177,3001,3993, 521, # 6342 -1161,2584,1787,2203,2406,4483,3994,1625,4196,4197, 412, 42,3096, 464,7759,2632, # 6358 -4484,3363,1760,1571,2875,3468,2530,1219,2204,3814,2633,2140,2368,4485,4486,3295, # 6374 -1651,3364,3572,7760,7761,3573,2481,3469,7762,3690,7763,7764,2271,2091, 460,7765, # 6390 -4487,7766,3002, 962, 588,3574, 289,3219,2634,1116, 52,7767,3047,1796,7768,7769, # 6406 -7770,1467,7771,1598,1143,3691,4198,1984,1734,1067,4488,1280,3365, 465,4489,1572, # 6422 - 510,7772,1927,2241,1812,1644,3575,7773,4490,3692,7774,7775,2663,1573,1534,7776, # 6438 -7777,4199, 536,1807,1761,3470,3815,3150,2635,7778,7779,7780,4491,3471,2915,1911, # 6454 -2796,7781,3296,1122, 377,3220,7782, 360,7783,7784,4200,1529, 551,7785,2059,3693, # 6470 -1769,2426,7786,2916,4201,3297,3097,2322,2108,2030,4492,1404, 136,1468,1479, 672, # 6486 -1171,3221,2303, 271,3151,7787,2762,7788,2049, 678,2727, 865,1947,4493,7789,2013, # 6502 -3995,2956,7790,2728,2223,1397,3048,3694,4494,4495,1735,2917,3366,3576,7791,3816, # 6518 - 509,2841,2453,2876,3817,7792,7793,3152,3153,4496,4202,2531,4497,2304,1166,1010, # 6534 - 552, 681,1887,7794,7795,2957,2958,3996,1287,1596,1861,3154, 358, 453, 736, 175, # 6550 - 478,1117, 905,1167,1097,7796,1853,1530,7797,1706,7798,2178,3472,2287,3695,3473, # 6566 -3577,4203,2092,4204,7799,3367,1193,2482,4205,1458,2190,2205,1862,1888,1421,3298, # 6582 -2918,3049,2179,3474, 595,2122,7800,3997,7801,7802,4206,1707,2636, 223,3696,1359, # 6598 - 751,3098, 183,3475,7803,2797,3003, 419,2369, 633, 704,3818,2389, 241,7804,7805, # 6614 -7806, 838,3004,3697,2272,2763,2454,3819,1938,2050,3998,1309,3099,2242,1181,7807, # 6630 -1136,2206,3820,2370,1446,4207,2305,4498,7808,7809,4208,1055,2605, 484,3698,7810, # 6646 -3999, 625,4209,2273,3368,1499,4210,4000,7811,4001,4211,3222,2274,2275,3476,7812, # 6662 -7813,2764, 808,2606,3699,3369,4002,4212,3100,2532, 526,3370,3821,4213, 955,7814, # 6678 -1620,4214,2637,2427,7815,1429,3700,1669,1831, 994, 928,7816,3578,1260,7817,7818, # 6694 -7819,1948,2288, 741,2919,1626,4215,2729,2455, 867,1184, 362,3371,1392,7820,7821, # 6710 -4003,4216,1770,1736,3223,2920,4499,4500,1928,2698,1459,1158,7822,3050,3372,2877, # 6726 -1292,1929,2506,2842,3701,1985,1187,2071,2014,2607,4217,7823,2566,2507,2169,3702, # 6742 -2483,3299,7824,3703,4501,7825,7826, 666,1003,3005,1022,3579,4218,7827,4502,1813, # 6758 -2253, 574,3822,1603, 295,1535, 705,3823,4219, 283, 858, 417,7828,7829,3224,4503, # 6774 -4504,3051,1220,1889,1046,2276,2456,4004,1393,1599, 689,2567, 388,4220,7830,2484, # 6790 - 802,7831,2798,3824,2060,1405,2254,7832,4505,3825,2109,1052,1345,3225,1585,7833, # 6806 - 809,7834,7835,7836, 575,2730,3477, 956,1552,1469,1144,2323,7837,2324,1560,2457, # 6822 -3580,3226,4005, 616,2207,3155,2180,2289,7838,1832,7839,3478,4506,7840,1319,3704, # 6838 -3705,1211,3581,1023,3227,1293,2799,7841,7842,7843,3826, 607,2306,3827, 762,2878, # 6854 -1439,4221,1360,7844,1485,3052,7845,4507,1038,4222,1450,2061,2638,4223,1379,4508, # 6870 -2585,7846,7847,4224,1352,1414,2325,2921,1172,7848,7849,3828,3829,7850,1797,1451, # 6886 -7851,7852,7853,7854,2922,4006,4007,2485,2346, 411,4008,4009,3582,3300,3101,4509, # 6902 -1561,2664,1452,4010,1375,7855,7856, 47,2959, 316,7857,1406,1591,2923,3156,7858, # 6918 -1025,2141,3102,3157, 354,2731, 884,2224,4225,2407, 508,3706, 726,3583, 996,2428, # 6934 -3584, 729,7859, 392,2191,1453,4011,4510,3707,7860,7861,2458,3585,2608,1675,2800, # 6950 - 919,2347,2960,2348,1270,4511,4012, 73,7862,7863, 647,7864,3228,2843,2255,1550, # 6966 -1346,3006,7865,1332, 883,3479,7866,7867,7868,7869,3301,2765,7870,1212, 831,1347, # 6982 -4226,4512,2326,3830,1863,3053, 720,3831,4513,4514,3832,7871,4227,7872,7873,4515, # 6998 -7874,7875,1798,4516,3708,2609,4517,3586,1645,2371,7876,7877,2924, 669,2208,2665, # 7014 -2429,7878,2879,7879,7880,1028,3229,7881,4228,2408,7882,2256,1353,7883,7884,4518, # 7030 -3158, 518,7885,4013,7886,4229,1960,7887,2142,4230,7888,7889,3007,2349,2350,3833, # 7046 - 516,1833,1454,4014,2699,4231,4519,2225,2610,1971,1129,3587,7890,2766,7891,2961, # 7062 -1422, 577,1470,3008,1524,3373,7892,7893, 432,4232,3054,3480,7894,2586,1455,2508, # 7078 -2226,1972,1175,7895,1020,2732,4015,3481,4520,7896,2733,7897,1743,1361,3055,3482, # 7094 -2639,4016,4233,4521,2290, 895, 924,4234,2170, 331,2243,3056, 166,1627,3057,1098, # 7110 -7898,1232,2880,2227,3374,4522, 657, 403,1196,2372, 542,3709,3375,1600,4235,3483, # 7126 -7899,4523,2767,3230, 576, 530,1362,7900,4524,2533,2666,3710,4017,7901, 842,3834, # 7142 -7902,2801,2031,1014,4018, 213,2700,3376, 665, 621,4236,7903,3711,2925,2430,7904, # 7158 -2431,3302,3588,3377,7905,4237,2534,4238,4525,3589,1682,4239,3484,1380,7906, 724, # 7174 -2277, 600,1670,7907,1337,1233,4526,3103,2244,7908,1621,4527,7909, 651,4240,7910, # 7190 -1612,4241,2611,7911,2844,7912,2734,2307,3058,7913, 716,2459,3059, 174,1255,2701, # 7206 -4019,3590, 548,1320,1398, 728,4020,1574,7914,1890,1197,3060,4021,7915,3061,3062, # 7222 -3712,3591,3713, 747,7916, 635,4242,4528,7917,7918,7919,4243,7920,7921,4529,7922, # 7238 -3378,4530,2432, 451,7923,3714,2535,2072,4244,2735,4245,4022,7924,1764,4531,7925, # 7254 -4246, 350,7926,2278,2390,2486,7927,4247,4023,2245,1434,4024, 488,4532, 458,4248, # 7270 -4025,3715, 771,1330,2391,3835,2568,3159,2159,2409,1553,2667,3160,4249,7928,2487, # 7286 -2881,2612,1720,2702,4250,3379,4533,7929,2536,4251,7930,3231,4252,2768,7931,2015, # 7302 -2736,7932,1155,1017,3716,3836,7933,3303,2308, 201,1864,4253,1430,7934,4026,7935, # 7318 -7936,7937,7938,7939,4254,1604,7940, 414,1865, 371,2587,4534,4535,3485,2016,3104, # 7334 -4536,1708, 960,4255, 887, 389,2171,1536,1663,1721,7941,2228,4027,2351,2926,1580, # 7350 -7942,7943,7944,1744,7945,2537,4537,4538,7946,4539,7947,2073,7948,7949,3592,3380, # 7366 -2882,4256,7950,4257,2640,3381,2802, 673,2703,2460, 709,3486,4028,3593,4258,7951, # 7382 -1148, 502, 634,7952,7953,1204,4540,3594,1575,4541,2613,3717,7954,3718,3105, 948, # 7398 -3232, 121,1745,3837,1110,7955,4259,3063,2509,3009,4029,3719,1151,1771,3838,1488, # 7414 -4030,1986,7956,2433,3487,7957,7958,2093,7959,4260,3839,1213,1407,2803, 531,2737, # 7430 -2538,3233,1011,1537,7960,2769,4261,3106,1061,7961,3720,3721,1866,2883,7962,2017, # 7446 - 120,4262,4263,2062,3595,3234,2309,3840,2668,3382,1954,4542,7963,7964,3488,1047, # 7462 -2704,1266,7965,1368,4543,2845, 649,3383,3841,2539,2738,1102,2846,2669,7966,7967, # 7478 -1999,7968,1111,3596,2962,7969,2488,3842,3597,2804,1854,3384,3722,7970,7971,3385, # 7494 -2410,2884,3304,3235,3598,7972,2569,7973,3599,2805,4031,1460, 856,7974,3600,7975, # 7510 -2885,2963,7976,2886,3843,7977,4264, 632,2510, 875,3844,1697,3845,2291,7978,7979, # 7526 -4544,3010,1239, 580,4545,4265,7980, 914, 936,2074,1190,4032,1039,2123,7981,7982, # 7542 -7983,3386,1473,7984,1354,4266,3846,7985,2172,3064,4033, 915,3305,4267,4268,3306, # 7558 -1605,1834,7986,2739, 398,3601,4269,3847,4034, 328,1912,2847,4035,3848,1331,4270, # 7574 -3011, 937,4271,7987,3602,4036,4037,3387,2160,4546,3388, 524, 742, 538,3065,1012, # 7590 -7988,7989,3849,2461,7990, 658,1103, 225,3850,7991,7992,4547,7993,4548,7994,3236, # 7606 -1243,7995,4038, 963,2246,4549,7996,2705,3603,3161,7997,7998,2588,2327,7999,4550, # 7622 -8000,8001,8002,3489,3307, 957,3389,2540,2032,1930,2927,2462, 870,2018,3604,1746, # 7638 -2770,2771,2434,2463,8003,3851,8004,3723,3107,3724,3490,3390,3725,8005,1179,3066, # 7654 -8006,3162,2373,4272,3726,2541,3163,3108,2740,4039,8007,3391,1556,2542,2292, 977, # 7670 -2887,2033,4040,1205,3392,8008,1765,3393,3164,2124,1271,1689, 714,4551,3491,8009, # 7686 -2328,3852, 533,4273,3605,2181, 617,8010,2464,3308,3492,2310,8011,8012,3165,8013, # 7702 -8014,3853,1987, 618, 427,2641,3493,3394,8015,8016,1244,1690,8017,2806,4274,4552, # 7718 -8018,3494,8019,8020,2279,1576, 473,3606,4275,3395, 972,8021,3607,8022,3067,8023, # 7734 -8024,4553,4554,8025,3727,4041,4042,8026, 153,4555, 356,8027,1891,2888,4276,2143, # 7750 - 408, 803,2352,8028,3854,8029,4277,1646,2570,2511,4556,4557,3855,8030,3856,4278, # 7766 -8031,2411,3396, 752,8032,8033,1961,2964,8034, 746,3012,2465,8035,4279,3728, 698, # 7782 -4558,1892,4280,3608,2543,4559,3609,3857,8036,3166,3397,8037,1823,1302,4043,2706, # 7798 -3858,1973,4281,8038,4282,3167, 823,1303,1288,1236,2848,3495,4044,3398, 774,3859, # 7814 -8039,1581,4560,1304,2849,3860,4561,8040,2435,2161,1083,3237,4283,4045,4284, 344, # 7830 -1173, 288,2311, 454,1683,8041,8042,1461,4562,4046,2589,8043,8044,4563, 985, 894, # 7846 -8045,3399,3168,8046,1913,2928,3729,1988,8047,2110,1974,8048,4047,8049,2571,1194, # 7862 - 425,8050,4564,3169,1245,3730,4285,8051,8052,2850,8053, 636,4565,1855,3861, 760, # 7878 -1799,8054,4286,2209,1508,4566,4048,1893,1684,2293,8055,8056,8057,4287,4288,2210, # 7894 - 479,8058,8059, 832,8060,4049,2489,8061,2965,2490,3731, 990,3109, 627,1814,2642, # 7910 -4289,1582,4290,2125,2111,3496,4567,8062, 799,4291,3170,8063,4568,2112,1737,3013, # 7926 -1018, 543, 754,4292,3309,1676,4569,4570,4050,8064,1489,8065,3497,8066,2614,2889, # 7942 -4051,8067,8068,2966,8069,8070,8071,8072,3171,4571,4572,2182,1722,8073,3238,3239, # 7958 -1842,3610,1715, 481, 365,1975,1856,8074,8075,1962,2491,4573,8076,2126,3611,3240, # 7974 - 433,1894,2063,2075,8077, 602,2741,8078,8079,8080,8081,8082,3014,1628,3400,8083, # 7990 -3172,4574,4052,2890,4575,2512,8084,2544,2772,8085,8086,8087,3310,4576,2891,8088, # 8006 -4577,8089,2851,4578,4579,1221,2967,4053,2513,8090,8091,8092,1867,1989,8093,8094, # 8022 -8095,1895,8096,8097,4580,1896,4054, 318,8098,2094,4055,4293,8099,8100, 485,8101, # 8038 - 938,3862, 553,2670, 116,8102,3863,3612,8103,3498,2671,2773,3401,3311,2807,8104, # 8054 -3613,2929,4056,1747,2930,2968,8105,8106, 207,8107,8108,2672,4581,2514,8109,3015, # 8070 - 890,3614,3864,8110,1877,3732,3402,8111,2183,2353,3403,1652,8112,8113,8114, 941, # 8086 -2294, 208,3499,4057,2019, 330,4294,3865,2892,2492,3733,4295,8115,8116,8117,8118, # 8102 -) - diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/euctwprober.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/euctwprober.py deleted file mode 100644 index 35669cc..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/euctwprober.py +++ /dev/null @@ -1,46 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is mozilla.org code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .mbcharsetprober import MultiByteCharSetProber -from .codingstatemachine import CodingStateMachine -from .chardistribution import EUCTWDistributionAnalysis -from .mbcssm import EUCTW_SM_MODEL - -class EUCTWProber(MultiByteCharSetProber): - def __init__(self): - super(EUCTWProber, self).__init__() - self.coding_sm = CodingStateMachine(EUCTW_SM_MODEL) - self.distribution_analyzer = EUCTWDistributionAnalysis() - self.reset() - - @property - def charset_name(self): - return "EUC-TW" - - @property - def language(self): - return "Taiwan" diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/gb2312freq.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/gb2312freq.py deleted file mode 100644 index 697837b..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/gb2312freq.py +++ /dev/null @@ -1,283 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -# GB2312 most frequently used character table -# -# Char to FreqOrder table , from hz6763 - -# 512 --> 0.79 -- 0.79 -# 1024 --> 0.92 -- 0.13 -# 2048 --> 0.98 -- 0.06 -# 6768 --> 1.00 -- 0.02 -# -# Ideal Distribution Ratio = 0.79135/(1-0.79135) = 3.79 -# Random Distribution Ration = 512 / (3755 - 512) = 0.157 -# -# Typical Distribution Ratio about 25% of Ideal one, still much higher that RDR - -GB2312_TYPICAL_DISTRIBUTION_RATIO = 0.9 - -GB2312_TABLE_SIZE = 3760 - -GB2312_CHAR_TO_FREQ_ORDER = ( -1671, 749,1443,2364,3924,3807,2330,3921,1704,3463,2691,1511,1515, 572,3191,2205, -2361, 224,2558, 479,1711, 963,3162, 440,4060,1905,2966,2947,3580,2647,3961,3842, -2204, 869,4207, 970,2678,5626,2944,2956,1479,4048, 514,3595, 588,1346,2820,3409, - 249,4088,1746,1873,2047,1774, 581,1813, 358,1174,3590,1014,1561,4844,2245, 670, -1636,3112, 889,1286, 953, 556,2327,3060,1290,3141, 613, 185,3477,1367, 850,3820, -1715,2428,2642,2303,2732,3041,2562,2648,3566,3946,1349, 388,3098,2091,1360,3585, - 152,1687,1539, 738,1559, 59,1232,2925,2267,1388,1249,1741,1679,2960, 151,1566, -1125,1352,4271, 924,4296, 385,3166,4459, 310,1245,2850, 70,3285,2729,3534,3575, -2398,3298,3466,1960,2265, 217,3647, 864,1909,2084,4401,2773,1010,3269,5152, 853, -3051,3121,1244,4251,1895, 364,1499,1540,2313,1180,3655,2268, 562, 715,2417,3061, - 544, 336,3768,2380,1752,4075, 950, 280,2425,4382, 183,2759,3272, 333,4297,2155, -1688,2356,1444,1039,4540, 736,1177,3349,2443,2368,2144,2225, 565, 196,1482,3406, - 927,1335,4147, 692, 878,1311,1653,3911,3622,1378,4200,1840,2969,3149,2126,1816, -2534,1546,2393,2760, 737,2494, 13, 447, 245,2747, 38,2765,2129,2589,1079, 606, - 360, 471,3755,2890, 404, 848, 699,1785,1236, 370,2221,1023,3746,2074,2026,2023, -2388,1581,2119, 812,1141,3091,2536,1519, 804,2053, 406,1596,1090, 784, 548,4414, -1806,2264,2936,1100, 343,4114,5096, 622,3358, 743,3668,1510,1626,5020,3567,2513, -3195,4115,5627,2489,2991, 24,2065,2697,1087,2719, 48,1634, 315, 68, 985,2052, - 198,2239,1347,1107,1439, 597,2366,2172, 871,3307, 919,2487,2790,1867, 236,2570, -1413,3794, 906,3365,3381,1701,1982,1818,1524,2924,1205, 616,2586,2072,2004, 575, - 253,3099, 32,1365,1182, 197,1714,2454,1201, 554,3388,3224,2748, 756,2587, 250, -2567,1507,1517,3529,1922,2761,2337,3416,1961,1677,2452,2238,3153, 615, 911,1506, -1474,2495,1265,1906,2749,3756,3280,2161, 898,2714,1759,3450,2243,2444, 563, 26, -3286,2266,3769,3344,2707,3677, 611,1402, 531,1028,2871,4548,1375, 261,2948, 835, -1190,4134, 353, 840,2684,1900,3082,1435,2109,1207,1674, 329,1872,2781,4055,2686, -2104, 608,3318,2423,2957,2768,1108,3739,3512,3271,3985,2203,1771,3520,1418,2054, -1681,1153, 225,1627,2929, 162,2050,2511,3687,1954, 124,1859,2431,1684,3032,2894, - 585,4805,3969,2869,2704,2088,2032,2095,3656,2635,4362,2209, 256, 518,2042,2105, -3777,3657, 643,2298,1148,1779, 190, 989,3544, 414, 11,2135,2063,2979,1471, 403, -3678, 126, 770,1563, 671,2499,3216,2877, 600,1179, 307,2805,4937,1268,1297,2694, - 252,4032,1448,1494,1331,1394, 127,2256, 222,1647,1035,1481,3056,1915,1048, 873, -3651, 210, 33,1608,2516, 200,1520, 415, 102, 0,3389,1287, 817, 91,3299,2940, - 836,1814, 549,2197,1396,1669,2987,3582,2297,2848,4528,1070, 687, 20,1819, 121, -1552,1364,1461,1968,2617,3540,2824,2083, 177, 948,4938,2291, 110,4549,2066, 648, -3359,1755,2110,2114,4642,4845,1693,3937,3308,1257,1869,2123, 208,1804,3159,2992, -2531,2549,3361,2418,1350,2347,2800,2568,1291,2036,2680, 72, 842,1990, 212,1233, -1154,1586, 75,2027,3410,4900,1823,1337,2710,2676, 728,2810,1522,3026,4995, 157, - 755,1050,4022, 710, 785,1936,2194,2085,1406,2777,2400, 150,1250,4049,1206, 807, -1910, 534, 529,3309,1721,1660, 274, 39,2827, 661,2670,1578, 925,3248,3815,1094, -4278,4901,4252, 41,1150,3747,2572,2227,4501,3658,4902,3813,3357,3617,2884,2258, - 887, 538,4187,3199,1294,2439,3042,2329,2343,2497,1255, 107, 543,1527, 521,3478, -3568, 194,5062, 15, 961,3870,1241,1192,2664, 66,5215,3260,2111,1295,1127,2152, -3805,4135, 901,1164,1976, 398,1278, 530,1460, 748, 904,1054,1966,1426, 53,2909, - 509, 523,2279,1534, 536,1019, 239,1685, 460,2353, 673,1065,2401,3600,4298,2272, -1272,2363, 284,1753,3679,4064,1695, 81, 815,2677,2757,2731,1386, 859, 500,4221, -2190,2566, 757,1006,2519,2068,1166,1455, 337,2654,3203,1863,1682,1914,3025,1252, -1409,1366, 847, 714,2834,2038,3209, 964,2970,1901, 885,2553,1078,1756,3049, 301, -1572,3326, 688,2130,1996,2429,1805,1648,2930,3421,2750,3652,3088, 262,1158,1254, - 389,1641,1812, 526,1719, 923,2073,1073,1902, 468, 489,4625,1140, 857,2375,3070, -3319,2863, 380, 116,1328,2693,1161,2244, 273,1212,1884,2769,3011,1775,1142, 461, -3066,1200,2147,2212, 790, 702,2695,4222,1601,1058, 434,2338,5153,3640, 67,2360, -4099,2502, 618,3472,1329, 416,1132, 830,2782,1807,2653,3211,3510,1662, 192,2124, - 296,3979,1739,1611,3684, 23, 118, 324, 446,1239,1225, 293,2520,3814,3795,2535, -3116, 17,1074, 467,2692,2201, 387,2922, 45,1326,3055,1645,3659,2817, 958, 243, -1903,2320,1339,2825,1784,3289, 356, 576, 865,2315,2381,3377,3916,1088,3122,1713, -1655, 935, 628,4689,1034,1327, 441, 800, 720, 894,1979,2183,1528,5289,2702,1071, -4046,3572,2399,1571,3281, 79, 761,1103, 327, 134, 758,1899,1371,1615, 879, 442, - 215,2605,2579, 173,2048,2485,1057,2975,3317,1097,2253,3801,4263,1403,1650,2946, - 814,4968,3487,1548,2644,1567,1285, 2, 295,2636, 97, 946,3576, 832, 141,4257, -3273, 760,3821,3521,3156,2607, 949,1024,1733,1516,1803,1920,2125,2283,2665,3180, -1501,2064,3560,2171,1592, 803,3518,1416, 732,3897,4258,1363,1362,2458, 119,1427, - 602,1525,2608,1605,1639,3175, 694,3064, 10, 465, 76,2000,4846,4208, 444,3781, -1619,3353,2206,1273,3796, 740,2483, 320,1723,2377,3660,2619,1359,1137,1762,1724, -2345,2842,1850,1862, 912, 821,1866, 612,2625,1735,2573,3369,1093, 844, 89, 937, - 930,1424,3564,2413,2972,1004,3046,3019,2011, 711,3171,1452,4178, 428, 801,1943, - 432, 445,2811, 206,4136,1472, 730, 349, 73, 397,2802,2547, 998,1637,1167, 789, - 396,3217, 154,1218, 716,1120,1780,2819,4826,1931,3334,3762,2139,1215,2627, 552, -3664,3628,3232,1405,2383,3111,1356,2652,3577,3320,3101,1703, 640,1045,1370,1246, -4996, 371,1575,2436,1621,2210, 984,4033,1734,2638, 16,4529, 663,2755,3255,1451, -3917,2257,1253,1955,2234,1263,2951, 214,1229, 617, 485, 359,1831,1969, 473,2310, - 750,2058, 165, 80,2864,2419, 361,4344,2416,2479,1134, 796,3726,1266,2943, 860, -2715, 938, 390,2734,1313,1384, 248, 202, 877,1064,2854, 522,3907, 279,1602, 297, -2357, 395,3740, 137,2075, 944,4089,2584,1267,3802, 62,1533,2285, 178, 176, 780, -2440, 201,3707, 590, 478,1560,4354,2117,1075, 30, 74,4643,4004,1635,1441,2745, - 776,2596, 238,1077,1692,1912,2844, 605, 499,1742,3947, 241,3053, 980,1749, 936, -2640,4511,2582, 515,1543,2162,5322,2892,2993, 890,2148,1924, 665,1827,3581,1032, - 968,3163, 339,1044,1896, 270, 583,1791,1720,4367,1194,3488,3669, 43,2523,1657, - 163,2167, 290,1209,1622,3378, 550, 634,2508,2510, 695,2634,2384,2512,1476,1414, - 220,1469,2341,2138,2852,3183,2900,4939,2865,3502,1211,3680, 854,3227,1299,2976, -3172, 186,2998,1459, 443,1067,3251,1495, 321,1932,3054, 909, 753,1410,1828, 436, -2441,1119,1587,3164,2186,1258, 227, 231,1425,1890,3200,3942, 247, 959, 725,5254, -2741, 577,2158,2079, 929, 120, 174, 838,2813, 591,1115, 417,2024, 40,3240,1536, -1037, 291,4151,2354, 632,1298,2406,2500,3535,1825,1846,3451, 205,1171, 345,4238, - 18,1163, 811, 685,2208,1217, 425,1312,1508,1175,4308,2552,1033, 587,1381,3059, -2984,3482, 340,1316,4023,3972, 792,3176, 519, 777,4690, 918, 933,4130,2981,3741, - 90,3360,2911,2200,5184,4550, 609,3079,2030, 272,3379,2736, 363,3881,1130,1447, - 286, 779, 357,1169,3350,3137,1630,1220,2687,2391, 747,1277,3688,2618,2682,2601, -1156,3196,5290,4034,3102,1689,3596,3128, 874, 219,2783, 798, 508,1843,2461, 269, -1658,1776,1392,1913,2983,3287,2866,2159,2372, 829,4076, 46,4253,2873,1889,1894, - 915,1834,1631,2181,2318, 298, 664,2818,3555,2735, 954,3228,3117, 527,3511,2173, - 681,2712,3033,2247,2346,3467,1652, 155,2164,3382, 113,1994, 450, 899, 494, 994, -1237,2958,1875,2336,1926,3727, 545,1577,1550, 633,3473, 204,1305,3072,2410,1956, -2471, 707,2134, 841,2195,2196,2663,3843,1026,4940, 990,3252,4997, 368,1092, 437, -3212,3258,1933,1829, 675,2977,2893, 412, 943,3723,4644,3294,3283,2230,2373,5154, -2389,2241,2661,2323,1404,2524, 593, 787, 677,3008,1275,2059, 438,2709,2609,2240, -2269,2246,1446, 36,1568,1373,3892,1574,2301,1456,3962, 693,2276,5216,2035,1143, -2720,1919,1797,1811,2763,4137,2597,1830,1699,1488,1198,2090, 424,1694, 312,3634, -3390,4179,3335,2252,1214, 561,1059,3243,2295,2561, 975,5155,2321,2751,3772, 472, -1537,3282,3398,1047,2077,2348,2878,1323,3340,3076, 690,2906, 51, 369, 170,3541, -1060,2187,2688,3670,2541,1083,1683, 928,3918, 459, 109,4427, 599,3744,4286, 143, -2101,2730,2490, 82,1588,3036,2121, 281,1860, 477,4035,1238,2812,3020,2716,3312, -1530,2188,2055,1317, 843, 636,1808,1173,3495, 649, 181,1002, 147,3641,1159,2414, -3750,2289,2795, 813,3123,2610,1136,4368, 5,3391,4541,2174, 420, 429,1728, 754, -1228,2115,2219, 347,2223,2733, 735,1518,3003,2355,3134,1764,3948,3329,1888,2424, -1001,1234,1972,3321,3363,1672,1021,1450,1584, 226, 765, 655,2526,3404,3244,2302, -3665, 731, 594,2184, 319,1576, 621, 658,2656,4299,2099,3864,1279,2071,2598,2739, - 795,3086,3699,3908,1707,2352,2402,1382,3136,2475,1465,4847,3496,3865,1085,3004, -2591,1084, 213,2287,1963,3565,2250, 822, 793,4574,3187,1772,1789,3050, 595,1484, -1959,2770,1080,2650, 456, 422,2996, 940,3322,4328,4345,3092,2742, 965,2784, 739, -4124, 952,1358,2498,2949,2565, 332,2698,2378, 660,2260,2473,4194,3856,2919, 535, -1260,2651,1208,1428,1300,1949,1303,2942, 433,2455,2450,1251,1946, 614,1269, 641, -1306,1810,2737,3078,2912, 564,2365,1419,1415,1497,4460,2367,2185,1379,3005,1307, -3218,2175,1897,3063, 682,1157,4040,4005,1712,1160,1941,1399, 394, 402,2952,1573, -1151,2986,2404, 862, 299,2033,1489,3006, 346, 171,2886,3401,1726,2932, 168,2533, - 47,2507,1030,3735,1145,3370,1395,1318,1579,3609,4560,2857,4116,1457,2529,1965, - 504,1036,2690,2988,2405, 745,5871, 849,2397,2056,3081, 863,2359,3857,2096, 99, -1397,1769,2300,4428,1643,3455,1978,1757,3718,1440, 35,4879,3742,1296,4228,2280, - 160,5063,1599,2013, 166, 520,3479,1646,3345,3012, 490,1937,1545,1264,2182,2505, -1096,1188,1369,1436,2421,1667,2792,2460,1270,2122, 727,3167,2143, 806,1706,1012, -1800,3037, 960,2218,1882, 805, 139,2456,1139,1521, 851,1052,3093,3089, 342,2039, - 744,5097,1468,1502,1585,2087, 223, 939, 326,2140,2577, 892,2481,1623,4077, 982, -3708, 135,2131, 87,2503,3114,2326,1106, 876,1616, 547,2997,2831,2093,3441,4530, -4314, 9,3256,4229,4148, 659,1462,1986,1710,2046,2913,2231,4090,4880,5255,3392, -3274,1368,3689,4645,1477, 705,3384,3635,1068,1529,2941,1458,3782,1509, 100,1656, -2548, 718,2339, 408,1590,2780,3548,1838,4117,3719,1345,3530, 717,3442,2778,3220, -2898,1892,4590,3614,3371,2043,1998,1224,3483, 891, 635, 584,2559,3355, 733,1766, -1729,1172,3789,1891,2307, 781,2982,2271,1957,1580,5773,2633,2005,4195,3097,1535, -3213,1189,1934,5693,3262, 586,3118,1324,1598, 517,1564,2217,1868,1893,4445,3728, -2703,3139,1526,1787,1992,3882,2875,1549,1199,1056,2224,1904,2711,5098,4287, 338, -1993,3129,3489,2689,1809,2815,1997, 957,1855,3898,2550,3275,3057,1105,1319, 627, -1505,1911,1883,3526, 698,3629,3456,1833,1431, 746, 77,1261,2017,2296,1977,1885, - 125,1334,1600, 525,1798,1109,2222,1470,1945, 559,2236,1186,3443,2476,1929,1411, -2411,3135,1777,3372,2621,1841,1613,3229, 668,1430,1839,2643,2916, 195,1989,2671, -2358,1387, 629,3205,2293,5256,4439, 123,1310, 888,1879,4300,3021,3605,1003,1162, -3192,2910,2010, 140,2395,2859, 55,1082,2012,2901, 662, 419,2081,1438, 680,2774, -4654,3912,1620,1731,1625,5035,4065,2328, 512,1344, 802,5443,2163,2311,2537, 524, -3399, 98,1155,2103,1918,2606,3925,2816,1393,2465,1504,3773,2177,3963,1478,4346, - 180,1113,4655,3461,2028,1698, 833,2696,1235,1322,1594,4408,3623,3013,3225,2040, -3022, 541,2881, 607,3632,2029,1665,1219, 639,1385,1686,1099,2803,3231,1938,3188, -2858, 427, 676,2772,1168,2025, 454,3253,2486,3556, 230,1950, 580, 791,1991,1280, -1086,1974,2034, 630, 257,3338,2788,4903,1017, 86,4790, 966,2789,1995,1696,1131, - 259,3095,4188,1308, 179,1463,5257, 289,4107,1248, 42,3413,1725,2288, 896,1947, - 774,4474,4254, 604,3430,4264, 392,2514,2588, 452, 237,1408,3018, 988,4531,1970, -3034,3310, 540,2370,1562,1288,2990, 502,4765,1147, 4,1853,2708, 207, 294,2814, -4078,2902,2509, 684, 34,3105,3532,2551, 644, 709,2801,2344, 573,1727,3573,3557, -2021,1081,3100,4315,2100,3681, 199,2263,1837,2385, 146,3484,1195,2776,3949, 997, -1939,3973,1008,1091,1202,1962,1847,1149,4209,5444,1076, 493, 117,5400,2521, 972, -1490,2934,1796,4542,2374,1512,2933,2657, 413,2888,1135,2762,2314,2156,1355,2369, - 766,2007,2527,2170,3124,2491,2593,2632,4757,2437, 234,3125,3591,1898,1750,1376, -1942,3468,3138, 570,2127,2145,3276,4131, 962, 132,1445,4196, 19, 941,3624,3480, -3366,1973,1374,4461,3431,2629, 283,2415,2275, 808,2887,3620,2112,2563,1353,3610, - 955,1089,3103,1053, 96, 88,4097, 823,3808,1583, 399, 292,4091,3313, 421,1128, - 642,4006, 903,2539,1877,2082, 596, 29,4066,1790, 722,2157, 130, 995,1569, 769, -1485, 464, 513,2213, 288,1923,1101,2453,4316, 133, 486,2445, 50, 625, 487,2207, - 57, 423, 481,2962, 159,3729,1558, 491, 303, 482, 501, 240,2837, 112,3648,2392, -1783, 362, 8,3433,3422, 610,2793,3277,1390,1284,1654, 21,3823, 734, 367, 623, - 193, 287, 374,1009,1483, 816, 476, 313,2255,2340,1262,2150,2899,1146,2581, 782, -2116,1659,2018,1880, 255,3586,3314,1110,2867,2137,2564, 986,2767,5185,2006, 650, - 158, 926, 762, 881,3157,2717,2362,3587, 306,3690,3245,1542,3077,2427,1691,2478, -2118,2985,3490,2438, 539,2305, 983, 129,1754, 355,4201,2386, 827,2923, 104,1773, -2838,2771, 411,2905,3919, 376, 767, 122,1114, 828,2422,1817,3506, 266,3460,1007, -1609,4998, 945,2612,4429,2274, 726,1247,1964,2914,2199,2070,4002,4108, 657,3323, -1422, 579, 455,2764,4737,1222,2895,1670, 824,1223,1487,2525, 558, 861,3080, 598, -2659,2515,1967, 752,2583,2376,2214,4180, 977, 704,2464,4999,2622,4109,1210,2961, - 819,1541, 142,2284, 44, 418, 457,1126,3730,4347,4626,1644,1876,3671,1864, 302, -1063,5694, 624, 723,1984,3745,1314,1676,2488,1610,1449,3558,3569,2166,2098, 409, -1011,2325,3704,2306, 818,1732,1383,1824,1844,3757, 999,2705,3497,1216,1423,2683, -2426,2954,2501,2726,2229,1475,2554,5064,1971,1794,1666,2014,1343, 783, 724, 191, -2434,1354,2220,5065,1763,2752,2472,4152, 131, 175,2885,3434, 92,1466,4920,2616, -3871,3872,3866, 128,1551,1632, 669,1854,3682,4691,4125,1230, 188,2973,3290,1302, -1213, 560,3266, 917, 763,3909,3249,1760, 868,1958, 764,1782,2097, 145,2277,3774, -4462, 64,1491,3062, 971,2132,3606,2442, 221,1226,1617, 218, 323,1185,3207,3147, - 571, 619,1473,1005,1744,2281, 449,1887,2396,3685, 275, 375,3816,1743,3844,3731, - 845,1983,2350,4210,1377, 773, 967,3499,3052,3743,2725,4007,1697,1022,3943,1464, -3264,2855,2722,1952,1029,2839,2467, 84,4383,2215, 820,1391,2015,2448,3672, 377, -1948,2168, 797,2545,3536,2578,2645, 94,2874,1678, 405,1259,3071, 771, 546,1315, - 470,1243,3083, 895,2468, 981, 969,2037, 846,4181, 653,1276,2928, 14,2594, 557, -3007,2474, 156, 902,1338,1740,2574, 537,2518, 973,2282,2216,2433,1928, 138,2903, -1293,2631,1612, 646,3457, 839,2935, 111, 496,2191,2847, 589,3186, 149,3994,2060, -4031,2641,4067,3145,1870, 37,3597,2136,1025,2051,3009,3383,3549,1121,1016,3261, -1301, 251,2446,2599,2153, 872,3246, 637, 334,3705, 831, 884, 921,3065,3140,4092, -2198,1944, 246,2964, 108,2045,1152,1921,2308,1031, 203,3173,4170,1907,3890, 810, -1401,2003,1690, 506, 647,1242,2828,1761,1649,3208,2249,1589,3709,2931,5156,1708, - 498, 666,2613, 834,3817,1231, 184,2851,1124, 883,3197,2261,3710,1765,1553,2658, -1178,2639,2351, 93,1193, 942,2538,2141,4402, 235,1821, 870,1591,2192,1709,1871, -3341,1618,4126,2595,2334, 603, 651, 69, 701, 268,2662,3411,2555,1380,1606, 503, - 448, 254,2371,2646, 574,1187,2309,1770, 322,2235,1292,1801, 305, 566,1133, 229, -2067,2057, 706, 167, 483,2002,2672,3295,1820,3561,3067, 316, 378,2746,3452,1112, - 136,1981, 507,1651,2917,1117, 285,4591, 182,2580,3522,1304, 335,3303,1835,2504, -1795,1792,2248, 674,1018,2106,2449,1857,2292,2845, 976,3047,1781,2600,2727,1389, -1281, 52,3152, 153, 265,3950, 672,3485,3951,4463, 430,1183, 365, 278,2169, 27, -1407,1336,2304, 209,1340,1730,2202,1852,2403,2883, 979,1737,1062, 631,2829,2542, -3876,2592, 825,2086,2226,3048,3625, 352,1417,3724, 542, 991, 431,1351,3938,1861, -2294, 826,1361,2927,3142,3503,1738, 463,2462,2723, 582,1916,1595,2808, 400,3845, -3891,2868,3621,2254, 58,2492,1123, 910,2160,2614,1372,1603,1196,1072,3385,1700, -3267,1980, 696, 480,2430, 920, 799,1570,2920,1951,2041,4047,2540,1321,4223,2469, -3562,2228,1271,2602, 401,2833,3351,2575,5157, 907,2312,1256, 410, 263,3507,1582, - 996, 678,1849,2316,1480, 908,3545,2237, 703,2322, 667,1826,2849,1531,2604,2999, -2407,3146,2151,2630,1786,3711, 469,3542, 497,3899,2409, 858, 837,4446,3393,1274, - 786, 620,1845,2001,3311, 484, 308,3367,1204,1815,3691,2332,1532,2557,1842,2020, -2724,1927,2333,4440, 567, 22,1673,2728,4475,1987,1858,1144,1597, 101,1832,3601, - 12, 974,3783,4391, 951,1412, 1,3720, 453,4608,4041, 528,1041,1027,3230,2628, -1129, 875,1051,3291,1203,2262,1069,2860,2799,2149,2615,3278, 144,1758,3040, 31, - 475,1680, 366,2685,3184, 311,1642,4008,2466,5036,1593,1493,2809, 216,1420,1668, - 233, 304,2128,3284, 232,1429,1768,1040,2008,3407,2740,2967,2543, 242,2133, 778, -1565,2022,2620, 505,2189,2756,1098,2273, 372,1614, 708, 553,2846,2094,2278, 169, -3626,2835,4161, 228,2674,3165, 809,1454,1309, 466,1705,1095, 900,3423, 880,2667, -3751,5258,2317,3109,2571,4317,2766,1503,1342, 866,4447,1118, 63,2076, 314,1881, -1348,1061, 172, 978,3515,1747, 532, 511,3970, 6, 601, 905,2699,3300,1751, 276, -1467,3725,2668, 65,4239,2544,2779,2556,1604, 578,2451,1802, 992,2331,2624,1320, -3446, 713,1513,1013, 103,2786,2447,1661, 886,1702, 916, 654,3574,2031,1556, 751, -2178,2821,2179,1498,1538,2176, 271, 914,2251,2080,1325, 638,1953,2937,3877,2432, -2754, 95,3265,1716, 260,1227,4083, 775, 106,1357,3254, 426,1607, 555,2480, 772, -1985, 244,2546, 474, 495,1046,2611,1851,2061, 71,2089,1675,2590, 742,3758,2843, -3222,1433, 267,2180,2576,2826,2233,2092,3913,2435, 956,1745,3075, 856,2113,1116, - 451, 3,1988,2896,1398, 993,2463,1878,2049,1341,2718,2721,2870,2108, 712,2904, -4363,2753,2324, 277,2872,2349,2649, 384, 987, 435, 691,3000, 922, 164,3939, 652, -1500,1184,4153,2482,3373,2165,4848,2335,3775,3508,3154,2806,2830,1554,2102,1664, -2530,1434,2408, 893,1547,2623,3447,2832,2242,2532,3169,2856,3223,2078, 49,3770, -3469, 462, 318, 656,2259,3250,3069, 679,1629,2758, 344,1138,1104,3120,1836,1283, -3115,2154,1437,4448, 934, 759,1999, 794,2862,1038, 533,2560,1722,2342, 855,2626, -1197,1663,4476,3127, 85,4240,2528, 25,1111,1181,3673, 407,3470,4561,2679,2713, - 768,1925,2841,3986,1544,1165, 932, 373,1240,2146,1930,2673, 721,4766, 354,4333, - 391,2963, 187, 61,3364,1442,1102, 330,1940,1767, 341,3809,4118, 393,2496,2062, -2211, 105, 331, 300, 439, 913,1332, 626, 379,3304,1557, 328, 689,3952, 309,1555, - 931, 317,2517,3027, 325, 569, 686,2107,3084, 60,1042,1333,2794, 264,3177,4014, -1628, 258,3712, 7,4464,1176,1043,1778, 683, 114,1975, 78,1492, 383,1886, 510, - 386, 645,5291,2891,2069,3305,4138,3867,2939,2603,2493,1935,1066,1848,3588,1015, -1282,1289,4609, 697,1453,3044,2666,3611,1856,2412, 54, 719,1330, 568,3778,2459, -1748, 788, 492, 551,1191,1000, 488,3394,3763, 282,1799, 348,2016,1523,3155,2390, -1049, 382,2019,1788,1170, 729,2968,3523, 897,3926,2785,2938,3292, 350,2319,3238, -1718,1717,2655,3453,3143,4465, 161,2889,2980,2009,1421, 56,1908,1640,2387,2232, -1917,1874,2477,4921, 148, 83,3438, 592,4245,2882,1822,1055, 741, 115,1496,1624, - 381,1638,4592,1020, 516,3214, 458, 947,4575,1432, 211,1514,2926,1865,2142, 189, - 852,1221,1400,1486, 882,2299,4036, 351, 28,1122, 700,6479,6480,6481,6482,6483, #last 512 -) - diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/gb2312prober.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/gb2312prober.py deleted file mode 100644 index 8446d2d..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/gb2312prober.py +++ /dev/null @@ -1,46 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is mozilla.org code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .mbcharsetprober import MultiByteCharSetProber -from .codingstatemachine import CodingStateMachine -from .chardistribution import GB2312DistributionAnalysis -from .mbcssm import GB2312_SM_MODEL - -class GB2312Prober(MultiByteCharSetProber): - def __init__(self): - super(GB2312Prober, self).__init__() - self.coding_sm = CodingStateMachine(GB2312_SM_MODEL) - self.distribution_analyzer = GB2312DistributionAnalysis() - self.reset() - - @property - def charset_name(self): - return "GB2312" - - @property - def language(self): - return "Chinese" diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/hebrewprober.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/hebrewprober.py deleted file mode 100644 index b0e1bf4..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/hebrewprober.py +++ /dev/null @@ -1,292 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Universal charset detector code. -# -# The Initial Developer of the Original Code is -# Shy Shalom -# Portions created by the Initial Developer are Copyright (C) 2005 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .charsetprober import CharSetProber -from .enums import ProbingState - -# This prober doesn't actually recognize a language or a charset. -# It is a helper prober for the use of the Hebrew model probers - -### General ideas of the Hebrew charset recognition ### -# -# Four main charsets exist in Hebrew: -# "ISO-8859-8" - Visual Hebrew -# "windows-1255" - Logical Hebrew -# "ISO-8859-8-I" - Logical Hebrew -# "x-mac-hebrew" - ?? Logical Hebrew ?? -# -# Both "ISO" charsets use a completely identical set of code points, whereas -# "windows-1255" and "x-mac-hebrew" are two different proper supersets of -# these code points. windows-1255 defines additional characters in the range -# 0x80-0x9F as some misc punctuation marks as well as some Hebrew-specific -# diacritics and additional 'Yiddish' ligature letters in the range 0xc0-0xd6. -# x-mac-hebrew defines similar additional code points but with a different -# mapping. -# -# As far as an average Hebrew text with no diacritics is concerned, all four -# charsets are identical with respect to code points. Meaning that for the -# main Hebrew alphabet, all four map the same values to all 27 Hebrew letters -# (including final letters). -# -# The dominant difference between these charsets is their directionality. -# "Visual" directionality means that the text is ordered as if the renderer is -# not aware of a BIDI rendering algorithm. The renderer sees the text and -# draws it from left to right. The text itself when ordered naturally is read -# backwards. A buffer of Visual Hebrew generally looks like so: -# "[last word of first line spelled backwards] [whole line ordered backwards -# and spelled backwards] [first word of first line spelled backwards] -# [end of line] [last word of second line] ... etc' " -# adding punctuation marks, numbers and English text to visual text is -# naturally also "visual" and from left to right. -# -# "Logical" directionality means the text is ordered "naturally" according to -# the order it is read. It is the responsibility of the renderer to display -# the text from right to left. A BIDI algorithm is used to place general -# punctuation marks, numbers and English text in the text. -# -# Texts in x-mac-hebrew are almost impossible to find on the Internet. From -# what little evidence I could find, it seems that its general directionality -# is Logical. -# -# To sum up all of the above, the Hebrew probing mechanism knows about two -# charsets: -# Visual Hebrew - "ISO-8859-8" - backwards text - Words and sentences are -# backwards while line order is natural. For charset recognition purposes -# the line order is unimportant (In fact, for this implementation, even -# word order is unimportant). -# Logical Hebrew - "windows-1255" - normal, naturally ordered text. -# -# "ISO-8859-8-I" is a subset of windows-1255 and doesn't need to be -# specifically identified. -# "x-mac-hebrew" is also identified as windows-1255. A text in x-mac-hebrew -# that contain special punctuation marks or diacritics is displayed with -# some unconverted characters showing as question marks. This problem might -# be corrected using another model prober for x-mac-hebrew. Due to the fact -# that x-mac-hebrew texts are so rare, writing another model prober isn't -# worth the effort and performance hit. -# -#### The Prober #### -# -# The prober is divided between two SBCharSetProbers and a HebrewProber, -# all of which are managed, created, fed data, inquired and deleted by the -# SBCSGroupProber. The two SBCharSetProbers identify that the text is in -# fact some kind of Hebrew, Logical or Visual. The final decision about which -# one is it is made by the HebrewProber by combining final-letter scores -# with the scores of the two SBCharSetProbers to produce a final answer. -# -# The SBCSGroupProber is responsible for stripping the original text of HTML -# tags, English characters, numbers, low-ASCII punctuation characters, spaces -# and new lines. It reduces any sequence of such characters to a single space. -# The buffer fed to each prober in the SBCS group prober is pure text in -# high-ASCII. -# The two SBCharSetProbers (model probers) share the same language model: -# Win1255Model. -# The first SBCharSetProber uses the model normally as any other -# SBCharSetProber does, to recognize windows-1255, upon which this model was -# built. The second SBCharSetProber is told to make the pair-of-letter -# lookup in the language model backwards. This in practice exactly simulates -# a visual Hebrew model using the windows-1255 logical Hebrew model. -# -# The HebrewProber is not using any language model. All it does is look for -# final-letter evidence suggesting the text is either logical Hebrew or visual -# Hebrew. Disjointed from the model probers, the results of the HebrewProber -# alone are meaningless. HebrewProber always returns 0.00 as confidence -# since it never identifies a charset by itself. Instead, the pointer to the -# HebrewProber is passed to the model probers as a helper "Name Prober". -# When the Group prober receives a positive identification from any prober, -# it asks for the name of the charset identified. If the prober queried is a -# Hebrew model prober, the model prober forwards the call to the -# HebrewProber to make the final decision. In the HebrewProber, the -# decision is made according to the final-letters scores maintained and Both -# model probers scores. The answer is returned in the form of the name of the -# charset identified, either "windows-1255" or "ISO-8859-8". - -class HebrewProber(CharSetProber): - # windows-1255 / ISO-8859-8 code points of interest - FINAL_KAF = 0xea - NORMAL_KAF = 0xeb - FINAL_MEM = 0xed - NORMAL_MEM = 0xee - FINAL_NUN = 0xef - NORMAL_NUN = 0xf0 - FINAL_PE = 0xf3 - NORMAL_PE = 0xf4 - FINAL_TSADI = 0xf5 - NORMAL_TSADI = 0xf6 - - # Minimum Visual vs Logical final letter score difference. - # If the difference is below this, don't rely solely on the final letter score - # distance. - MIN_FINAL_CHAR_DISTANCE = 5 - - # Minimum Visual vs Logical model score difference. - # If the difference is below this, don't rely at all on the model score - # distance. - MIN_MODEL_DISTANCE = 0.01 - - VISUAL_HEBREW_NAME = "ISO-8859-8" - LOGICAL_HEBREW_NAME = "windows-1255" - - def __init__(self): - super(HebrewProber, self).__init__() - self._final_char_logical_score = None - self._final_char_visual_score = None - self._prev = None - self._before_prev = None - self._logical_prober = None - self._visual_prober = None - self.reset() - - def reset(self): - self._final_char_logical_score = 0 - self._final_char_visual_score = 0 - # The two last characters seen in the previous buffer, - # mPrev and mBeforePrev are initialized to space in order to simulate - # a word delimiter at the beginning of the data - self._prev = ' ' - self._before_prev = ' ' - # These probers are owned by the group prober. - - def set_model_probers(self, logicalProber, visualProber): - self._logical_prober = logicalProber - self._visual_prober = visualProber - - def is_final(self, c): - return c in [self.FINAL_KAF, self.FINAL_MEM, self.FINAL_NUN, - self.FINAL_PE, self.FINAL_TSADI] - - def is_non_final(self, c): - # The normal Tsadi is not a good Non-Final letter due to words like - # 'lechotet' (to chat) containing an apostrophe after the tsadi. This - # apostrophe is converted to a space in FilterWithoutEnglishLetters - # causing the Non-Final tsadi to appear at an end of a word even - # though this is not the case in the original text. - # The letters Pe and Kaf rarely display a related behavior of not being - # a good Non-Final letter. Words like 'Pop', 'Winamp' and 'Mubarak' - # for example legally end with a Non-Final Pe or Kaf. However, the - # benefit of these letters as Non-Final letters outweighs the damage - # since these words are quite rare. - return c in [self.NORMAL_KAF, self.NORMAL_MEM, - self.NORMAL_NUN, self.NORMAL_PE] - - def feed(self, byte_str): - # Final letter analysis for logical-visual decision. - # Look for evidence that the received buffer is either logical Hebrew - # or visual Hebrew. - # The following cases are checked: - # 1) A word longer than 1 letter, ending with a final letter. This is - # an indication that the text is laid out "naturally" since the - # final letter really appears at the end. +1 for logical score. - # 2) A word longer than 1 letter, ending with a Non-Final letter. In - # normal Hebrew, words ending with Kaf, Mem, Nun, Pe or Tsadi, - # should not end with the Non-Final form of that letter. Exceptions - # to this rule are mentioned above in isNonFinal(). This is an - # indication that the text is laid out backwards. +1 for visual - # score - # 3) A word longer than 1 letter, starting with a final letter. Final - # letters should not appear at the beginning of a word. This is an - # indication that the text is laid out backwards. +1 for visual - # score. - # - # The visual score and logical score are accumulated throughout the - # text and are finally checked against each other in GetCharSetName(). - # No checking for final letters in the middle of words is done since - # that case is not an indication for either Logical or Visual text. - # - # We automatically filter out all 7-bit characters (replace them with - # spaces) so the word boundary detection works properly. [MAP] - - if self.state == ProbingState.NOT_ME: - # Both model probers say it's not them. No reason to continue. - return ProbingState.NOT_ME - - byte_str = self.filter_high_byte_only(byte_str) - - for cur in byte_str: - if cur == ' ': - # We stand on a space - a word just ended - if self._before_prev != ' ': - # next-to-last char was not a space so self._prev is not a - # 1 letter word - if self.is_final(self._prev): - # case (1) [-2:not space][-1:final letter][cur:space] - self._final_char_logical_score += 1 - elif self.is_non_final(self._prev): - # case (2) [-2:not space][-1:Non-Final letter][ - # cur:space] - self._final_char_visual_score += 1 - else: - # Not standing on a space - if ((self._before_prev == ' ') and - (self.is_final(self._prev)) and (cur != ' ')): - # case (3) [-2:space][-1:final letter][cur:not space] - self._final_char_visual_score += 1 - self._before_prev = self._prev - self._prev = cur - - # Forever detecting, till the end or until both model probers return - # ProbingState.NOT_ME (handled above) - return ProbingState.DETECTING - - @property - def charset_name(self): - # Make the decision: is it Logical or Visual? - # If the final letter score distance is dominant enough, rely on it. - finalsub = self._final_char_logical_score - self._final_char_visual_score - if finalsub >= self.MIN_FINAL_CHAR_DISTANCE: - return self.LOGICAL_HEBREW_NAME - if finalsub <= -self.MIN_FINAL_CHAR_DISTANCE: - return self.VISUAL_HEBREW_NAME - - # It's not dominant enough, try to rely on the model scores instead. - modelsub = (self._logical_prober.get_confidence() - - self._visual_prober.get_confidence()) - if modelsub > self.MIN_MODEL_DISTANCE: - return self.LOGICAL_HEBREW_NAME - if modelsub < -self.MIN_MODEL_DISTANCE: - return self.VISUAL_HEBREW_NAME - - # Still no good, back to final letter distance, maybe it'll save the - # day. - if finalsub < 0.0: - return self.VISUAL_HEBREW_NAME - - # (finalsub > 0 - Logical) or (don't know what to do) default to - # Logical. - return self.LOGICAL_HEBREW_NAME - - @property - def language(self): - return 'Hebrew' - - @property - def state(self): - # Remain active as long as any of the model probers are active. - if (self._logical_prober.state == ProbingState.NOT_ME) and \ - (self._visual_prober.state == ProbingState.NOT_ME): - return ProbingState.NOT_ME - return ProbingState.DETECTING diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/jisfreq.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/jisfreq.py deleted file mode 100644 index 83fc082..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/jisfreq.py +++ /dev/null @@ -1,325 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -# Sampling from about 20M text materials include literature and computer technology -# -# Japanese frequency table, applied to both S-JIS and EUC-JP -# They are sorted in order. - -# 128 --> 0.77094 -# 256 --> 0.85710 -# 512 --> 0.92635 -# 1024 --> 0.97130 -# 2048 --> 0.99431 -# -# Ideal Distribution Ratio = 0.92635 / (1-0.92635) = 12.58 -# Random Distribution Ration = 512 / (2965+62+83+86-512) = 0.191 -# -# Typical Distribution Ratio, 25% of IDR - -JIS_TYPICAL_DISTRIBUTION_RATIO = 3.0 - -# Char to FreqOrder table , -JIS_TABLE_SIZE = 4368 - -JIS_CHAR_TO_FREQ_ORDER = ( - 40, 1, 6, 182, 152, 180, 295,2127, 285, 381,3295,4304,3068,4606,3165,3510, # 16 -3511,1822,2785,4607,1193,2226,5070,4608, 171,2996,1247, 18, 179,5071, 856,1661, # 32 -1262,5072, 619, 127,3431,3512,3230,1899,1700, 232, 228,1294,1298, 284, 283,2041, # 48 -2042,1061,1062, 48, 49, 44, 45, 433, 434,1040,1041, 996, 787,2997,1255,4305, # 64 -2108,4609,1684,1648,5073,5074,5075,5076,5077,5078,3687,5079,4610,5080,3927,3928, # 80 -5081,3296,3432, 290,2285,1471,2187,5082,2580,2825,1303,2140,1739,1445,2691,3375, # 96 -1691,3297,4306,4307,4611, 452,3376,1182,2713,3688,3069,4308,5083,5084,5085,5086, # 112 -5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102, # 128 -5103,5104,5105,5106,5107,5108,5109,5110,5111,5112,4097,5113,5114,5115,5116,5117, # 144 -5118,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,5129,5130,5131,5132,5133, # 160 -5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149, # 176 -5150,5151,5152,4612,5153,5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164, # 192 -5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,1472, 598, 618, 820,1205, # 208 -1309,1412,1858,1307,1692,5176,5177,5178,5179,5180,5181,5182,1142,1452,1234,1172, # 224 -1875,2043,2149,1793,1382,2973, 925,2404,1067,1241, 960,1377,2935,1491, 919,1217, # 240 -1865,2030,1406,1499,2749,4098,5183,5184,5185,5186,5187,5188,2561,4099,3117,1804, # 256 -2049,3689,4309,3513,1663,5189,3166,3118,3298,1587,1561,3433,5190,3119,1625,2998, # 272 -3299,4613,1766,3690,2786,4614,5191,5192,5193,5194,2161, 26,3377, 2,3929, 20, # 288 -3691, 47,4100, 50, 17, 16, 35, 268, 27, 243, 42, 155, 24, 154, 29, 184, # 304 - 4, 91, 14, 92, 53, 396, 33, 289, 9, 37, 64, 620, 21, 39, 321, 5, # 320 - 12, 11, 52, 13, 3, 208, 138, 0, 7, 60, 526, 141, 151,1069, 181, 275, # 336 -1591, 83, 132,1475, 126, 331, 829, 15, 69, 160, 59, 22, 157, 55,1079, 312, # 352 - 109, 38, 23, 25, 10, 19, 79,5195, 61, 382,1124, 8, 30,5196,5197,5198, # 368 -5199,5200,5201,5202,5203,5204,5205,5206, 89, 62, 74, 34,2416, 112, 139, 196, # 384 - 271, 149, 84, 607, 131, 765, 46, 88, 153, 683, 76, 874, 101, 258, 57, 80, # 400 - 32, 364, 121,1508, 169,1547, 68, 235, 145,2999, 41, 360,3027, 70, 63, 31, # 416 - 43, 259, 262,1383, 99, 533, 194, 66, 93, 846, 217, 192, 56, 106, 58, 565, # 432 - 280, 272, 311, 256, 146, 82, 308, 71, 100, 128, 214, 655, 110, 261, 104,1140, # 448 - 54, 51, 36, 87, 67,3070, 185,2618,2936,2020, 28,1066,2390,2059,5207,5208, # 464 -5209,5210,5211,5212,5213,5214,5215,5216,4615,5217,5218,5219,5220,5221,5222,5223, # 480 -5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234,5235,5236,3514,5237,5238, # 496 -5239,5240,5241,5242,5243,5244,2297,2031,4616,4310,3692,5245,3071,5246,3598,5247, # 512 -4617,3231,3515,5248,4101,4311,4618,3808,4312,4102,5249,4103,4104,3599,5250,5251, # 528 -5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,5264,5265,5266,5267, # 544 -5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,5279,5280,5281,5282,5283, # 560 -5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299, # 576 -5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315, # 592 -5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331, # 608 -5332,5333,5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347, # 624 -5348,5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363, # 640 -5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379, # 656 -5380,5381, 363, 642,2787,2878,2788,2789,2316,3232,2317,3434,2011, 165,1942,3930, # 672 -3931,3932,3933,5382,4619,5383,4620,5384,5385,5386,5387,5388,5389,5390,5391,5392, # 688 -5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408, # 704 -5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424, # 720 -5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,5440, # 736 -5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456, # 752 -5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472, # 768 -5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488, # 784 -5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504, # 800 -5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520, # 816 -5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536, # 832 -5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,5549,5550,5551,5552, # 848 -5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,5564,5565,5566,5567,5568, # 864 -5569,5570,5571,5572,5573,5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584, # 880 -5585,5586,5587,5588,5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600, # 896 -5601,5602,5603,5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616, # 912 -5617,5618,5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632, # 928 -5633,5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648, # 944 -5649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664, # 960 -5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,5680, # 976 -5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,5695,5696, # 992 -5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,5710,5711,5712, # 1008 -5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,5725,5726,5727,5728, # 1024 -5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,5740,5741,5742,5743,5744, # 1040 -5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756,5757,5758,5759,5760, # 1056 -5761,5762,5763,5764,5765,5766,5767,5768,5769,5770,5771,5772,5773,5774,5775,5776, # 1072 -5777,5778,5779,5780,5781,5782,5783,5784,5785,5786,5787,5788,5789,5790,5791,5792, # 1088 -5793,5794,5795,5796,5797,5798,5799,5800,5801,5802,5803,5804,5805,5806,5807,5808, # 1104 -5809,5810,5811,5812,5813,5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824, # 1120 -5825,5826,5827,5828,5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840, # 1136 -5841,5842,5843,5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856, # 1152 -5857,5858,5859,5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872, # 1168 -5873,5874,5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888, # 1184 -5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904, # 1200 -5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920, # 1216 -5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936, # 1232 -5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951,5952, # 1248 -5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968, # 1264 -5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,5980,5981,5982,5983,5984, # 1280 -5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,5995,5996,5997,5998,5999,6000, # 1296 -6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,6011,6012,6013,6014,6015,6016, # 1312 -6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,6029,6030,6031,6032, # 1328 -6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,6044,6045,6046,6047,6048, # 1344 -6049,6050,6051,6052,6053,6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064, # 1360 -6065,6066,6067,6068,6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080, # 1376 -6081,6082,6083,6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096, # 1392 -6097,6098,6099,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112, # 1408 -6113,6114,2044,2060,4621, 997,1235, 473,1186,4622, 920,3378,6115,6116, 379,1108, # 1424 -4313,2657,2735,3934,6117,3809, 636,3233, 573,1026,3693,3435,2974,3300,2298,4105, # 1440 - 854,2937,2463, 393,2581,2417, 539, 752,1280,2750,2480, 140,1161, 440, 708,1569, # 1456 - 665,2497,1746,1291,1523,3000, 164,1603, 847,1331, 537,1997, 486, 508,1693,2418, # 1472 -1970,2227, 878,1220, 299,1030, 969, 652,2751, 624,1137,3301,2619, 65,3302,2045, # 1488 -1761,1859,3120,1930,3694,3516, 663,1767, 852, 835,3695, 269, 767,2826,2339,1305, # 1504 - 896,1150, 770,1616,6118, 506,1502,2075,1012,2519, 775,2520,2975,2340,2938,4314, # 1520 -3028,2086,1224,1943,2286,6119,3072,4315,2240,1273,1987,3935,1557, 175, 597, 985, # 1536 -3517,2419,2521,1416,3029, 585, 938,1931,1007,1052,1932,1685,6120,3379,4316,4623, # 1552 - 804, 599,3121,1333,2128,2539,1159,1554,2032,3810, 687,2033,2904, 952, 675,1467, # 1568 -3436,6121,2241,1096,1786,2440,1543,1924, 980,1813,2228, 781,2692,1879, 728,1918, # 1584 -3696,4624, 548,1950,4625,1809,1088,1356,3303,2522,1944, 502, 972, 373, 513,2827, # 1600 - 586,2377,2391,1003,1976,1631,6122,2464,1084, 648,1776,4626,2141, 324, 962,2012, # 1616 -2177,2076,1384, 742,2178,1448,1173,1810, 222, 102, 301, 445, 125,2420, 662,2498, # 1632 - 277, 200,1476,1165,1068, 224,2562,1378,1446, 450,1880, 659, 791, 582,4627,2939, # 1648 -3936,1516,1274, 555,2099,3697,1020,1389,1526,3380,1762,1723,1787,2229, 412,2114, # 1664 -1900,2392,3518, 512,2597, 427,1925,2341,3122,1653,1686,2465,2499, 697, 330, 273, # 1680 - 380,2162, 951, 832, 780, 991,1301,3073, 965,2270,3519, 668,2523,2636,1286, 535, # 1696 -1407, 518, 671, 957,2658,2378, 267, 611,2197,3030,6123, 248,2299, 967,1799,2356, # 1712 - 850,1418,3437,1876,1256,1480,2828,1718,6124,6125,1755,1664,2405,6126,4628,2879, # 1728 -2829, 499,2179, 676,4629, 557,2329,2214,2090, 325,3234, 464, 811,3001, 992,2342, # 1744 -2481,1232,1469, 303,2242, 466,1070,2163, 603,1777,2091,4630,2752,4631,2714, 322, # 1760 -2659,1964,1768, 481,2188,1463,2330,2857,3600,2092,3031,2421,4632,2318,2070,1849, # 1776 -2598,4633,1302,2254,1668,1701,2422,3811,2905,3032,3123,2046,4106,1763,1694,4634, # 1792 -1604, 943,1724,1454, 917, 868,2215,1169,2940, 552,1145,1800,1228,1823,1955, 316, # 1808 -1080,2510, 361,1807,2830,4107,2660,3381,1346,1423,1134,4108,6127, 541,1263,1229, # 1824 -1148,2540, 545, 465,1833,2880,3438,1901,3074,2482, 816,3937, 713,1788,2500, 122, # 1840 -1575, 195,1451,2501,1111,6128, 859, 374,1225,2243,2483,4317, 390,1033,3439,3075, # 1856 -2524,1687, 266, 793,1440,2599, 946, 779, 802, 507, 897,1081, 528,2189,1292, 711, # 1872 -1866,1725,1167,1640, 753, 398,2661,1053, 246, 348,4318, 137,1024,3440,1600,2077, # 1888 -2129, 825,4319, 698, 238, 521, 187,2300,1157,2423,1641,1605,1464,1610,1097,2541, # 1904 -1260,1436, 759,2255,1814,2150, 705,3235, 409,2563,3304, 561,3033,2005,2564, 726, # 1920 -1956,2343,3698,4109, 949,3812,3813,3520,1669, 653,1379,2525, 881,2198, 632,2256, # 1936 -1027, 778,1074, 733,1957, 514,1481,2466, 554,2180, 702,3938,1606,1017,1398,6129, # 1952 -1380,3521, 921, 993,1313, 594, 449,1489,1617,1166, 768,1426,1360, 495,1794,3601, # 1968 -1177,3602,1170,4320,2344, 476, 425,3167,4635,3168,1424, 401,2662,1171,3382,1998, # 1984 -1089,4110, 477,3169, 474,6130,1909, 596,2831,1842, 494, 693,1051,1028,1207,3076, # 2000 - 606,2115, 727,2790,1473,1115, 743,3522, 630, 805,1532,4321,2021, 366,1057, 838, # 2016 - 684,1114,2142,4322,2050,1492,1892,1808,2271,3814,2424,1971,1447,1373,3305,1090, # 2032 -1536,3939,3523,3306,1455,2199, 336, 369,2331,1035, 584,2393, 902, 718,2600,6131, # 2048 -2753, 463,2151,1149,1611,2467, 715,1308,3124,1268, 343,1413,3236,1517,1347,2663, # 2064 -2093,3940,2022,1131,1553,2100,2941,1427,3441,2942,1323,2484,6132,1980, 872,2368, # 2080 -2441,2943, 320,2369,2116,1082, 679,1933,3941,2791,3815, 625,1143,2023, 422,2200, # 2096 -3816,6133, 730,1695, 356,2257,1626,2301,2858,2637,1627,1778, 937, 883,2906,2693, # 2112 -3002,1769,1086, 400,1063,1325,3307,2792,4111,3077, 456,2345,1046, 747,6134,1524, # 2128 - 884,1094,3383,1474,2164,1059, 974,1688,2181,2258,1047, 345,1665,1187, 358, 875, # 2144 -3170, 305, 660,3524,2190,1334,1135,3171,1540,1649,2542,1527, 927, 968,2793, 885, # 2160 -1972,1850, 482, 500,2638,1218,1109,1085,2543,1654,2034, 876, 78,2287,1482,1277, # 2176 - 861,1675,1083,1779, 724,2754, 454, 397,1132,1612,2332, 893, 672,1237, 257,2259, # 2192 -2370, 135,3384, 337,2244, 547, 352, 340, 709,2485,1400, 788,1138,2511, 540, 772, # 2208 -1682,2260,2272,2544,2013,1843,1902,4636,1999,1562,2288,4637,2201,1403,1533, 407, # 2224 - 576,3308,1254,2071, 978,3385, 170, 136,1201,3125,2664,3172,2394, 213, 912, 873, # 2240 -3603,1713,2202, 699,3604,3699, 813,3442, 493, 531,1054, 468,2907,1483, 304, 281, # 2256 -4112,1726,1252,2094, 339,2319,2130,2639, 756,1563,2944, 748, 571,2976,1588,2425, # 2272 -2715,1851,1460,2426,1528,1392,1973,3237, 288,3309, 685,3386, 296, 892,2716,2216, # 2288 -1570,2245, 722,1747,2217, 905,3238,1103,6135,1893,1441,1965, 251,1805,2371,3700, # 2304 -2601,1919,1078, 75,2182,1509,1592,1270,2640,4638,2152,6136,3310,3817, 524, 706, # 2320 -1075, 292,3818,1756,2602, 317, 98,3173,3605,3525,1844,2218,3819,2502, 814, 567, # 2336 - 385,2908,1534,6137, 534,1642,3239, 797,6138,1670,1529, 953,4323, 188,1071, 538, # 2352 - 178, 729,3240,2109,1226,1374,2000,2357,2977, 731,2468,1116,2014,2051,6139,1261, # 2368 -1593, 803,2859,2736,3443, 556, 682, 823,1541,6140,1369,2289,1706,2794, 845, 462, # 2384 -2603,2665,1361, 387, 162,2358,1740, 739,1770,1720,1304,1401,3241,1049, 627,1571, # 2400 -2427,3526,1877,3942,1852,1500, 431,1910,1503, 677, 297,2795, 286,1433,1038,1198, # 2416 -2290,1133,1596,4113,4639,2469,1510,1484,3943,6141,2442, 108, 712,4640,2372, 866, # 2432 -3701,2755,3242,1348, 834,1945,1408,3527,2395,3243,1811, 824, 994,1179,2110,1548, # 2448 -1453, 790,3003, 690,4324,4325,2832,2909,3820,1860,3821, 225,1748, 310, 346,1780, # 2464 -2470, 821,1993,2717,2796, 828, 877,3528,2860,2471,1702,2165,2910,2486,1789, 453, # 2480 - 359,2291,1676, 73,1164,1461,1127,3311, 421, 604, 314,1037, 589, 116,2487, 737, # 2496 - 837,1180, 111, 244, 735,6142,2261,1861,1362, 986, 523, 418, 581,2666,3822, 103, # 2512 - 855, 503,1414,1867,2488,1091, 657,1597, 979, 605,1316,4641,1021,2443,2078,2001, # 2528 -1209, 96, 587,2166,1032, 260,1072,2153, 173, 94, 226,3244, 819,2006,4642,4114, # 2544 -2203, 231,1744, 782, 97,2667, 786,3387, 887, 391, 442,2219,4326,1425,6143,2694, # 2560 - 633,1544,1202, 483,2015, 592,2052,1958,2472,1655, 419, 129,4327,3444,3312,1714, # 2576 -1257,3078,4328,1518,1098, 865,1310,1019,1885,1512,1734, 469,2444, 148, 773, 436, # 2592 -1815,1868,1128,1055,4329,1245,2756,3445,2154,1934,1039,4643, 579,1238, 932,2320, # 2608 - 353, 205, 801, 115,2428, 944,2321,1881, 399,2565,1211, 678, 766,3944, 335,2101, # 2624 -1459,1781,1402,3945,2737,2131,1010, 844, 981,1326,1013, 550,1816,1545,2620,1335, # 2640 -1008, 371,2881, 936,1419,1613,3529,1456,1395,2273,1834,2604,1317,2738,2503, 416, # 2656 -1643,4330, 806,1126, 229, 591,3946,1314,1981,1576,1837,1666, 347,1790, 977,3313, # 2672 - 764,2861,1853, 688,2429,1920,1462, 77, 595, 415,2002,3034, 798,1192,4115,6144, # 2688 -2978,4331,3035,2695,2582,2072,2566, 430,2430,1727, 842,1396,3947,3702, 613, 377, # 2704 - 278, 236,1417,3388,3314,3174, 757,1869, 107,3530,6145,1194, 623,2262, 207,1253, # 2720 -2167,3446,3948, 492,1117,1935, 536,1838,2757,1246,4332, 696,2095,2406,1393,1572, # 2736 -3175,1782, 583, 190, 253,1390,2230, 830,3126,3389, 934,3245,1703,1749,2979,1870, # 2752 -2545,1656,2204, 869,2346,4116,3176,1817, 496,1764,4644, 942,1504, 404,1903,1122, # 2768 -1580,3606,2945,1022, 515, 372,1735, 955,2431,3036,6146,2797,1110,2302,2798, 617, # 2784 -6147, 441, 762,1771,3447,3607,3608,1904, 840,3037, 86, 939,1385, 572,1370,2445, # 2800 -1336, 114,3703, 898, 294, 203,3315, 703,1583,2274, 429, 961,4333,1854,1951,3390, # 2816 -2373,3704,4334,1318,1381, 966,1911,2322,1006,1155, 309, 989, 458,2718,1795,1372, # 2832 -1203, 252,1689,1363,3177, 517,1936, 168,1490, 562, 193,3823,1042,4117,1835, 551, # 2848 - 470,4645, 395, 489,3448,1871,1465,2583,2641, 417,1493, 279,1295, 511,1236,1119, # 2864 - 72,1231,1982,1812,3004, 871,1564, 984,3449,1667,2696,2096,4646,2347,2833,1673, # 2880 -3609, 695,3246,2668, 807,1183,4647, 890, 388,2333,1801,1457,2911,1765,1477,1031, # 2896 -3316,3317,1278,3391,2799,2292,2526, 163,3450,4335,2669,1404,1802,6148,2323,2407, # 2912 -1584,1728,1494,1824,1269, 298, 909,3318,1034,1632, 375, 776,1683,2061, 291, 210, # 2928 -1123, 809,1249,1002,2642,3038, 206,1011,2132, 144, 975, 882,1565, 342, 667, 754, # 2944 -1442,2143,1299,2303,2062, 447, 626,2205,1221,2739,2912,1144,1214,2206,2584, 760, # 2960 -1715, 614, 950,1281,2670,2621, 810, 577,1287,2546,4648, 242,2168, 250,2643, 691, # 2976 - 123,2644, 647, 313,1029, 689,1357,2946,1650, 216, 771,1339,1306, 808,2063, 549, # 2992 - 913,1371,2913,2914,6149,1466,1092,1174,1196,1311,2605,2396,1783,1796,3079, 406, # 3008 -2671,2117,3949,4649, 487,1825,2220,6150,2915, 448,2348,1073,6151,2397,1707, 130, # 3024 - 900,1598, 329, 176,1959,2527,1620,6152,2275,4336,3319,1983,2191,3705,3610,2155, # 3040 -3706,1912,1513,1614,6153,1988, 646, 392,2304,1589,3320,3039,1826,1239,1352,1340, # 3056 -2916, 505,2567,1709,1437,2408,2547, 906,6154,2672, 384,1458,1594,1100,1329, 710, # 3072 - 423,3531,2064,2231,2622,1989,2673,1087,1882, 333, 841,3005,1296,2882,2379, 580, # 3088 -1937,1827,1293,2585, 601, 574, 249,1772,4118,2079,1120, 645, 901,1176,1690, 795, # 3104 -2207, 478,1434, 516,1190,1530, 761,2080, 930,1264, 355, 435,1552, 644,1791, 987, # 3120 - 220,1364,1163,1121,1538, 306,2169,1327,1222, 546,2645, 218, 241, 610,1704,3321, # 3136 -1984,1839,1966,2528, 451,6155,2586,3707,2568, 907,3178, 254,2947, 186,1845,4650, # 3152 - 745, 432,1757, 428,1633, 888,2246,2221,2489,3611,2118,1258,1265, 956,3127,1784, # 3168 -4337,2490, 319, 510, 119, 457,3612, 274,2035,2007,4651,1409,3128, 970,2758, 590, # 3184 -2800, 661,2247,4652,2008,3950,1420,1549,3080,3322,3951,1651,1375,2111, 485,2491, # 3200 -1429,1156,6156,2548,2183,1495, 831,1840,2529,2446, 501,1657, 307,1894,3247,1341, # 3216 - 666, 899,2156,1539,2549,1559, 886, 349,2208,3081,2305,1736,3824,2170,2759,1014, # 3232 -1913,1386, 542,1397,2948, 490, 368, 716, 362, 159, 282,2569,1129,1658,1288,1750, # 3248 -2674, 276, 649,2016, 751,1496, 658,1818,1284,1862,2209,2087,2512,3451, 622,2834, # 3264 - 376, 117,1060,2053,1208,1721,1101,1443, 247,1250,3179,1792,3952,2760,2398,3953, # 3280 -6157,2144,3708, 446,2432,1151,2570,3452,2447,2761,2835,1210,2448,3082, 424,2222, # 3296 -1251,2449,2119,2836, 504,1581,4338, 602, 817, 857,3825,2349,2306, 357,3826,1470, # 3312 -1883,2883, 255, 958, 929,2917,3248, 302,4653,1050,1271,1751,2307,1952,1430,2697, # 3328 -2719,2359, 354,3180, 777, 158,2036,4339,1659,4340,4654,2308,2949,2248,1146,2232, # 3344 -3532,2720,1696,2623,3827,6158,3129,1550,2698,1485,1297,1428, 637, 931,2721,2145, # 3360 - 914,2550,2587, 81,2450, 612, 827,2646,1242,4655,1118,2884, 472,1855,3181,3533, # 3376 -3534, 569,1353,2699,1244,1758,2588,4119,2009,2762,2171,3709,1312,1531,6159,1152, # 3392 -1938, 134,1830, 471,3710,2276,1112,1535,3323,3453,3535, 982,1337,2950, 488, 826, # 3408 - 674,1058,1628,4120,2017, 522,2399, 211, 568,1367,3454, 350, 293,1872,1139,3249, # 3424 -1399,1946,3006,1300,2360,3324, 588, 736,6160,2606, 744, 669,3536,3828,6161,1358, # 3440 - 199, 723, 848, 933, 851,1939,1505,1514,1338,1618,1831,4656,1634,3613, 443,2740, # 3456 -3829, 717,1947, 491,1914,6162,2551,1542,4121,1025,6163,1099,1223, 198,3040,2722, # 3472 - 370, 410,1905,2589, 998,1248,3182,2380, 519,1449,4122,1710, 947, 928,1153,4341, # 3488 -2277, 344,2624,1511, 615, 105, 161,1212,1076,1960,3130,2054,1926,1175,1906,2473, # 3504 - 414,1873,2801,6164,2309, 315,1319,3325, 318,2018,2146,2157, 963, 631, 223,4342, # 3520 -4343,2675, 479,3711,1197,2625,3712,2676,2361,6165,4344,4123,6166,2451,3183,1886, # 3536 -2184,1674,1330,1711,1635,1506, 799, 219,3250,3083,3954,1677,3713,3326,2081,3614, # 3552 -1652,2073,4657,1147,3041,1752, 643,1961, 147,1974,3955,6167,1716,2037, 918,3007, # 3568 -1994, 120,1537, 118, 609,3184,4345, 740,3455,1219, 332,1615,3830,6168,1621,2980, # 3584 -1582, 783, 212, 553,2350,3714,1349,2433,2082,4124, 889,6169,2310,1275,1410, 973, # 3600 - 166,1320,3456,1797,1215,3185,2885,1846,2590,2763,4658, 629, 822,3008, 763, 940, # 3616 -1990,2862, 439,2409,1566,1240,1622, 926,1282,1907,2764, 654,2210,1607, 327,1130, # 3632 -3956,1678,1623,6170,2434,2192, 686, 608,3831,3715, 903,3957,3042,6171,2741,1522, # 3648 -1915,1105,1555,2552,1359, 323,3251,4346,3457, 738,1354,2553,2311,2334,1828,2003, # 3664 -3832,1753,2351,1227,6172,1887,4125,1478,6173,2410,1874,1712,1847, 520,1204,2607, # 3680 - 264,4659, 836,2677,2102, 600,4660,3833,2278,3084,6174,4347,3615,1342, 640, 532, # 3696 - 543,2608,1888,2400,2591,1009,4348,1497, 341,1737,3616,2723,1394, 529,3252,1321, # 3712 - 983,4661,1515,2120, 971,2592, 924, 287,1662,3186,4349,2700,4350,1519, 908,1948, # 3728 -2452, 156, 796,1629,1486,2223,2055, 694,4126,1259,1036,3392,1213,2249,2742,1889, # 3744 -1230,3958,1015, 910, 408, 559,3617,4662, 746, 725, 935,4663,3959,3009,1289, 563, # 3760 - 867,4664,3960,1567,2981,2038,2626, 988,2263,2381,4351, 143,2374, 704,1895,6175, # 3776 -1188,3716,2088, 673,3085,2362,4352, 484,1608,1921,2765,2918, 215, 904,3618,3537, # 3792 - 894, 509, 976,3043,2701,3961,4353,2837,2982, 498,6176,6177,1102,3538,1332,3393, # 3808 -1487,1636,1637, 233, 245,3962, 383, 650, 995,3044, 460,1520,1206,2352, 749,3327, # 3824 - 530, 700, 389,1438,1560,1773,3963,2264, 719,2951,2724,3834, 870,1832,1644,1000, # 3840 - 839,2474,3717, 197,1630,3394, 365,2886,3964,1285,2133, 734, 922, 818,1106, 732, # 3856 - 480,2083,1774,3458, 923,2279,1350, 221,3086, 85,2233,2234,3835,1585,3010,2147, # 3872 -1387,1705,2382,1619,2475, 133, 239,2802,1991,1016,2084,2383, 411,2838,1113, 651, # 3888 -1985,1160,3328, 990,1863,3087,1048,1276,2647, 265,2627,1599,3253,2056, 150, 638, # 3904 -2019, 656, 853, 326,1479, 680,1439,4354,1001,1759, 413,3459,3395,2492,1431, 459, # 3920 -4355,1125,3329,2265,1953,1450,2065,2863, 849, 351,2678,3131,3254,3255,1104,1577, # 3936 - 227,1351,1645,2453,2193,1421,2887, 812,2121, 634, 95,2435, 201,2312,4665,1646, # 3952 -1671,2743,1601,2554,2702,2648,2280,1315,1366,2089,3132,1573,3718,3965,1729,1189, # 3968 - 328,2679,1077,1940,1136, 558,1283, 964,1195, 621,2074,1199,1743,3460,3619,1896, # 3984 -1916,1890,3836,2952,1154,2112,1064, 862, 378,3011,2066,2113,2803,1568,2839,6178, # 4000 -3088,2919,1941,1660,2004,1992,2194, 142, 707,1590,1708,1624,1922,1023,1836,1233, # 4016 -1004,2313, 789, 741,3620,6179,1609,2411,1200,4127,3719,3720,4666,2057,3721, 593, # 4032 -2840, 367,2920,1878,6180,3461,1521, 628,1168, 692,2211,2649, 300, 720,2067,2571, # 4048 -2953,3396, 959,2504,3966,3539,3462,1977, 701,6181, 954,1043, 800, 681, 183,3722, # 4064 -1803,1730,3540,4128,2103, 815,2314, 174, 467, 230,2454,1093,2134, 755,3541,3397, # 4080 -1141,1162,6182,1738,2039, 270,3256,2513,1005,1647,2185,3837, 858,1679,1897,1719, # 4096 -2954,2324,1806, 402, 670, 167,4129,1498,2158,2104, 750,6183, 915, 189,1680,1551, # 4112 - 455,4356,1501,2455, 405,1095,2955, 338,1586,1266,1819, 570, 641,1324, 237,1556, # 4128 -2650,1388,3723,6184,1368,2384,1343,1978,3089,2436, 879,3724, 792,1191, 758,3012, # 4144 -1411,2135,1322,4357, 240,4667,1848,3725,1574,6185, 420,3045,1546,1391, 714,4358, # 4160 -1967, 941,1864, 863, 664, 426, 560,1731,2680,1785,2864,1949,2363, 403,3330,1415, # 4176 -1279,2136,1697,2335, 204, 721,2097,3838, 90,6186,2085,2505, 191,3967, 124,2148, # 4192 -1376,1798,1178,1107,1898,1405, 860,4359,1243,1272,2375,2983,1558,2456,1638, 113, # 4208 -3621, 578,1923,2609, 880, 386,4130, 784,2186,2266,1422,2956,2172,1722, 497, 263, # 4224 -2514,1267,2412,2610, 177,2703,3542, 774,1927,1344, 616,1432,1595,1018, 172,4360, # 4240 -2325, 911,4361, 438,1468,3622, 794,3968,2024,2173,1681,1829,2957, 945, 895,3090, # 4256 - 575,2212,2476, 475,2401,2681, 785,2744,1745,2293,2555,1975,3133,2865, 394,4668, # 4272 -3839, 635,4131, 639, 202,1507,2195,2766,1345,1435,2572,3726,1908,1184,1181,2457, # 4288 -3727,3134,4362, 843,2611, 437, 916,4669, 234, 769,1884,3046,3047,3623, 833,6187, # 4304 -1639,2250,2402,1355,1185,2010,2047, 999, 525,1732,1290,1488,2612, 948,1578,3728, # 4320 -2413,2477,1216,2725,2159, 334,3840,1328,3624,2921,1525,4132, 564,1056, 891,4363, # 4336 -1444,1698,2385,2251,3729,1365,2281,2235,1717,6188, 864,3841,2515, 444, 527,2767, # 4352 -2922,3625, 544, 461,6189, 566, 209,2437,3398,2098,1065,2068,3331,3626,3257,2137, # 4368 #last 512 -) - - diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/jpcntx.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/jpcntx.py deleted file mode 100644 index 20044e4..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/jpcntx.py +++ /dev/null @@ -1,233 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - - -# This is hiragana 2-char sequence table, the number in each cell represents its frequency category -jp2CharContext = ( -(0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1), -(2,4,0,4,0,3,0,4,0,3,4,4,4,2,4,3,3,4,3,2,3,3,4,2,3,3,3,2,4,1,4,3,3,1,5,4,3,4,3,4,3,5,3,0,3,5,4,2,0,3,1,0,3,3,0,3,3,0,1,1,0,4,3,0,3,3,0,4,0,2,0,3,5,5,5,5,4,0,4,1,0,3,4), -(0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2), -(0,4,0,5,0,5,0,4,0,4,5,4,4,3,5,3,5,1,5,3,4,3,4,4,3,4,3,3,4,3,5,4,4,3,5,5,3,5,5,5,3,5,5,3,4,5,5,3,1,3,2,0,3,4,0,4,2,0,4,2,1,5,3,2,3,5,0,4,0,2,0,5,4,4,5,4,5,0,4,0,0,4,4), -(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), -(0,3,0,4,0,3,0,3,0,4,5,4,3,3,3,3,4,3,5,4,4,3,5,4,4,3,4,3,4,4,4,4,5,3,4,4,3,4,5,5,4,5,5,1,4,5,4,3,0,3,3,1,3,3,0,4,4,0,3,3,1,5,3,3,3,5,0,4,0,3,0,4,4,3,4,3,3,0,4,1,1,3,4), -(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), -(0,4,0,3,0,3,0,4,0,3,4,4,3,2,2,1,2,1,3,1,3,3,3,3,3,4,3,1,3,3,5,3,3,0,4,3,0,5,4,3,3,5,4,4,3,4,4,5,0,1,2,0,1,2,0,2,2,0,1,0,0,5,2,2,1,4,0,3,0,1,0,4,4,3,5,4,3,0,2,1,0,4,3), -(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), -(0,3,0,5,0,4,0,2,1,4,4,2,4,1,4,2,4,2,4,3,3,3,4,3,3,3,3,1,4,2,3,3,3,1,4,4,1,1,1,4,3,3,2,0,2,4,3,2,0,3,3,0,3,1,1,0,0,0,3,3,0,4,2,2,3,4,0,4,0,3,0,4,4,5,3,4,4,0,3,0,0,1,4), -(1,4,0,4,0,4,0,4,0,3,5,4,4,3,4,3,5,4,3,3,4,3,5,4,4,4,4,3,4,2,4,3,3,1,5,4,3,2,4,5,4,5,5,4,4,5,4,4,0,3,2,2,3,3,0,4,3,1,3,2,1,4,3,3,4,5,0,3,0,2,0,4,5,5,4,5,4,0,4,0,0,5,4), -(0,5,0,5,0,4,0,3,0,4,4,3,4,3,3,3,4,0,4,4,4,3,4,3,4,3,3,1,4,2,4,3,4,0,5,4,1,4,5,4,4,5,3,2,4,3,4,3,2,4,1,3,3,3,2,3,2,0,4,3,3,4,3,3,3,4,0,4,0,3,0,4,5,4,4,4,3,0,4,1,0,1,3), -(0,3,1,4,0,3,0,2,0,3,4,4,3,1,4,2,3,3,4,3,4,3,4,3,4,4,3,2,3,1,5,4,4,1,4,4,3,5,4,4,3,5,5,4,3,4,4,3,1,2,3,1,2,2,0,3,2,0,3,1,0,5,3,3,3,4,3,3,3,3,4,4,4,4,5,4,2,0,3,3,2,4,3), -(0,2,0,3,0,1,0,1,0,0,3,2,0,0,2,0,1,0,2,1,3,3,3,1,2,3,1,0,1,0,4,2,1,1,3,3,0,4,3,3,1,4,3,3,0,3,3,2,0,0,0,0,1,0,0,2,0,0,0,0,0,4,1,0,2,3,2,2,2,1,3,3,3,4,4,3,2,0,3,1,0,3,3), -(0,4,0,4,0,3,0,3,0,4,4,4,3,3,3,3,3,3,4,3,4,2,4,3,4,3,3,2,4,3,4,5,4,1,4,5,3,5,4,5,3,5,4,0,3,5,5,3,1,3,3,2,2,3,0,3,4,1,3,3,2,4,3,3,3,4,0,4,0,3,0,4,5,4,4,5,3,0,4,1,0,3,4), -(0,2,0,3,0,3,0,0,0,2,2,2,1,0,1,0,0,0,3,0,3,0,3,0,1,3,1,0,3,1,3,3,3,1,3,3,3,0,1,3,1,3,4,0,0,3,1,1,0,3,2,0,0,0,0,1,3,0,1,0,0,3,3,2,0,3,0,0,0,0,0,3,4,3,4,3,3,0,3,0,0,2,3), -(2,3,0,3,0,2,0,1,0,3,3,4,3,1,3,1,1,1,3,1,4,3,4,3,3,3,0,0,3,1,5,4,3,1,4,3,2,5,5,4,4,4,4,3,3,4,4,4,0,2,1,1,3,2,0,1,2,0,0,1,0,4,1,3,3,3,0,3,0,1,0,4,4,4,5,5,3,0,2,0,0,4,4), -(0,2,0,1,0,3,1,3,0,2,3,3,3,0,3,1,0,0,3,0,3,2,3,1,3,2,1,1,0,0,4,2,1,0,2,3,1,4,3,2,0,4,4,3,1,3,1,3,0,1,0,0,1,0,0,0,1,0,0,0,0,4,1,1,1,2,0,3,0,0,0,3,4,2,4,3,2,0,1,0,0,3,3), -(0,1,0,4,0,5,0,4,0,2,4,4,2,3,3,2,3,3,5,3,3,3,4,3,4,2,3,0,4,3,3,3,4,1,4,3,2,1,5,5,3,4,5,1,3,5,4,2,0,3,3,0,1,3,0,4,2,0,1,3,1,4,3,3,3,3,0,3,0,1,0,3,4,4,4,5,5,0,3,0,1,4,5), -(0,2,0,3,0,3,0,0,0,2,3,1,3,0,4,0,1,1,3,0,3,4,3,2,3,1,0,3,3,2,3,1,3,0,2,3,0,2,1,4,1,2,2,0,0,3,3,0,0,2,0,0,0,1,0,0,0,0,2,2,0,3,2,1,3,3,0,2,0,2,0,0,3,3,1,2,4,0,3,0,2,2,3), -(2,4,0,5,0,4,0,4,0,2,4,4,4,3,4,3,3,3,1,2,4,3,4,3,4,4,5,0,3,3,3,3,2,0,4,3,1,4,3,4,1,4,4,3,3,4,4,3,1,2,3,0,4,2,0,4,1,0,3,3,0,4,3,3,3,4,0,4,0,2,0,3,5,3,4,5,2,0,3,0,0,4,5), -(0,3,0,4,0,1,0,1,0,1,3,2,2,1,3,0,3,0,2,0,2,0,3,0,2,0,0,0,1,0,1,1,0,0,3,1,0,0,0,4,0,3,1,0,2,1,3,0,0,0,0,0,0,3,0,0,0,0,0,0,0,4,2,2,3,1,0,3,0,0,0,1,4,4,4,3,0,0,4,0,0,1,4), -(1,4,1,5,0,3,0,3,0,4,5,4,4,3,5,3,3,4,4,3,4,1,3,3,3,3,2,1,4,1,5,4,3,1,4,4,3,5,4,4,3,5,4,3,3,4,4,4,0,3,3,1,2,3,0,3,1,0,3,3,0,5,4,4,4,4,4,4,3,3,5,4,4,3,3,5,4,0,3,2,0,4,4), -(0,2,0,3,0,1,0,0,0,1,3,3,3,2,4,1,3,0,3,1,3,0,2,2,1,1,0,0,2,0,4,3,1,0,4,3,0,4,4,4,1,4,3,1,1,3,3,1,0,2,0,0,1,3,0,0,0,0,2,0,0,4,3,2,4,3,5,4,3,3,3,4,3,3,4,3,3,0,2,1,0,3,3), -(0,2,0,4,0,3,0,2,0,2,5,5,3,4,4,4,4,1,4,3,3,0,4,3,4,3,1,3,3,2,4,3,0,3,4,3,0,3,4,4,2,4,4,0,4,5,3,3,2,2,1,1,1,2,0,1,5,0,3,3,2,4,3,3,3,4,0,3,0,2,0,4,4,3,5,5,0,0,3,0,2,3,3), -(0,3,0,4,0,3,0,1,0,3,4,3,3,1,3,3,3,0,3,1,3,0,4,3,3,1,1,0,3,0,3,3,0,0,4,4,0,1,5,4,3,3,5,0,3,3,4,3,0,2,0,1,1,1,0,1,3,0,1,2,1,3,3,2,3,3,0,3,0,1,0,1,3,3,4,4,1,0,1,2,2,1,3), -(0,1,0,4,0,4,0,3,0,1,3,3,3,2,3,1,1,0,3,0,3,3,4,3,2,4,2,0,1,0,4,3,2,0,4,3,0,5,3,3,2,4,4,4,3,3,3,4,0,1,3,0,0,1,0,0,1,0,0,0,0,4,2,3,3,3,0,3,0,0,0,4,4,4,5,3,2,0,3,3,0,3,5), -(0,2,0,3,0,0,0,3,0,1,3,0,2,0,0,0,1,0,3,1,1,3,3,0,0,3,0,0,3,0,2,3,1,0,3,1,0,3,3,2,0,4,2,2,0,2,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,2,1,2,0,1,0,1,0,0,0,1,3,1,2,0,0,0,1,0,0,1,4), -(0,3,0,3,0,5,0,1,0,2,4,3,1,3,3,2,1,1,5,2,1,0,5,1,2,0,0,0,3,3,2,2,3,2,4,3,0,0,3,3,1,3,3,0,2,5,3,4,0,3,3,0,1,2,0,2,2,0,3,2,0,2,2,3,3,3,0,2,0,1,0,3,4,4,2,5,4,0,3,0,0,3,5), -(0,3,0,3,0,3,0,1,0,3,3,3,3,0,3,0,2,0,2,1,1,0,2,0,1,0,0,0,2,1,0,0,1,0,3,2,0,0,3,3,1,2,3,1,0,3,3,0,0,1,0,0,0,0,0,2,0,0,0,0,0,2,3,1,2,3,0,3,0,1,0,3,2,1,0,4,3,0,1,1,0,3,3), -(0,4,0,5,0,3,0,3,0,4,5,5,4,3,5,3,4,3,5,3,3,2,5,3,4,4,4,3,4,3,4,5,5,3,4,4,3,4,4,5,4,4,4,3,4,5,5,4,2,3,4,2,3,4,0,3,3,1,4,3,2,4,3,3,5,5,0,3,0,3,0,5,5,5,5,4,4,0,4,0,1,4,4), -(0,4,0,4,0,3,0,3,0,3,5,4,4,2,3,2,5,1,3,2,5,1,4,2,3,2,3,3,4,3,3,3,3,2,5,4,1,3,3,5,3,4,4,0,4,4,3,1,1,3,1,0,2,3,0,2,3,0,3,0,0,4,3,1,3,4,0,3,0,2,0,4,4,4,3,4,5,0,4,0,0,3,4), -(0,3,0,3,0,3,1,2,0,3,4,4,3,3,3,0,2,2,4,3,3,1,3,3,3,1,1,0,3,1,4,3,2,3,4,4,2,4,4,4,3,4,4,3,2,4,4,3,1,3,3,1,3,3,0,4,1,0,2,2,1,4,3,2,3,3,5,4,3,3,5,4,4,3,3,0,4,0,3,2,2,4,4), -(0,2,0,1,0,0,0,0,0,1,2,1,3,0,0,0,0,0,2,0,1,2,1,0,0,1,0,0,0,0,3,0,0,1,0,1,1,3,1,0,0,0,1,1,0,1,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,1,2,2,0,3,4,0,0,0,1,1,0,0,1,0,0,0,0,0,1,1), -(0,1,0,0,0,1,0,0,0,0,4,0,4,1,4,0,3,0,4,0,3,0,4,0,3,0,3,0,4,1,5,1,4,0,0,3,0,5,0,5,2,0,1,0,0,0,2,1,4,0,1,3,0,0,3,0,0,3,1,1,4,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0), -(1,4,0,5,0,3,0,2,0,3,5,4,4,3,4,3,5,3,4,3,3,0,4,3,3,3,3,3,3,2,4,4,3,1,3,4,4,5,4,4,3,4,4,1,3,5,4,3,3,3,1,2,2,3,3,1,3,1,3,3,3,5,3,3,4,5,0,3,0,3,0,3,4,3,4,4,3,0,3,0,2,4,3), -(0,1,0,4,0,0,0,0,0,1,4,0,4,1,4,2,4,0,3,0,1,0,1,0,0,0,0,0,2,0,3,1,1,1,0,3,0,0,0,1,2,1,0,0,1,1,1,1,0,1,0,0,0,1,0,0,3,0,0,0,0,3,2,0,2,2,0,1,0,0,0,2,3,2,3,3,0,0,0,0,2,1,0), -(0,5,1,5,0,3,0,3,0,5,4,4,5,1,5,3,3,0,4,3,4,3,5,3,4,3,3,2,4,3,4,3,3,0,3,3,1,4,4,3,4,4,4,3,4,5,5,3,2,3,1,1,3,3,1,3,1,1,3,3,2,4,5,3,3,5,0,4,0,3,0,4,4,3,5,3,3,0,3,4,0,4,3), -(0,5,0,5,0,3,0,2,0,4,4,3,5,2,4,3,3,3,4,4,4,3,5,3,5,3,3,1,4,0,4,3,3,0,3,3,0,4,4,4,4,5,4,3,3,5,5,3,2,3,1,2,3,2,0,1,0,0,3,2,2,4,4,3,1,5,0,4,0,3,0,4,3,1,3,2,1,0,3,3,0,3,3), -(0,4,0,5,0,5,0,4,0,4,5,5,5,3,4,3,3,2,5,4,4,3,5,3,5,3,4,0,4,3,4,4,3,2,4,4,3,4,5,4,4,5,5,0,3,5,5,4,1,3,3,2,3,3,1,3,1,0,4,3,1,4,4,3,4,5,0,4,0,2,0,4,3,4,4,3,3,0,4,0,0,5,5), -(0,4,0,4,0,5,0,1,1,3,3,4,4,3,4,1,3,0,5,1,3,0,3,1,3,1,1,0,3,0,3,3,4,0,4,3,0,4,4,4,3,4,4,0,3,5,4,1,0,3,0,0,2,3,0,3,1,0,3,1,0,3,2,1,3,5,0,3,0,1,0,3,2,3,3,4,4,0,2,2,0,4,4), -(2,4,0,5,0,4,0,3,0,4,5,5,4,3,5,3,5,3,5,3,5,2,5,3,4,3,3,4,3,4,5,3,2,1,5,4,3,2,3,4,5,3,4,1,2,5,4,3,0,3,3,0,3,2,0,2,3,0,4,1,0,3,4,3,3,5,0,3,0,1,0,4,5,5,5,4,3,0,4,2,0,3,5), -(0,5,0,4,0,4,0,2,0,5,4,3,4,3,4,3,3,3,4,3,4,2,5,3,5,3,4,1,4,3,4,4,4,0,3,5,0,4,4,4,4,5,3,1,3,4,5,3,3,3,3,3,3,3,0,2,2,0,3,3,2,4,3,3,3,5,3,4,1,3,3,5,3,2,0,0,0,0,4,3,1,3,3), -(0,1,0,3,0,3,0,1,0,1,3,3,3,2,3,3,3,0,3,0,0,0,3,1,3,0,0,0,2,2,2,3,0,0,3,2,0,1,2,4,1,3,3,0,0,3,3,3,0,1,0,0,2,1,0,0,3,0,3,1,0,3,0,0,1,3,0,2,0,1,0,3,3,1,3,3,0,0,1,1,0,3,3), -(0,2,0,3,0,2,1,4,0,2,2,3,1,1,3,1,1,0,2,0,3,1,2,3,1,3,0,0,1,0,4,3,2,3,3,3,1,4,2,3,3,3,3,1,0,3,1,4,0,1,1,0,1,2,0,1,1,0,1,1,0,3,1,3,2,2,0,1,0,0,0,2,3,3,3,1,0,0,0,0,0,2,3), -(0,5,0,4,0,5,0,2,0,4,5,5,3,3,4,3,3,1,5,4,4,2,4,4,4,3,4,2,4,3,5,5,4,3,3,4,3,3,5,5,4,5,5,1,3,4,5,3,1,4,3,1,3,3,0,3,3,1,4,3,1,4,5,3,3,5,0,4,0,3,0,5,3,3,1,4,3,0,4,0,1,5,3), -(0,5,0,5,0,4,0,2,0,4,4,3,4,3,3,3,3,3,5,4,4,4,4,4,4,5,3,3,5,2,4,4,4,3,4,4,3,3,4,4,5,5,3,3,4,3,4,3,3,4,3,3,3,3,1,2,2,1,4,3,3,5,4,4,3,4,0,4,0,3,0,4,4,4,4,4,1,0,4,2,0,2,4), -(0,4,0,4,0,3,0,1,0,3,5,2,3,0,3,0,2,1,4,2,3,3,4,1,4,3,3,2,4,1,3,3,3,0,3,3,0,0,3,3,3,5,3,3,3,3,3,2,0,2,0,0,2,0,0,2,0,0,1,0,0,3,1,2,2,3,0,3,0,2,0,4,4,3,3,4,1,0,3,0,0,2,4), -(0,0,0,4,0,0,0,0,0,0,1,0,1,0,2,0,0,0,0,0,1,0,2,0,1,0,0,0,0,0,3,1,3,0,3,2,0,0,0,1,0,3,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,4,0,2,0,0,0,0,0,0,2), -(0,2,1,3,0,2,0,2,0,3,3,3,3,1,3,1,3,3,3,3,3,3,4,2,2,1,2,1,4,0,4,3,1,3,3,3,2,4,3,5,4,3,3,3,3,3,3,3,0,1,3,0,2,0,0,1,0,0,1,0,0,4,2,0,2,3,0,3,3,0,3,3,4,2,3,1,4,0,1,2,0,2,3), -(0,3,0,3,0,1,0,3,0,2,3,3,3,0,3,1,2,0,3,3,2,3,3,2,3,2,3,1,3,0,4,3,2,0,3,3,1,4,3,3,2,3,4,3,1,3,3,1,1,0,1,1,0,1,0,1,0,1,0,0,0,4,1,1,0,3,0,3,1,0,2,3,3,3,3,3,1,0,0,2,0,3,3), -(0,0,0,0,0,0,0,0,0,0,3,0,2,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,3,0,3,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,2,0,2,3,0,0,0,0,0,0,0,0,3), -(0,2,0,3,1,3,0,3,0,2,3,3,3,1,3,1,3,1,3,1,3,3,3,1,3,0,2,3,1,1,4,3,3,2,3,3,1,2,2,4,1,3,3,0,1,4,2,3,0,1,3,0,3,0,0,1,3,0,2,0,0,3,3,2,1,3,0,3,0,2,0,3,4,4,4,3,1,0,3,0,0,3,3), -(0,2,0,1,0,2,0,0,0,1,3,2,2,1,3,0,1,1,3,0,3,2,3,1,2,0,2,0,1,1,3,3,3,0,3,3,1,1,2,3,2,3,3,1,2,3,2,0,0,1,0,0,0,0,0,0,3,0,1,0,0,2,1,2,1,3,0,3,0,0,0,3,4,4,4,3,2,0,2,0,0,2,4), -(0,0,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,2,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,3,1,0,0,0,0,0,0,0,3), -(0,3,0,3,0,2,0,3,0,3,3,3,2,3,2,2,2,0,3,1,3,3,3,2,3,3,0,0,3,0,3,2,2,0,2,3,1,4,3,4,3,3,2,3,1,5,4,4,0,3,1,2,1,3,0,3,1,1,2,0,2,3,1,3,1,3,0,3,0,1,0,3,3,4,4,2,1,0,2,1,0,2,4), -(0,1,0,3,0,1,0,2,0,1,4,2,5,1,4,0,2,0,2,1,3,1,4,0,2,1,0,0,2,1,4,1,1,0,3,3,0,5,1,3,2,3,3,1,0,3,2,3,0,1,0,0,0,0,0,0,1,0,0,0,0,4,0,1,0,3,0,2,0,1,0,3,3,3,4,3,3,0,0,0,0,2,3), -(0,0,0,1,0,0,0,0,0,0,2,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,0,0,1,0,0,0,0,0,3), -(0,1,0,3,0,4,0,3,0,2,4,3,1,0,3,2,2,1,3,1,2,2,3,1,1,1,2,1,3,0,1,2,0,1,3,2,1,3,0,5,5,1,0,0,1,3,2,1,0,3,0,0,1,0,0,0,0,0,3,4,0,1,1,1,3,2,0,2,0,1,0,2,3,3,1,2,3,0,1,0,1,0,4), -(0,0,0,1,0,3,0,3,0,2,2,1,0,0,4,0,3,0,3,1,3,0,3,0,3,0,1,0,3,0,3,1,3,0,3,3,0,0,1,2,1,1,1,0,1,2,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,2,2,1,2,0,0,2,0,0,0,0,2,3,3,3,3,0,0,0,0,1,4), -(0,0,0,3,0,3,0,0,0,0,3,1,1,0,3,0,1,0,2,0,1,0,0,0,0,0,0,0,1,0,3,0,2,0,2,3,0,0,2,2,3,1,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,2,0,0,0,0,2,3), -(2,4,0,5,0,5,0,4,0,3,4,3,3,3,4,3,3,3,4,3,4,4,5,4,5,5,5,2,3,0,5,5,4,1,5,4,3,1,5,4,3,4,4,3,3,4,3,3,0,3,2,0,2,3,0,3,0,0,3,3,0,5,3,2,3,3,0,3,0,3,0,3,4,5,4,5,3,0,4,3,0,3,4), -(0,3,0,3,0,3,0,3,0,3,3,4,3,2,3,2,3,0,4,3,3,3,3,3,3,3,3,0,3,2,4,3,3,1,3,4,3,4,4,4,3,4,4,3,2,4,4,1,0,2,0,0,1,1,0,2,0,0,3,1,0,5,3,2,1,3,0,3,0,1,2,4,3,2,4,3,3,0,3,2,0,4,4), -(0,3,0,3,0,1,0,0,0,1,4,3,3,2,3,1,3,1,4,2,3,2,4,2,3,4,3,0,2,2,3,3,3,0,3,3,3,0,3,4,1,3,3,0,3,4,3,3,0,1,1,0,1,0,0,0,4,0,3,0,0,3,1,2,1,3,0,4,0,1,0,4,3,3,4,3,3,0,2,0,0,3,3), -(0,3,0,4,0,1,0,3,0,3,4,3,3,0,3,3,3,1,3,1,3,3,4,3,3,3,0,0,3,1,5,3,3,1,3,3,2,5,4,3,3,4,5,3,2,5,3,4,0,1,0,0,0,0,0,2,0,0,1,1,0,4,2,2,1,3,0,3,0,2,0,4,4,3,5,3,2,0,1,1,0,3,4), -(0,5,0,4,0,5,0,2,0,4,4,3,3,2,3,3,3,1,4,3,4,1,5,3,4,3,4,0,4,2,4,3,4,1,5,4,0,4,4,4,4,5,4,1,3,5,4,2,1,4,1,1,3,2,0,3,1,0,3,2,1,4,3,3,3,4,0,4,0,3,0,4,4,4,3,3,3,0,4,2,0,3,4), -(1,4,0,4,0,3,0,1,0,3,3,3,1,1,3,3,2,2,3,3,1,0,3,2,2,1,2,0,3,1,2,1,2,0,3,2,0,2,2,3,3,4,3,0,3,3,1,2,0,1,1,3,1,2,0,0,3,0,1,1,0,3,2,2,3,3,0,3,0,0,0,2,3,3,4,3,3,0,1,0,0,1,4), -(0,4,0,4,0,4,0,0,0,3,4,4,3,1,4,2,3,2,3,3,3,1,4,3,4,0,3,0,4,2,3,3,2,2,5,4,2,1,3,4,3,4,3,1,3,3,4,2,0,2,1,0,3,3,0,0,2,0,3,1,0,4,4,3,4,3,0,4,0,1,0,2,4,4,4,4,4,0,3,2,0,3,3), -(0,0,0,1,0,4,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,3,2,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,2), -(0,2,0,3,0,4,0,4,0,1,3,3,3,0,4,0,2,1,2,1,1,1,2,0,3,1,1,0,1,0,3,1,0,0,3,3,2,0,1,1,0,0,0,0,0,1,0,2,0,2,2,0,3,1,0,0,1,0,1,1,0,1,2,0,3,0,0,0,0,1,0,0,3,3,4,3,1,0,1,0,3,0,2), -(0,0,0,3,0,5,0,0,0,0,1,0,2,0,3,1,0,1,3,0,0,0,2,0,0,0,1,0,0,0,1,1,0,0,4,0,0,0,2,3,0,1,4,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,1,0,0,0,0,0,0,0,2,0,0,3,0,0,0,0,0,3), -(0,2,0,5,0,5,0,1,0,2,4,3,3,2,5,1,3,2,3,3,3,0,4,1,2,0,3,0,4,0,2,2,1,1,5,3,0,0,1,4,2,3,2,0,3,3,3,2,0,2,4,1,1,2,0,1,1,0,3,1,0,1,3,1,2,3,0,2,0,0,0,1,3,5,4,4,4,0,3,0,0,1,3), -(0,4,0,5,0,4,0,4,0,4,5,4,3,3,4,3,3,3,4,3,4,4,5,3,4,5,4,2,4,2,3,4,3,1,4,4,1,3,5,4,4,5,5,4,4,5,5,5,2,3,3,1,4,3,1,3,3,0,3,3,1,4,3,4,4,4,0,3,0,4,0,3,3,4,4,5,0,0,4,3,0,4,5), -(0,4,0,4,0,3,0,3,0,3,4,4,4,3,3,2,4,3,4,3,4,3,5,3,4,3,2,1,4,2,4,4,3,1,3,4,2,4,5,5,3,4,5,4,1,5,4,3,0,3,2,2,3,2,1,3,1,0,3,3,3,5,3,3,3,5,4,4,2,3,3,4,3,3,3,2,1,0,3,2,1,4,3), -(0,4,0,5,0,4,0,3,0,3,5,5,3,2,4,3,4,0,5,4,4,1,4,4,4,3,3,3,4,3,5,5,2,3,3,4,1,2,5,5,3,5,5,2,3,5,5,4,0,3,2,0,3,3,1,1,5,1,4,1,0,4,3,2,3,5,0,4,0,3,0,5,4,3,4,3,0,0,4,1,0,4,4), -(1,3,0,4,0,2,0,2,0,2,5,5,3,3,3,3,3,0,4,2,3,4,4,4,3,4,0,0,3,4,5,4,3,3,3,3,2,5,5,4,5,5,5,4,3,5,5,5,1,3,1,0,1,0,0,3,2,0,4,2,0,5,2,3,2,4,1,3,0,3,0,4,5,4,5,4,3,0,4,2,0,5,4), -(0,3,0,4,0,5,0,3,0,3,4,4,3,2,3,2,3,3,3,3,3,2,4,3,3,2,2,0,3,3,3,3,3,1,3,3,3,0,4,4,3,4,4,1,1,4,4,2,0,3,1,0,1,1,0,4,1,0,2,3,1,3,3,1,3,4,0,3,0,1,0,3,1,3,0,0,1,0,2,0,0,4,4), -(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), -(0,3,0,3,0,2,0,3,0,1,5,4,3,3,3,1,4,2,1,2,3,4,4,2,4,4,5,0,3,1,4,3,4,0,4,3,3,3,2,3,2,5,3,4,3,2,2,3,0,0,3,0,2,1,0,1,2,0,0,0,0,2,1,1,3,1,0,2,0,4,0,3,4,4,4,5,2,0,2,0,0,1,3), -(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,1,1,0,0,0,4,2,1,1,0,1,0,3,2,0,0,3,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,1,0,0,0,2,0,0,0,1,4,0,4,2,1,0,0,0,0,0,1), -(0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,0,3,1,0,0,0,2,0,2,1,0,0,1,2,1,0,1,1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,1,3,1,0,0,0,0,0,1,0,0,2,1,0,0,0,0,0,0,0,0,2), -(0,4,0,4,0,4,0,3,0,4,4,3,4,2,4,3,2,0,4,4,4,3,5,3,5,3,3,2,4,2,4,3,4,3,1,4,0,2,3,4,4,4,3,3,3,4,4,4,3,4,1,3,4,3,2,1,2,1,3,3,3,4,4,3,3,5,0,4,0,3,0,4,3,3,3,2,1,0,3,0,0,3,3), -(0,4,0,3,0,3,0,3,0,3,5,5,3,3,3,3,4,3,4,3,3,3,4,4,4,3,3,3,3,4,3,5,3,3,1,3,2,4,5,5,5,5,4,3,4,5,5,3,2,2,3,3,3,3,2,3,3,1,2,3,2,4,3,3,3,4,0,4,0,2,0,4,3,2,2,1,2,0,3,0,0,4,1), -) - -class JapaneseContextAnalysis(object): - NUM_OF_CATEGORY = 6 - DONT_KNOW = -1 - ENOUGH_REL_THRESHOLD = 100 - MAX_REL_THRESHOLD = 1000 - MINIMUM_DATA_THRESHOLD = 4 - - def __init__(self): - self._total_rel = None - self._rel_sample = None - self._need_to_skip_char_num = None - self._last_char_order = None - self._done = None - self.reset() - - def reset(self): - self._total_rel = 0 # total sequence received - # category counters, each integer counts sequence in its category - self._rel_sample = [0] * self.NUM_OF_CATEGORY - # if last byte in current buffer is not the last byte of a character, - # we need to know how many bytes to skip in next buffer - self._need_to_skip_char_num = 0 - self._last_char_order = -1 # The order of previous char - # If this flag is set to True, detection is done and conclusion has - # been made - self._done = False - - def feed(self, byte_str, num_bytes): - if self._done: - return - - # The buffer we got is byte oriented, and a character may span in more than one - # buffers. In case the last one or two byte in last buffer is not - # complete, we record how many byte needed to complete that character - # and skip these bytes here. We can choose to record those bytes as - # well and analyse the character once it is complete, but since a - # character will not make much difference, by simply skipping - # this character will simply our logic and improve performance. - i = self._need_to_skip_char_num - while i < num_bytes: - order, char_len = self.get_order(byte_str[i:i + 2]) - i += char_len - if i > num_bytes: - self._need_to_skip_char_num = i - num_bytes - self._last_char_order = -1 - else: - if (order != -1) and (self._last_char_order != -1): - self._total_rel += 1 - if self._total_rel > self.MAX_REL_THRESHOLD: - self._done = True - break - self._rel_sample[jp2CharContext[self._last_char_order][order]] += 1 - self._last_char_order = order - - def got_enough_data(self): - return self._total_rel > self.ENOUGH_REL_THRESHOLD - - def get_confidence(self): - # This is just one way to calculate confidence. It works well for me. - if self._total_rel > self.MINIMUM_DATA_THRESHOLD: - return (self._total_rel - self._rel_sample[0]) / self._total_rel - else: - return self.DONT_KNOW - - def get_order(self, byte_str): - return -1, 1 - -class SJISContextAnalysis(JapaneseContextAnalysis): - def __init__(self): - super(SJISContextAnalysis, self).__init__() - self._charset_name = "SHIFT_JIS" - - @property - def charset_name(self): - return self._charset_name - - def get_order(self, byte_str): - if not byte_str: - return -1, 1 - # find out current char's byte length - first_char = byte_str[0] - if (0x81 <= first_char <= 0x9F) or (0xE0 <= first_char <= 0xFC): - char_len = 2 - if (first_char == 0x87) or (0xFA <= first_char <= 0xFC): - self._charset_name = "CP932" - else: - char_len = 1 - - # return its order if it is hiragana - if len(byte_str) > 1: - second_char = byte_str[1] - if (first_char == 202) and (0x9F <= second_char <= 0xF1): - return second_char - 0x9F, char_len - - return -1, char_len - -class EUCJPContextAnalysis(JapaneseContextAnalysis): - def get_order(self, byte_str): - if not byte_str: - return -1, 1 - # find out current char's byte length - first_char = byte_str[0] - if (first_char == 0x8E) or (0xA1 <= first_char <= 0xFE): - char_len = 2 - elif first_char == 0x8F: - char_len = 3 - else: - char_len = 1 - - # return its order if it is hiragana - if len(byte_str) > 1: - second_char = byte_str[1] - if (first_char == 0xA4) and (0xA1 <= second_char <= 0xF3): - return second_char - 0xA1, char_len - - return -1, char_len - - diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langbulgarianmodel.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langbulgarianmodel.py deleted file mode 100644 index 2aa4fb2..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langbulgarianmodel.py +++ /dev/null @@ -1,228 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -# 255: Control characters that usually does not exist in any text -# 254: Carriage/Return -# 253: symbol (punctuation) that does not belong to word -# 252: 0 - 9 - -# Character Mapping Table: -# this table is modified base on win1251BulgarianCharToOrderMap, so -# only number <64 is sure valid - -Latin5_BulgarianCharToOrderMap = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253, 77, 90, 99,100, 72,109,107,101, 79,185, 81,102, 76, 94, 82, # 40 -110,186,108, 91, 74,119, 84, 96,111,187,115,253,253,253,253,253, # 50 -253, 65, 69, 70, 66, 63, 68,112,103, 92,194,104, 95, 86, 87, 71, # 60 -116,195, 85, 93, 97,113,196,197,198,199,200,253,253,253,253,253, # 70 -194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209, # 80 -210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225, # 90 - 81,226,227,228,229,230,105,231,232,233,234,235,236, 45,237,238, # a0 - 31, 32, 35, 43, 37, 44, 55, 47, 40, 59, 33, 46, 38, 36, 41, 30, # b0 - 39, 28, 34, 51, 48, 49, 53, 50, 54, 57, 61,239, 67,240, 60, 56, # c0 - 1, 18, 9, 20, 11, 3, 23, 15, 2, 26, 12, 10, 14, 6, 4, 13, # d0 - 7, 8, 5, 19, 29, 25, 22, 21, 27, 24, 17, 75, 52,241, 42, 16, # e0 - 62,242,243,244, 58,245, 98,246,247,248,249,250,251, 91,252,253, # f0 -) - -win1251BulgarianCharToOrderMap = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253, 77, 90, 99,100, 72,109,107,101, 79,185, 81,102, 76, 94, 82, # 40 -110,186,108, 91, 74,119, 84, 96,111,187,115,253,253,253,253,253, # 50 -253, 65, 69, 70, 66, 63, 68,112,103, 92,194,104, 95, 86, 87, 71, # 60 -116,195, 85, 93, 97,113,196,197,198,199,200,253,253,253,253,253, # 70 -206,207,208,209,210,211,212,213,120,214,215,216,217,218,219,220, # 80 -221, 78, 64, 83,121, 98,117,105,222,223,224,225,226,227,228,229, # 90 - 88,230,231,232,233,122, 89,106,234,235,236,237,238, 45,239,240, # a0 - 73, 80,118,114,241,242,243,244,245, 62, 58,246,247,248,249,250, # b0 - 31, 32, 35, 43, 37, 44, 55, 47, 40, 59, 33, 46, 38, 36, 41, 30, # c0 - 39, 28, 34, 51, 48, 49, 53, 50, 54, 57, 61,251, 67,252, 60, 56, # d0 - 1, 18, 9, 20, 11, 3, 23, 15, 2, 26, 12, 10, 14, 6, 4, 13, # e0 - 7, 8, 5, 19, 29, 25, 22, 21, 27, 24, 17, 75, 52,253, 42, 16, # f0 -) - -# Model Table: -# total sequences: 100% -# first 512 sequences: 96.9392% -# first 1024 sequences:3.0618% -# rest sequences: 0.2992% -# negative sequences: 0.0020% -BulgarianLangModel = ( -0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,3,3,3,3,3, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,2,2,3,2,2,1,2,2, -3,1,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,3,3,3,3,3,3,3,0,3,0,1, -0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,3,3,3,3,3,3,0,3,1,0, -0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -3,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,2,3,3,3,3,3,3,3,3,0,3,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,2,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,1,3,2,3,3,3,3,3,3,3,3,0,3,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,3,2,3,2,2,1,3,3,3,3,2,2,2,1,1,2,0,1,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,3,3,2,3,2,2,3,3,1,1,2,3,3,2,3,3,3,3,2,1,2,0,2,0,3,0,0, -0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,3,3,1,3,3,3,3,3,2,3,2,3,3,3,3,3,2,3,3,1,3,0,3,0,2,0,0, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,3,3,3,1,3,3,2,3,3,3,1,3,3,2,3,2,2,2,0,0,2,0,2,0,2,0,0, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,3,3,3,3,0,3,3,3,2,2,3,3,3,1,2,2,3,2,1,1,2,0,2,0,0,0,0, -1,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,3,3,2,3,3,1,2,3,2,2,2,3,3,3,3,3,2,2,3,1,2,0,2,1,2,0,0, -0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,1,3,3,3,3,3,2,3,3,3,2,3,3,2,3,2,2,2,3,1,2,0,1,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,3,3,3,3,3,3,1,1,1,2,2,1,3,1,3,2,2,3,0,0,1,0,1,0,1,0,0, -0,0,0,1,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,2,2,3,2,2,3,1,2,1,1,1,2,3,1,3,1,2,2,0,1,1,1,1,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,1,3,2,2,3,3,1,2,3,1,1,3,3,3,3,1,2,2,1,1,1,0,2,0,2,0,1, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,2,2,3,3,3,2,2,1,1,2,0,2,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,0,1,2,1,3,3,2,3,3,3,3,3,2,3,2,1,0,3,1,2,1,2,1,2,3,2,1,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,1,1,2,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,1,3,3,2,3,3,2,2,2,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,3,3,3,3,0,3,3,3,3,3,2,1,1,2,1,3,3,0,3,1,1,1,1,3,2,0,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,3,2,2,2,3,3,3,3,3,3,3,3,3,3,3,1,1,3,1,3,3,2,3,2,2,2,3,0,2,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,2,3,3,2,2,3,2,1,1,1,1,1,3,1,3,1,1,0,0,0,1,0,0,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,2,3,2,0,3,2,0,3,0,2,0,0,2,1,3,1,0,0,1,0,0,0,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,2,1,1,1,1,2,1,1,2,1,1,1,2,2,1,2,1,1,1,0,1,1,0,1,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,2,1,3,1,1,2,1,3,2,1,1,0,1,2,3,2,1,1,1,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,3,3,3,3,2,2,1,0,1,0,0,1,0,0,0,2,1,0,3,0,0,1,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,2,3,2,3,3,1,3,2,1,1,1,2,1,1,2,1,3,0,1,0,0,0,1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,1,1,2,2,3,3,2,3,2,2,2,3,1,2,2,1,1,2,1,1,2,2,0,1,1,0,1,0,2,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,2,1,3,1,0,2,2,1,3,2,1,0,0,2,0,2,0,1,0,0,0,0,0,0,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,3,1,2,0,2,3,1,2,3,2,0,1,3,1,2,1,1,1,0,0,1,0,0,2,2,2,3, -2,2,2,2,1,2,1,1,2,2,1,1,2,0,1,1,1,0,0,1,1,0,0,1,1,0,0,0,1,1,0,1, -3,3,3,3,3,2,1,2,2,1,2,0,2,0,1,0,1,2,1,2,1,1,0,0,0,1,0,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, -3,3,2,3,3,1,1,3,1,0,3,2,1,0,0,0,1,2,0,2,0,1,0,0,0,1,0,1,2,1,2,2, -1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,0,1,2,1,1,1,0,0,0,0,0,1,1,0,0, -3,1,0,1,0,2,3,2,2,2,3,2,2,2,2,2,1,0,2,1,2,1,1,1,0,1,2,1,2,2,2,1, -1,1,2,2,2,2,1,2,1,1,0,1,2,1,2,2,2,1,1,1,0,1,1,1,1,2,0,1,0,0,0,0, -2,3,2,3,3,0,0,2,1,0,2,1,0,0,0,0,2,3,0,2,0,0,0,0,0,1,0,0,2,0,1,2, -2,1,2,1,2,2,1,1,1,2,1,1,1,0,1,2,2,1,1,1,1,1,0,1,1,1,0,0,1,2,0,0, -3,3,2,2,3,0,2,3,1,1,2,0,0,0,1,0,0,2,0,2,0,0,0,1,0,1,0,1,2,0,2,2, -1,1,1,1,2,1,0,1,2,2,2,1,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,1,0,0, -2,3,2,3,3,0,0,3,0,1,1,0,1,0,0,0,2,2,1,2,0,0,0,0,0,0,0,0,2,0,1,2, -2,2,1,1,1,1,1,2,2,2,1,0,2,0,1,0,1,0,0,1,0,1,0,0,1,0,0,0,0,1,0,0, -3,3,3,3,2,2,2,2,2,0,2,1,1,1,1,2,1,2,1,1,0,2,0,1,0,1,0,0,2,0,1,2, -1,1,1,1,1,1,1,2,2,1,1,0,2,0,1,0,2,0,0,1,1,1,0,0,2,0,0,0,1,1,0,0, -2,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,0,0,0,0,0,0,1,2,0,1,2, -2,2,2,1,1,2,1,1,2,2,2,1,2,0,1,1,1,1,1,1,0,1,1,1,1,0,0,1,1,1,0,0, -2,3,3,3,3,0,2,2,0,2,1,0,0,0,1,1,1,2,0,2,0,0,0,3,0,0,0,0,2,0,2,2, -1,1,1,2,1,2,1,1,2,2,2,1,2,0,1,1,1,0,1,1,1,1,0,2,1,0,0,0,1,1,0,0, -2,3,3,3,3,0,2,1,0,0,2,0,0,0,0,0,1,2,0,2,0,0,0,0,0,0,0,0,2,0,1,2, -1,1,1,2,1,1,1,1,2,2,2,0,1,0,1,1,1,0,0,1,1,1,0,0,1,0,0,0,0,1,0,0, -3,3,2,2,3,0,1,0,1,0,0,0,0,0,0,0,1,1,0,3,0,0,0,0,0,0,0,0,1,0,2,2, -1,1,1,1,1,2,1,1,2,2,1,2,2,1,0,1,1,1,1,1,0,1,0,0,1,0,0,0,1,1,0,0, -3,1,0,1,0,2,2,2,2,3,2,1,1,1,2,3,0,0,1,0,2,1,1,0,1,1,1,1,2,1,1,1, -1,2,2,1,2,1,2,2,1,1,0,1,2,1,2,2,1,1,1,0,0,1,1,1,2,1,0,1,0,0,0,0, -2,1,0,1,0,3,1,2,2,2,2,1,2,2,1,1,1,0,2,1,2,2,1,1,2,1,1,0,2,1,1,1, -1,2,2,2,2,2,2,2,1,2,0,1,1,0,2,1,1,1,1,1,0,0,1,1,1,1,0,1,0,0,0,0, -2,1,1,1,1,2,2,2,2,1,2,2,2,1,2,2,1,1,2,1,2,3,2,2,1,1,1,1,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,3,2,0,1,2,0,1,2,1,1,0,1,0,1,2,1,2,0,0,0,1,1,0,0,0,1,0,0,2, -1,1,0,0,1,1,0,1,1,1,1,0,2,0,1,1,1,0,0,1,1,0,0,0,0,1,0,0,0,1,0,0, -2,0,0,0,0,1,2,2,2,2,2,2,2,1,2,1,1,1,1,1,1,1,0,1,1,1,1,1,2,1,1,1, -1,2,2,2,2,1,1,2,1,2,1,1,1,0,2,1,2,1,1,1,0,2,1,1,1,1,0,1,0,0,0,0, -3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0, -1,1,0,1,0,1,1,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,3,2,0,0,0,0,1,0,0,0,0,0,0,1,1,0,2,0,0,0,0,0,0,0,0,1,0,1,2, -1,1,1,1,1,1,0,0,2,2,2,2,2,0,1,1,0,1,1,1,1,1,0,0,1,0,0,0,1,1,0,1, -2,3,1,2,1,0,1,1,0,2,2,2,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,1,2, -1,1,1,1,2,1,1,1,1,1,1,1,1,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0, -2,2,2,2,2,0,0,2,0,0,2,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,0,2,2, -1,1,1,1,1,0,0,1,2,1,1,0,1,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, -1,2,2,2,2,0,0,2,0,1,1,0,0,0,1,0,0,2,0,2,0,0,0,0,0,0,0,0,0,0,1,1, -0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, -1,2,2,3,2,0,0,1,0,0,1,0,0,0,0,0,0,1,0,2,0,0,0,1,0,0,0,0,0,0,0,2, -1,1,0,0,1,0,0,0,1,1,0,0,1,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, -2,1,2,2,2,1,2,1,2,2,1,1,2,1,1,1,0,1,1,1,1,2,0,1,0,1,1,1,1,0,1,1, -1,1,2,1,1,1,1,1,1,0,0,1,2,1,1,1,1,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0, -1,0,0,1,3,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,2,1,0,0,1,0,2,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,0,2,0,0,1, -0,2,0,1,0,0,1,1,2,0,1,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, -1,2,2,2,2,0,1,1,0,2,1,0,1,1,1,0,0,1,0,2,0,1,0,0,0,0,0,0,0,0,0,1, -0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,2,2,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1, -0,1,0,1,1,1,0,0,1,1,1,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, -2,0,1,0,0,1,2,1,1,1,1,1,1,2,2,1,0,0,1,0,1,0,0,0,0,1,1,1,1,0,0,0, -1,1,2,1,1,1,1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,2,1,2,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1, -0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0, -0,1,1,0,1,1,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0, -1,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,2,0,0,2,0,1,0,0,1,0,0,1, -1,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0, -1,1,1,1,1,1,1,2,0,0,0,0,0,0,2,1,0,1,1,0,0,1,1,1,0,1,0,0,0,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -) - -Latin5BulgarianModel = { - 'char_to_order_map': Latin5_BulgarianCharToOrderMap, - 'precedence_matrix': BulgarianLangModel, - 'typical_positive_ratio': 0.969392, - 'keep_english_letter': False, - 'charset_name': "ISO-8859-5", - 'language': 'Bulgairan', -} - -Win1251BulgarianModel = { - 'char_to_order_map': win1251BulgarianCharToOrderMap, - 'precedence_matrix': BulgarianLangModel, - 'typical_positive_ratio': 0.969392, - 'keep_english_letter': False, - 'charset_name': "windows-1251", - 'language': 'Bulgarian', -} diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langcyrillicmodel.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langcyrillicmodel.py deleted file mode 100644 index e5f9a1f..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langcyrillicmodel.py +++ /dev/null @@ -1,333 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -# KOI8-R language model -# Character Mapping Table: -KOI8R_char_to_order_map = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 -155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 -253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 - 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 -191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, # 80 -207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, # 90 -223,224,225, 68,226,227,228,229,230,231,232,233,234,235,236,237, # a0 -238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253, # b0 - 27, 3, 21, 28, 13, 2, 39, 19, 26, 4, 23, 11, 8, 12, 5, 1, # c0 - 15, 16, 9, 7, 6, 14, 24, 10, 17, 18, 20, 25, 30, 29, 22, 54, # d0 - 59, 37, 44, 58, 41, 48, 53, 46, 55, 42, 60, 36, 49, 38, 31, 34, # e0 - 35, 43, 45, 32, 40, 52, 56, 33, 61, 62, 51, 57, 47, 63, 50, 70, # f0 -) - -win1251_char_to_order_map = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 -155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 -253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 - 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 -191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, -207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, -223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, -239,240,241,242,243,244,245,246, 68,247,248,249,250,251,252,253, - 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, - 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, - 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, - 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, -) - -latin5_char_to_order_map = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 -155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 -253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 - 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 -191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, -207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, -223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, - 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, - 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, - 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, - 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, -239, 68,240,241,242,243,244,245,246,247,248,249,250,251,252,255, -) - -macCyrillic_char_to_order_map = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 -155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 -253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 - 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 - 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, - 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, -191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, -207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, -223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, -239,240,241,242,243,244,245,246,247,248,249,250,251,252, 68, 16, - 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, - 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27,255, -) - -IBM855_char_to_order_map = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 -155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 -253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 - 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 -191,192,193,194, 68,195,196,197,198,199,200,201,202,203,204,205, -206,207,208,209,210,211,212,213,214,215,216,217, 27, 59, 54, 70, - 3, 37, 21, 44, 28, 58, 13, 41, 2, 48, 39, 53, 19, 46,218,219, -220,221,222,223,224, 26, 55, 4, 42,225,226,227,228, 23, 60,229, -230,231,232,233,234,235, 11, 36,236,237,238,239,240,241,242,243, - 8, 49, 12, 38, 5, 31, 1, 34, 15,244,245,246,247, 35, 16,248, - 43, 9, 45, 7, 32, 6, 40, 14, 52, 24, 56, 10, 33, 17, 61,249, -250, 18, 62, 20, 51, 25, 57, 30, 47, 29, 63, 22, 50,251,252,255, -) - -IBM866_char_to_order_map = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 -155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 -253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 - 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 - 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, - 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, - 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, -191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, -207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, -223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, - 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, -239, 68,240,241,242,243,244,245,246,247,248,249,250,251,252,255, -) - -# Model Table: -# total sequences: 100% -# first 512 sequences: 97.6601% -# first 1024 sequences: 2.3389% -# rest sequences: 0.1237% -# negative sequences: 0.0009% -RussianLangModel = ( -0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,3,3,3,3,1,3,3,3,2,3,2,3,3, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,2,2,2,2,2,0,0,2, -3,3,3,2,3,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,3,2,3,2,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,2,2,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,2,3,3,1,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,2,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,2,1, -0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,2,1, -0,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,2,2,2,3,1,3,3,1,3,3,3,3,2,2,3,0,2,2,2,3,3,2,1,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,2,3,3,3,3,3,2,2,3,2,3,3,3,2,1,2,2,0,1,2,2,2,2,2,2,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,3,0,2,2,3,3,2,1,2,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,2,3,3,1,2,3,2,2,3,2,3,3,3,3,2,2,3,0,3,2,2,3,1,1,1,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,2,3,3,3,3,2,2,2,0,3,3,3,2,2,2,2,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,3,3,3,3,2,3,2,2,0,1,3,2,1,2,2,1,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,3,2,1,1,3,0,1,1,1,1,2,1,1,0,2,2,2,1,2,0,1,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,2,3,3,2,2,2,2,1,3,2,3,2,3,2,1,2,2,0,1,1,2,1,2,1,2,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,3,3,2,2,3,2,3,3,3,2,2,2,2,0,2,2,2,2,3,1,1,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, -3,2,3,2,2,3,3,3,3,3,3,3,3,3,1,3,2,0,0,3,3,3,3,2,3,3,3,3,2,3,2,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,3,3,3,3,3,2,2,3,3,0,2,1,0,3,2,3,2,3,0,0,1,2,0,0,1,0,1,2,1,1,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,3,0,2,3,3,3,3,2,3,3,3,3,1,2,2,0,0,2,3,2,2,2,3,2,3,2,2,3,0,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,2,3,0,2,3,2,3,0,1,2,3,3,2,0,2,3,0,0,2,3,2,2,0,1,3,1,3,2,2,1,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,1,3,0,2,3,3,3,3,3,3,3,3,2,1,3,2,0,0,2,2,3,3,3,2,3,3,0,2,2,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,2,2,3,3,2,2,2,3,3,0,0,1,1,1,1,1,2,0,0,1,1,1,1,0,1,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,2,2,3,3,3,3,3,3,3,0,3,2,3,3,2,3,2,0,2,1,0,1,1,0,1,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,2,3,3,3,2,2,2,2,3,1,3,2,3,1,1,2,1,0,2,2,2,2,1,3,1,0, -0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, -2,2,3,3,3,3,3,1,2,2,1,3,1,0,3,0,0,3,0,0,0,1,1,0,1,2,1,0,0,0,0,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,2,2,1,1,3,3,3,2,2,1,2,2,3,1,1,2,0,0,2,2,1,3,0,0,2,1,1,2,1,1,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,2,3,3,3,3,1,2,2,2,1,2,1,3,3,1,1,2,1,2,1,2,2,0,2,0,0,1,1,0,1,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,3,3,3,3,3,2,1,3,2,2,3,2,0,3,2,0,3,0,1,0,1,1,0,0,1,1,1,1,0,1,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,2,3,3,3,2,2,2,3,3,1,2,1,2,1,0,1,0,1,1,0,1,0,0,2,1,1,1,0,1,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, -3,1,1,2,1,2,3,3,2,2,1,2,2,3,0,2,1,0,0,2,2,3,2,1,2,2,2,2,2,3,1,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,1,1,0,1,1,2,2,1,1,3,0,0,1,3,1,1,1,0,0,0,1,0,1,1,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,1,3,3,3,2,0,0,0,2,1,0,1,0,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,0,1,0,0,2,3,2,2,2,1,2,2,2,1,2,1,0,0,1,1,1,0,2,0,1,1,1,0,0,1,1, -1,0,0,0,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, -2,3,3,3,3,0,0,0,0,1,0,0,0,0,3,0,1,2,1,0,0,0,0,0,0,0,1,1,0,0,1,1, -1,0,1,0,1,2,0,0,1,1,2,1,0,1,1,1,1,0,1,1,1,1,0,1,0,0,1,0,0,1,1,0, -2,2,3,2,2,2,3,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,0,1,0,1,1,1,0,2,1, -1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,0,1,1,0, -3,3,3,2,2,2,2,3,2,2,1,1,2,2,2,2,1,1,3,1,2,1,2,0,0,1,1,0,1,0,2,1, -1,1,1,1,1,2,1,0,1,1,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,1,0, -2,0,0,1,0,3,2,2,2,2,1,2,1,2,1,2,0,0,0,2,1,2,2,1,1,2,2,0,1,1,0,2, -1,1,1,1,1,0,1,1,1,2,1,1,1,2,1,0,1,2,1,1,1,1,0,1,1,1,0,0,1,0,0,1, -1,3,2,2,2,1,1,1,2,3,0,0,0,0,2,0,2,2,1,0,0,0,0,0,0,1,0,0,0,0,1,1, -1,0,1,1,0,1,0,1,1,0,1,1,0,2,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0, -2,3,2,3,2,1,2,2,2,2,1,0,0,0,2,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,2,1, -1,1,2,1,0,2,0,0,1,0,1,0,0,1,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,0, -3,0,0,1,0,2,2,2,3,2,2,2,2,2,2,2,0,0,0,2,1,2,1,1,1,2,2,0,0,0,1,2, -1,1,1,1,1,0,1,2,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,1, -2,3,2,3,3,2,0,1,1,1,0,0,1,0,2,0,1,1,3,1,0,0,0,0,0,0,0,1,0,0,2,1, -1,1,1,1,1,1,1,0,1,0,1,1,1,1,0,1,1,1,0,0,1,1,0,1,0,0,0,0,0,0,1,0, -2,3,3,3,3,1,2,2,2,2,0,1,1,0,2,1,1,1,2,1,0,1,1,0,0,1,0,1,0,0,2,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,3,3,3,2,0,0,1,1,2,2,1,0,0,2,0,1,1,3,0,0,1,0,0,0,0,0,1,0,1,2,1, -1,1,2,0,1,1,1,0,1,0,1,1,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,1,0,1,1,0, -1,3,2,3,2,1,0,0,2,2,2,0,1,0,2,0,1,1,1,0,1,0,0,0,3,0,1,1,0,0,2,1, -1,1,1,0,1,1,0,0,0,0,1,1,0,1,0,0,2,1,1,0,1,0,0,0,1,0,1,0,0,1,1,0, -3,1,2,1,1,2,2,2,2,2,2,1,2,2,1,1,0,0,0,2,2,2,0,0,0,1,2,1,0,1,0,1, -2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,2,1,1,1,0,1,0,1,1,0,1,1,1,0,0,1, -3,0,0,0,0,2,0,1,1,1,1,1,1,1,0,1,0,0,0,1,1,1,0,1,0,1,1,0,0,1,0,1, -1,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1, -1,3,3,2,2,0,0,0,2,2,0,0,0,1,2,0,1,1,2,0,0,0,0,0,0,0,0,1,0,0,2,1, -0,1,1,0,0,1,1,0,0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0, -2,3,2,3,2,0,0,0,0,1,1,0,0,0,2,0,2,0,2,0,0,0,0,0,1,0,0,1,0,0,1,1, -1,1,2,0,1,2,1,0,1,1,2,1,1,1,1,1,2,1,1,0,1,0,0,1,1,1,1,1,0,1,1,0, -1,3,2,2,2,1,0,0,2,2,1,0,1,2,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,1, -0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, -1,0,0,1,0,2,3,1,2,2,2,2,2,2,1,1,0,0,0,1,0,1,0,2,1,1,1,0,0,0,0,1, -1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0, -2,0,2,0,0,1,0,3,2,1,2,1,2,2,0,1,0,0,0,2,1,0,0,2,1,1,1,1,0,2,0,2, -2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,0,0,0,1,1,1,1,0,1,0,0,1, -1,2,2,2,2,1,0,0,1,0,0,0,0,0,2,0,1,1,1,1,0,0,0,0,1,0,1,2,0,0,2,0, -1,0,1,1,1,2,1,0,1,0,1,1,0,0,1,0,1,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0, -2,1,2,2,2,0,3,0,1,1,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -0,0,0,1,1,1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0, -1,2,2,3,2,2,0,0,1,1,2,0,1,2,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1, -0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0, -2,2,1,1,2,1,2,2,2,2,2,1,2,2,0,1,0,0,0,1,2,2,2,1,2,1,1,1,1,1,2,1, -1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,1,1,1,0,0,0,0,1,1,1,0,1,1,0,0,1, -1,2,2,2,2,0,1,0,2,2,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0, -0,0,1,0,0,1,0,0,0,0,1,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, -0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,2,2,2,2,0,0,0,2,2,2,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1, -0,1,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,2,2,2,2,0,0,0,0,1,0,0,1,1,2,0,0,0,0,1,0,1,0,0,1,0,0,2,0,0,0,1, -0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, -1,2,2,2,1,1,2,0,2,1,1,1,1,0,2,2,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1, -0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, -1,0,2,1,2,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0, -0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0, -1,0,0,0,0,2,0,1,2,1,0,1,1,1,0,1,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,1, -0,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1, -2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -1,1,1,0,1,0,1,0,0,1,1,1,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0, -1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -1,1,0,1,1,0,1,0,1,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,0, -0,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, -) - -Koi8rModel = { - 'char_to_order_map': KOI8R_char_to_order_map, - 'precedence_matrix': RussianLangModel, - 'typical_positive_ratio': 0.976601, - 'keep_english_letter': False, - 'charset_name': "KOI8-R", - 'language': 'Russian', -} - -Win1251CyrillicModel = { - 'char_to_order_map': win1251_char_to_order_map, - 'precedence_matrix': RussianLangModel, - 'typical_positive_ratio': 0.976601, - 'keep_english_letter': False, - 'charset_name': "windows-1251", - 'language': 'Russian', -} - -Latin5CyrillicModel = { - 'char_to_order_map': latin5_char_to_order_map, - 'precedence_matrix': RussianLangModel, - 'typical_positive_ratio': 0.976601, - 'keep_english_letter': False, - 'charset_name': "ISO-8859-5", - 'language': 'Russian', -} - -MacCyrillicModel = { - 'char_to_order_map': macCyrillic_char_to_order_map, - 'precedence_matrix': RussianLangModel, - 'typical_positive_ratio': 0.976601, - 'keep_english_letter': False, - 'charset_name': "MacCyrillic", - 'language': 'Russian', -} - -Ibm866Model = { - 'char_to_order_map': IBM866_char_to_order_map, - 'precedence_matrix': RussianLangModel, - 'typical_positive_ratio': 0.976601, - 'keep_english_letter': False, - 'charset_name': "IBM866", - 'language': 'Russian', -} - -Ibm855Model = { - 'char_to_order_map': IBM855_char_to_order_map, - 'precedence_matrix': RussianLangModel, - 'typical_positive_ratio': 0.976601, - 'keep_english_letter': False, - 'charset_name': "IBM855", - 'language': 'Russian', -} diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langgreekmodel.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langgreekmodel.py deleted file mode 100644 index 5332221..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langgreekmodel.py +++ /dev/null @@ -1,225 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -# 255: Control characters that usually does not exist in any text -# 254: Carriage/Return -# 253: symbol (punctuation) that does not belong to word -# 252: 0 - 9 - -# Character Mapping Table: -Latin7_char_to_order_map = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253, 82,100,104, 94, 98,101,116,102,111,187,117, 92, 88,113, 85, # 40 - 79,118,105, 83, 67,114,119, 95, 99,109,188,253,253,253,253,253, # 50 -253, 72, 70, 80, 81, 60, 96, 93, 89, 68,120, 97, 77, 86, 69, 55, # 60 - 78,115, 65, 66, 58, 76,106,103, 87,107,112,253,253,253,253,253, # 70 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 80 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 90 -253,233, 90,253,253,253,253,253,253,253,253,253,253, 74,253,253, # a0 -253,253,253,253,247,248, 61, 36, 46, 71, 73,253, 54,253,108,123, # b0 -110, 31, 51, 43, 41, 34, 91, 40, 52, 47, 44, 53, 38, 49, 59, 39, # c0 - 35, 48,250, 37, 33, 45, 56, 50, 84, 57,120,121, 17, 18, 22, 15, # d0 -124, 1, 29, 20, 21, 3, 32, 13, 25, 5, 11, 16, 10, 6, 30, 4, # e0 - 9, 8, 14, 7, 2, 12, 28, 23, 42, 24, 64, 75, 19, 26, 27,253, # f0 -) - -win1253_char_to_order_map = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253, 82,100,104, 94, 98,101,116,102,111,187,117, 92, 88,113, 85, # 40 - 79,118,105, 83, 67,114,119, 95, 99,109,188,253,253,253,253,253, # 50 -253, 72, 70, 80, 81, 60, 96, 93, 89, 68,120, 97, 77, 86, 69, 55, # 60 - 78,115, 65, 66, 58, 76,106,103, 87,107,112,253,253,253,253,253, # 70 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 80 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 90 -253,233, 61,253,253,253,253,253,253,253,253,253,253, 74,253,253, # a0 -253,253,253,253,247,253,253, 36, 46, 71, 73,253, 54,253,108,123, # b0 -110, 31, 51, 43, 41, 34, 91, 40, 52, 47, 44, 53, 38, 49, 59, 39, # c0 - 35, 48,250, 37, 33, 45, 56, 50, 84, 57,120,121, 17, 18, 22, 15, # d0 -124, 1, 29, 20, 21, 3, 32, 13, 25, 5, 11, 16, 10, 6, 30, 4, # e0 - 9, 8, 14, 7, 2, 12, 28, 23, 42, 24, 64, 75, 19, 26, 27,253, # f0 -) - -# Model Table: -# total sequences: 100% -# first 512 sequences: 98.2851% -# first 1024 sequences:1.7001% -# rest sequences: 0.0359% -# negative sequences: 0.0148% -GreekLangModel = ( -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,3,2,2,3,3,3,3,3,3,3,3,1,3,3,3,0,2,2,3,3,0,3,0,3,2,0,3,3,3,0, -3,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,3,0,3,3,0,3,2,3,3,0,3,2,3,3,3,0,0,3,0,3,0,3,3,2,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, -0,2,3,2,2,3,3,3,3,3,3,3,3,0,3,3,3,3,0,2,3,3,0,3,3,3,3,2,3,3,3,0, -2,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,2,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,0,2,1,3,3,3,3,2,3,3,2,3,3,2,0, -0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,0,3,3,3,3,3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,3,0,3,2,3,3,0, -2,0,1,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, -0,3,3,3,3,3,2,3,0,0,0,0,3,3,0,3,1,3,3,3,0,3,3,0,3,3,3,3,0,0,0,0, -2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,3,0,3,0,3,3,3,3,3,0,3,2,2,2,3,0,2,3,3,3,3,3,2,3,3,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,3,3,2,2,2,3,3,3,3,0,3,1,3,3,3,3,2,3,3,3,3,3,3,3,2,2,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,3,2,0,3,0,0,0,3,3,2,3,3,3,3,3,0,0,3,2,3,0,2,3,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,0,3,3,3,3,0,0,3,3,0,2,3,0,3,0,3,3,3,0,0,3,0,3,0,2,2,3,3,0,0, -0,0,1,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,3,2,0,3,2,3,3,3,3,0,3,3,3,3,3,0,3,3,2,3,2,3,3,2,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,2,3,2,3,3,3,3,3,3,0,2,3,2,3,2,2,2,3,2,3,3,2,3,0,2,2,2,3,0, -2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,3,0,0,0,3,3,3,2,3,3,0,0,3,0,3,0,0,0,3,2,0,3,0,3,0,0,2,0,2,0, -0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,0,3,3,3,3,3,3,0,3,3,0,3,0,0,0,3,3,0,3,3,3,0,0,1,2,3,0, -3,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,3,2,0,0,3,2,2,3,3,0,3,3,3,3,3,2,1,3,0,3,2,3,3,2,1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,3,3,0,2,3,3,3,3,3,3,0,0,3,0,3,0,0,0,3,3,0,3,2,3,0,0,3,3,3,0, -3,0,0,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,0,3,3,3,3,3,3,0,0,3,0,3,0,0,0,3,2,0,3,2,3,0,0,3,2,3,0, -2,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,3,1,2,2,3,3,3,3,3,3,0,2,3,0,3,0,0,0,3,3,0,3,0,2,0,0,2,3,1,0, -2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,0,3,3,3,3,0,3,0,3,3,2,3,0,3,3,3,3,3,3,0,3,3,3,0,2,3,0,0,3,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,0,3,3,3,0,0,3,0,0,0,3,3,0,3,0,2,3,3,0,0,3,0,3,0,3,3,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,3,0,0,0,3,3,3,3,3,3,0,0,3,0,2,0,0,0,3,3,0,3,0,3,0,0,2,0,2,0, -0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,3,3,0,3,0,2,0,3,2,0,3,2,3,2,3,0,0,3,2,3,2,3,3,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,3,0,0,2,3,3,3,3,3,0,0,0,3,0,2,1,0,0,3,2,2,2,0,3,0,0,2,2,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,0,3,3,3,2,0,3,0,3,0,3,3,0,2,1,2,3,3,0,0,3,0,3,0,3,3,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,2,3,3,3,0,3,3,3,3,3,3,0,2,3,0,3,0,0,0,2,1,0,2,2,3,0,0,2,2,2,0, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,3,0,0,2,3,3,3,2,3,0,0,1,3,0,2,0,0,0,0,3,0,1,0,2,0,0,1,1,1,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,3,1,0,3,0,0,0,3,2,0,3,2,3,3,3,0,0,3,0,3,2,2,2,1,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,0,3,3,3,0,0,3,0,0,0,0,2,0,2,3,3,2,2,2,2,3,0,2,0,2,2,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,2,0,0,0,0,0,0,2,3,0,2,0,2,3,2,0,0,3,0,3,0,3,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,3,2,3,3,2,2,3,0,2,0,3,0,0,0,2,0,0,0,0,1,2,0,2,0,2,0, -0,2,0,2,0,2,2,0,0,1,0,2,2,2,0,2,2,2,0,2,2,2,0,0,2,0,0,1,0,0,0,0, -0,2,0,3,3,2,0,0,0,0,0,0,1,3,0,2,0,2,2,2,0,0,2,0,3,0,0,2,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,0,2,3,2,0,2,2,0,2,0,2,2,0,2,0,2,2,2,0,0,0,0,0,0,2,3,0,0,0,2, -0,1,2,0,0,0,0,2,2,0,0,0,2,1,0,2,2,0,0,0,0,0,0,1,0,2,0,0,0,0,0,0, -0,0,2,1,0,2,3,2,2,3,2,3,2,0,0,3,3,3,0,0,3,2,0,0,0,1,1,0,2,0,2,2, -0,2,0,2,0,2,2,0,0,2,0,2,2,2,0,2,2,2,2,0,0,2,0,0,0,2,0,1,0,0,0,0, -0,3,0,3,3,2,2,0,3,0,0,0,2,2,0,2,2,2,1,2,0,0,1,2,2,0,0,3,0,0,0,2, -0,1,2,0,0,0,1,2,0,0,0,0,0,0,0,2,2,0,1,0,0,2,0,0,0,2,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,2,3,3,2,2,0,0,0,2,0,2,3,3,0,2,0,0,0,0,0,0,2,2,2,0,2,2,0,2,0,2, -0,2,2,0,0,2,2,2,2,1,0,0,2,2,0,2,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0, -0,2,0,3,2,3,0,0,0,3,0,0,2,2,0,2,0,2,2,2,0,0,2,0,0,0,0,0,0,0,0,2, -0,0,2,2,0,0,2,2,2,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,2,0,0,3,2,0,2,2,2,2,2,0,0,0,2,0,0,0,0,2,0,1,0,0,2,0,1,0,0,0, -0,2,2,2,0,2,2,0,1,2,0,2,2,2,0,2,2,2,2,1,2,2,0,0,2,0,0,0,0,0,0,0, -0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, -0,2,0,2,0,2,2,0,0,0,0,1,2,1,0,0,2,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,3,2,3,0,0,2,0,0,0,2,2,0,2,0,0,0,1,0,0,2,0,2,0,2,2,0,0,0,0, -0,0,2,0,0,0,0,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0, -0,2,2,3,2,2,0,0,0,0,0,0,1,3,0,2,0,2,2,0,0,0,1,0,2,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,2,0,2,0,3,2,0,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -0,0,2,0,0,0,0,1,1,0,0,2,1,2,0,2,2,0,1,0,0,1,0,0,0,2,0,0,0,0,0,0, -0,3,0,2,2,2,0,0,2,0,0,0,2,0,0,0,2,3,0,2,0,0,0,0,0,0,2,2,0,0,0,2, -0,1,2,0,0,0,1,2,2,1,0,0,0,2,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,2,1,2,0,2,2,0,2,0,0,2,0,0,0,0,1,2,1,0,2,1,0,0,0,0,0,0,0,0,0,0, -0,0,2,0,0,0,3,1,2,2,0,2,0,0,0,0,2,0,0,0,2,0,0,3,0,0,0,0,2,2,2,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,2,1,0,2,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,2, -0,2,2,0,0,2,2,2,2,2,0,1,2,0,0,0,2,2,0,1,0,2,0,0,2,2,0,0,0,0,0,0, -0,0,0,0,1,0,0,0,0,0,0,0,3,0,0,2,0,0,0,0,0,0,0,0,2,0,2,0,0,0,0,2, -0,1,2,0,0,0,0,2,2,1,0,1,0,1,0,2,2,2,1,0,0,0,0,0,0,1,0,0,0,0,0,0, -0,2,0,1,2,0,0,0,0,0,0,0,0,0,0,2,0,0,2,2,0,0,0,0,1,0,0,0,0,0,0,2, -0,2,2,0,0,0,0,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0, -0,2,2,2,2,0,0,0,3,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,1, -0,0,2,0,0,0,0,1,2,0,0,0,0,0,0,2,2,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0, -0,2,0,2,2,2,0,0,2,0,0,0,0,0,0,0,2,2,2,0,0,0,2,0,0,0,0,0,0,0,0,2, -0,0,1,0,0,0,0,2,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, -0,3,0,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,2, -0,0,2,0,0,0,0,2,2,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,2,0,2,2,1,0,0,0,0,0,0,2,0,0,2,0,2,2,2,0,0,0,0,0,0,2,0,0,0,0,2, -0,0,2,0,0,2,0,2,2,0,0,0,0,2,0,2,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0, -0,0,3,0,0,0,2,2,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0,0,0, -0,2,2,2,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1, -0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, -0,2,0,0,0,2,0,0,0,0,0,1,0,0,0,0,2,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,2,0,0,0, -0,2,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,2,0,2,0,0,0, -0,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,2,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -) - -Latin7GreekModel = { - 'char_to_order_map': Latin7_char_to_order_map, - 'precedence_matrix': GreekLangModel, - 'typical_positive_ratio': 0.982851, - 'keep_english_letter': False, - 'charset_name': "ISO-8859-7", - 'language': 'Greek', -} - -Win1253GreekModel = { - 'char_to_order_map': win1253_char_to_order_map, - 'precedence_matrix': GreekLangModel, - 'typical_positive_ratio': 0.982851, - 'keep_english_letter': False, - 'charset_name': "windows-1253", - 'language': 'Greek', -} diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langhebrewmodel.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langhebrewmodel.py deleted file mode 100644 index 58f4c87..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langhebrewmodel.py +++ /dev/null @@ -1,200 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Universal charset detector code. -# -# The Initial Developer of the Original Code is -# Simon Montagu -# Portions created by the Initial Developer are Copyright (C) 2005 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# Shy Shalom - original C code -# Shoshannah Forbes - original C code (?) -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -# 255: Control characters that usually does not exist in any text -# 254: Carriage/Return -# 253: symbol (punctuation) that does not belong to word -# 252: 0 - 9 - -# Windows-1255 language model -# Character Mapping Table: -WIN1255_CHAR_TO_ORDER_MAP = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253, 69, 91, 79, 80, 92, 89, 97, 90, 68,111,112, 82, 73, 95, 85, # 40 - 78,121, 86, 71, 67,102,107, 84,114,103,115,253,253,253,253,253, # 50 -253, 50, 74, 60, 61, 42, 76, 70, 64, 53,105, 93, 56, 65, 54, 49, # 60 - 66,110, 51, 43, 44, 63, 81, 77, 98, 75,108,253,253,253,253,253, # 70 -124,202,203,204,205, 40, 58,206,207,208,209,210,211,212,213,214, -215, 83, 52, 47, 46, 72, 32, 94,216,113,217,109,218,219,220,221, - 34,116,222,118,100,223,224,117,119,104,125,225,226, 87, 99,227, -106,122,123,228, 55,229,230,101,231,232,120,233, 48, 39, 57,234, - 30, 59, 41, 88, 33, 37, 36, 31, 29, 35,235, 62, 28,236,126,237, -238, 38, 45,239,240,241,242,243,127,244,245,246,247,248,249,250, - 9, 8, 20, 16, 3, 2, 24, 14, 22, 1, 25, 15, 4, 11, 6, 23, - 12, 19, 13, 26, 18, 27, 21, 17, 7, 10, 5,251,252,128, 96,253, -) - -# Model Table: -# total sequences: 100% -# first 512 sequences: 98.4004% -# first 1024 sequences: 1.5981% -# rest sequences: 0.087% -# negative sequences: 0.0015% -HEBREW_LANG_MODEL = ( -0,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,2,3,2,1,2,0,1,0,0, -3,0,3,1,0,0,1,3,2,0,1,1,2,0,2,2,2,1,1,1,1,2,1,1,1,2,0,0,2,2,0,1, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2, -1,2,1,2,1,2,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2, -1,2,1,3,1,1,0,0,2,0,0,0,1,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,1,2,2,1,3, -1,2,1,1,2,2,0,0,2,2,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,1,0,1,1,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,2,2,2,2,3,2, -1,2,1,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,2,3,2,2,3,2,2,2,1,2,2,2,2, -1,2,1,1,2,2,0,1,2,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,0,2,2,2,2,2, -0,2,0,2,2,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,0,2,2,2, -0,2,1,2,2,2,0,0,2,1,0,0,0,0,1,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,2,1,2,3,2,2,2, -1,2,1,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0, -3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,2,0,2, -0,2,1,2,2,2,0,0,1,2,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,2,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,2,3,2,2,3,2,1,2,1,1,1, -0,1,1,1,1,1,3,0,1,0,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,0,0,1,0,0,1,0,0,0,0, -0,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2, -0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,2,3,3,3,2,1,2,3,3,2,3,3,3,3,2,3,2,1,2,0,2,1,2, -0,2,0,2,2,2,0,0,1,2,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0, -3,3,3,3,3,3,3,3,3,2,3,3,3,1,2,2,3,3,2,3,2,3,2,2,3,1,2,2,0,2,2,2, -0,2,1,2,2,2,0,0,1,2,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,2,2,2,3,3,3,3,1,3,2,2,2, -0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,2,3,2,2,2,1,2,2,0,2,2,2,2, -0,2,0,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,1,3,2,3,3,2,3,3,2,2,1,2,2,2,2,2,2, -0,2,1,2,1,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,2,3,2,3,3,2,3,3,3,3,2,3,2,3,3,3,3,3,2,2,2,2,2,2,2,1, -0,2,0,1,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,2,1,2,3,3,3,3,3,3,3,2,3,2,3,2,1,2,3,0,2,1,2,2, -0,2,1,1,2,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,2,0, -3,3,3,3,3,3,3,3,3,2,3,3,3,3,2,1,3,1,2,2,2,1,2,3,3,1,2,1,2,2,2,2, -0,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,0,2,3,3,3,1,3,3,3,1,2,2,2,2,1,1,2,2,2,2,2,2, -0,2,0,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,2,3,3,3,2,2,3,3,3,2,1,2,3,2,3,2,2,2,2,1,2,1,1,1,2,2, -0,2,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,1,0,0,0,0,0, -1,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,2,3,3,2,3,1,2,2,2,2,3,2,3,1,1,2,2,1,2,2,1,1,0,2,2,2,2, -0,1,0,1,2,2,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, -3,0,0,1,1,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,0, -0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,1,0,1,0,1,1,0,1,1,0,0,0,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0, -0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,0,0,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, -3,2,2,1,2,2,2,2,2,2,2,1,2,2,1,2,2,1,1,1,1,1,1,1,1,2,1,1,0,3,3,3, -0,3,0,2,2,2,2,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,1,2,2,2,1,1,1,2,0,1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,0,0,0,0,0,0, -0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,3,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,0,2,1,0, -0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, -0,3,1,1,2,2,2,2,2,1,2,2,2,1,1,2,2,2,2,2,2,2,1,2,2,1,0,1,1,1,1,0, -0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,2,1,1,1,1,2,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0, -0,0,2,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,0,0, -2,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,2,1,2,1,1,1,1,0,0,0,0, -0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,2,1,2,2,2,2,2,2,2,2,2,2,1,2,1,2,1,1,2,1,1,1,2,1,2,1,2,0,1,0,1, -0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,1,2,2,2,1,2,2,2,2,2,2,2,2,1,2,1,1,1,1,1,1,2,1,2,1,1,0,1,0,1, -0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,1,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2, -0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,1,1,1,1,1,1,1,0,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,2,0,1,1,1,0,1,0,0,0,1,1,0,1,1,0,0,0,0,0,1,1,0,0, -0,1,1,1,2,1,2,2,2,0,2,0,2,0,1,1,2,1,1,1,1,2,1,0,1,1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,1,0,0,0,0,0,1,0,1,2,2,0,1,0,0,1,1,2,2,1,2,0,2,0,0,0,1,2,0,1, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,2,0,2,1,2,0,2,0,0,1,1,1,1,1,1,0,1,0,0,0,1,0,0,1, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,1,0,0,0,0,0,1,0,2,1,1,0,1,0,0,1,1,1,2,2,0,0,1,0,0,0,1,0,0,1, -1,1,2,1,0,1,1,1,0,1,0,1,1,1,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,2,1, -0,2,0,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,1,0,0,1,0,1,1,1,1,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,1,1,0,1,0,0,0,1,1,0,1, -2,0,1,0,1,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,0,1,1,2,1,1,2,0,1,0,0,0,1,1,0,1, -1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,0,0,2,1,1,2,0,2,0,0,0,1,1,0,1, -1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,1,0,2,1,1,0,1,0,0,2,2,1,2,1,1,0,1,0,0,0,1,1,0,1, -2,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,1,2,2,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,1,0,1, -1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,1,2,2,0,0,0,0,2,1,1,1,0,2,1,1,0,0,0,2,1,0,1, -1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,1,1,0,2,1,1,0,1,0,0,0,1,1,0,1, -2,2,1,1,1,0,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,1,0,2,1,1,0,1,0,0,1,1,0,1,2,1,0,2,0,0,0,1,1,0,1, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0, -0,1,0,0,2,0,2,1,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,1,1,1,0,1,0,0,1,0,0,0,1,0,0,1, -1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,0,0,0,0,0,0,1,0,1,1,0,0,1,0,0,2,1,1,1,1,1,0,1,0,0,0,0,1,0,1, -0,1,1,1,2,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,1,2,1,0,0,0,0,0,1,1,1,1,1,0,1,0,0,0,1,1,0,0, -) - -Win1255HebrewModel = { - 'char_to_order_map': WIN1255_CHAR_TO_ORDER_MAP, - 'precedence_matrix': HEBREW_LANG_MODEL, - 'typical_positive_ratio': 0.984004, - 'keep_english_letter': False, - 'charset_name': "windows-1255", - 'language': 'Hebrew', -} diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langhungarianmodel.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langhungarianmodel.py deleted file mode 100644 index bb7c095..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langhungarianmodel.py +++ /dev/null @@ -1,225 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -# 255: Control characters that usually does not exist in any text -# 254: Carriage/Return -# 253: symbol (punctuation) that does not belong to word -# 252: 0 - 9 - -# Character Mapping Table: -Latin2_HungarianCharToOrderMap = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253, 28, 40, 54, 45, 32, 50, 49, 38, 39, 53, 36, 41, 34, 35, 47, - 46, 71, 43, 33, 37, 57, 48, 64, 68, 55, 52,253,253,253,253,253, -253, 2, 18, 26, 17, 1, 27, 12, 20, 9, 22, 7, 6, 13, 4, 8, - 23, 67, 10, 5, 3, 21, 19, 65, 62, 16, 11,253,253,253,253,253, -159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174, -175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190, -191,192,193,194,195,196,197, 75,198,199,200,201,202,203,204,205, - 79,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, -221, 51, 81,222, 78,223,224,225,226, 44,227,228,229, 61,230,231, -232,233,234, 58,235, 66, 59,236,237,238, 60, 69, 63,239,240,241, - 82, 14, 74,242, 70, 80,243, 72,244, 15, 83, 77, 84, 30, 76, 85, -245,246,247, 25, 73, 42, 24,248,249,250, 31, 56, 29,251,252,253, -) - -win1250HungarianCharToOrderMap = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253, 28, 40, 54, 45, 32, 50, 49, 38, 39, 53, 36, 41, 34, 35, 47, - 46, 72, 43, 33, 37, 57, 48, 64, 68, 55, 52,253,253,253,253,253, -253, 2, 18, 26, 17, 1, 27, 12, 20, 9, 22, 7, 6, 13, 4, 8, - 23, 67, 10, 5, 3, 21, 19, 65, 62, 16, 11,253,253,253,253,253, -161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176, -177,178,179,180, 78,181, 69,182,183,184,185,186,187,188,189,190, -191,192,193,194,195,196,197, 76,198,199,200,201,202,203,204,205, - 81,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, -221, 51, 83,222, 80,223,224,225,226, 44,227,228,229, 61,230,231, -232,233,234, 58,235, 66, 59,236,237,238, 60, 70, 63,239,240,241, - 84, 14, 75,242, 71, 82,243, 73,244, 15, 85, 79, 86, 30, 77, 87, -245,246,247, 25, 74, 42, 24,248,249,250, 31, 56, 29,251,252,253, -) - -# Model Table: -# total sequences: 100% -# first 512 sequences: 94.7368% -# first 1024 sequences:5.2623% -# rest sequences: 0.8894% -# negative sequences: 0.0009% -HungarianLangModel = ( -0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, -3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,2,3,3,1,1,2,2,2,2,2,1,2, -3,2,2,3,3,3,3,3,2,3,3,3,3,3,3,1,2,3,3,3,3,2,3,3,1,1,3,3,0,1,1,1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0, -3,2,1,3,3,3,3,3,2,3,3,3,3,3,1,1,2,3,3,3,3,3,3,3,1,1,3,2,0,1,1,1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,1,1,2,3,3,3,1,3,3,3,3,3,1,3,3,2,2,0,3,2,3, -0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, -3,3,3,3,3,3,2,3,3,3,2,3,3,2,3,3,3,3,3,2,3,3,2,2,3,2,3,2,0,3,2,2, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0, -3,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,1,2,3,2,2,3,1,2,3,3,2,2,0,3,3,3, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,3,2,3,3,3,3,2,3,3,3,3,0,2,3,2, -0,0,0,1,1,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,3,1,1,1,3,3,2,1,3,2,2,3,2,1,3,2,2,1,0,3,3,1, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,2,2,3,3,3,3,3,1,2,3,3,3,3,1,2,1,3,3,3,3,2,2,3,1,1,3,2,0,1,1,1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,2,1,3,3,3,3,3,2,2,1,3,3,3,0,1,1,2, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,2,3,3,3,2,0,3,2,3, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,1,0, -3,3,3,3,3,3,2,3,3,3,2,3,2,3,3,3,1,3,2,2,2,3,1,1,3,3,1,1,0,3,3,2, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,2,3,3,3,2,3,2,3,3,3,2,3,3,3,3,3,1,2,3,2,2,0,2,2,2, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,3,3,2,2,2,3,1,3,3,2,2,1,3,3,3,1,1,3,1,2,3,2,3,2,2,2,1,0,2,2,2, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, -3,1,1,3,3,3,3,3,1,2,3,3,3,3,1,2,1,3,3,3,2,2,3,2,1,0,3,2,0,1,1,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,1,1,3,3,3,3,3,1,2,3,3,3,3,1,1,0,3,3,3,3,0,2,3,0,0,2,1,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,2,2,3,3,2,2,2,2,3,3,0,1,2,3,2,3,2,2,3,2,1,2,0,2,2,2, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, -3,3,3,3,3,3,1,2,3,3,3,2,1,2,3,3,2,2,2,3,2,3,3,1,3,3,1,1,0,2,3,2, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,3,3,1,2,2,2,2,3,3,3,1,1,1,3,3,1,1,3,1,1,3,2,1,2,3,1,1,0,2,2,2, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,3,3,2,1,2,1,1,3,3,1,1,1,1,3,3,1,1,2,2,1,2,1,1,2,2,1,1,0,2,2,1, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,3,3,1,1,2,1,1,3,3,1,0,1,1,3,3,2,0,1,1,2,3,1,0,2,2,1,0,0,1,3,2, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,2,1,3,3,3,3,3,1,2,3,2,3,3,2,1,1,3,2,3,2,1,2,2,0,1,2,1,0,0,1,1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -3,3,3,3,2,2,2,2,3,1,2,2,1,1,3,3,0,3,2,1,2,3,2,1,3,3,1,1,0,2,1,3, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,3,3,2,2,2,3,2,3,3,3,2,1,1,3,3,1,1,1,2,2,3,2,3,2,2,2,1,0,2,2,1, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -1,0,0,3,3,3,3,3,0,0,3,3,2,3,0,0,0,2,3,3,1,0,1,2,0,0,1,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,1,2,3,3,3,3,3,1,2,3,3,2,2,1,1,0,3,3,2,2,1,2,2,1,0,2,2,0,1,1,1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,2,2,1,3,1,2,3,3,2,2,1,1,2,2,1,1,1,1,3,2,1,1,1,1,2,1,0,1,2,1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0, -2,3,3,1,1,1,1,1,3,3,3,0,1,1,3,3,1,1,1,1,1,2,2,0,3,1,1,2,0,2,1,1, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,1,0,1,2,1,2,2,0,1,2,3,1,2,0,0,0,2,1,1,1,1,1,2,0,0,1,1,0,0,0,0, -1,2,1,2,2,2,1,2,1,2,0,2,0,2,2,1,1,2,1,1,2,1,1,1,0,1,0,0,0,1,1,0, -1,1,1,2,3,2,3,3,0,1,2,2,3,1,0,1,0,2,1,2,2,0,1,1,0,0,1,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,0,3,3,2,2,1,0,0,3,2,3,2,0,0,0,1,1,3,0,0,1,1,0,0,2,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,1,1,2,2,3,3,1,0,1,3,2,3,1,1,1,0,1,1,1,1,1,3,1,0,0,2,2,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,1,1,1,2,2,2,1,0,1,2,3,3,2,0,0,0,2,1,1,1,2,1,1,1,0,1,1,1,0,0,0, -1,2,2,2,2,2,1,1,1,2,0,2,1,1,1,1,1,2,1,1,1,1,1,1,0,1,1,1,0,0,1,1, -3,2,2,1,0,0,1,1,2,2,0,3,0,1,2,1,1,0,0,1,1,1,0,1,1,1,1,0,2,1,1,1, -2,2,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,2,3,1,1,1,1,1,1,1,1,1,0,1, -2,3,3,0,1,0,0,0,3,3,1,0,0,1,2,2,1,0,0,0,0,2,0,0,1,1,1,0,2,1,1,1, -2,1,1,1,1,1,1,2,1,1,0,1,1,0,1,1,1,0,1,2,1,1,0,1,1,1,1,1,1,1,0,1, -2,3,3,0,1,0,0,0,2,2,0,0,0,0,1,2,2,0,0,0,0,1,0,0,1,1,0,0,2,0,1,0, -2,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,0,1,1,1,1,1,0,1, -3,2,2,0,1,0,1,0,2,3,2,0,0,1,2,2,1,0,0,1,1,1,0,0,2,1,0,1,2,2,1,1, -2,1,1,1,1,1,1,2,1,1,1,1,1,1,0,2,1,0,1,1,0,1,1,1,0,1,1,2,1,1,0,1, -2,2,2,0,0,1,0,0,2,2,1,1,0,0,2,1,1,0,0,0,1,2,0,0,2,1,0,0,2,1,1,1, -2,1,1,1,1,2,1,2,1,1,1,2,2,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,0,1, -1,2,3,0,0,0,1,0,3,2,1,0,0,1,2,1,1,0,0,0,0,2,1,0,1,1,0,0,2,1,2,1, -1,1,0,0,0,1,0,1,1,1,1,1,2,0,0,1,0,0,0,2,0,0,1,1,1,1,1,1,1,1,0,1, -3,0,0,2,1,2,2,1,0,0,2,1,2,2,0,0,0,2,1,1,1,0,1,1,0,0,1,1,2,0,0,0, -1,2,1,2,2,1,1,2,1,2,0,1,1,1,1,1,1,1,1,1,2,1,1,0,0,1,1,1,1,0,0,1, -1,3,2,0,0,0,1,0,2,2,2,0,0,0,2,2,1,0,0,0,0,3,1,1,1,1,0,0,2,1,1,1, -2,1,0,1,1,1,0,1,1,1,1,1,1,1,0,2,1,0,0,1,0,1,1,0,1,1,1,1,1,1,0,1, -2,3,2,0,0,0,1,0,2,2,0,0,0,0,2,1,1,0,0,0,0,2,1,0,1,1,0,0,2,1,1,0, -2,1,1,1,1,2,1,2,1,2,0,1,1,1,0,2,1,1,1,2,1,1,1,1,0,1,1,1,1,1,0,1, -3,1,1,2,2,2,3,2,1,1,2,2,1,1,0,1,0,2,2,1,1,1,1,1,0,0,1,1,0,1,1,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,0,0,0,0,0,2,2,0,0,0,0,2,2,1,0,0,0,1,1,0,0,1,2,0,0,2,1,1,1, -2,2,1,1,1,2,1,2,1,1,0,1,1,1,1,2,1,1,1,2,1,1,1,1,0,1,2,1,1,1,0,1, -1,0,0,1,2,3,2,1,0,0,2,0,1,1,0,0,0,1,1,1,1,0,1,1,0,0,1,0,0,0,0,0, -1,2,1,2,1,2,1,1,1,2,0,2,1,1,1,0,1,2,0,0,1,1,1,0,0,0,0,0,0,0,0,0, -2,3,2,0,0,0,0,0,1,1,2,1,0,0,1,1,1,0,0,0,0,2,0,0,1,1,0,0,2,1,1,1, -2,1,1,1,1,1,1,2,1,0,1,1,1,1,0,2,1,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1, -1,2,2,0,1,1,1,0,2,2,2,0,0,0,3,2,1,0,0,0,1,1,0,0,1,1,0,1,1,1,0,0, -1,1,0,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,0,0,1,1,1,0,1,0,1, -2,1,0,2,1,1,2,2,1,1,2,1,1,1,0,0,0,1,1,0,1,1,1,1,0,0,1,1,1,0,0,0, -1,2,2,2,2,2,1,1,1,2,0,2,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,1,0, -1,2,3,0,0,0,1,0,2,2,0,0,0,0,2,2,0,0,0,0,0,1,0,0,1,0,0,0,2,0,1,0, -2,1,1,1,1,1,0,2,0,0,0,1,2,1,1,1,1,0,1,2,0,1,0,1,0,1,1,1,0,1,0,1, -2,2,2,0,0,0,1,0,2,1,2,0,0,0,1,1,2,0,0,0,0,1,0,0,1,1,0,0,2,1,0,1, -2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,1,1,1,1,1,0,1, -1,2,2,0,0,0,1,0,2,2,2,0,0,0,1,1,0,0,0,0,0,1,1,0,2,0,0,1,1,1,0,1, -1,0,1,1,1,1,1,1,0,1,1,1,1,0,0,1,0,0,1,1,0,1,0,1,1,1,1,1,0,0,0,1, -1,0,0,1,0,1,2,1,0,0,1,1,1,2,0,0,0,1,1,0,1,0,1,1,0,0,1,0,0,0,0,0, -0,2,1,2,1,1,1,1,1,2,0,2,0,1,1,0,1,2,1,0,1,1,1,0,0,0,0,0,0,1,0,0, -2,1,1,0,1,2,0,0,1,1,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,0,0,0,2,1,0,1, -2,2,1,1,1,1,1,2,1,1,0,1,1,1,1,2,1,1,1,2,1,1,0,1,0,1,1,1,1,1,0,1, -1,2,2,0,0,0,0,0,1,1,0,0,0,0,2,1,0,0,0,0,0,2,0,0,2,2,0,0,2,0,0,1, -2,1,1,1,1,1,1,1,0,1,1,0,1,1,0,1,0,0,0,1,1,1,1,0,0,1,1,1,1,0,0,1, -1,1,2,0,0,3,1,0,2,1,1,1,0,0,1,1,1,0,0,0,1,1,0,0,0,1,0,0,1,0,1,0, -1,2,1,0,1,1,1,2,1,1,0,1,1,1,1,1,0,0,0,1,1,1,1,1,0,1,0,0,0,1,0,0, -2,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,2,0,0,0, -2,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,2,1,1,0,0,1,1,1,1,1,0,1, -2,1,1,1,2,1,1,1,0,1,1,2,1,0,0,0,0,1,1,1,1,0,1,0,0,0,0,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,1,0,1,1,1,1,1,0,0,1,1,2,1,0,0,0,1,1,0,0,0,1,1,0,0,1,0,1,0,0,0, -1,2,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0, -2,0,0,0,1,1,1,1,0,0,1,1,0,0,0,0,0,1,1,1,2,0,0,1,0,0,1,0,1,0,0,0, -0,1,1,1,1,1,1,1,1,2,0,1,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, -1,0,0,1,1,1,1,1,0,0,2,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0, -0,1,1,1,1,1,1,0,1,1,0,1,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0, -1,0,0,1,1,1,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, -0,1,1,1,1,1,0,0,1,1,0,1,0,1,0,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, -0,0,0,1,0,0,0,0,0,0,1,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,1,1,1,0,1,0,0,1,1,0,1,0,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, -2,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,0,1,0,0,1,0,1,0,1,1,1,0,0,1,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,0,1,1,1,1,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, -0,1,1,1,1,1,1,0,1,1,0,1,0,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0, -) - -Latin2HungarianModel = { - 'char_to_order_map': Latin2_HungarianCharToOrderMap, - 'precedence_matrix': HungarianLangModel, - 'typical_positive_ratio': 0.947368, - 'keep_english_letter': True, - 'charset_name': "ISO-8859-2", - 'language': 'Hungarian', -} - -Win1250HungarianModel = { - 'char_to_order_map': win1250HungarianCharToOrderMap, - 'precedence_matrix': HungarianLangModel, - 'typical_positive_ratio': 0.947368, - 'keep_english_letter': True, - 'charset_name': "windows-1250", - 'language': 'Hungarian', -} diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langthaimodel.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langthaimodel.py deleted file mode 100644 index 15f94c2..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langthaimodel.py +++ /dev/null @@ -1,199 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -# 255: Control characters that usually does not exist in any text -# 254: Carriage/Return -# 253: symbol (punctuation) that does not belong to word -# 252: 0 - 9 - -# The following result for thai was collected from a limited sample (1M). - -# Character Mapping Table: -TIS620CharToOrderMap = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253,182,106,107,100,183,184,185,101, 94,186,187,108,109,110,111, # 40 -188,189,190, 89, 95,112,113,191,192,193,194,253,253,253,253,253, # 50 -253, 64, 72, 73,114, 74,115,116,102, 81,201,117, 90,103, 78, 82, # 60 - 96,202, 91, 79, 84,104,105, 97, 98, 92,203,253,253,253,253,253, # 70 -209,210,211,212,213, 88,214,215,216,217,218,219,220,118,221,222, -223,224, 99, 85, 83,225,226,227,228,229,230,231,232,233,234,235, -236, 5, 30,237, 24,238, 75, 8, 26, 52, 34, 51,119, 47, 58, 57, - 49, 53, 55, 43, 20, 19, 44, 14, 48, 3, 17, 25, 39, 62, 31, 54, - 45, 9, 16, 2, 61, 15,239, 12, 42, 46, 18, 21, 76, 4, 66, 63, - 22, 10, 1, 36, 23, 13, 40, 27, 32, 35, 86,240,241,242,243,244, - 11, 28, 41, 29, 33,245, 50, 37, 6, 7, 67, 77, 38, 93,246,247, - 68, 56, 59, 65, 69, 60, 70, 80, 71, 87,248,249,250,251,252,253, -) - -# Model Table: -# total sequences: 100% -# first 512 sequences: 92.6386% -# first 1024 sequences:7.3177% -# rest sequences: 1.0230% -# negative sequences: 0.0436% -ThaiLangModel = ( -0,1,3,3,3,3,0,0,3,3,0,3,3,0,3,3,3,3,3,3,3,3,0,0,3,3,3,0,3,3,3,3, -0,3,3,0,0,0,1,3,0,3,3,2,3,3,0,1,2,3,3,3,3,0,2,0,2,0,0,3,2,1,2,2, -3,0,3,3,2,3,0,0,3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,0,3,2,3,0,2,2,2,3, -0,2,3,0,0,0,0,1,0,1,2,3,1,1,3,2,2,0,1,1,0,0,1,0,0,0,0,0,0,0,1,1, -3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,3,3,2,3,2,3,3,2,2,2, -3,1,2,3,0,3,3,2,2,1,2,3,3,1,2,0,1,3,0,1,0,0,1,0,0,0,0,0,0,0,1,1, -3,3,2,2,3,3,3,3,1,2,3,3,3,3,3,2,2,2,2,3,3,2,2,3,3,2,2,3,2,3,2,2, -3,3,1,2,3,1,2,2,3,3,1,0,2,1,0,0,3,1,2,1,0,0,1,0,0,0,0,0,0,1,0,1, -3,3,3,3,3,3,2,2,3,3,3,3,2,3,2,2,3,3,2,2,3,2,2,2,2,1,1,3,1,2,1,1, -3,2,1,0,2,1,0,1,0,1,1,0,1,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0, -3,3,3,2,3,2,3,3,2,2,3,2,3,3,2,3,1,1,2,3,2,2,2,3,2,2,2,2,2,1,2,1, -2,2,1,1,3,3,2,1,0,1,2,2,0,1,3,0,0,0,1,1,0,0,0,0,0,2,3,0,0,2,1,1, -3,3,2,3,3,2,0,0,3,3,0,3,3,0,2,2,3,1,2,2,1,1,1,0,2,2,2,0,2,2,1,1, -0,2,1,0,2,0,0,2,0,1,0,0,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0, -3,3,2,3,3,2,0,0,3,3,0,2,3,0,2,1,2,2,2,2,1,2,0,0,2,2,2,0,2,2,1,1, -0,2,1,0,2,0,0,2,0,1,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0, -3,3,2,3,2,3,2,0,2,2,1,3,2,1,3,2,1,2,3,2,2,3,0,2,3,2,2,1,2,2,2,2, -1,2,2,0,0,0,0,2,0,1,2,0,1,1,1,0,1,0,3,1,1,0,0,0,0,0,0,0,0,0,1,0, -3,3,2,3,3,2,3,2,2,2,3,2,2,3,2,2,1,2,3,2,2,3,1,3,2,2,2,3,2,2,2,3, -3,2,1,3,0,1,1,1,0,2,1,1,1,1,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,2,0,0, -1,0,0,3,0,3,3,3,3,3,0,0,3,0,2,2,3,3,3,3,3,0,0,0,1,1,3,0,0,0,0,2, -0,0,1,0,0,0,0,0,0,0,2,3,0,0,0,3,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0,0, -2,0,3,3,3,3,0,0,2,3,0,0,3,0,3,3,2,3,3,3,3,3,0,0,3,3,3,0,0,0,3,3, -0,0,3,0,0,0,0,2,0,0,2,1,1,3,0,0,1,0,0,2,3,0,1,0,0,0,0,0,0,0,1,0, -3,3,3,3,2,3,3,3,3,3,3,3,1,2,1,3,3,2,2,1,2,2,2,3,1,1,2,0,2,1,2,1, -2,2,1,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0, -3,0,2,1,2,3,3,3,0,2,0,2,2,0,2,1,3,2,2,1,2,1,0,0,2,2,1,0,2,1,2,2, -0,1,1,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,2,1,3,3,1,1,3,0,2,3,1,1,3,2,1,1,2,0,2,2,3,2,1,1,1,1,1,2, -3,0,0,1,3,1,2,1,2,0,3,0,0,0,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, -3,3,1,1,3,2,3,3,3,1,3,2,1,3,2,1,3,2,2,2,2,1,3,3,1,2,1,3,1,2,3,0, -2,1,1,3,2,2,2,1,2,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2, -3,3,2,3,2,3,3,2,3,2,3,2,3,3,2,1,0,3,2,2,2,1,2,2,2,1,2,2,1,2,1,1, -2,2,2,3,0,1,3,1,1,1,1,0,1,1,0,2,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,2,3,2,2,1,1,3,2,3,2,3,2,0,3,2,2,1,2,0,2,2,2,1,2,2,2,2,1, -3,2,1,2,2,1,0,2,0,1,0,0,1,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,2,3,1,2,3,3,2,2,3,0,1,1,2,0,3,3,2,2,3,0,1,1,3,0,0,0,0, -3,1,0,3,3,0,2,0,2,1,0,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,2,3,2,3,3,0,1,3,1,1,2,1,2,1,1,3,1,1,0,2,3,1,1,1,1,1,1,1,1, -3,1,1,2,2,2,2,1,1,1,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -3,2,2,1,1,2,1,3,3,2,3,2,2,3,2,2,3,1,2,2,1,2,0,3,2,1,2,2,2,2,2,1, -3,2,1,2,2,2,1,1,1,1,0,0,1,1,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,1,3,3,0,2,1,0,3,2,0,0,3,1,0,1,1,0,1,0,0,0,0,0,1, -1,0,0,1,0,3,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,2,2,2,3,0,0,1,3,0,3,2,0,3,2,2,3,3,3,3,3,1,0,2,2,2,0,2,2,1,2, -0,2,3,0,0,0,0,1,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -3,0,2,3,1,3,3,2,3,3,0,3,3,0,3,2,2,3,2,3,3,3,0,0,2,2,3,0,1,1,1,3, -0,0,3,0,0,0,2,2,0,1,3,0,1,2,2,2,3,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1, -3,2,3,3,2,0,3,3,2,2,3,1,3,2,1,3,2,0,1,2,2,0,2,3,2,1,0,3,0,0,0,0, -3,0,0,2,3,1,3,0,0,3,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,1,3,2,2,2,1,2,0,1,3,1,1,3,1,3,0,0,2,1,1,1,1,2,1,1,1,0,2,1,0,1, -1,2,0,0,0,3,1,1,0,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,3,1,0,0,0,1,0, -3,3,3,3,2,2,2,2,2,1,3,1,1,1,2,0,1,1,2,1,2,1,3,2,0,0,3,1,1,1,1,1, -3,1,0,2,3,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,2,3,0,3,3,0,2,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,0, -0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,2,3,1,3,0,0,1,2,0,0,2,0,3,3,2,3,3,3,2,3,0,0,2,2,2,0,0,0,2,2, -0,0,1,0,0,0,0,3,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, -0,0,0,3,0,2,0,0,0,0,0,0,0,0,0,0,1,2,3,1,3,3,0,0,1,0,3,0,0,0,0,0, -0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,1,2,3,1,2,3,1,0,3,0,2,2,1,0,2,1,1,2,0,1,0,0,1,1,1,1,0,1,0,0, -1,0,0,0,0,1,1,0,3,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,2,1,0,1,1,1,3,1,2,2,2,2,2,2,1,1,1,1,0,3,1,0,1,3,1,1,1,1, -1,1,0,2,0,1,3,1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1, -3,0,2,2,1,3,3,2,3,3,0,1,1,0,2,2,1,2,1,3,3,1,0,0,3,2,0,0,0,0,2,1, -0,1,0,0,0,0,1,2,0,1,1,3,1,1,2,2,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, -0,0,3,0,0,1,0,0,0,3,0,0,3,0,3,1,0,1,1,1,3,2,0,0,0,3,0,0,0,0,2,0, -0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, -3,3,1,3,2,1,3,3,1,2,2,0,1,2,1,0,1,2,0,0,0,0,0,3,0,0,0,3,0,0,0,0, -3,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,1,2,0,3,3,3,2,2,0,1,1,0,1,3,0,0,0,2,2,0,0,0,0,3,1,0,1,0,0,0, -0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,2,3,1,2,0,0,2,1,0,3,1,0,1,2,0,1,1,1,1,3,0,0,3,1,1,0,2,2,1,1, -0,2,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,0,3,1,2,0,0,2,2,0,1,2,0,1,0,1,3,1,2,1,0,0,0,2,0,3,0,0,0,1,0, -0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,1,1,2,2,0,0,0,2,0,2,1,0,1,1,0,1,1,1,2,1,0,0,1,1,1,0,2,1,1,1, -0,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1, -0,0,0,2,0,1,3,1,1,1,1,0,0,0,0,3,2,0,1,0,0,0,1,2,0,0,0,1,0,0,0,0, -0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,2,3,2,2,0,0,0,1,0,0,0,0,2,3,2,1,2,2,3,0,0,0,2,3,1,0,0,0,1,1, -0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0, -3,3,2,2,0,1,0,0,0,0,2,0,2,0,1,0,0,0,1,1,0,0,0,2,1,0,1,0,1,1,0,0, -0,1,0,2,0,0,1,0,3,0,1,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,1,0,0,1,0,0,0,0,0,1,1,2,0,0,0,0,1,0,0,1,3,1,0,0,0,0,1,1,0,0, -0,1,0,0,0,0,3,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0, -3,3,1,1,1,1,2,3,0,0,2,1,1,1,1,1,0,2,1,1,0,0,0,2,1,0,1,2,1,1,0,1, -2,1,0,3,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,3,1,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1, -0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,2,0,0,0,0,0,0,1,2,1,0,1,1,0,2,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,2,0,0,0,1,3,0,1,0,0,0,2,0,0,0,0,0,0,0,1,2,0,0,0,0,0, -3,3,0,0,1,1,2,0,0,1,2,1,0,1,1,1,0,1,1,0,0,2,1,1,0,1,0,0,1,1,1,0, -0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,1,0,0,0,0,1,0,0,0,0,3,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0, -2,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,3,0,0,1,1,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,1,0,1,2,0,1,2,0,0,1,1,0,2,0,1,0,0,1,0,0,0,0,1,0,0,0,2,0,0,0,0, -1,0,0,1,0,1,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,1,0,0,0,0,0,0,0,1,1,0,1,1,0,2,1,3,0,0,0,0,1,1,0,0,0,0,0,0,0,3, -1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,0,1,0,1,0,0,2,0,0,2,0,0,1,1,2,0,0,1,1,0,0,0,1,0,0,0,1,1,0,0,0, -1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, -1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,3,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0, -1,0,0,0,0,0,0,0,0,1,0,0,0,0,2,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,1,1,0,0,2,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -) - -TIS620ThaiModel = { - 'char_to_order_map': TIS620CharToOrderMap, - 'precedence_matrix': ThaiLangModel, - 'typical_positive_ratio': 0.926386, - 'keep_english_letter': False, - 'charset_name': "TIS-620", - 'language': 'Thai', -} diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langturkishmodel.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langturkishmodel.py deleted file mode 100644 index a427a45..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/langturkishmodel.py +++ /dev/null @@ -1,193 +0,0 @@ -# -*- coding: utf-8 -*- -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# Özgür Baskın - Turkish Language Model -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -# 255: Control characters that usually does not exist in any text -# 254: Carriage/Return -# 253: symbol (punctuation) that does not belong to word -# 252: 0 - 9 - -# Character Mapping Table: -Latin5_TurkishCharToOrderMap = ( -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255, 23, 37, 47, 39, 29, 52, 36, 45, 53, 60, 16, 49, 20, 46, 42, - 48, 69, 44, 35, 31, 51, 38, 62, 65, 43, 56,255,255,255,255,255, -255, 1, 21, 28, 12, 2, 18, 27, 25, 3, 24, 10, 5, 13, 4, 15, - 26, 64, 7, 8, 9, 14, 32, 57, 58, 11, 22,255,255,255,255,255, -180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165, -164,163,162,161,160,159,101,158,157,156,155,154,153,152,151,106, -150,149,148,147,146,145,144,100,143,142,141,140,139,138,137,136, - 94, 80, 93,135,105,134,133, 63,132,131,130,129,128,127,126,125, -124,104, 73, 99, 79, 85,123, 54,122, 98, 92,121,120, 91,103,119, - 68,118,117, 97,116,115, 50, 90,114,113,112,111, 55, 41, 40, 86, - 89, 70, 59, 78, 71, 82, 88, 33, 77, 66, 84, 83,110, 75, 61, 96, - 30, 67,109, 74, 87,102, 34, 95, 81,108, 76, 72, 17, 6, 19,107, -) - -TurkishLangModel = ( -3,2,3,3,3,1,3,3,3,3,3,3,3,3,2,1,1,3,3,1,3,3,0,3,3,3,3,3,0,3,1,3, -3,2,1,0,0,1,1,0,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,2,2,0,0,1,0,0,1, -3,2,2,3,3,0,3,3,3,3,3,3,3,2,3,1,0,3,3,1,3,3,0,3,3,3,3,3,0,3,0,3, -3,1,1,0,1,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,2,2,0,0,0,1,0,1, -3,3,2,3,3,0,3,3,3,3,3,3,3,2,3,1,1,3,3,0,3,3,1,2,3,3,3,3,0,3,0,3, -3,1,1,0,0,0,1,0,0,0,0,1,1,0,1,2,1,0,0,0,1,0,0,0,0,2,0,0,0,0,0,1, -3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,1,3,3,2,0,3,2,1,2,2,1,3,3,0,0,0,2, -2,2,0,1,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,1,0,0,1, -3,3,3,2,3,3,1,2,3,3,3,3,3,3,3,1,3,2,1,0,3,2,0,1,2,3,3,2,1,0,0,2, -2,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,2,0,0,0, -1,0,1,3,3,1,3,3,3,3,3,3,3,1,2,0,0,2,3,0,2,3,0,0,2,2,2,3,0,3,0,1, -2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,0,3,2,0,2,3,2,3,3,1,0,0,2, -3,2,0,0,1,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,0,2,0,0,1, -3,3,3,2,3,3,2,3,3,3,3,2,3,3,3,0,3,3,0,0,2,1,0,0,2,3,2,2,0,0,0,2, -2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,0,1,0,2,0,0,1, -3,3,3,2,3,3,3,3,3,3,3,2,3,3,3,0,3,2,0,1,3,2,1,1,3,2,3,2,1,0,0,2, -2,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, -3,3,3,2,3,3,3,3,3,3,3,2,3,3,3,0,3,2,2,0,2,3,0,0,2,2,2,2,0,0,0,2, -3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,0,1,0,0,0, -3,3,3,3,3,3,3,2,2,2,2,3,2,3,3,0,3,3,1,1,2,2,0,0,2,2,3,2,0,0,1,3, -0,3,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1, -3,3,3,2,3,3,3,2,1,2,2,3,2,3,3,0,3,2,0,0,1,1,0,1,1,2,1,2,0,0,0,1, -0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,0,0, -3,3,3,2,3,3,2,3,2,2,2,3,3,3,3,1,3,1,1,0,3,2,1,1,3,3,2,3,1,0,0,1, -1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,0,0,1, -3,2,2,3,3,0,3,3,3,3,3,3,3,2,2,1,0,3,3,1,3,3,0,1,3,3,2,3,0,3,0,3, -2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, -2,2,2,3,3,0,3,3,3,3,3,3,3,3,3,0,0,3,2,0,3,3,0,3,2,3,3,3,0,3,1,3, -2,0,0,0,0,0,0,0,0,0,0,1,0,1,2,0,1,0,0,0,0,0,0,0,2,2,0,0,1,0,0,1, -3,3,3,1,2,3,3,1,0,0,1,0,0,3,3,2,3,0,0,2,0,0,2,0,2,0,0,0,2,0,2,0, -0,3,1,0,1,0,0,0,2,2,1,0,1,1,2,1,2,2,2,0,2,1,1,0,0,0,2,0,0,0,0,0, -1,2,1,3,3,0,3,3,3,3,3,2,3,0,0,0,0,2,3,0,2,3,1,0,2,3,1,3,0,3,0,2, -3,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,1,3,3,2,2,3,2,2,0,1,2,3,0,1,2,1,0,1,0,0,0,1,0,2,2,0,0,0,1, -1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0, -3,3,3,1,3,3,1,1,3,3,1,1,3,3,1,0,2,1,2,0,2,1,0,0,1,1,2,1,0,0,0,2, -2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,1,0,2,1,3,0,0,2,0,0,3,3,0,3,0,0,1,0,1,2,0,0,1,1,2,2,0,1,0, -0,1,2,1,1,0,1,0,1,1,1,1,1,0,1,1,1,2,2,1,2,0,1,0,0,0,0,0,0,1,0,0, -3,3,3,2,3,2,3,3,0,2,2,2,3,3,3,0,3,0,0,0,2,2,0,1,2,1,1,1,0,0,0,1, -0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, -3,3,3,3,3,3,2,1,2,2,3,3,3,3,2,0,2,0,0,0,2,2,0,0,2,1,3,3,0,0,1,1, -1,1,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0, -1,1,2,3,3,0,3,3,3,3,3,3,2,2,0,2,0,2,3,2,3,2,2,2,2,2,2,2,1,3,2,3, -2,0,2,1,2,2,2,2,1,1,2,2,1,2,2,1,2,0,0,2,1,1,0,2,1,0,0,1,0,0,0,1, -2,3,3,1,1,1,0,1,1,1,2,3,2,1,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0, -0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,2,2,2,3,2,3,2,2,1,3,3,3,0,2,1,2,0,2,1,0,0,1,1,1,1,1,0,0,1, -2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,2,0,1,0,0,0, -3,3,3,2,3,3,3,3,3,2,3,1,2,3,3,1,2,0,0,0,0,0,0,0,3,2,1,1,0,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, -3,3,3,2,2,3,3,2,1,1,1,1,1,3,3,0,3,1,0,0,1,1,0,0,3,1,2,1,0,0,0,0, -0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0, -3,3,3,2,2,3,2,2,2,3,2,1,1,3,3,0,3,0,0,0,0,1,0,0,3,1,1,2,0,0,0,1, -1,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -1,1,1,3,3,0,3,3,3,3,3,2,2,2,1,2,0,2,1,2,2,1,1,0,1,2,2,2,2,2,2,2, -0,0,2,1,2,1,2,1,0,1,1,3,1,2,1,1,2,0,0,2,0,1,0,1,0,1,0,0,0,1,0,1, -3,3,3,1,3,3,3,0,1,1,0,2,2,3,1,0,3,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0, -1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,2,0,0,2,2,1,0,0,1,0,0,3,3,1,3,0,0,1,1,0,2,0,3,0,0,0,2,0,1,1, -0,1,2,0,1,2,2,0,2,2,2,2,1,0,2,1,1,0,2,0,2,1,2,0,0,0,0,0,0,0,0,0, -3,3,3,1,3,2,3,2,0,2,2,2,1,3,2,0,2,1,2,0,1,2,0,0,1,0,2,2,0,0,0,2, -1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0, -3,3,3,0,3,3,1,1,2,3,1,0,3,2,3,0,3,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0, -1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,3,3,0,3,3,2,3,3,2,2,0,0,0,0,1,2,0,1,3,0,0,0,3,1,1,0,3,0,2, -2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,1,2,2,1,0,3,1,1,1,1,3,3,2,3,0,0,1,0,1,2,0,2,2,0,2,2,0,2,1, -0,2,2,1,1,1,1,0,2,1,1,0,1,1,1,1,2,1,2,1,2,0,1,0,1,0,0,0,0,0,0,0, -3,3,3,0,1,1,3,0,0,1,1,0,0,2,2,0,3,0,0,1,1,0,1,0,0,0,0,0,2,0,0,0, -0,3,1,0,1,0,1,0,2,0,0,1,0,1,0,1,1,1,2,1,1,0,2,0,0,0,0,0,0,0,0,0, -3,3,3,0,2,0,2,0,1,1,1,0,0,3,3,0,2,0,0,1,0,0,2,1,1,0,1,0,1,0,1,0, -0,2,0,1,2,0,2,0,2,1,1,0,1,0,2,1,1,0,2,1,1,0,1,0,0,0,1,1,0,0,0,0, -3,2,3,0,1,0,0,0,0,0,0,0,0,1,2,0,1,0,0,1,0,0,1,0,0,0,0,0,2,0,0,0, -0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,2,1,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,0,0,2,3,0,0,1,0,1,0,2,3,2,3,0,0,1,3,0,2,1,0,0,0,0,2,0,1,0, -0,2,1,0,0,1,1,0,2,1,0,0,1,0,0,1,1,0,1,1,2,0,1,0,0,0,0,1,0,0,0,0, -3,2,2,0,0,1,1,0,0,0,0,0,0,3,1,1,1,0,0,0,0,0,1,0,0,0,0,0,2,0,1,0, -0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0, -0,0,0,3,3,0,2,3,2,2,1,2,2,1,1,2,0,1,3,2,2,2,0,0,2,2,0,0,0,1,2,1, -3,0,2,1,1,0,1,1,1,0,1,2,2,2,1,1,2,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0, -0,1,1,2,3,0,3,3,3,2,2,2,2,1,0,1,0,1,0,1,2,2,0,0,2,2,1,3,1,1,2,1, -0,0,1,1,2,0,1,1,0,0,1,2,0,2,1,1,2,0,0,1,0,0,0,1,0,1,0,1,0,0,0,0, -3,3,2,0,0,3,1,0,0,0,0,0,0,3,2,1,2,0,0,1,0,0,2,0,0,0,0,0,2,0,1,0, -0,2,1,1,0,0,1,0,1,2,0,0,1,1,0,0,2,1,1,1,1,0,2,0,0,0,0,0,0,0,0,0, -3,3,2,0,0,1,0,0,0,0,1,0,0,3,3,2,2,0,0,1,0,0,2,0,1,0,0,0,2,0,1,0, -0,0,1,1,0,0,2,0,2,1,0,0,1,1,2,1,2,0,2,1,2,1,1,1,0,0,1,1,0,0,0,0, -3,3,2,0,0,2,2,0,0,0,1,1,0,2,2,1,3,1,0,1,0,1,2,0,0,0,0,0,1,0,1,0, -0,1,1,0,0,0,0,0,1,0,0,1,0,0,0,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,2,0,0,0,1,0,0,1,0,0,2,3,1,2,0,0,1,0,0,2,0,0,0,1,0,2,0,2,0, -0,1,1,2,2,1,2,0,2,1,1,0,0,1,1,0,1,1,1,1,2,1,1,0,0,0,0,0,0,0,0,0, -3,3,3,0,2,1,2,1,0,0,1,1,0,3,3,1,2,0,0,1,0,0,2,0,2,0,1,1,2,0,0,0, -0,0,1,1,1,1,2,0,1,1,0,1,1,1,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,0,0, -3,3,3,0,2,2,3,2,0,0,1,0,0,2,3,1,0,0,0,0,0,0,2,0,2,0,0,0,2,0,0,0, -0,1,1,0,0,0,1,0,0,1,0,1,1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0, -3,2,3,0,0,0,0,0,0,0,1,0,0,2,2,2,2,0,0,1,0,0,2,0,0,0,0,0,2,0,1,0, -0,0,2,1,1,0,1,0,2,1,1,0,0,1,1,2,1,0,2,0,2,0,1,0,0,0,2,0,0,0,0,0, -0,0,0,2,2,0,2,1,1,1,1,2,2,0,0,1,0,1,0,0,1,3,0,0,0,0,1,0,0,2,1,0, -0,0,1,0,1,0,0,0,0,0,2,1,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, -2,0,0,2,3,0,2,3,1,2,2,0,2,0,0,2,0,2,1,1,1,2,1,0,0,1,2,1,1,2,1,0, -1,0,2,0,1,0,1,1,0,0,2,2,1,2,1,1,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,0,2,1,2,0,0,0,1,0,0,3,2,0,1,0,0,1,0,0,2,0,0,0,1,2,1,0,1,0, -0,0,0,0,1,0,1,0,0,1,0,0,0,0,1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0, -0,0,0,2,2,0,2,2,1,1,0,1,1,1,1,1,0,0,1,2,1,1,1,0,1,0,0,0,1,1,1,1, -0,0,2,1,0,1,1,1,0,1,1,2,1,2,1,1,2,0,1,1,2,1,0,2,0,0,0,0,0,0,0,0, -3,2,2,0,0,2,0,0,0,0,0,0,0,2,2,0,2,0,0,1,0,0,2,0,0,0,0,0,2,0,0,0, -0,2,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0, -0,0,0,3,2,0,2,2,0,1,1,0,1,0,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0, -2,0,1,0,1,0,1,1,0,0,1,2,0,1,0,1,1,0,0,1,0,1,0,2,0,0,0,0,0,0,0,0, -2,2,2,0,1,1,0,0,0,1,0,0,0,1,2,0,1,0,0,1,0,0,1,0,0,0,0,1,2,0,1,0, -0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,2,1,0,1,1,1,0,0,0,0,1,2,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, -1,1,2,0,1,0,0,0,1,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,1, -0,0,1,2,2,0,2,1,2,1,1,2,2,0,0,0,0,1,0,0,1,1,0,0,2,0,0,0,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, -2,2,2,0,0,0,1,0,0,0,0,0,0,2,2,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, -0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,0,1,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,1,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -) - -Latin5TurkishModel = { - 'char_to_order_map': Latin5_TurkishCharToOrderMap, - 'precedence_matrix': TurkishLangModel, - 'typical_positive_ratio': 0.970290, - 'keep_english_letter': True, - 'charset_name': "ISO-8859-9", - 'language': 'Turkish', -} diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/latin1prober.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/latin1prober.py deleted file mode 100644 index 7d1e8c2..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/latin1prober.py +++ /dev/null @@ -1,145 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Universal charset detector code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 2001 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# Shy Shalom - original C code -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .charsetprober import CharSetProber -from .enums import ProbingState - -FREQ_CAT_NUM = 4 - -UDF = 0 # undefined -OTH = 1 # other -ASC = 2 # ascii capital letter -ASS = 3 # ascii small letter -ACV = 4 # accent capital vowel -ACO = 5 # accent capital other -ASV = 6 # accent small vowel -ASO = 7 # accent small other -CLASS_NUM = 8 # total classes - -Latin1_CharToClass = ( - OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 00 - 07 - OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 08 - 0F - OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 10 - 17 - OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 18 - 1F - OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 20 - 27 - OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 28 - 2F - OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 30 - 37 - OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 38 - 3F - OTH, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 40 - 47 - ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 48 - 4F - ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 50 - 57 - ASC, ASC, ASC, OTH, OTH, OTH, OTH, OTH, # 58 - 5F - OTH, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 60 - 67 - ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 68 - 6F - ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 70 - 77 - ASS, ASS, ASS, OTH, OTH, OTH, OTH, OTH, # 78 - 7F - OTH, UDF, OTH, ASO, OTH, OTH, OTH, OTH, # 80 - 87 - OTH, OTH, ACO, OTH, ACO, UDF, ACO, UDF, # 88 - 8F - UDF, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 90 - 97 - OTH, OTH, ASO, OTH, ASO, UDF, ASO, ACO, # 98 - 9F - OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # A0 - A7 - OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # A8 - AF - OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # B0 - B7 - OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # B8 - BF - ACV, ACV, ACV, ACV, ACV, ACV, ACO, ACO, # C0 - C7 - ACV, ACV, ACV, ACV, ACV, ACV, ACV, ACV, # C8 - CF - ACO, ACO, ACV, ACV, ACV, ACV, ACV, OTH, # D0 - D7 - ACV, ACV, ACV, ACV, ACV, ACO, ACO, ACO, # D8 - DF - ASV, ASV, ASV, ASV, ASV, ASV, ASO, ASO, # E0 - E7 - ASV, ASV, ASV, ASV, ASV, ASV, ASV, ASV, # E8 - EF - ASO, ASO, ASV, ASV, ASV, ASV, ASV, OTH, # F0 - F7 - ASV, ASV, ASV, ASV, ASV, ASO, ASO, ASO, # F8 - FF -) - -# 0 : illegal -# 1 : very unlikely -# 2 : normal -# 3 : very likely -Latin1ClassModel = ( -# UDF OTH ASC ASS ACV ACO ASV ASO - 0, 0, 0, 0, 0, 0, 0, 0, # UDF - 0, 3, 3, 3, 3, 3, 3, 3, # OTH - 0, 3, 3, 3, 3, 3, 3, 3, # ASC - 0, 3, 3, 3, 1, 1, 3, 3, # ASS - 0, 3, 3, 3, 1, 2, 1, 2, # ACV - 0, 3, 3, 3, 3, 3, 3, 3, # ACO - 0, 3, 1, 3, 1, 1, 1, 3, # ASV - 0, 3, 1, 3, 1, 1, 3, 3, # ASO -) - - -class Latin1Prober(CharSetProber): - def __init__(self): - super(Latin1Prober, self).__init__() - self._last_char_class = None - self._freq_counter = None - self.reset() - - def reset(self): - self._last_char_class = OTH - self._freq_counter = [0] * FREQ_CAT_NUM - CharSetProber.reset(self) - - @property - def charset_name(self): - return "ISO-8859-1" - - @property - def language(self): - return "" - - def feed(self, byte_str): - byte_str = self.filter_with_english_letters(byte_str) - for c in byte_str: - char_class = Latin1_CharToClass[c] - freq = Latin1ClassModel[(self._last_char_class * CLASS_NUM) - + char_class] - if freq == 0: - self._state = ProbingState.NOT_ME - break - self._freq_counter[freq] += 1 - self._last_char_class = char_class - - return self.state - - def get_confidence(self): - if self.state == ProbingState.NOT_ME: - return 0.01 - - total = sum(self._freq_counter) - if total < 0.01: - confidence = 0.0 - else: - confidence = ((self._freq_counter[3] - self._freq_counter[1] * 20.0) - / total) - if confidence < 0.0: - confidence = 0.0 - # lower the confidence of latin1 so that other more accurate - # detector can take priority. - confidence = confidence * 0.73 - return confidence diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/mbcharsetprober.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/mbcharsetprober.py deleted file mode 100644 index 6256ecf..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/mbcharsetprober.py +++ /dev/null @@ -1,91 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Universal charset detector code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 2001 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# Shy Shalom - original C code -# Proofpoint, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .charsetprober import CharSetProber -from .enums import ProbingState, MachineState - - -class MultiByteCharSetProber(CharSetProber): - """ - MultiByteCharSetProber - """ - - def __init__(self, lang_filter=None): - super(MultiByteCharSetProber, self).__init__(lang_filter=lang_filter) - self.distribution_analyzer = None - self.coding_sm = None - self._last_char = [0, 0] - - def reset(self): - super(MultiByteCharSetProber, self).reset() - if self.coding_sm: - self.coding_sm.reset() - if self.distribution_analyzer: - self.distribution_analyzer.reset() - self._last_char = [0, 0] - - @property - def charset_name(self): - raise NotImplementedError - - @property - def language(self): - raise NotImplementedError - - def feed(self, byte_str): - for i in range(len(byte_str)): - coding_state = self.coding_sm.next_state(byte_str[i]) - if coding_state == MachineState.ERROR: - self.logger.debug('%s %s prober hit error at byte %s', - self.charset_name, self.language, i) - self._state = ProbingState.NOT_ME - break - elif coding_state == MachineState.ITS_ME: - self._state = ProbingState.FOUND_IT - break - elif coding_state == MachineState.START: - char_len = self.coding_sm.get_current_charlen() - if i == 0: - self._last_char[1] = byte_str[0] - self.distribution_analyzer.feed(self._last_char, char_len) - else: - self.distribution_analyzer.feed(byte_str[i - 1:i + 1], - char_len) - - self._last_char[0] = byte_str[-1] - - if self.state == ProbingState.DETECTING: - if (self.distribution_analyzer.got_enough_data() and - (self.get_confidence() > self.SHORTCUT_THRESHOLD)): - self._state = ProbingState.FOUND_IT - - return self.state - - def get_confidence(self): - return self.distribution_analyzer.get_confidence() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/mbcsgroupprober.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/mbcsgroupprober.py deleted file mode 100644 index 530abe7..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/mbcsgroupprober.py +++ /dev/null @@ -1,54 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Universal charset detector code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 2001 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# Shy Shalom - original C code -# Proofpoint, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .charsetgroupprober import CharSetGroupProber -from .utf8prober import UTF8Prober -from .sjisprober import SJISProber -from .eucjpprober import EUCJPProber -from .gb2312prober import GB2312Prober -from .euckrprober import EUCKRProber -from .cp949prober import CP949Prober -from .big5prober import Big5Prober -from .euctwprober import EUCTWProber - - -class MBCSGroupProber(CharSetGroupProber): - def __init__(self, lang_filter=None): - super(MBCSGroupProber, self).__init__(lang_filter=lang_filter) - self.probers = [ - UTF8Prober(), - SJISProber(), - EUCJPProber(), - GB2312Prober(), - EUCKRProber(), - CP949Prober(), - Big5Prober(), - EUCTWProber() - ] - self.reset() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/mbcssm.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/mbcssm.py deleted file mode 100644 index 8360d0f..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/mbcssm.py +++ /dev/null @@ -1,572 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is mozilla.org code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .enums import MachineState - -# BIG5 - -BIG5_CLS = ( - 1,1,1,1,1,1,1,1, # 00 - 07 #allow 0x00 as legal value - 1,1,1,1,1,1,0,0, # 08 - 0f - 1,1,1,1,1,1,1,1, # 10 - 17 - 1,1,1,0,1,1,1,1, # 18 - 1f - 1,1,1,1,1,1,1,1, # 20 - 27 - 1,1,1,1,1,1,1,1, # 28 - 2f - 1,1,1,1,1,1,1,1, # 30 - 37 - 1,1,1,1,1,1,1,1, # 38 - 3f - 2,2,2,2,2,2,2,2, # 40 - 47 - 2,2,2,2,2,2,2,2, # 48 - 4f - 2,2,2,2,2,2,2,2, # 50 - 57 - 2,2,2,2,2,2,2,2, # 58 - 5f - 2,2,2,2,2,2,2,2, # 60 - 67 - 2,2,2,2,2,2,2,2, # 68 - 6f - 2,2,2,2,2,2,2,2, # 70 - 77 - 2,2,2,2,2,2,2,1, # 78 - 7f - 4,4,4,4,4,4,4,4, # 80 - 87 - 4,4,4,4,4,4,4,4, # 88 - 8f - 4,4,4,4,4,4,4,4, # 90 - 97 - 4,4,4,4,4,4,4,4, # 98 - 9f - 4,3,3,3,3,3,3,3, # a0 - a7 - 3,3,3,3,3,3,3,3, # a8 - af - 3,3,3,3,3,3,3,3, # b0 - b7 - 3,3,3,3,3,3,3,3, # b8 - bf - 3,3,3,3,3,3,3,3, # c0 - c7 - 3,3,3,3,3,3,3,3, # c8 - cf - 3,3,3,3,3,3,3,3, # d0 - d7 - 3,3,3,3,3,3,3,3, # d8 - df - 3,3,3,3,3,3,3,3, # e0 - e7 - 3,3,3,3,3,3,3,3, # e8 - ef - 3,3,3,3,3,3,3,3, # f0 - f7 - 3,3,3,3,3,3,3,0 # f8 - ff -) - -BIG5_ST = ( - MachineState.ERROR,MachineState.START,MachineState.START, 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 - MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,#08-0f - MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START#10-17 -) - -BIG5_CHAR_LEN_TABLE = (0, 1, 1, 2, 0) - -BIG5_SM_MODEL = {'class_table': BIG5_CLS, - 'class_factor': 5, - 'state_table': BIG5_ST, - 'char_len_table': BIG5_CHAR_LEN_TABLE, - 'name': 'Big5'} - -# CP949 - -CP949_CLS = ( - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,0,0, # 00 - 0f - 1,1,1,1,1,1,1,1, 1,1,1,0,1,1,1,1, # 10 - 1f - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, # 20 - 2f - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, # 30 - 3f - 1,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4, # 40 - 4f - 4,4,5,5,5,5,5,5, 5,5,5,1,1,1,1,1, # 50 - 5f - 1,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5, # 60 - 6f - 5,5,5,5,5,5,5,5, 5,5,5,1,1,1,1,1, # 70 - 7f - 0,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6, # 80 - 8f - 6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6, # 90 - 9f - 6,7,7,7,7,7,7,7, 7,7,7,7,7,8,8,8, # a0 - af - 7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7, # b0 - bf - 7,7,7,7,7,7,9,2, 2,3,2,2,2,2,2,2, # c0 - cf - 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, # d0 - df - 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, # e0 - ef - 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,0, # f0 - ff -) - -CP949_ST = ( -#cls= 0 1 2 3 4 5 6 7 8 9 # previous state = - MachineState.ERROR,MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START, 4, 5,MachineState.ERROR, 6, # MachineState.START - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, # MachineState.ERROR - MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME, # MachineState.ITS_ME - MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START, # 3 - MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START, # 4 - MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START, # 5 - MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START, # 6 -) - -CP949_CHAR_LEN_TABLE = (0, 1, 2, 0, 1, 1, 2, 2, 0, 2) - -CP949_SM_MODEL = {'class_table': CP949_CLS, - 'class_factor': 10, - 'state_table': CP949_ST, - 'char_len_table': CP949_CHAR_LEN_TABLE, - 'name': 'CP949'} - -# EUC-JP - -EUCJP_CLS = ( - 4,4,4,4,4,4,4,4, # 00 - 07 - 4,4,4,4,4,4,5,5, # 08 - 0f - 4,4,4,4,4,4,4,4, # 10 - 17 - 4,4,4,5,4,4,4,4, # 18 - 1f - 4,4,4,4,4,4,4,4, # 20 - 27 - 4,4,4,4,4,4,4,4, # 28 - 2f - 4,4,4,4,4,4,4,4, # 30 - 37 - 4,4,4,4,4,4,4,4, # 38 - 3f - 4,4,4,4,4,4,4,4, # 40 - 47 - 4,4,4,4,4,4,4,4, # 48 - 4f - 4,4,4,4,4,4,4,4, # 50 - 57 - 4,4,4,4,4,4,4,4, # 58 - 5f - 4,4,4,4,4,4,4,4, # 60 - 67 - 4,4,4,4,4,4,4,4, # 68 - 6f - 4,4,4,4,4,4,4,4, # 70 - 77 - 4,4,4,4,4,4,4,4, # 78 - 7f - 5,5,5,5,5,5,5,5, # 80 - 87 - 5,5,5,5,5,5,1,3, # 88 - 8f - 5,5,5,5,5,5,5,5, # 90 - 97 - 5,5,5,5,5,5,5,5, # 98 - 9f - 5,2,2,2,2,2,2,2, # a0 - a7 - 2,2,2,2,2,2,2,2, # a8 - af - 2,2,2,2,2,2,2,2, # b0 - b7 - 2,2,2,2,2,2,2,2, # b8 - bf - 2,2,2,2,2,2,2,2, # c0 - c7 - 2,2,2,2,2,2,2,2, # c8 - cf - 2,2,2,2,2,2,2,2, # d0 - d7 - 2,2,2,2,2,2,2,2, # d8 - df - 0,0,0,0,0,0,0,0, # e0 - e7 - 0,0,0,0,0,0,0,0, # e8 - ef - 0,0,0,0,0,0,0,0, # f0 - f7 - 0,0,0,0,0,0,0,5 # f8 - ff -) - -EUCJP_ST = ( - 3, 4, 3, 5,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f - MachineState.ITS_ME,MachineState.ITS_ME,MachineState.START,MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#10-17 - MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 3,MachineState.ERROR,#18-1f - 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START#20-27 -) - -EUCJP_CHAR_LEN_TABLE = (2, 2, 2, 3, 1, 0) - -EUCJP_SM_MODEL = {'class_table': EUCJP_CLS, - 'class_factor': 6, - 'state_table': EUCJP_ST, - 'char_len_table': EUCJP_CHAR_LEN_TABLE, - 'name': 'EUC-JP'} - -# EUC-KR - -EUCKR_CLS = ( - 1,1,1,1,1,1,1,1, # 00 - 07 - 1,1,1,1,1,1,0,0, # 08 - 0f - 1,1,1,1,1,1,1,1, # 10 - 17 - 1,1,1,0,1,1,1,1, # 18 - 1f - 1,1,1,1,1,1,1,1, # 20 - 27 - 1,1,1,1,1,1,1,1, # 28 - 2f - 1,1,1,1,1,1,1,1, # 30 - 37 - 1,1,1,1,1,1,1,1, # 38 - 3f - 1,1,1,1,1,1,1,1, # 40 - 47 - 1,1,1,1,1,1,1,1, # 48 - 4f - 1,1,1,1,1,1,1,1, # 50 - 57 - 1,1,1,1,1,1,1,1, # 58 - 5f - 1,1,1,1,1,1,1,1, # 60 - 67 - 1,1,1,1,1,1,1,1, # 68 - 6f - 1,1,1,1,1,1,1,1, # 70 - 77 - 1,1,1,1,1,1,1,1, # 78 - 7f - 0,0,0,0,0,0,0,0, # 80 - 87 - 0,0,0,0,0,0,0,0, # 88 - 8f - 0,0,0,0,0,0,0,0, # 90 - 97 - 0,0,0,0,0,0,0,0, # 98 - 9f - 0,2,2,2,2,2,2,2, # a0 - a7 - 2,2,2,2,2,3,3,3, # a8 - af - 2,2,2,2,2,2,2,2, # b0 - b7 - 2,2,2,2,2,2,2,2, # b8 - bf - 2,2,2,2,2,2,2,2, # c0 - c7 - 2,3,2,2,2,2,2,2, # c8 - cf - 2,2,2,2,2,2,2,2, # d0 - d7 - 2,2,2,2,2,2,2,2, # d8 - df - 2,2,2,2,2,2,2,2, # e0 - e7 - 2,2,2,2,2,2,2,2, # e8 - ef - 2,2,2,2,2,2,2,2, # f0 - f7 - 2,2,2,2,2,2,2,0 # f8 - ff -) - -EUCKR_ST = ( - MachineState.ERROR,MachineState.START, 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 - MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START #08-0f -) - -EUCKR_CHAR_LEN_TABLE = (0, 1, 2, 0) - -EUCKR_SM_MODEL = {'class_table': EUCKR_CLS, - 'class_factor': 4, - 'state_table': EUCKR_ST, - 'char_len_table': EUCKR_CHAR_LEN_TABLE, - 'name': 'EUC-KR'} - -# EUC-TW - -EUCTW_CLS = ( - 2,2,2,2,2,2,2,2, # 00 - 07 - 2,2,2,2,2,2,0,0, # 08 - 0f - 2,2,2,2,2,2,2,2, # 10 - 17 - 2,2,2,0,2,2,2,2, # 18 - 1f - 2,2,2,2,2,2,2,2, # 20 - 27 - 2,2,2,2,2,2,2,2, # 28 - 2f - 2,2,2,2,2,2,2,2, # 30 - 37 - 2,2,2,2,2,2,2,2, # 38 - 3f - 2,2,2,2,2,2,2,2, # 40 - 47 - 2,2,2,2,2,2,2,2, # 48 - 4f - 2,2,2,2,2,2,2,2, # 50 - 57 - 2,2,2,2,2,2,2,2, # 58 - 5f - 2,2,2,2,2,2,2,2, # 60 - 67 - 2,2,2,2,2,2,2,2, # 68 - 6f - 2,2,2,2,2,2,2,2, # 70 - 77 - 2,2,2,2,2,2,2,2, # 78 - 7f - 0,0,0,0,0,0,0,0, # 80 - 87 - 0,0,0,0,0,0,6,0, # 88 - 8f - 0,0,0,0,0,0,0,0, # 90 - 97 - 0,0,0,0,0,0,0,0, # 98 - 9f - 0,3,4,4,4,4,4,4, # a0 - a7 - 5,5,1,1,1,1,1,1, # a8 - af - 1,1,1,1,1,1,1,1, # b0 - b7 - 1,1,1,1,1,1,1,1, # b8 - bf - 1,1,3,1,3,3,3,3, # c0 - c7 - 3,3,3,3,3,3,3,3, # c8 - cf - 3,3,3,3,3,3,3,3, # d0 - d7 - 3,3,3,3,3,3,3,3, # d8 - df - 3,3,3,3,3,3,3,3, # e0 - e7 - 3,3,3,3,3,3,3,3, # e8 - ef - 3,3,3,3,3,3,3,3, # f0 - f7 - 3,3,3,3,3,3,3,0 # f8 - ff -) - -EUCTW_ST = ( - MachineState.ERROR,MachineState.ERROR,MachineState.START, 3, 3, 3, 4,MachineState.ERROR,#00-07 - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f - MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.START,MachineState.ERROR,#10-17 - MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#18-1f - 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.START,MachineState.START,#20-27 - MachineState.START,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START #28-2f -) - -EUCTW_CHAR_LEN_TABLE = (0, 0, 1, 2, 2, 2, 3) - -EUCTW_SM_MODEL = {'class_table': EUCTW_CLS, - 'class_factor': 7, - 'state_table': EUCTW_ST, - 'char_len_table': EUCTW_CHAR_LEN_TABLE, - 'name': 'x-euc-tw'} - -# GB2312 - -GB2312_CLS = ( - 1,1,1,1,1,1,1,1, # 00 - 07 - 1,1,1,1,1,1,0,0, # 08 - 0f - 1,1,1,1,1,1,1,1, # 10 - 17 - 1,1,1,0,1,1,1,1, # 18 - 1f - 1,1,1,1,1,1,1,1, # 20 - 27 - 1,1,1,1,1,1,1,1, # 28 - 2f - 3,3,3,3,3,3,3,3, # 30 - 37 - 3,3,1,1,1,1,1,1, # 38 - 3f - 2,2,2,2,2,2,2,2, # 40 - 47 - 2,2,2,2,2,2,2,2, # 48 - 4f - 2,2,2,2,2,2,2,2, # 50 - 57 - 2,2,2,2,2,2,2,2, # 58 - 5f - 2,2,2,2,2,2,2,2, # 60 - 67 - 2,2,2,2,2,2,2,2, # 68 - 6f - 2,2,2,2,2,2,2,2, # 70 - 77 - 2,2,2,2,2,2,2,4, # 78 - 7f - 5,6,6,6,6,6,6,6, # 80 - 87 - 6,6,6,6,6,6,6,6, # 88 - 8f - 6,6,6,6,6,6,6,6, # 90 - 97 - 6,6,6,6,6,6,6,6, # 98 - 9f - 6,6,6,6,6,6,6,6, # a0 - a7 - 6,6,6,6,6,6,6,6, # a8 - af - 6,6,6,6,6,6,6,6, # b0 - b7 - 6,6,6,6,6,6,6,6, # b8 - bf - 6,6,6,6,6,6,6,6, # c0 - c7 - 6,6,6,6,6,6,6,6, # c8 - cf - 6,6,6,6,6,6,6,6, # d0 - d7 - 6,6,6,6,6,6,6,6, # d8 - df - 6,6,6,6,6,6,6,6, # e0 - e7 - 6,6,6,6,6,6,6,6, # e8 - ef - 6,6,6,6,6,6,6,6, # f0 - f7 - 6,6,6,6,6,6,6,0 # f8 - ff -) - -GB2312_ST = ( - MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START, 3,MachineState.ERROR,#00-07 - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f - MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,#10-17 - 4,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#18-1f - MachineState.ERROR,MachineState.ERROR, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,#20-27 - MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START #28-2f -) - -# To be accurate, the length of class 6 can be either 2 or 4. -# But it is not necessary to discriminate between the two since -# it is used for frequency analysis only, and we are validating -# each code range there as well. So it is safe to set it to be -# 2 here. -GB2312_CHAR_LEN_TABLE = (0, 1, 1, 1, 1, 1, 2) - -GB2312_SM_MODEL = {'class_table': GB2312_CLS, - 'class_factor': 7, - 'state_table': GB2312_ST, - 'char_len_table': GB2312_CHAR_LEN_TABLE, - 'name': 'GB2312'} - -# Shift_JIS - -SJIS_CLS = ( - 1,1,1,1,1,1,1,1, # 00 - 07 - 1,1,1,1,1,1,0,0, # 08 - 0f - 1,1,1,1,1,1,1,1, # 10 - 17 - 1,1,1,0,1,1,1,1, # 18 - 1f - 1,1,1,1,1,1,1,1, # 20 - 27 - 1,1,1,1,1,1,1,1, # 28 - 2f - 1,1,1,1,1,1,1,1, # 30 - 37 - 1,1,1,1,1,1,1,1, # 38 - 3f - 2,2,2,2,2,2,2,2, # 40 - 47 - 2,2,2,2,2,2,2,2, # 48 - 4f - 2,2,2,2,2,2,2,2, # 50 - 57 - 2,2,2,2,2,2,2,2, # 58 - 5f - 2,2,2,2,2,2,2,2, # 60 - 67 - 2,2,2,2,2,2,2,2, # 68 - 6f - 2,2,2,2,2,2,2,2, # 70 - 77 - 2,2,2,2,2,2,2,1, # 78 - 7f - 3,3,3,3,3,2,2,3, # 80 - 87 - 3,3,3,3,3,3,3,3, # 88 - 8f - 3,3,3,3,3,3,3,3, # 90 - 97 - 3,3,3,3,3,3,3,3, # 98 - 9f - #0xa0 is illegal in sjis encoding, but some pages does - #contain such byte. We need to be more error forgiven. - 2,2,2,2,2,2,2,2, # a0 - a7 - 2,2,2,2,2,2,2,2, # a8 - af - 2,2,2,2,2,2,2,2, # b0 - b7 - 2,2,2,2,2,2,2,2, # b8 - bf - 2,2,2,2,2,2,2,2, # c0 - c7 - 2,2,2,2,2,2,2,2, # c8 - cf - 2,2,2,2,2,2,2,2, # d0 - d7 - 2,2,2,2,2,2,2,2, # d8 - df - 3,3,3,3,3,3,3,3, # e0 - e7 - 3,3,3,3,3,4,4,4, # e8 - ef - 3,3,3,3,3,3,3,3, # f0 - f7 - 3,3,3,3,3,0,0,0) # f8 - ff - - -SJIS_ST = ( - MachineState.ERROR,MachineState.START,MachineState.START, 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f - MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START #10-17 -) - -SJIS_CHAR_LEN_TABLE = (0, 1, 1, 2, 0, 0) - -SJIS_SM_MODEL = {'class_table': SJIS_CLS, - 'class_factor': 6, - 'state_table': SJIS_ST, - 'char_len_table': SJIS_CHAR_LEN_TABLE, - 'name': 'Shift_JIS'} - -# UCS2-BE - -UCS2BE_CLS = ( - 0,0,0,0,0,0,0,0, # 00 - 07 - 0,0,1,0,0,2,0,0, # 08 - 0f - 0,0,0,0,0,0,0,0, # 10 - 17 - 0,0,0,3,0,0,0,0, # 18 - 1f - 0,0,0,0,0,0,0,0, # 20 - 27 - 0,3,3,3,3,3,0,0, # 28 - 2f - 0,0,0,0,0,0,0,0, # 30 - 37 - 0,0,0,0,0,0,0,0, # 38 - 3f - 0,0,0,0,0,0,0,0, # 40 - 47 - 0,0,0,0,0,0,0,0, # 48 - 4f - 0,0,0,0,0,0,0,0, # 50 - 57 - 0,0,0,0,0,0,0,0, # 58 - 5f - 0,0,0,0,0,0,0,0, # 60 - 67 - 0,0,0,0,0,0,0,0, # 68 - 6f - 0,0,0,0,0,0,0,0, # 70 - 77 - 0,0,0,0,0,0,0,0, # 78 - 7f - 0,0,0,0,0,0,0,0, # 80 - 87 - 0,0,0,0,0,0,0,0, # 88 - 8f - 0,0,0,0,0,0,0,0, # 90 - 97 - 0,0,0,0,0,0,0,0, # 98 - 9f - 0,0,0,0,0,0,0,0, # a0 - a7 - 0,0,0,0,0,0,0,0, # a8 - af - 0,0,0,0,0,0,0,0, # b0 - b7 - 0,0,0,0,0,0,0,0, # b8 - bf - 0,0,0,0,0,0,0,0, # c0 - c7 - 0,0,0,0,0,0,0,0, # c8 - cf - 0,0,0,0,0,0,0,0, # d0 - d7 - 0,0,0,0,0,0,0,0, # d8 - df - 0,0,0,0,0,0,0,0, # e0 - e7 - 0,0,0,0,0,0,0,0, # e8 - ef - 0,0,0,0,0,0,0,0, # f0 - f7 - 0,0,0,0,0,0,4,5 # f8 - ff -) - -UCS2BE_ST = ( - 5, 7, 7,MachineState.ERROR, 4, 3,MachineState.ERROR,MachineState.ERROR,#00-07 - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f - MachineState.ITS_ME,MachineState.ITS_ME, 6, 6, 6, 6,MachineState.ERROR,MachineState.ERROR,#10-17 - 6, 6, 6, 6, 6,MachineState.ITS_ME, 6, 6,#18-1f - 6, 6, 6, 6, 5, 7, 7,MachineState.ERROR,#20-27 - 5, 8, 6, 6,MachineState.ERROR, 6, 6, 6,#28-2f - 6, 6, 6, 6,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START #30-37 -) - -UCS2BE_CHAR_LEN_TABLE = (2, 2, 2, 0, 2, 2) - -UCS2BE_SM_MODEL = {'class_table': UCS2BE_CLS, - 'class_factor': 6, - 'state_table': UCS2BE_ST, - 'char_len_table': UCS2BE_CHAR_LEN_TABLE, - 'name': 'UTF-16BE'} - -# UCS2-LE - -UCS2LE_CLS = ( - 0,0,0,0,0,0,0,0, # 00 - 07 - 0,0,1,0,0,2,0,0, # 08 - 0f - 0,0,0,0,0,0,0,0, # 10 - 17 - 0,0,0,3,0,0,0,0, # 18 - 1f - 0,0,0,0,0,0,0,0, # 20 - 27 - 0,3,3,3,3,3,0,0, # 28 - 2f - 0,0,0,0,0,0,0,0, # 30 - 37 - 0,0,0,0,0,0,0,0, # 38 - 3f - 0,0,0,0,0,0,0,0, # 40 - 47 - 0,0,0,0,0,0,0,0, # 48 - 4f - 0,0,0,0,0,0,0,0, # 50 - 57 - 0,0,0,0,0,0,0,0, # 58 - 5f - 0,0,0,0,0,0,0,0, # 60 - 67 - 0,0,0,0,0,0,0,0, # 68 - 6f - 0,0,0,0,0,0,0,0, # 70 - 77 - 0,0,0,0,0,0,0,0, # 78 - 7f - 0,0,0,0,0,0,0,0, # 80 - 87 - 0,0,0,0,0,0,0,0, # 88 - 8f - 0,0,0,0,0,0,0,0, # 90 - 97 - 0,0,0,0,0,0,0,0, # 98 - 9f - 0,0,0,0,0,0,0,0, # a0 - a7 - 0,0,0,0,0,0,0,0, # a8 - af - 0,0,0,0,0,0,0,0, # b0 - b7 - 0,0,0,0,0,0,0,0, # b8 - bf - 0,0,0,0,0,0,0,0, # c0 - c7 - 0,0,0,0,0,0,0,0, # c8 - cf - 0,0,0,0,0,0,0,0, # d0 - d7 - 0,0,0,0,0,0,0,0, # d8 - df - 0,0,0,0,0,0,0,0, # e0 - e7 - 0,0,0,0,0,0,0,0, # e8 - ef - 0,0,0,0,0,0,0,0, # f0 - f7 - 0,0,0,0,0,0,4,5 # f8 - ff -) - -UCS2LE_ST = ( - 6, 6, 7, 6, 4, 3,MachineState.ERROR,MachineState.ERROR,#00-07 - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f - MachineState.ITS_ME,MachineState.ITS_ME, 5, 5, 5,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,#10-17 - 5, 5, 5,MachineState.ERROR, 5,MachineState.ERROR, 6, 6,#18-1f - 7, 6, 8, 8, 5, 5, 5,MachineState.ERROR,#20-27 - 5, 5, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 5, 5,#28-2f - 5, 5, 5,MachineState.ERROR, 5,MachineState.ERROR,MachineState.START,MachineState.START #30-37 -) - -UCS2LE_CHAR_LEN_TABLE = (2, 2, 2, 2, 2, 2) - -UCS2LE_SM_MODEL = {'class_table': UCS2LE_CLS, - 'class_factor': 6, - 'state_table': UCS2LE_ST, - 'char_len_table': UCS2LE_CHAR_LEN_TABLE, - 'name': 'UTF-16LE'} - -# UTF-8 - -UTF8_CLS = ( - 1,1,1,1,1,1,1,1, # 00 - 07 #allow 0x00 as a legal value - 1,1,1,1,1,1,0,0, # 08 - 0f - 1,1,1,1,1,1,1,1, # 10 - 17 - 1,1,1,0,1,1,1,1, # 18 - 1f - 1,1,1,1,1,1,1,1, # 20 - 27 - 1,1,1,1,1,1,1,1, # 28 - 2f - 1,1,1,1,1,1,1,1, # 30 - 37 - 1,1,1,1,1,1,1,1, # 38 - 3f - 1,1,1,1,1,1,1,1, # 40 - 47 - 1,1,1,1,1,1,1,1, # 48 - 4f - 1,1,1,1,1,1,1,1, # 50 - 57 - 1,1,1,1,1,1,1,1, # 58 - 5f - 1,1,1,1,1,1,1,1, # 60 - 67 - 1,1,1,1,1,1,1,1, # 68 - 6f - 1,1,1,1,1,1,1,1, # 70 - 77 - 1,1,1,1,1,1,1,1, # 78 - 7f - 2,2,2,2,3,3,3,3, # 80 - 87 - 4,4,4,4,4,4,4,4, # 88 - 8f - 4,4,4,4,4,4,4,4, # 90 - 97 - 4,4,4,4,4,4,4,4, # 98 - 9f - 5,5,5,5,5,5,5,5, # a0 - a7 - 5,5,5,5,5,5,5,5, # a8 - af - 5,5,5,5,5,5,5,5, # b0 - b7 - 5,5,5,5,5,5,5,5, # b8 - bf - 0,0,6,6,6,6,6,6, # c0 - c7 - 6,6,6,6,6,6,6,6, # c8 - cf - 6,6,6,6,6,6,6,6, # d0 - d7 - 6,6,6,6,6,6,6,6, # d8 - df - 7,8,8,8,8,8,8,8, # e0 - e7 - 8,8,8,8,8,9,8,8, # e8 - ef - 10,11,11,11,11,11,11,11, # f0 - f7 - 12,13,13,13,14,15,0,0 # f8 - ff -) - -UTF8_ST = ( - MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 12, 10,#00-07 - 9, 11, 8, 7, 6, 5, 4, 3,#08-0f - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#10-17 - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#18-1f - MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#20-27 - MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#28-2f - MachineState.ERROR,MachineState.ERROR, 5, 5, 5, 5,MachineState.ERROR,MachineState.ERROR,#30-37 - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#38-3f - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 5, 5, 5,MachineState.ERROR,MachineState.ERROR,#40-47 - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#48-4f - MachineState.ERROR,MachineState.ERROR, 7, 7, 7, 7,MachineState.ERROR,MachineState.ERROR,#50-57 - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#58-5f - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 7, 7,MachineState.ERROR,MachineState.ERROR,#60-67 - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#68-6f - MachineState.ERROR,MachineState.ERROR, 9, 9, 9, 9,MachineState.ERROR,MachineState.ERROR,#70-77 - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#78-7f - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 9,MachineState.ERROR,MachineState.ERROR,#80-87 - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#88-8f - MachineState.ERROR,MachineState.ERROR, 12, 12, 12, 12,MachineState.ERROR,MachineState.ERROR,#90-97 - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#98-9f - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 12,MachineState.ERROR,MachineState.ERROR,#a0-a7 - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#a8-af - MachineState.ERROR,MachineState.ERROR, 12, 12, 12,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#b0-b7 - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#b8-bf - MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,#c0-c7 - MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR #c8-cf -) - -UTF8_CHAR_LEN_TABLE = (0, 1, 0, 0, 0, 0, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6) - -UTF8_SM_MODEL = {'class_table': UTF8_CLS, - 'class_factor': 16, - 'state_table': UTF8_ST, - 'char_len_table': UTF8_CHAR_LEN_TABLE, - 'name': 'UTF-8'} diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/sbcharsetprober.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/sbcharsetprober.py deleted file mode 100644 index 0adb51d..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/sbcharsetprober.py +++ /dev/null @@ -1,132 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Universal charset detector code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 2001 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# Shy Shalom - original C code -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .charsetprober import CharSetProber -from .enums import CharacterCategory, ProbingState, SequenceLikelihood - - -class SingleByteCharSetProber(CharSetProber): - SAMPLE_SIZE = 64 - SB_ENOUGH_REL_THRESHOLD = 1024 # 0.25 * SAMPLE_SIZE^2 - POSITIVE_SHORTCUT_THRESHOLD = 0.95 - NEGATIVE_SHORTCUT_THRESHOLD = 0.05 - - def __init__(self, model, reversed=False, name_prober=None): - super(SingleByteCharSetProber, self).__init__() - self._model = model - # TRUE if we need to reverse every pair in the model lookup - self._reversed = reversed - # Optional auxiliary prober for name decision - self._name_prober = name_prober - self._last_order = None - self._seq_counters = None - self._total_seqs = None - self._total_char = None - self._freq_char = None - self.reset() - - def reset(self): - super(SingleByteCharSetProber, self).reset() - # char order of last character - self._last_order = 255 - self._seq_counters = [0] * SequenceLikelihood.get_num_categories() - self._total_seqs = 0 - self._total_char = 0 - # characters that fall in our sampling range - self._freq_char = 0 - - @property - def charset_name(self): - if self._name_prober: - return self._name_prober.charset_name - else: - return self._model['charset_name'] - - @property - def language(self): - if self._name_prober: - return self._name_prober.language - else: - return self._model.get('language') - - def feed(self, byte_str): - if not self._model['keep_english_letter']: - byte_str = self.filter_international_words(byte_str) - if not byte_str: - return self.state - char_to_order_map = self._model['char_to_order_map'] - for i, c in enumerate(byte_str): - # XXX: Order is in range 1-64, so one would think we want 0-63 here, - # but that leads to 27 more test failures than before. - order = char_to_order_map[c] - # XXX: This was SYMBOL_CAT_ORDER before, with a value of 250, but - # CharacterCategory.SYMBOL is actually 253, so we use CONTROL - # to make it closer to the original intent. The only difference - # is whether or not we count digits and control characters for - # _total_char purposes. - if order < CharacterCategory.CONTROL: - self._total_char += 1 - if order < self.SAMPLE_SIZE: - self._freq_char += 1 - if self._last_order < self.SAMPLE_SIZE: - self._total_seqs += 1 - if not self._reversed: - i = (self._last_order * self.SAMPLE_SIZE) + order - model = self._model['precedence_matrix'][i] - else: # reverse the order of the letters in the lookup - i = (order * self.SAMPLE_SIZE) + self._last_order - model = self._model['precedence_matrix'][i] - self._seq_counters[model] += 1 - self._last_order = order - - charset_name = self._model['charset_name'] - if self.state == ProbingState.DETECTING: - if self._total_seqs > self.SB_ENOUGH_REL_THRESHOLD: - confidence = self.get_confidence() - if confidence > self.POSITIVE_SHORTCUT_THRESHOLD: - self.logger.debug('%s confidence = %s, we have a winner', - charset_name, confidence) - self._state = ProbingState.FOUND_IT - elif confidence < self.NEGATIVE_SHORTCUT_THRESHOLD: - self.logger.debug('%s confidence = %s, below negative ' - 'shortcut threshhold %s', charset_name, - confidence, - self.NEGATIVE_SHORTCUT_THRESHOLD) - self._state = ProbingState.NOT_ME - - return self.state - - def get_confidence(self): - r = 0.01 - if self._total_seqs > 0: - r = ((1.0 * self._seq_counters[SequenceLikelihood.POSITIVE]) / - self._total_seqs / self._model['typical_positive_ratio']) - r = r * self._freq_char / self._total_char - if r >= 1.0: - r = 0.99 - return r diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/sbcsgroupprober.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/sbcsgroupprober.py deleted file mode 100644 index 98e95dc..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/sbcsgroupprober.py +++ /dev/null @@ -1,73 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Universal charset detector code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 2001 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# Shy Shalom - original C code -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .charsetgroupprober import CharSetGroupProber -from .sbcharsetprober import SingleByteCharSetProber -from .langcyrillicmodel import (Win1251CyrillicModel, Koi8rModel, - Latin5CyrillicModel, MacCyrillicModel, - Ibm866Model, Ibm855Model) -from .langgreekmodel import Latin7GreekModel, Win1253GreekModel -from .langbulgarianmodel import Latin5BulgarianModel, Win1251BulgarianModel -# from .langhungarianmodel import Latin2HungarianModel, Win1250HungarianModel -from .langthaimodel import TIS620ThaiModel -from .langhebrewmodel import Win1255HebrewModel -from .hebrewprober import HebrewProber -from .langturkishmodel import Latin5TurkishModel - - -class SBCSGroupProber(CharSetGroupProber): - def __init__(self): - super(SBCSGroupProber, self).__init__() - self.probers = [ - SingleByteCharSetProber(Win1251CyrillicModel), - SingleByteCharSetProber(Koi8rModel), - SingleByteCharSetProber(Latin5CyrillicModel), - SingleByteCharSetProber(MacCyrillicModel), - SingleByteCharSetProber(Ibm866Model), - SingleByteCharSetProber(Ibm855Model), - SingleByteCharSetProber(Latin7GreekModel), - SingleByteCharSetProber(Win1253GreekModel), - SingleByteCharSetProber(Latin5BulgarianModel), - SingleByteCharSetProber(Win1251BulgarianModel), - # TODO: Restore Hungarian encodings (iso-8859-2 and windows-1250) - # after we retrain model. - # SingleByteCharSetProber(Latin2HungarianModel), - # SingleByteCharSetProber(Win1250HungarianModel), - SingleByteCharSetProber(TIS620ThaiModel), - SingleByteCharSetProber(Latin5TurkishModel), - ] - hebrew_prober = HebrewProber() - logical_hebrew_prober = SingleByteCharSetProber(Win1255HebrewModel, - False, hebrew_prober) - visual_hebrew_prober = SingleByteCharSetProber(Win1255HebrewModel, True, - hebrew_prober) - hebrew_prober.set_model_probers(logical_hebrew_prober, visual_hebrew_prober) - self.probers.extend([hebrew_prober, logical_hebrew_prober, - visual_hebrew_prober]) - - self.reset() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/sjisprober.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/sjisprober.py deleted file mode 100644 index 9e29623..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/sjisprober.py +++ /dev/null @@ -1,92 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is mozilla.org code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .mbcharsetprober import MultiByteCharSetProber -from .codingstatemachine import CodingStateMachine -from .chardistribution import SJISDistributionAnalysis -from .jpcntx import SJISContextAnalysis -from .mbcssm import SJIS_SM_MODEL -from .enums import ProbingState, MachineState - - -class SJISProber(MultiByteCharSetProber): - def __init__(self): - super(SJISProber, self).__init__() - self.coding_sm = CodingStateMachine(SJIS_SM_MODEL) - self.distribution_analyzer = SJISDistributionAnalysis() - self.context_analyzer = SJISContextAnalysis() - self.reset() - - def reset(self): - super(SJISProber, self).reset() - self.context_analyzer.reset() - - @property - def charset_name(self): - return self.context_analyzer.charset_name - - @property - def language(self): - return "Japanese" - - def feed(self, byte_str): - for i in range(len(byte_str)): - coding_state = self.coding_sm.next_state(byte_str[i]) - if coding_state == MachineState.ERROR: - self.logger.debug('%s %s prober hit error at byte %s', - self.charset_name, self.language, i) - self._state = ProbingState.NOT_ME - break - elif coding_state == MachineState.ITS_ME: - self._state = ProbingState.FOUND_IT - break - elif coding_state == MachineState.START: - char_len = self.coding_sm.get_current_charlen() - if i == 0: - self._last_char[1] = byte_str[0] - self.context_analyzer.feed(self._last_char[2 - char_len:], - char_len) - self.distribution_analyzer.feed(self._last_char, char_len) - else: - self.context_analyzer.feed(byte_str[i + 1 - char_len:i + 3 - - char_len], char_len) - self.distribution_analyzer.feed(byte_str[i - 1:i + 1], - char_len) - - self._last_char[0] = byte_str[-1] - - if self.state == ProbingState.DETECTING: - if (self.context_analyzer.got_enough_data() and - (self.get_confidence() > self.SHORTCUT_THRESHOLD)): - self._state = ProbingState.FOUND_IT - - return self.state - - def get_confidence(self): - context_conf = self.context_analyzer.get_confidence() - distrib_conf = self.distribution_analyzer.get_confidence() - return max(context_conf, distrib_conf) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/universaldetector.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/universaldetector.py deleted file mode 100644 index 7b4e92d..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/universaldetector.py +++ /dev/null @@ -1,286 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Universal charset detector code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 2001 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# Shy Shalom - original C code -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### -""" -Module containing the UniversalDetector detector class, which is the primary -class a user of ``chardet`` should use. - -:author: Mark Pilgrim (initial port to Python) -:author: Shy Shalom (original C code) -:author: Dan Blanchard (major refactoring for 3.0) -:author: Ian Cordasco -""" - - -import codecs -import logging -import re - -from .charsetgroupprober import CharSetGroupProber -from .enums import InputState, LanguageFilter, ProbingState -from .escprober import EscCharSetProber -from .latin1prober import Latin1Prober -from .mbcsgroupprober import MBCSGroupProber -from .sbcsgroupprober import SBCSGroupProber - - -class UniversalDetector(object): - """ - The ``UniversalDetector`` class underlies the ``chardet.detect`` function - and coordinates all of the different charset probers. - - To get a ``dict`` containing an encoding and its confidence, you can simply - run: - - .. code:: - - u = UniversalDetector() - u.feed(some_bytes) - u.close() - detected = u.result - - """ - - MINIMUM_THRESHOLD = 0.20 - HIGH_BYTE_DETECTOR = re.compile(b'[\x80-\xFF]') - ESC_DETECTOR = re.compile(b'(\033|~{)') - WIN_BYTE_DETECTOR = re.compile(b'[\x80-\x9F]') - ISO_WIN_MAP = {'iso-8859-1': 'Windows-1252', - 'iso-8859-2': 'Windows-1250', - 'iso-8859-5': 'Windows-1251', - 'iso-8859-6': 'Windows-1256', - 'iso-8859-7': 'Windows-1253', - 'iso-8859-8': 'Windows-1255', - 'iso-8859-9': 'Windows-1254', - 'iso-8859-13': 'Windows-1257'} - - def __init__(self, lang_filter=LanguageFilter.ALL): - self._esc_charset_prober = None - self._charset_probers = [] - self.result = None - self.done = None - self._got_data = None - self._input_state = None - self._last_char = None - self.lang_filter = lang_filter - self.logger = logging.getLogger(__name__) - self._has_win_bytes = None - self.reset() - - def reset(self): - """ - Reset the UniversalDetector and all of its probers back to their - initial states. This is called by ``__init__``, so you only need to - call this directly in between analyses of different documents. - """ - self.result = {'encoding': None, 'confidence': 0.0, 'language': None} - self.done = False - self._got_data = False - self._has_win_bytes = False - self._input_state = InputState.PURE_ASCII - self._last_char = b'' - if self._esc_charset_prober: - self._esc_charset_prober.reset() - for prober in self._charset_probers: - prober.reset() - - def feed(self, byte_str): - """ - Takes a chunk of a document and feeds it through all of the relevant - charset probers. - - After calling ``feed``, you can check the value of the ``done`` - attribute to see if you need to continue feeding the - ``UniversalDetector`` more data, or if it has made a prediction - (in the ``result`` attribute). - - .. note:: - You should always call ``close`` when you're done feeding in your - document if ``done`` is not already ``True``. - """ - if self.done: - return - - if not len(byte_str): - return - - if not isinstance(byte_str, bytearray): - byte_str = bytearray(byte_str) - - # First check for known BOMs, since these are guaranteed to be correct - if not self._got_data: - # If the data starts with BOM, we know it is UTF - if byte_str.startswith(codecs.BOM_UTF8): - # EF BB BF UTF-8 with BOM - self.result = {'encoding': "UTF-8-SIG", - 'confidence': 1.0, - 'language': ''} - elif byte_str.startswith((codecs.BOM_UTF32_LE, - codecs.BOM_UTF32_BE)): - # FF FE 00 00 UTF-32, little-endian BOM - # 00 00 FE FF UTF-32, big-endian BOM - self.result = {'encoding': "UTF-32", - 'confidence': 1.0, - 'language': ''} - elif byte_str.startswith(b'\xFE\xFF\x00\x00'): - # FE FF 00 00 UCS-4, unusual octet order BOM (3412) - self.result = {'encoding': "X-ISO-10646-UCS-4-3412", - 'confidence': 1.0, - 'language': ''} - elif byte_str.startswith(b'\x00\x00\xFF\xFE'): - # 00 00 FF FE UCS-4, unusual octet order BOM (2143) - self.result = {'encoding': "X-ISO-10646-UCS-4-2143", - 'confidence': 1.0, - 'language': ''} - elif byte_str.startswith((codecs.BOM_LE, codecs.BOM_BE)): - # FF FE UTF-16, little endian BOM - # FE FF UTF-16, big endian BOM - self.result = {'encoding': "UTF-16", - 'confidence': 1.0, - 'language': ''} - - self._got_data = True - if self.result['encoding'] is not None: - self.done = True - return - - # If none of those matched and we've only see ASCII so far, check - # for high bytes and escape sequences - if self._input_state == InputState.PURE_ASCII: - if self.HIGH_BYTE_DETECTOR.search(byte_str): - self._input_state = InputState.HIGH_BYTE - elif self._input_state == InputState.PURE_ASCII and \ - self.ESC_DETECTOR.search(self._last_char + byte_str): - self._input_state = InputState.ESC_ASCII - - self._last_char = byte_str[-1:] - - # If we've seen escape sequences, use the EscCharSetProber, which - # uses a simple state machine to check for known escape sequences in - # HZ and ISO-2022 encodings, since those are the only encodings that - # use such sequences. - if self._input_state == InputState.ESC_ASCII: - if not self._esc_charset_prober: - self._esc_charset_prober = EscCharSetProber(self.lang_filter) - if self._esc_charset_prober.feed(byte_str) == ProbingState.FOUND_IT: - self.result = {'encoding': - self._esc_charset_prober.charset_name, - 'confidence': - self._esc_charset_prober.get_confidence(), - 'language': - self._esc_charset_prober.language} - self.done = True - # If we've seen high bytes (i.e., those with values greater than 127), - # we need to do more complicated checks using all our multi-byte and - # single-byte probers that are left. The single-byte probers - # use character bigram distributions to determine the encoding, whereas - # the multi-byte probers use a combination of character unigram and - # bigram distributions. - elif self._input_state == InputState.HIGH_BYTE: - if not self._charset_probers: - self._charset_probers = [MBCSGroupProber(self.lang_filter)] - # If we're checking non-CJK encodings, use single-byte prober - if self.lang_filter & LanguageFilter.NON_CJK: - self._charset_probers.append(SBCSGroupProber()) - self._charset_probers.append(Latin1Prober()) - for prober in self._charset_probers: - if prober.feed(byte_str) == ProbingState.FOUND_IT: - self.result = {'encoding': prober.charset_name, - 'confidence': prober.get_confidence(), - 'language': prober.language} - self.done = True - break - if self.WIN_BYTE_DETECTOR.search(byte_str): - self._has_win_bytes = True - - def close(self): - """ - Stop analyzing the current document and come up with a final - prediction. - - :returns: The ``result`` attribute, a ``dict`` with the keys - `encoding`, `confidence`, and `language`. - """ - # Don't bother with checks if we're already done - if self.done: - return self.result - self.done = True - - if not self._got_data: - self.logger.debug('no data received!') - - # Default to ASCII if it is all we've seen so far - elif self._input_state == InputState.PURE_ASCII: - self.result = {'encoding': 'ascii', - 'confidence': 1.0, - 'language': ''} - - # If we have seen non-ASCII, return the best that met MINIMUM_THRESHOLD - elif self._input_state == InputState.HIGH_BYTE: - prober_confidence = None - max_prober_confidence = 0.0 - max_prober = None - for prober in self._charset_probers: - if not prober: - continue - prober_confidence = prober.get_confidence() - if prober_confidence > max_prober_confidence: - max_prober_confidence = prober_confidence - max_prober = prober - if max_prober and (max_prober_confidence > self.MINIMUM_THRESHOLD): - charset_name = max_prober.charset_name - lower_charset_name = max_prober.charset_name.lower() - confidence = max_prober.get_confidence() - # Use Windows encoding name instead of ISO-8859 if we saw any - # extra Windows-specific bytes - if lower_charset_name.startswith('iso-8859'): - if self._has_win_bytes: - charset_name = self.ISO_WIN_MAP.get(lower_charset_name, - charset_name) - self.result = {'encoding': charset_name, - 'confidence': confidence, - 'language': max_prober.language} - - # Log all prober confidences if none met MINIMUM_THRESHOLD - if self.logger.getEffectiveLevel() == logging.DEBUG: - if self.result['encoding'] is None: - self.logger.debug('no probers hit minimum threshold') - for group_prober in self._charset_probers: - if not group_prober: - continue - if isinstance(group_prober, CharSetGroupProber): - for prober in group_prober.probers: - self.logger.debug('%s %s confidence = %s', - prober.charset_name, - prober.language, - prober.get_confidence()) - else: - self.logger.debug('%s %s confidence = %s', - prober.charset_name, - prober.language, - prober.get_confidence()) - return self.result diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/utf8prober.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/utf8prober.py deleted file mode 100644 index 6c3196c..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/utf8prober.py +++ /dev/null @@ -1,82 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is mozilla.org code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -from .charsetprober import CharSetProber -from .enums import ProbingState, MachineState -from .codingstatemachine import CodingStateMachine -from .mbcssm import UTF8_SM_MODEL - - - -class UTF8Prober(CharSetProber): - ONE_CHAR_PROB = 0.5 - - def __init__(self): - super(UTF8Prober, self).__init__() - self.coding_sm = CodingStateMachine(UTF8_SM_MODEL) - self._num_mb_chars = None - self.reset() - - def reset(self): - super(UTF8Prober, self).reset() - self.coding_sm.reset() - self._num_mb_chars = 0 - - @property - def charset_name(self): - return "utf-8" - - @property - def language(self): - return "" - - def feed(self, byte_str): - for c in byte_str: - coding_state = self.coding_sm.next_state(c) - if coding_state == MachineState.ERROR: - self._state = ProbingState.NOT_ME - break - elif coding_state == MachineState.ITS_ME: - self._state = ProbingState.FOUND_IT - break - elif coding_state == MachineState.START: - if self.coding_sm.get_current_charlen() >= 2: - self._num_mb_chars += 1 - - if self.state == ProbingState.DETECTING: - if self.get_confidence() > self.SHORTCUT_THRESHOLD: - self._state = ProbingState.FOUND_IT - - return self.state - - def get_confidence(self): - unlike = 0.99 - if self._num_mb_chars < 6: - unlike *= self.ONE_CHAR_PROB ** self._num_mb_chars - return 1.0 - unlike - else: - return unlike diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/version.py b/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/version.py deleted file mode 100644 index bb2a34a..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/chardet/version.py +++ /dev/null @@ -1,9 +0,0 @@ -""" -This module exists only to simplify retrieving the version number of chardet -from within setup.py and from chardet subpackages. - -:author: Dan Blanchard (dan.blanchard@gmail.com) -""" - -__version__ = "3.0.4" -VERSION = __version__.split('.') diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/colorama/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/colorama/__init__.py deleted file mode 100644 index 2a3bf47..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/colorama/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# 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' diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/colorama/ansi.py b/venv2/lib/python2.7/site-packages/pip/_vendor/colorama/ansi.py deleted file mode 100644 index 7877658..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/colorama/ansi.py +++ /dev/null @@ -1,102 +0,0 @@ -# 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() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/colorama/ansitowin32.py b/venv2/lib/python2.7/site-packages/pip/_vendor/colorama/ansitowin32.py deleted file mode 100644 index 359c92b..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/colorama/ansitowin32.py +++ /dev/null @@ -1,257 +0,0 @@ -# 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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/colorama/initialise.py b/venv2/lib/python2.7/site-packages/pip/_vendor/colorama/initialise.py deleted file mode 100644 index 430d066..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/colorama/initialise.py +++ /dev/null @@ -1,80 +0,0 @@ -# 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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/colorama/win32.py b/venv2/lib/python2.7/site-packages/pip/_vendor/colorama/win32.py deleted file mode 100644 index c2d8360..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/colorama/win32.py +++ /dev/null @@ -1,152 +0,0 @@ -# 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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/colorama/winterm.py b/venv2/lib/python2.7/site-packages/pip/_vendor/colorama/winterm.py deleted file mode 100644 index 0fdb4ec..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/colorama/winterm.py +++ /dev/null @@ -1,169 +0,0 @@ -# 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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/__init__.py deleted file mode 100644 index a786b4d..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -# -*- 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. -# -import logging - -__version__ = '0.2.8' - -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()) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/__init__.py deleted file mode 100644 index f7dbf4c..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -"""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. -""" diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/misc.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/misc.py deleted file mode 100644 index cfb318d..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/misc.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- 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__) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/shutil.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/shutil.py deleted file mode 100644 index 159e49e..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/shutil.py +++ /dev/null @@ -1,761 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012 The Python Software Foundation. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -"""Utility functions for copying and archiving files and directory trees. - -XXX The functions here don't copy the resource fork or other metadata on Mac. - -""" - -import os -import sys -import stat -from os.path import abspath -import fnmatch -import collections -import errno -from . import tarfile - -try: - import bz2 - _BZ2_SUPPORTED = True -except ImportError: - _BZ2_SUPPORTED = False - -try: - from pwd import getpwnam -except ImportError: - getpwnam = None - -try: - from grp import getgrnam -except ImportError: - getgrnam = None - -__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2", - "copytree", "move", "rmtree", "Error", "SpecialFileError", - "ExecError", "make_archive", "get_archive_formats", - "register_archive_format", "unregister_archive_format", - "get_unpack_formats", "register_unpack_format", - "unregister_unpack_format", "unpack_archive", "ignore_patterns"] - -class Error(EnvironmentError): - pass - -class SpecialFileError(EnvironmentError): - """Raised when trying to do a kind of operation (e.g. copying) which is - not supported on a special file (e.g. a named pipe)""" - -class ExecError(EnvironmentError): - """Raised when a command could not be executed""" - -class ReadError(EnvironmentError): - """Raised when an archive cannot be read""" - -class RegistryError(Exception): - """Raised when a registry operation with the archiving - and unpacking registries fails""" - - -try: - WindowsError -except NameError: - WindowsError = None - -def copyfileobj(fsrc, fdst, length=16*1024): - """copy data from file-like object fsrc to file-like object fdst""" - while 1: - buf = fsrc.read(length) - if not buf: - break - fdst.write(buf) - -def _samefile(src, dst): - # Macintosh, Unix. - if hasattr(os.path, 'samefile'): - try: - return os.path.samefile(src, dst) - except OSError: - return False - - # All other platforms: check for same pathname. - return (os.path.normcase(os.path.abspath(src)) == - os.path.normcase(os.path.abspath(dst))) - -def copyfile(src, dst): - """Copy data from src to dst""" - if _samefile(src, dst): - raise Error("`%s` and `%s` are the same file" % (src, dst)) - - for fn in [src, dst]: - try: - st = os.stat(fn) - except OSError: - # File most likely does not exist - pass - else: - # XXX What about other special files? (sockets, devices...) - if stat.S_ISFIFO(st.st_mode): - raise SpecialFileError("`%s` is a named pipe" % fn) - - with open(src, 'rb') as fsrc: - with open(dst, 'wb') as fdst: - copyfileobj(fsrc, fdst) - -def copymode(src, dst): - """Copy mode bits from src to dst""" - if hasattr(os, 'chmod'): - st = os.stat(src) - mode = stat.S_IMODE(st.st_mode) - os.chmod(dst, mode) - -def copystat(src, dst): - """Copy all stat info (mode bits, atime, mtime, flags) from src to dst""" - st = os.stat(src) - mode = stat.S_IMODE(st.st_mode) - if hasattr(os, 'utime'): - os.utime(dst, (st.st_atime, st.st_mtime)) - if hasattr(os, 'chmod'): - os.chmod(dst, mode) - if hasattr(os, 'chflags') and hasattr(st, 'st_flags'): - try: - os.chflags(dst, st.st_flags) - except OSError as why: - if (not hasattr(errno, 'EOPNOTSUPP') or - why.errno != errno.EOPNOTSUPP): - raise - -def copy(src, dst): - """Copy data and mode bits ("cp src dst"). - - The destination may be a directory. - - """ - if os.path.isdir(dst): - dst = os.path.join(dst, os.path.basename(src)) - copyfile(src, dst) - copymode(src, dst) - -def copy2(src, dst): - """Copy data and all stat info ("cp -p src dst"). - - The destination may be a directory. - - """ - if os.path.isdir(dst): - dst = os.path.join(dst, os.path.basename(src)) - copyfile(src, dst) - copystat(src, dst) - -def ignore_patterns(*patterns): - """Function that can be used as copytree() ignore parameter. - - Patterns is a sequence of glob-style patterns - that are used to exclude files""" - def _ignore_patterns(path, names): - ignored_names = [] - for pattern in patterns: - ignored_names.extend(fnmatch.filter(names, pattern)) - return set(ignored_names) - return _ignore_patterns - -def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, - ignore_dangling_symlinks=False): - """Recursively copy a directory tree. - - The destination directory must not already exist. - If exception(s) occur, an Error is raised with a list of reasons. - - If the optional symlinks flag is true, symbolic links in the - source tree result in symbolic links in the destination tree; if - it is false, the contents of the files pointed to by symbolic - links are copied. If the file pointed by the symlink doesn't - exist, an exception will be added in the list of errors raised in - an Error exception at the end of the copy process. - - You can set the optional ignore_dangling_symlinks flag to true if you - want to silence this exception. Notice that this has no effect on - platforms that don't support os.symlink. - - The optional ignore argument is a callable. If given, it - is called with the `src` parameter, which is the directory - being visited by copytree(), and `names` which is the list of - `src` contents, as returned by os.listdir(): - - callable(src, names) -> ignored_names - - Since copytree() is called recursively, the callable will be - called once for each directory that is copied. It returns a - list of names relative to the `src` directory that should - not be copied. - - The optional copy_function argument is a callable that will be used - to copy each file. It will be called with the source path and the - destination path as arguments. By default, copy2() is used, but any - function that supports the same signature (like copy()) can be used. - - """ - names = os.listdir(src) - if ignore is not None: - ignored_names = ignore(src, names) - else: - ignored_names = set() - - os.makedirs(dst) - errors = [] - for name in names: - if name in ignored_names: - continue - srcname = os.path.join(src, name) - dstname = os.path.join(dst, name) - try: - if os.path.islink(srcname): - linkto = os.readlink(srcname) - if symlinks: - os.symlink(linkto, dstname) - else: - # ignore dangling symlink if the flag is on - if not os.path.exists(linkto) and ignore_dangling_symlinks: - continue - # otherwise let the copy occurs. copy2 will raise an error - copy_function(srcname, dstname) - elif os.path.isdir(srcname): - copytree(srcname, dstname, symlinks, ignore, copy_function) - else: - # Will raise a SpecialFileError for unsupported file types - copy_function(srcname, dstname) - # catch the Error from the recursive copytree so that we can - # continue with other files - except Error as err: - errors.extend(err.args[0]) - except EnvironmentError as why: - errors.append((srcname, dstname, str(why))) - try: - copystat(src, dst) - except OSError as why: - if WindowsError is not None and isinstance(why, WindowsError): - # Copying file access times may fail on Windows - pass - else: - errors.extend((src, dst, str(why))) - if errors: - raise Error(errors) - -def rmtree(path, ignore_errors=False, onerror=None): - """Recursively delete a directory tree. - - If ignore_errors is set, errors are ignored; otherwise, if onerror - is set, it is called to handle the error with arguments (func, - path, exc_info) where func is os.listdir, os.remove, or os.rmdir; - path is the argument to that function that caused it to fail; and - exc_info is a tuple returned by sys.exc_info(). If ignore_errors - is false and onerror is None, an exception is raised. - - """ - if ignore_errors: - def onerror(*args): - pass - elif onerror is None: - def onerror(*args): - raise - try: - if os.path.islink(path): - # symlinks to directories are forbidden, see bug #1669 - raise OSError("Cannot call rmtree on a symbolic link") - except OSError: - onerror(os.path.islink, path, sys.exc_info()) - # can't continue even if onerror hook returns - return - names = [] - try: - names = os.listdir(path) - except os.error: - onerror(os.listdir, path, sys.exc_info()) - for name in names: - fullname = os.path.join(path, name) - try: - mode = os.lstat(fullname).st_mode - except os.error: - mode = 0 - if stat.S_ISDIR(mode): - rmtree(fullname, ignore_errors, onerror) - else: - try: - os.remove(fullname) - except os.error: - onerror(os.remove, fullname, sys.exc_info()) - try: - os.rmdir(path) - except os.error: - onerror(os.rmdir, path, sys.exc_info()) - - -def _basename(path): - # A basename() variant which first strips the trailing slash, if present. - # Thus we always get the last component of the path, even for directories. - return os.path.basename(path.rstrip(os.path.sep)) - -def move(src, dst): - """Recursively move a file or directory to another location. This is - similar to the Unix "mv" command. - - If the destination is a directory or a symlink to a directory, the source - is moved inside the directory. The destination path must not already - exist. - - If the destination already exists but is not a directory, it may be - overwritten depending on os.rename() semantics. - - If the destination is on our current filesystem, then rename() is used. - Otherwise, src is copied to the destination and then removed. - A lot more could be done here... A look at a mv.c shows a lot of - the issues this implementation glosses over. - - """ - real_dst = dst - if os.path.isdir(dst): - if _samefile(src, dst): - # We might be on a case insensitive filesystem, - # perform the rename anyway. - os.rename(src, dst) - return - - real_dst = os.path.join(dst, _basename(src)) - if os.path.exists(real_dst): - raise Error("Destination path '%s' already exists" % real_dst) - try: - os.rename(src, real_dst) - except OSError: - if os.path.isdir(src): - if _destinsrc(src, dst): - raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst)) - copytree(src, real_dst, symlinks=True) - rmtree(src) - else: - copy2(src, real_dst) - os.unlink(src) - -def _destinsrc(src, dst): - src = abspath(src) - dst = abspath(dst) - if not src.endswith(os.path.sep): - src += os.path.sep - if not dst.endswith(os.path.sep): - dst += os.path.sep - return dst.startswith(src) - -def _get_gid(name): - """Returns a gid, given a group name.""" - if getgrnam is None or name is None: - return None - try: - result = getgrnam(name) - except KeyError: - result = None - if result is not None: - return result[2] - return None - -def _get_uid(name): - """Returns an uid, given a user name.""" - if getpwnam is None or name is None: - return None - try: - result = getpwnam(name) - except KeyError: - result = None - if result is not None: - return result[2] - return None - -def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0, - owner=None, group=None, logger=None): - """Create a (possibly compressed) tar file from all the files under - 'base_dir'. - - 'compress' must be "gzip" (the default), "bzip2", or None. - - 'owner' and 'group' can be used to define an owner and a group for the - archive that is being built. If not provided, the current owner and group - will be used. - - The output tar file will be named 'base_name' + ".tar", possibly plus - the appropriate compression extension (".gz", or ".bz2"). - - Returns the output filename. - """ - tar_compression = {'gzip': 'gz', None: ''} - compress_ext = {'gzip': '.gz'} - - if _BZ2_SUPPORTED: - tar_compression['bzip2'] = 'bz2' - compress_ext['bzip2'] = '.bz2' - - # flags for compression program, each element of list will be an argument - if compress is not None and compress not in compress_ext: - raise ValueError("bad value for 'compress', or compression format not " - "supported : {0}".format(compress)) - - archive_name = base_name + '.tar' + compress_ext.get(compress, '') - archive_dir = os.path.dirname(archive_name) - - if not os.path.exists(archive_dir): - if logger is not None: - logger.info("creating %s", archive_dir) - if not dry_run: - os.makedirs(archive_dir) - - # creating the tarball - if logger is not None: - logger.info('Creating tar archive') - - uid = _get_uid(owner) - gid = _get_gid(group) - - def _set_uid_gid(tarinfo): - if gid is not None: - tarinfo.gid = gid - tarinfo.gname = group - if uid is not None: - tarinfo.uid = uid - tarinfo.uname = owner - return tarinfo - - if not dry_run: - tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress]) - try: - tar.add(base_dir, filter=_set_uid_gid) - finally: - tar.close() - - return archive_name - -def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False): - # XXX see if we want to keep an external call here - if verbose: - zipoptions = "-r" - else: - zipoptions = "-rq" - from distutils.errors import DistutilsExecError - from distutils.spawn import spawn - try: - spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run) - except DistutilsExecError: - # XXX really should distinguish between "couldn't find - # external 'zip' command" and "zip failed". - raise ExecError("unable to create zip file '%s': " - "could neither import the 'zipfile' module nor " - "find a standalone zip utility") % zip_filename - -def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None): - """Create a zip file from all the files under 'base_dir'. - - The output zip file will be named 'base_name' + ".zip". Uses either the - "zipfile" Python module (if available) or the InfoZIP "zip" utility - (if installed and found on the default search path). If neither tool is - available, raises ExecError. Returns the name of the output zip - file. - """ - zip_filename = base_name + ".zip" - archive_dir = os.path.dirname(base_name) - - if not os.path.exists(archive_dir): - if logger is not None: - logger.info("creating %s", archive_dir) - if not dry_run: - os.makedirs(archive_dir) - - # If zipfile module is not available, try spawning an external 'zip' - # command. - try: - import zipfile - except ImportError: - zipfile = None - - if zipfile is None: - _call_external_zip(base_dir, zip_filename, verbose, dry_run) - else: - if logger is not None: - logger.info("creating '%s' and adding '%s' to it", - zip_filename, base_dir) - - if not dry_run: - zip = zipfile.ZipFile(zip_filename, "w", - compression=zipfile.ZIP_DEFLATED) - - for dirpath, dirnames, filenames in os.walk(base_dir): - for name in filenames: - path = os.path.normpath(os.path.join(dirpath, name)) - if os.path.isfile(path): - zip.write(path, path) - if logger is not None: - logger.info("adding '%s'", path) - zip.close() - - return zip_filename - -_ARCHIVE_FORMATS = { - 'gztar': (_make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"), - 'bztar': (_make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"), - 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"), - 'zip': (_make_zipfile, [], "ZIP file"), - } - -if _BZ2_SUPPORTED: - _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')], - "bzip2'ed tar-file") - -def get_archive_formats(): - """Returns a list of supported formats for archiving and unarchiving. - - Each element of the returned sequence is a tuple (name, description) - """ - formats = [(name, registry[2]) for name, registry in - _ARCHIVE_FORMATS.items()] - formats.sort() - return formats - -def register_archive_format(name, function, extra_args=None, description=''): - """Registers an archive format. - - name is the name of the format. function is the callable that will be - used to create archives. If provided, extra_args is a sequence of - (name, value) tuples that will be passed as arguments to the callable. - description can be provided to describe the format, and will be returned - by the get_archive_formats() function. - """ - if extra_args is None: - extra_args = [] - if not isinstance(function, collections.Callable): - raise TypeError('The %s object is not callable' % function) - if not isinstance(extra_args, (tuple, list)): - raise TypeError('extra_args needs to be a sequence') - for element in extra_args: - if not isinstance(element, (tuple, list)) or len(element) !=2: - raise TypeError('extra_args elements are : (arg_name, value)') - - _ARCHIVE_FORMATS[name] = (function, extra_args, description) - -def unregister_archive_format(name): - del _ARCHIVE_FORMATS[name] - -def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, - dry_run=0, owner=None, group=None, logger=None): - """Create an archive file (eg. zip or tar). - - 'base_name' is the name of the file to create, minus any format-specific - extension; 'format' is the archive format: one of "zip", "tar", "bztar" - or "gztar". - - 'root_dir' is a directory that will be the root directory of the - archive; ie. we typically chdir into 'root_dir' before creating the - archive. 'base_dir' is the directory where we start archiving from; - ie. 'base_dir' will be the common prefix of all files and - directories in the archive. 'root_dir' and 'base_dir' both default - to the current directory. Returns the name of the archive file. - - 'owner' and 'group' are used when creating a tar archive. By default, - uses the current owner and group. - """ - save_cwd = os.getcwd() - if root_dir is not None: - if logger is not None: - logger.debug("changing into '%s'", root_dir) - base_name = os.path.abspath(base_name) - if not dry_run: - os.chdir(root_dir) - - if base_dir is None: - base_dir = os.curdir - - kwargs = {'dry_run': dry_run, 'logger': logger} - - try: - format_info = _ARCHIVE_FORMATS[format] - except KeyError: - raise ValueError("unknown archive format '%s'" % format) - - func = format_info[0] - for arg, val in format_info[1]: - kwargs[arg] = val - - if format != 'zip': - kwargs['owner'] = owner - kwargs['group'] = group - - try: - filename = func(base_name, base_dir, **kwargs) - finally: - if root_dir is not None: - if logger is not None: - logger.debug("changing back to '%s'", save_cwd) - os.chdir(save_cwd) - - return filename - - -def get_unpack_formats(): - """Returns a list of supported formats for unpacking. - - Each element of the returned sequence is a tuple - (name, extensions, description) - """ - formats = [(name, info[0], info[3]) for name, info in - _UNPACK_FORMATS.items()] - formats.sort() - return formats - -def _check_unpack_options(extensions, function, extra_args): - """Checks what gets registered as an unpacker.""" - # first make sure no other unpacker is registered for this extension - existing_extensions = {} - for name, info in _UNPACK_FORMATS.items(): - for ext in info[0]: - existing_extensions[ext] = name - - for extension in extensions: - if extension in existing_extensions: - msg = '%s is already registered for "%s"' - raise RegistryError(msg % (extension, - existing_extensions[extension])) - - if not isinstance(function, collections.Callable): - raise TypeError('The registered function must be a callable') - - -def register_unpack_format(name, extensions, function, extra_args=None, - description=''): - """Registers an unpack format. - - `name` is the name of the format. `extensions` is a list of extensions - corresponding to the format. - - `function` is the callable that will be - used to unpack archives. The callable will receive archives to unpack. - If it's unable to handle an archive, it needs to raise a ReadError - exception. - - If provided, `extra_args` is a sequence of - (name, value) tuples that will be passed as arguments to the callable. - description can be provided to describe the format, and will be returned - by the get_unpack_formats() function. - """ - if extra_args is None: - extra_args = [] - _check_unpack_options(extensions, function, extra_args) - _UNPACK_FORMATS[name] = extensions, function, extra_args, description - -def unregister_unpack_format(name): - """Removes the pack format from the registry.""" - del _UNPACK_FORMATS[name] - -def _ensure_directory(path): - """Ensure that the parent directory of `path` exists""" - dirname = os.path.dirname(path) - if not os.path.isdir(dirname): - os.makedirs(dirname) - -def _unpack_zipfile(filename, extract_dir): - """Unpack zip `filename` to `extract_dir` - """ - try: - import zipfile - except ImportError: - raise ReadError('zlib not supported, cannot unpack this archive.') - - if not zipfile.is_zipfile(filename): - raise ReadError("%s is not a zip file" % filename) - - zip = zipfile.ZipFile(filename) - try: - for info in zip.infolist(): - name = info.filename - - # don't extract absolute paths or ones with .. in them - if name.startswith('/') or '..' in name: - continue - - target = os.path.join(extract_dir, *name.split('/')) - if not target: - continue - - _ensure_directory(target) - if not name.endswith('/'): - # file - data = zip.read(info.filename) - f = open(target, 'wb') - try: - f.write(data) - finally: - f.close() - del data - finally: - zip.close() - -def _unpack_tarfile(filename, extract_dir): - """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir` - """ - try: - tarobj = tarfile.open(filename) - except tarfile.TarError: - raise ReadError( - "%s is not a compressed or uncompressed tar file" % filename) - try: - tarobj.extractall(extract_dir) - finally: - tarobj.close() - -_UNPACK_FORMATS = { - 'gztar': (['.tar.gz', '.tgz'], _unpack_tarfile, [], "gzip'ed tar-file"), - 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"), - 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file") - } - -if _BZ2_SUPPORTED: - _UNPACK_FORMATS['bztar'] = (['.bz2'], _unpack_tarfile, [], - "bzip2'ed tar-file") - -def _find_unpack_format(filename): - for name, info in _UNPACK_FORMATS.items(): - for extension in info[0]: - if filename.endswith(extension): - return name - return None - -def unpack_archive(filename, extract_dir=None, format=None): - """Unpack an archive. - - `filename` is the name of the archive. - - `extract_dir` is the name of the target directory, where the archive - is unpacked. If not provided, the current working directory is used. - - `format` is the archive format: one of "zip", "tar", or "gztar". Or any - other registered format. If not provided, unpack_archive will use the - filename extension and see if an unpacker was registered for that - extension. - - In case none is found, a ValueError is raised. - """ - if extract_dir is None: - extract_dir = os.getcwd() - - if format is not None: - try: - format_info = _UNPACK_FORMATS[format] - except KeyError: - raise ValueError("Unknown unpack format '{0}'".format(format)) - - func = format_info[1] - func(filename, extract_dir, **dict(format_info[2])) - else: - # we need to look at the registered unpackers supported extensions - format = _find_unpack_format(filename) - if format is None: - raise ReadError("Unknown archive format '{0}'".format(filename)) - - func = _UNPACK_FORMATS[format][1] - kwargs = dict(_UNPACK_FORMATS[format][2]) - func(filename, extract_dir, **kwargs) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg deleted file mode 100644 index 1746bd0..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg +++ /dev/null @@ -1,84 +0,0 @@ -[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} diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/sysconfig.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/sysconfig.py deleted file mode 100644 index 1df3aba..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/sysconfig.py +++ /dev/null @@ -1,788 +0,0 @@ -# -*- 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'<key>ProductUserVisibleVersion</key>\s*' - r'<string>(.*?)</string>', 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() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/tarfile.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/tarfile.py deleted file mode 100644 index d66d856..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/_backport/tarfile.py +++ /dev/null @@ -1,2607 +0,0 @@ -#------------------------------------------------------------------- -# tarfile.py -#------------------------------------------------------------------- -# Copyright (C) 2002 Lars Gustaebel <lars@gustaebel.de> -# All rights reserved. -# -# 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. -# -from __future__ import print_function - -"""Read from and write to tar format archives. -""" - -__version__ = "$Revision$" - -version = "0.9.0" -__author__ = "Lars Gust\u00e4bel (lars@gustaebel.de)" -__date__ = "$Date: 2011-02-25 17:42:01 +0200 (Fri, 25 Feb 2011) $" -__cvsid__ = "$Id: tarfile.py 88586 2011-02-25 15:42:01Z marc-andre.lemburg $" -__credits__ = "Gustavo Niemeyer, Niels Gust\u00e4bel, Richard Townsend." - -#--------- -# Imports -#--------- -import sys -import os -import stat -import errno -import time -import struct -import copy -import re - -try: - import grp, pwd -except ImportError: - grp = pwd = None - -# os.symlink on Windows prior to 6.0 raises NotImplementedError -symlink_exception = (AttributeError, NotImplementedError) -try: - # WindowsError (1314) will be raised if the caller does not hold the - # SeCreateSymbolicLinkPrivilege privilege - symlink_exception += (WindowsError,) -except NameError: - pass - -# from tarfile import * -__all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError"] - -if sys.version_info[0] < 3: - import __builtin__ as builtins -else: - import builtins - -_open = builtins.open # Since 'open' is TarFile.open - -#--------------------------------------------------------- -# tar constants -#--------------------------------------------------------- -NUL = b"\0" # the null character -BLOCKSIZE = 512 # length of processing blocks -RECORDSIZE = BLOCKSIZE * 20 # length of records -GNU_MAGIC = b"ustar \0" # magic gnu tar string -POSIX_MAGIC = b"ustar\x0000" # magic posix tar string - -LENGTH_NAME = 100 # maximum length of a filename -LENGTH_LINK = 100 # maximum length of a linkname -LENGTH_PREFIX = 155 # maximum length of the prefix field - -REGTYPE = b"0" # regular file -AREGTYPE = b"\0" # regular file -LNKTYPE = b"1" # link (inside tarfile) -SYMTYPE = b"2" # symbolic link -CHRTYPE = b"3" # character special device -BLKTYPE = b"4" # block special device -DIRTYPE = b"5" # directory -FIFOTYPE = b"6" # fifo special device -CONTTYPE = b"7" # contiguous file - -GNUTYPE_LONGNAME = b"L" # GNU tar longname -GNUTYPE_LONGLINK = b"K" # GNU tar longlink -GNUTYPE_SPARSE = b"S" # GNU tar sparse file - -XHDTYPE = b"x" # POSIX.1-2001 extended header -XGLTYPE = b"g" # POSIX.1-2001 global header -SOLARIS_XHDTYPE = b"X" # Solaris extended header - -USTAR_FORMAT = 0 # POSIX.1-1988 (ustar) format -GNU_FORMAT = 1 # GNU tar format -PAX_FORMAT = 2 # POSIX.1-2001 (pax) format -DEFAULT_FORMAT = GNU_FORMAT - -#--------------------------------------------------------- -# tarfile constants -#--------------------------------------------------------- -# File types that tarfile supports: -SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE, - SYMTYPE, DIRTYPE, FIFOTYPE, - CONTTYPE, CHRTYPE, BLKTYPE, - GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, - GNUTYPE_SPARSE) - -# File types that will be treated as a regular file. -REGULAR_TYPES = (REGTYPE, AREGTYPE, - CONTTYPE, GNUTYPE_SPARSE) - -# File types that are part of the GNU tar format. -GNU_TYPES = (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, - GNUTYPE_SPARSE) - -# Fields from a pax header that override a TarInfo attribute. -PAX_FIELDS = ("path", "linkpath", "size", "mtime", - "uid", "gid", "uname", "gname") - -# Fields from a pax header that are affected by hdrcharset. -PAX_NAME_FIELDS = set(("path", "linkpath", "uname", "gname")) - -# Fields in a pax header that are numbers, all other fields -# are treated as strings. -PAX_NUMBER_FIELDS = { - "atime": float, - "ctime": float, - "mtime": float, - "uid": int, - "gid": int, - "size": int -} - -#--------------------------------------------------------- -# Bits used in the mode field, values in octal. -#--------------------------------------------------------- -S_IFLNK = 0o120000 # symbolic link -S_IFREG = 0o100000 # regular file -S_IFBLK = 0o060000 # block device -S_IFDIR = 0o040000 # directory -S_IFCHR = 0o020000 # character device -S_IFIFO = 0o010000 # fifo - -TSUID = 0o4000 # set UID on execution -TSGID = 0o2000 # set GID on execution -TSVTX = 0o1000 # reserved - -TUREAD = 0o400 # read by owner -TUWRITE = 0o200 # write by owner -TUEXEC = 0o100 # execute/search by owner -TGREAD = 0o040 # read by group -TGWRITE = 0o020 # write by group -TGEXEC = 0o010 # execute/search by group -TOREAD = 0o004 # read by other -TOWRITE = 0o002 # write by other -TOEXEC = 0o001 # execute/search by other - -#--------------------------------------------------------- -# initialization -#--------------------------------------------------------- -if os.name in ("nt", "ce"): - ENCODING = "utf-8" -else: - ENCODING = sys.getfilesystemencoding() - -#--------------------------------------------------------- -# Some useful functions -#--------------------------------------------------------- - -def stn(s, length, encoding, errors): - """Convert a string to a null-terminated bytes object. - """ - s = s.encode(encoding, errors) - return s[:length] + (length - len(s)) * NUL - -def nts(s, encoding, errors): - """Convert a null-terminated bytes object to a string. - """ - p = s.find(b"\0") - if p != -1: - s = s[:p] - return s.decode(encoding, errors) - -def nti(s): - """Convert a number field to a python number. - """ - # There are two possible encodings for a number field, see - # itn() below. - if s[0] != chr(0o200): - try: - n = int(nts(s, "ascii", "strict") or "0", 8) - except ValueError: - raise InvalidHeaderError("invalid header") - else: - n = 0 - for i in range(len(s) - 1): - n <<= 8 - n += ord(s[i + 1]) - return n - -def itn(n, digits=8, format=DEFAULT_FORMAT): - """Convert a python number to a number field. - """ - # POSIX 1003.1-1988 requires numbers to be encoded as a string of - # octal digits followed by a null-byte, this allows values up to - # (8**(digits-1))-1. GNU tar allows storing numbers greater than - # that if necessary. A leading 0o200 byte indicates this particular - # encoding, the following digits-1 bytes are a big-endian - # representation. This allows values up to (256**(digits-1))-1. - if 0 <= n < 8 ** (digits - 1): - s = ("%0*o" % (digits - 1, n)).encode("ascii") + NUL - else: - if format != GNU_FORMAT or n >= 256 ** (digits - 1): - raise ValueError("overflow in number field") - - if n < 0: - # XXX We mimic GNU tar's behaviour with negative numbers, - # this could raise OverflowError. - n = struct.unpack("L", struct.pack("l", n))[0] - - s = bytearray() - for i in range(digits - 1): - s.insert(0, n & 0o377) - n >>= 8 - s.insert(0, 0o200) - return s - -def calc_chksums(buf): - """Calculate the checksum for a member's header by summing up all - characters except for the chksum field which is treated as if - it was filled with spaces. According to the GNU tar sources, - some tars (Sun and NeXT) calculate chksum with signed char, - which will be different if there are chars in the buffer with - the high bit set. So we calculate two checksums, unsigned and - signed. - """ - unsigned_chksum = 256 + sum(struct.unpack("148B", buf[:148]) + struct.unpack("356B", buf[156:512])) - signed_chksum = 256 + sum(struct.unpack("148b", buf[:148]) + struct.unpack("356b", buf[156:512])) - return unsigned_chksum, signed_chksum - -def copyfileobj(src, dst, length=None): - """Copy length bytes from fileobj src to fileobj dst. - If length is None, copy the entire content. - """ - if length == 0: - return - if length is None: - while True: - buf = src.read(16*1024) - if not buf: - break - dst.write(buf) - return - - BUFSIZE = 16 * 1024 - blocks, remainder = divmod(length, BUFSIZE) - for b in range(blocks): - buf = src.read(BUFSIZE) - if len(buf) < BUFSIZE: - raise IOError("end of file reached") - dst.write(buf) - - if remainder != 0: - buf = src.read(remainder) - if len(buf) < remainder: - raise IOError("end of file reached") - dst.write(buf) - return - -filemode_table = ( - ((S_IFLNK, "l"), - (S_IFREG, "-"), - (S_IFBLK, "b"), - (S_IFDIR, "d"), - (S_IFCHR, "c"), - (S_IFIFO, "p")), - - ((TUREAD, "r"),), - ((TUWRITE, "w"),), - ((TUEXEC|TSUID, "s"), - (TSUID, "S"), - (TUEXEC, "x")), - - ((TGREAD, "r"),), - ((TGWRITE, "w"),), - ((TGEXEC|TSGID, "s"), - (TSGID, "S"), - (TGEXEC, "x")), - - ((TOREAD, "r"),), - ((TOWRITE, "w"),), - ((TOEXEC|TSVTX, "t"), - (TSVTX, "T"), - (TOEXEC, "x")) -) - -def filemode(mode): - """Convert a file's mode to a string of the form - -rwxrwxrwx. - Used by TarFile.list() - """ - perm = [] - for table in filemode_table: - for bit, char in table: - if mode & bit == bit: - perm.append(char) - break - else: - perm.append("-") - return "".join(perm) - -class TarError(Exception): - """Base exception.""" - pass -class ExtractError(TarError): - """General exception for extract errors.""" - pass -class ReadError(TarError): - """Exception for unreadable tar archives.""" - pass -class CompressionError(TarError): - """Exception for unavailable compression methods.""" - pass -class StreamError(TarError): - """Exception for unsupported operations on stream-like TarFiles.""" - pass -class HeaderError(TarError): - """Base exception for header errors.""" - pass -class EmptyHeaderError(HeaderError): - """Exception for empty headers.""" - pass -class TruncatedHeaderError(HeaderError): - """Exception for truncated headers.""" - pass -class EOFHeaderError(HeaderError): - """Exception for end of file headers.""" - pass -class InvalidHeaderError(HeaderError): - """Exception for invalid headers.""" - pass -class SubsequentHeaderError(HeaderError): - """Exception for missing and invalid extended headers.""" - pass - -#--------------------------- -# internal stream interface -#--------------------------- -class _LowLevelFile(object): - """Low-level file object. Supports reading and writing. - It is used instead of a regular file object for streaming - access. - """ - - def __init__(self, name, mode): - mode = { - "r": os.O_RDONLY, - "w": os.O_WRONLY | os.O_CREAT | os.O_TRUNC, - }[mode] - if hasattr(os, "O_BINARY"): - mode |= os.O_BINARY - self.fd = os.open(name, mode, 0o666) - - def close(self): - os.close(self.fd) - - def read(self, size): - return os.read(self.fd, size) - - def write(self, s): - os.write(self.fd, s) - -class _Stream(object): - """Class that serves as an adapter between TarFile and - a stream-like object. The stream-like object only - needs to have a read() or write() method and is accessed - blockwise. Use of gzip or bzip2 compression is possible. - A stream-like object could be for example: sys.stdin, - sys.stdout, a socket, a tape device etc. - - _Stream is intended to be used only internally. - """ - - def __init__(self, name, mode, comptype, fileobj, bufsize): - """Construct a _Stream object. - """ - self._extfileobj = True - if fileobj is None: - fileobj = _LowLevelFile(name, mode) - self._extfileobj = False - - if comptype == '*': - # Enable transparent compression detection for the - # stream interface - fileobj = _StreamProxy(fileobj) - comptype = fileobj.getcomptype() - - self.name = name or "" - self.mode = mode - self.comptype = comptype - self.fileobj = fileobj - self.bufsize = bufsize - self.buf = b"" - self.pos = 0 - self.closed = False - - try: - if comptype == "gz": - try: - import zlib - except ImportError: - raise CompressionError("zlib module is not available") - self.zlib = zlib - self.crc = zlib.crc32(b"") - if mode == "r": - self._init_read_gz() - else: - self._init_write_gz() - - if comptype == "bz2": - try: - import bz2 - except ImportError: - raise CompressionError("bz2 module is not available") - if mode == "r": - self.dbuf = b"" - self.cmp = bz2.BZ2Decompressor() - else: - self.cmp = bz2.BZ2Compressor() - except: - if not self._extfileobj: - self.fileobj.close() - self.closed = True - raise - - def __del__(self): - if hasattr(self, "closed") and not self.closed: - self.close() - - def _init_write_gz(self): - """Initialize for writing with gzip compression. - """ - self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED, - -self.zlib.MAX_WBITS, - self.zlib.DEF_MEM_LEVEL, - 0) - timestamp = struct.pack("<L", int(time.time())) - self.__write(b"\037\213\010\010" + timestamp + b"\002\377") - if self.name.endswith(".gz"): - self.name = self.name[:-3] - # RFC1952 says we must use ISO-8859-1 for the FNAME field. - self.__write(self.name.encode("iso-8859-1", "replace") + NUL) - - def write(self, s): - """Write string s to the stream. - """ - if self.comptype == "gz": - self.crc = self.zlib.crc32(s, self.crc) - self.pos += len(s) - if self.comptype != "tar": - s = self.cmp.compress(s) - self.__write(s) - - def __write(self, s): - """Write string s to the stream if a whole new block - is ready to be written. - """ - self.buf += s - while len(self.buf) > self.bufsize: - self.fileobj.write(self.buf[:self.bufsize]) - self.buf = self.buf[self.bufsize:] - - def close(self): - """Close the _Stream object. No operation should be - done on it afterwards. - """ - if self.closed: - return - - if self.mode == "w" and self.comptype != "tar": - self.buf += self.cmp.flush() - - if self.mode == "w" and self.buf: - self.fileobj.write(self.buf) - self.buf = b"" - if self.comptype == "gz": - # The native zlib crc is an unsigned 32-bit integer, but - # the Python wrapper implicitly casts that to a signed C - # long. So, on a 32-bit box self.crc may "look negative", - # while the same crc on a 64-bit box may "look positive". - # To avoid irksome warnings from the `struct` module, force - # it to look positive on all boxes. - self.fileobj.write(struct.pack("<L", self.crc & 0xffffffff)) - self.fileobj.write(struct.pack("<L", self.pos & 0xffffFFFF)) - - if not self._extfileobj: - self.fileobj.close() - - self.closed = True - - def _init_read_gz(self): - """Initialize for reading a gzip compressed fileobj. - """ - self.cmp = self.zlib.decompressobj(-self.zlib.MAX_WBITS) - self.dbuf = b"" - - # taken from gzip.GzipFile with some alterations - if self.__read(2) != b"\037\213": - raise ReadError("not a gzip file") - if self.__read(1) != b"\010": - raise CompressionError("unsupported compression method") - - flag = ord(self.__read(1)) - self.__read(6) - - if flag & 4: - xlen = ord(self.__read(1)) + 256 * ord(self.__read(1)) - self.read(xlen) - if flag & 8: - while True: - s = self.__read(1) - if not s or s == NUL: - break - if flag & 16: - while True: - s = self.__read(1) - if not s or s == NUL: - break - if flag & 2: - self.__read(2) - - def tell(self): - """Return the stream's file pointer position. - """ - return self.pos - - def seek(self, pos=0): - """Set the stream's file pointer to pos. Negative seeking - is forbidden. - """ - if pos - self.pos >= 0: - blocks, remainder = divmod(pos - self.pos, self.bufsize) - for i in range(blocks): - self.read(self.bufsize) - self.read(remainder) - else: - raise StreamError("seeking backwards is not allowed") - return self.pos - - def read(self, size=None): - """Return the next size number of bytes from the stream. - If size is not defined, return all bytes of the stream - up to EOF. - """ - if size is None: - t = [] - while True: - buf = self._read(self.bufsize) - if not buf: - break - t.append(buf) - buf = "".join(t) - else: - buf = self._read(size) - self.pos += len(buf) - return buf - - def _read(self, size): - """Return size bytes from the stream. - """ - if self.comptype == "tar": - return self.__read(size) - - c = len(self.dbuf) - while c < size: - buf = self.__read(self.bufsize) - if not buf: - break - try: - buf = self.cmp.decompress(buf) - except IOError: - raise ReadError("invalid compressed data") - self.dbuf += buf - c += len(buf) - buf = self.dbuf[:size] - self.dbuf = self.dbuf[size:] - return buf - - def __read(self, size): - """Return size bytes from stream. If internal buffer is empty, - read another block from the stream. - """ - c = len(self.buf) - while c < size: - buf = self.fileobj.read(self.bufsize) - if not buf: - break - self.buf += buf - c += len(buf) - buf = self.buf[:size] - self.buf = self.buf[size:] - return buf -# class _Stream - -class _StreamProxy(object): - """Small proxy class that enables transparent compression - detection for the Stream interface (mode 'r|*'). - """ - - def __init__(self, fileobj): - self.fileobj = fileobj - self.buf = self.fileobj.read(BLOCKSIZE) - - def read(self, size): - self.read = self.fileobj.read - return self.buf - - def getcomptype(self): - if self.buf.startswith(b"\037\213\010"): - return "gz" - if self.buf.startswith(b"BZh91"): - return "bz2" - return "tar" - - def close(self): - self.fileobj.close() -# class StreamProxy - -class _BZ2Proxy(object): - """Small proxy class that enables external file object - support for "r:bz2" and "w:bz2" modes. This is actually - a workaround for a limitation in bz2 module's BZ2File - class which (unlike gzip.GzipFile) has no support for - a file object argument. - """ - - blocksize = 16 * 1024 - - def __init__(self, fileobj, mode): - self.fileobj = fileobj - self.mode = mode - self.name = getattr(self.fileobj, "name", None) - self.init() - - def init(self): - import bz2 - self.pos = 0 - if self.mode == "r": - self.bz2obj = bz2.BZ2Decompressor() - self.fileobj.seek(0) - self.buf = b"" - else: - self.bz2obj = bz2.BZ2Compressor() - - def read(self, size): - x = len(self.buf) - while x < size: - raw = self.fileobj.read(self.blocksize) - if not raw: - break - data = self.bz2obj.decompress(raw) - self.buf += data - x += len(data) - - buf = self.buf[:size] - self.buf = self.buf[size:] - self.pos += len(buf) - return buf - - def seek(self, pos): - if pos < self.pos: - self.init() - self.read(pos - self.pos) - - def tell(self): - return self.pos - - def write(self, data): - self.pos += len(data) - raw = self.bz2obj.compress(data) - self.fileobj.write(raw) - - def close(self): - if self.mode == "w": - raw = self.bz2obj.flush() - self.fileobj.write(raw) -# class _BZ2Proxy - -#------------------------ -# Extraction file object -#------------------------ -class _FileInFile(object): - """A thin wrapper around an existing file object that - provides a part of its data as an individual file - object. - """ - - def __init__(self, fileobj, offset, size, blockinfo=None): - self.fileobj = fileobj - self.offset = offset - self.size = size - self.position = 0 - - if blockinfo is None: - blockinfo = [(0, size)] - - # Construct a map with data and zero blocks. - self.map_index = 0 - self.map = [] - lastpos = 0 - realpos = self.offset - for offset, size in blockinfo: - if offset > lastpos: - self.map.append((False, lastpos, offset, None)) - self.map.append((True, offset, offset + size, realpos)) - realpos += size - lastpos = offset + size - if lastpos < self.size: - self.map.append((False, lastpos, self.size, None)) - - def seekable(self): - if not hasattr(self.fileobj, "seekable"): - # XXX gzip.GzipFile and bz2.BZ2File - return True - return self.fileobj.seekable() - - def tell(self): - """Return the current file position. - """ - return self.position - - def seek(self, position): - """Seek to a position in the file. - """ - self.position = position - - def read(self, size=None): - """Read data from the file. - """ - if size is None: - size = self.size - self.position - else: - size = min(size, self.size - self.position) - - buf = b"" - while size > 0: - while True: - data, start, stop, offset = self.map[self.map_index] - if start <= self.position < stop: - break - else: - self.map_index += 1 - if self.map_index == len(self.map): - self.map_index = 0 - length = min(size, stop - self.position) - if data: - self.fileobj.seek(offset + (self.position - start)) - buf += self.fileobj.read(length) - else: - buf += NUL * length - size -= length - self.position += length - return buf -#class _FileInFile - - -class ExFileObject(object): - """File-like object for reading an archive member. - Is returned by TarFile.extractfile(). - """ - blocksize = 1024 - - def __init__(self, tarfile, tarinfo): - self.fileobj = _FileInFile(tarfile.fileobj, - tarinfo.offset_data, - tarinfo.size, - tarinfo.sparse) - self.name = tarinfo.name - self.mode = "r" - self.closed = False - self.size = tarinfo.size - - self.position = 0 - self.buffer = b"" - - def readable(self): - return True - - def writable(self): - return False - - def seekable(self): - return self.fileobj.seekable() - - def read(self, size=None): - """Read at most size bytes from the file. If size is not - present or None, read all data until EOF is reached. - """ - if self.closed: - raise ValueError("I/O operation on closed file") - - buf = b"" - if self.buffer: - if size is None: - buf = self.buffer - self.buffer = b"" - else: - buf = self.buffer[:size] - self.buffer = self.buffer[size:] - - if size is None: - buf += self.fileobj.read() - else: - buf += self.fileobj.read(size - len(buf)) - - self.position += len(buf) - return buf - - # XXX TextIOWrapper uses the read1() method. - read1 = read - - def readline(self, size=-1): - """Read one entire line from the file. If size is present - and non-negative, return a string with at most that - size, which may be an incomplete line. - """ - if self.closed: - raise ValueError("I/O operation on closed file") - - pos = self.buffer.find(b"\n") + 1 - if pos == 0: - # no newline found. - while True: - buf = self.fileobj.read(self.blocksize) - self.buffer += buf - if not buf or b"\n" in buf: - pos = self.buffer.find(b"\n") + 1 - if pos == 0: - # no newline found. - pos = len(self.buffer) - break - - if size != -1: - pos = min(size, pos) - - buf = self.buffer[:pos] - self.buffer = self.buffer[pos:] - self.position += len(buf) - return buf - - def readlines(self): - """Return a list with all remaining lines. - """ - result = [] - while True: - line = self.readline() - if not line: break - result.append(line) - return result - - def tell(self): - """Return the current file position. - """ - if self.closed: - raise ValueError("I/O operation on closed file") - - return self.position - - def seek(self, pos, whence=os.SEEK_SET): - """Seek to a position in the file. - """ - if self.closed: - raise ValueError("I/O operation on closed file") - - if whence == os.SEEK_SET: - self.position = min(max(pos, 0), self.size) - elif whence == os.SEEK_CUR: - if pos < 0: - self.position = max(self.position + pos, 0) - else: - self.position = min(self.position + pos, self.size) - elif whence == os.SEEK_END: - self.position = max(min(self.size + pos, self.size), 0) - else: - raise ValueError("Invalid argument") - - self.buffer = b"" - self.fileobj.seek(self.position) - - def close(self): - """Close the file object. - """ - self.closed = True - - def __iter__(self): - """Get an iterator over the file's lines. - """ - while True: - line = self.readline() - if not line: - break - yield line -#class ExFileObject - -#------------------ -# Exported Classes -#------------------ -class TarInfo(object): - """Informational class which holds the details about an - archive member given by a tar header block. - TarInfo objects are returned by TarFile.getmember(), - TarFile.getmembers() and TarFile.gettarinfo() and are - usually created internally. - """ - - __slots__ = ("name", "mode", "uid", "gid", "size", "mtime", - "chksum", "type", "linkname", "uname", "gname", - "devmajor", "devminor", - "offset", "offset_data", "pax_headers", "sparse", - "tarfile", "_sparse_structs", "_link_target") - - def __init__(self, name=""): - """Construct a TarInfo object. name is the optional name - of the member. - """ - self.name = name # member name - self.mode = 0o644 # file permissions - self.uid = 0 # user id - self.gid = 0 # group id - self.size = 0 # file size - self.mtime = 0 # modification time - self.chksum = 0 # header checksum - self.type = REGTYPE # member type - self.linkname = "" # link name - self.uname = "" # user name - self.gname = "" # group name - self.devmajor = 0 # device major number - self.devminor = 0 # device minor number - - self.offset = 0 # the tar header starts here - self.offset_data = 0 # the file's data starts here - - self.sparse = None # sparse member information - self.pax_headers = {} # pax header information - - # In pax headers the "name" and "linkname" field are called - # "path" and "linkpath". - def _getpath(self): - return self.name - def _setpath(self, name): - self.name = name - path = property(_getpath, _setpath) - - def _getlinkpath(self): - return self.linkname - def _setlinkpath(self, linkname): - self.linkname = linkname - linkpath = property(_getlinkpath, _setlinkpath) - - def __repr__(self): - return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self)) - - def get_info(self): - """Return the TarInfo's attributes as a dictionary. - """ - info = { - "name": self.name, - "mode": self.mode & 0o7777, - "uid": self.uid, - "gid": self.gid, - "size": self.size, - "mtime": self.mtime, - "chksum": self.chksum, - "type": self.type, - "linkname": self.linkname, - "uname": self.uname, - "gname": self.gname, - "devmajor": self.devmajor, - "devminor": self.devminor - } - - if info["type"] == DIRTYPE and not info["name"].endswith("/"): - info["name"] += "/" - - return info - - def tobuf(self, format=DEFAULT_FORMAT, encoding=ENCODING, errors="surrogateescape"): - """Return a tar header as a string of 512 byte blocks. - """ - info = self.get_info() - - if format == USTAR_FORMAT: - return self.create_ustar_header(info, encoding, errors) - elif format == GNU_FORMAT: - return self.create_gnu_header(info, encoding, errors) - elif format == PAX_FORMAT: - return self.create_pax_header(info, encoding) - else: - raise ValueError("invalid format") - - def create_ustar_header(self, info, encoding, errors): - """Return the object as a ustar header block. - """ - info["magic"] = POSIX_MAGIC - - if len(info["linkname"]) > LENGTH_LINK: - raise ValueError("linkname is too long") - - if len(info["name"]) > LENGTH_NAME: - info["prefix"], info["name"] = self._posix_split_name(info["name"]) - - return self._create_header(info, USTAR_FORMAT, encoding, errors) - - def create_gnu_header(self, info, encoding, errors): - """Return the object as a GNU header block sequence. - """ - info["magic"] = GNU_MAGIC - - buf = b"" - if len(info["linkname"]) > LENGTH_LINK: - buf += self._create_gnu_long_header(info["linkname"], GNUTYPE_LONGLINK, encoding, errors) - - if len(info["name"]) > LENGTH_NAME: - buf += self._create_gnu_long_header(info["name"], GNUTYPE_LONGNAME, encoding, errors) - - return buf + self._create_header(info, GNU_FORMAT, encoding, errors) - - def create_pax_header(self, info, encoding): - """Return the object as a ustar header block. If it cannot be - represented this way, prepend a pax extended header sequence - with supplement information. - """ - info["magic"] = POSIX_MAGIC - pax_headers = self.pax_headers.copy() - - # Test string fields for values that exceed the field length or cannot - # be represented in ASCII encoding. - for name, hname, length in ( - ("name", "path", LENGTH_NAME), ("linkname", "linkpath", LENGTH_LINK), - ("uname", "uname", 32), ("gname", "gname", 32)): - - if hname in pax_headers: - # The pax header has priority. - continue - - # Try to encode the string as ASCII. - try: - info[name].encode("ascii", "strict") - except UnicodeEncodeError: - pax_headers[hname] = info[name] - continue - - if len(info[name]) > length: - pax_headers[hname] = info[name] - - # Test number fields for values that exceed the field limit or values - # that like to be stored as float. - for name, digits in (("uid", 8), ("gid", 8), ("size", 12), ("mtime", 12)): - if name in pax_headers: - # The pax header has priority. Avoid overflow. - info[name] = 0 - continue - - val = info[name] - if not 0 <= val < 8 ** (digits - 1) or isinstance(val, float): - pax_headers[name] = str(val) - info[name] = 0 - - # Create a pax extended header if necessary. - if pax_headers: - buf = self._create_pax_generic_header(pax_headers, XHDTYPE, encoding) - else: - buf = b"" - - return buf + self._create_header(info, USTAR_FORMAT, "ascii", "replace") - - @classmethod - def create_pax_global_header(cls, pax_headers): - """Return the object as a pax global header block sequence. - """ - return cls._create_pax_generic_header(pax_headers, XGLTYPE, "utf8") - - def _posix_split_name(self, name): - """Split a name longer than 100 chars into a prefix - and a name part. - """ - prefix = name[:LENGTH_PREFIX + 1] - while prefix and prefix[-1] != "/": - prefix = prefix[:-1] - - name = name[len(prefix):] - prefix = prefix[:-1] - - if not prefix or len(name) > LENGTH_NAME: - raise ValueError("name is too long") - return prefix, name - - @staticmethod - def _create_header(info, format, encoding, errors): - """Return a header block. info is a dictionary with file - information, format must be one of the *_FORMAT constants. - """ - parts = [ - stn(info.get("name", ""), 100, encoding, errors), - itn(info.get("mode", 0) & 0o7777, 8, format), - itn(info.get("uid", 0), 8, format), - itn(info.get("gid", 0), 8, format), - itn(info.get("size", 0), 12, format), - itn(info.get("mtime", 0), 12, format), - b" ", # checksum field - info.get("type", REGTYPE), - stn(info.get("linkname", ""), 100, encoding, errors), - info.get("magic", POSIX_MAGIC), - stn(info.get("uname", ""), 32, encoding, errors), - stn(info.get("gname", ""), 32, encoding, errors), - itn(info.get("devmajor", 0), 8, format), - itn(info.get("devminor", 0), 8, format), - stn(info.get("prefix", ""), 155, encoding, errors) - ] - - buf = struct.pack("%ds" % BLOCKSIZE, b"".join(parts)) - chksum = calc_chksums(buf[-BLOCKSIZE:])[0] - buf = buf[:-364] + ("%06o\0" % chksum).encode("ascii") + buf[-357:] - return buf - - @staticmethod - def _create_payload(payload): - """Return the string payload filled with zero bytes - up to the next 512 byte border. - """ - blocks, remainder = divmod(len(payload), BLOCKSIZE) - if remainder > 0: - payload += (BLOCKSIZE - remainder) * NUL - return payload - - @classmethod - def _create_gnu_long_header(cls, name, type, encoding, errors): - """Return a GNUTYPE_LONGNAME or GNUTYPE_LONGLINK sequence - for name. - """ - name = name.encode(encoding, errors) + NUL - - info = {} - info["name"] = "././@LongLink" - info["type"] = type - info["size"] = len(name) - info["magic"] = GNU_MAGIC - - # create extended header + name blocks. - return cls._create_header(info, USTAR_FORMAT, encoding, errors) + \ - cls._create_payload(name) - - @classmethod - def _create_pax_generic_header(cls, pax_headers, type, encoding): - """Return a POSIX.1-2008 extended or global header sequence - that contains a list of keyword, value pairs. The values - must be strings. - """ - # Check if one of the fields contains surrogate characters and thereby - # forces hdrcharset=BINARY, see _proc_pax() for more information. - binary = False - for keyword, value in pax_headers.items(): - try: - value.encode("utf8", "strict") - except UnicodeEncodeError: - binary = True - break - - records = b"" - if binary: - # Put the hdrcharset field at the beginning of the header. - records += b"21 hdrcharset=BINARY\n" - - for keyword, value in pax_headers.items(): - keyword = keyword.encode("utf8") - if binary: - # Try to restore the original byte representation of `value'. - # Needless to say, that the encoding must match the string. - value = value.encode(encoding, "surrogateescape") - else: - value = value.encode("utf8") - - l = len(keyword) + len(value) + 3 # ' ' + '=' + '\n' - n = p = 0 - while True: - n = l + len(str(p)) - if n == p: - break - p = n - records += bytes(str(p), "ascii") + b" " + keyword + b"=" + value + b"\n" - - # We use a hardcoded "././@PaxHeader" name like star does - # instead of the one that POSIX recommends. - info = {} - info["name"] = "././@PaxHeader" - info["type"] = type - info["size"] = len(records) - info["magic"] = POSIX_MAGIC - - # Create pax header + record blocks. - return cls._create_header(info, USTAR_FORMAT, "ascii", "replace") + \ - cls._create_payload(records) - - @classmethod - def frombuf(cls, buf, encoding, errors): - """Construct a TarInfo object from a 512 byte bytes object. - """ - if len(buf) == 0: - raise EmptyHeaderError("empty header") - if len(buf) != BLOCKSIZE: - raise TruncatedHeaderError("truncated header") - if buf.count(NUL) == BLOCKSIZE: - raise EOFHeaderError("end of file header") - - chksum = nti(buf[148:156]) - if chksum not in calc_chksums(buf): - raise InvalidHeaderError("bad checksum") - - obj = cls() - obj.name = nts(buf[0:100], encoding, errors) - obj.mode = nti(buf[100:108]) - obj.uid = nti(buf[108:116]) - obj.gid = nti(buf[116:124]) - obj.size = nti(buf[124:136]) - obj.mtime = nti(buf[136:148]) - obj.chksum = chksum - obj.type = buf[156:157] - obj.linkname = nts(buf[157:257], encoding, errors) - obj.uname = nts(buf[265:297], encoding, errors) - obj.gname = nts(buf[297:329], encoding, errors) - obj.devmajor = nti(buf[329:337]) - obj.devminor = nti(buf[337:345]) - prefix = nts(buf[345:500], encoding, errors) - - # Old V7 tar format represents a directory as a regular - # file with a trailing slash. - if obj.type == AREGTYPE and obj.name.endswith("/"): - obj.type = DIRTYPE - - # The old GNU sparse format occupies some of the unused - # space in the buffer for up to 4 sparse structures. - # Save the them for later processing in _proc_sparse(). - if obj.type == GNUTYPE_SPARSE: - pos = 386 - structs = [] - for i in range(4): - try: - offset = nti(buf[pos:pos + 12]) - numbytes = nti(buf[pos + 12:pos + 24]) - except ValueError: - break - structs.append((offset, numbytes)) - pos += 24 - isextended = bool(buf[482]) - origsize = nti(buf[483:495]) - obj._sparse_structs = (structs, isextended, origsize) - - # Remove redundant slashes from directories. - if obj.isdir(): - obj.name = obj.name.rstrip("/") - - # Reconstruct a ustar longname. - if prefix and obj.type not in GNU_TYPES: - obj.name = prefix + "/" + obj.name - return obj - - @classmethod - def fromtarfile(cls, tarfile): - """Return the next TarInfo object from TarFile object - tarfile. - """ - buf = tarfile.fileobj.read(BLOCKSIZE) - obj = cls.frombuf(buf, tarfile.encoding, tarfile.errors) - obj.offset = tarfile.fileobj.tell() - BLOCKSIZE - return obj._proc_member(tarfile) - - #-------------------------------------------------------------------------- - # The following are methods that are called depending on the type of a - # member. The entry point is _proc_member() which can be overridden in a - # subclass to add custom _proc_*() methods. A _proc_*() method MUST - # implement the following - # operations: - # 1. Set self.offset_data to the position where the data blocks begin, - # if there is data that follows. - # 2. Set tarfile.offset to the position where the next member's header will - # begin. - # 3. Return self or another valid TarInfo object. - def _proc_member(self, tarfile): - """Choose the right processing method depending on - the type and call it. - """ - if self.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK): - return self._proc_gnulong(tarfile) - elif self.type == GNUTYPE_SPARSE: - return self._proc_sparse(tarfile) - elif self.type in (XHDTYPE, XGLTYPE, SOLARIS_XHDTYPE): - return self._proc_pax(tarfile) - else: - return self._proc_builtin(tarfile) - - def _proc_builtin(self, tarfile): - """Process a builtin type or an unknown type which - will be treated as a regular file. - """ - self.offset_data = tarfile.fileobj.tell() - offset = self.offset_data - if self.isreg() or self.type not in SUPPORTED_TYPES: - # Skip the following data blocks. - offset += self._block(self.size) - tarfile.offset = offset - - # Patch the TarInfo object with saved global - # header information. - self._apply_pax_info(tarfile.pax_headers, tarfile.encoding, tarfile.errors) - - return self - - def _proc_gnulong(self, tarfile): - """Process the blocks that hold a GNU longname - or longlink member. - """ - buf = tarfile.fileobj.read(self._block(self.size)) - - # Fetch the next header and process it. - try: - next = self.fromtarfile(tarfile) - except HeaderError: - raise SubsequentHeaderError("missing or bad subsequent header") - - # Patch the TarInfo object from the next header with - # the longname information. - next.offset = self.offset - if self.type == GNUTYPE_LONGNAME: - next.name = nts(buf, tarfile.encoding, tarfile.errors) - elif self.type == GNUTYPE_LONGLINK: - next.linkname = nts(buf, tarfile.encoding, tarfile.errors) - - return next - - def _proc_sparse(self, tarfile): - """Process a GNU sparse header plus extra headers. - """ - # We already collected some sparse structures in frombuf(). - structs, isextended, origsize = self._sparse_structs - del self._sparse_structs - - # Collect sparse structures from extended header blocks. - while isextended: - buf = tarfile.fileobj.read(BLOCKSIZE) - pos = 0 - for i in range(21): - try: - offset = nti(buf[pos:pos + 12]) - numbytes = nti(buf[pos + 12:pos + 24]) - except ValueError: - break - if offset and numbytes: - structs.append((offset, numbytes)) - pos += 24 - isextended = bool(buf[504]) - self.sparse = structs - - self.offset_data = tarfile.fileobj.tell() - tarfile.offset = self.offset_data + self._block(self.size) - self.size = origsize - return self - - def _proc_pax(self, tarfile): - """Process an extended or global header as described in - POSIX.1-2008. - """ - # Read the header information. - buf = tarfile.fileobj.read(self._block(self.size)) - - # A pax header stores supplemental information for either - # the following file (extended) or all following files - # (global). - if self.type == XGLTYPE: - pax_headers = tarfile.pax_headers - else: - pax_headers = tarfile.pax_headers.copy() - - # Check if the pax header contains a hdrcharset field. This tells us - # the encoding of the path, linkpath, uname and gname fields. Normally, - # these fields are UTF-8 encoded but since POSIX.1-2008 tar - # implementations are allowed to store them as raw binary strings if - # the translation to UTF-8 fails. - match = re.search(br"\d+ hdrcharset=([^\n]+)\n", buf) - if match is not None: - pax_headers["hdrcharset"] = match.group(1).decode("utf8") - - # For the time being, we don't care about anything other than "BINARY". - # The only other value that is currently allowed by the standard is - # "ISO-IR 10646 2000 UTF-8" in other words UTF-8. - hdrcharset = pax_headers.get("hdrcharset") - if hdrcharset == "BINARY": - encoding = tarfile.encoding - else: - encoding = "utf8" - - # Parse pax header information. A record looks like that: - # "%d %s=%s\n" % (length, keyword, value). length is the size - # of the complete record including the length field itself and - # the newline. keyword and value are both UTF-8 encoded strings. - regex = re.compile(br"(\d+) ([^=]+)=") - pos = 0 - while True: - match = regex.match(buf, pos) - if not match: - break - - length, keyword = match.groups() - length = int(length) - value = buf[match.end(2) + 1:match.start(1) + length - 1] - - # Normally, we could just use "utf8" as the encoding and "strict" - # as the error handler, but we better not take the risk. For - # example, GNU tar <= 1.23 is known to store filenames it cannot - # translate to UTF-8 as raw strings (unfortunately without a - # hdrcharset=BINARY header). - # We first try the strict standard encoding, and if that fails we - # fall back on the user's encoding and error handler. - keyword = self._decode_pax_field(keyword, "utf8", "utf8", - tarfile.errors) - if keyword in PAX_NAME_FIELDS: - value = self._decode_pax_field(value, encoding, tarfile.encoding, - tarfile.errors) - else: - value = self._decode_pax_field(value, "utf8", "utf8", - tarfile.errors) - - pax_headers[keyword] = value - pos += length - - # Fetch the next header. - try: - next = self.fromtarfile(tarfile) - except HeaderError: - raise SubsequentHeaderError("missing or bad subsequent header") - - # Process GNU sparse information. - if "GNU.sparse.map" in pax_headers: - # GNU extended sparse format version 0.1. - self._proc_gnusparse_01(next, pax_headers) - - elif "GNU.sparse.size" in pax_headers: - # GNU extended sparse format version 0.0. - self._proc_gnusparse_00(next, pax_headers, buf) - - elif pax_headers.get("GNU.sparse.major") == "1" and pax_headers.get("GNU.sparse.minor") == "0": - # GNU extended sparse format version 1.0. - self._proc_gnusparse_10(next, pax_headers, tarfile) - - if self.type in (XHDTYPE, SOLARIS_XHDTYPE): - # Patch the TarInfo object with the extended header info. - next._apply_pax_info(pax_headers, tarfile.encoding, tarfile.errors) - next.offset = self.offset - - if "size" in pax_headers: - # If the extended header replaces the size field, - # we need to recalculate the offset where the next - # header starts. - offset = next.offset_data - if next.isreg() or next.type not in SUPPORTED_TYPES: - offset += next._block(next.size) - tarfile.offset = offset - - return next - - def _proc_gnusparse_00(self, next, pax_headers, buf): - """Process a GNU tar extended sparse header, version 0.0. - """ - offsets = [] - for match in re.finditer(br"\d+ GNU.sparse.offset=(\d+)\n", buf): - offsets.append(int(match.group(1))) - numbytes = [] - for match in re.finditer(br"\d+ GNU.sparse.numbytes=(\d+)\n", buf): - numbytes.append(int(match.group(1))) - next.sparse = list(zip(offsets, numbytes)) - - def _proc_gnusparse_01(self, next, pax_headers): - """Process a GNU tar extended sparse header, version 0.1. - """ - sparse = [int(x) for x in pax_headers["GNU.sparse.map"].split(",")] - next.sparse = list(zip(sparse[::2], sparse[1::2])) - - def _proc_gnusparse_10(self, next, pax_headers, tarfile): - """Process a GNU tar extended sparse header, version 1.0. - """ - fields = None - sparse = [] - buf = tarfile.fileobj.read(BLOCKSIZE) - fields, buf = buf.split(b"\n", 1) - fields = int(fields) - while len(sparse) < fields * 2: - if b"\n" not in buf: - buf += tarfile.fileobj.read(BLOCKSIZE) - number, buf = buf.split(b"\n", 1) - sparse.append(int(number)) - next.offset_data = tarfile.fileobj.tell() - next.sparse = list(zip(sparse[::2], sparse[1::2])) - - def _apply_pax_info(self, pax_headers, encoding, errors): - """Replace fields with supplemental information from a previous - pax extended or global header. - """ - for keyword, value in pax_headers.items(): - if keyword == "GNU.sparse.name": - setattr(self, "path", value) - elif keyword == "GNU.sparse.size": - setattr(self, "size", int(value)) - elif keyword == "GNU.sparse.realsize": - setattr(self, "size", int(value)) - elif keyword in PAX_FIELDS: - if keyword in PAX_NUMBER_FIELDS: - try: - value = PAX_NUMBER_FIELDS[keyword](value) - except ValueError: - value = 0 - if keyword == "path": - value = value.rstrip("/") - setattr(self, keyword, value) - - self.pax_headers = pax_headers.copy() - - def _decode_pax_field(self, value, encoding, fallback_encoding, fallback_errors): - """Decode a single field from a pax record. - """ - try: - return value.decode(encoding, "strict") - except UnicodeDecodeError: - return value.decode(fallback_encoding, fallback_errors) - - def _block(self, count): - """Round up a byte count by BLOCKSIZE and return it, - e.g. _block(834) => 1024. - """ - blocks, remainder = divmod(count, BLOCKSIZE) - if remainder: - blocks += 1 - return blocks * BLOCKSIZE - - def isreg(self): - return self.type in REGULAR_TYPES - def isfile(self): - return self.isreg() - def isdir(self): - return self.type == DIRTYPE - def issym(self): - return self.type == SYMTYPE - def islnk(self): - return self.type == LNKTYPE - def ischr(self): - return self.type == CHRTYPE - def isblk(self): - return self.type == BLKTYPE - def isfifo(self): - return self.type == FIFOTYPE - def issparse(self): - return self.sparse is not None - def isdev(self): - return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE) -# class TarInfo - -class TarFile(object): - """The TarFile Class provides an interface to tar archives. - """ - - debug = 0 # May be set from 0 (no msgs) to 3 (all msgs) - - dereference = False # If true, add content of linked file to the - # tar file, else the link. - - ignore_zeros = False # If true, skips empty or invalid blocks and - # continues processing. - - errorlevel = 1 # If 0, fatal errors only appear in debug - # messages (if debug >= 0). If > 0, errors - # are passed to the caller as exceptions. - - format = DEFAULT_FORMAT # The format to use when creating an archive. - - encoding = ENCODING # Encoding for 8-bit character strings. - - errors = None # Error handler for unicode conversion. - - tarinfo = TarInfo # The default TarInfo class to use. - - fileobject = ExFileObject # The default ExFileObject class to use. - - def __init__(self, name=None, mode="r", fileobj=None, format=None, - tarinfo=None, dereference=None, ignore_zeros=None, encoding=None, - errors="surrogateescape", pax_headers=None, debug=None, errorlevel=None): - """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to - read from an existing archive, 'a' to append data to an existing - file or 'w' to create a new file overwriting an existing one. `mode' - defaults to 'r'. - If `fileobj' is given, it is used for reading or writing data. If it - can be determined, `mode' is overridden by `fileobj's mode. - `fileobj' is not closed, when TarFile is closed. - """ - if len(mode) > 1 or mode not in "raw": - raise ValueError("mode must be 'r', 'a' or 'w'") - self.mode = mode - self._mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode] - - if not fileobj: - if self.mode == "a" and not os.path.exists(name): - # Create nonexistent files in append mode. - self.mode = "w" - self._mode = "wb" - fileobj = bltn_open(name, self._mode) - self._extfileobj = False - else: - if name is None and hasattr(fileobj, "name"): - name = fileobj.name - if hasattr(fileobj, "mode"): - self._mode = fileobj.mode - self._extfileobj = True - self.name = os.path.abspath(name) if name else None - self.fileobj = fileobj - - # Init attributes. - if format is not None: - self.format = format - if tarinfo is not None: - self.tarinfo = tarinfo - if dereference is not None: - self.dereference = dereference - if ignore_zeros is not None: - self.ignore_zeros = ignore_zeros - if encoding is not None: - self.encoding = encoding - self.errors = errors - - if pax_headers is not None and self.format == PAX_FORMAT: - self.pax_headers = pax_headers - else: - self.pax_headers = {} - - if debug is not None: - self.debug = debug - if errorlevel is not None: - self.errorlevel = errorlevel - - # Init datastructures. - self.closed = False - self.members = [] # list of members as TarInfo objects - self._loaded = False # flag if all members have been read - self.offset = self.fileobj.tell() - # current position in the archive file - self.inodes = {} # dictionary caching the inodes of - # archive members already added - - try: - if self.mode == "r": - self.firstmember = None - self.firstmember = self.next() - - if self.mode == "a": - # Move to the end of the archive, - # before the first empty block. - while True: - self.fileobj.seek(self.offset) - try: - tarinfo = self.tarinfo.fromtarfile(self) - self.members.append(tarinfo) - except EOFHeaderError: - self.fileobj.seek(self.offset) - break - except HeaderError as e: - raise ReadError(str(e)) - - if self.mode in "aw": - self._loaded = True - - if self.pax_headers: - buf = self.tarinfo.create_pax_global_header(self.pax_headers.copy()) - self.fileobj.write(buf) - self.offset += len(buf) - except: - if not self._extfileobj: - self.fileobj.close() - self.closed = True - raise - - #-------------------------------------------------------------------------- - # Below are the classmethods which act as alternate constructors to the - # TarFile class. The open() method is the only one that is needed for - # public use; it is the "super"-constructor and is able to select an - # adequate "sub"-constructor for a particular compression using the mapping - # from OPEN_METH. - # - # This concept allows one to subclass TarFile without losing the comfort of - # the super-constructor. A sub-constructor is registered and made available - # by adding it to the mapping in OPEN_METH. - - @classmethod - def open(cls, name=None, mode="r", fileobj=None, bufsize=RECORDSIZE, **kwargs): - """Open a tar archive for reading, writing or appending. Return - an appropriate TarFile class. - - mode: - 'r' or 'r:*' open for reading with transparent compression - 'r:' open for reading exclusively uncompressed - 'r:gz' open for reading with gzip compression - 'r:bz2' open for reading with bzip2 compression - 'a' or 'a:' open for appending, creating the file if necessary - 'w' or 'w:' open for writing without compression - 'w:gz' open for writing with gzip compression - 'w:bz2' open for writing with bzip2 compression - - 'r|*' open a stream of tar blocks with transparent compression - 'r|' open an uncompressed stream of tar blocks for reading - 'r|gz' open a gzip compressed stream of tar blocks - 'r|bz2' open a bzip2 compressed stream of tar blocks - 'w|' open an uncompressed stream for writing - 'w|gz' open a gzip compressed stream for writing - 'w|bz2' open a bzip2 compressed stream for writing - """ - - if not name and not fileobj: - raise ValueError("nothing to open") - - if mode in ("r", "r:*"): - # Find out which *open() is appropriate for opening the file. - for comptype in cls.OPEN_METH: - func = getattr(cls, cls.OPEN_METH[comptype]) - if fileobj is not None: - saved_pos = fileobj.tell() - try: - return func(name, "r", fileobj, **kwargs) - except (ReadError, CompressionError) as e: - if fileobj is not None: - fileobj.seek(saved_pos) - continue - raise ReadError("file could not be opened successfully") - - elif ":" in mode: - filemode, comptype = mode.split(":", 1) - filemode = filemode or "r" - comptype = comptype or "tar" - - # Select the *open() function according to - # given compression. - if comptype in cls.OPEN_METH: - func = getattr(cls, cls.OPEN_METH[comptype]) - else: - raise CompressionError("unknown compression type %r" % comptype) - return func(name, filemode, fileobj, **kwargs) - - elif "|" in mode: - filemode, comptype = mode.split("|", 1) - filemode = filemode or "r" - comptype = comptype or "tar" - - if filemode not in "rw": - raise ValueError("mode must be 'r' or 'w'") - - stream = _Stream(name, filemode, comptype, fileobj, bufsize) - try: - t = cls(name, filemode, stream, **kwargs) - except: - stream.close() - raise - t._extfileobj = False - return t - - elif mode in "aw": - return cls.taropen(name, mode, fileobj, **kwargs) - - raise ValueError("undiscernible mode") - - @classmethod - def taropen(cls, name, mode="r", fileobj=None, **kwargs): - """Open uncompressed tar archive name for reading or writing. - """ - if len(mode) > 1 or mode not in "raw": - raise ValueError("mode must be 'r', 'a' or 'w'") - return cls(name, mode, fileobj, **kwargs) - - @classmethod - def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs): - """Open gzip compressed tar archive name for reading or writing. - Appending is not allowed. - """ - if len(mode) > 1 or mode not in "rw": - raise ValueError("mode must be 'r' or 'w'") - - try: - import gzip - gzip.GzipFile - except (ImportError, AttributeError): - raise CompressionError("gzip module is not available") - - extfileobj = fileobj is not None - try: - fileobj = gzip.GzipFile(name, mode + "b", compresslevel, fileobj) - t = cls.taropen(name, mode, fileobj, **kwargs) - except IOError: - if not extfileobj and fileobj is not None: - fileobj.close() - if fileobj is None: - raise - raise ReadError("not a gzip file") - except: - if not extfileobj and fileobj is not None: - fileobj.close() - raise - t._extfileobj = extfileobj - return t - - @classmethod - def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs): - """Open bzip2 compressed tar archive name for reading or writing. - Appending is not allowed. - """ - if len(mode) > 1 or mode not in "rw": - raise ValueError("mode must be 'r' or 'w'.") - - try: - import bz2 - except ImportError: - raise CompressionError("bz2 module is not available") - - if fileobj is not None: - fileobj = _BZ2Proxy(fileobj, mode) - else: - fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel) - - try: - t = cls.taropen(name, mode, fileobj, **kwargs) - except (IOError, EOFError): - fileobj.close() - raise ReadError("not a bzip2 file") - t._extfileobj = False - return t - - # All *open() methods are registered here. - OPEN_METH = { - "tar": "taropen", # uncompressed tar - "gz": "gzopen", # gzip compressed tar - "bz2": "bz2open" # bzip2 compressed tar - } - - #-------------------------------------------------------------------------- - # The public methods which TarFile provides: - - def close(self): - """Close the TarFile. In write-mode, two finishing zero blocks are - appended to the archive. - """ - if self.closed: - return - - if self.mode in "aw": - self.fileobj.write(NUL * (BLOCKSIZE * 2)) - self.offset += (BLOCKSIZE * 2) - # fill up the end with zero-blocks - # (like option -b20 for tar does) - blocks, remainder = divmod(self.offset, RECORDSIZE) - if remainder > 0: - self.fileobj.write(NUL * (RECORDSIZE - remainder)) - - if not self._extfileobj: - self.fileobj.close() - self.closed = True - - def getmember(self, name): - """Return a TarInfo object for member `name'. If `name' can not be - found in the archive, KeyError is raised. If a member occurs more - than once in the archive, its last occurrence is assumed to be the - most up-to-date version. - """ - tarinfo = self._getmember(name) - if tarinfo is None: - raise KeyError("filename %r not found" % name) - return tarinfo - - def getmembers(self): - """Return the members of the archive as a list of TarInfo objects. The - list has the same order as the members in the archive. - """ - self._check() - if not self._loaded: # if we want to obtain a list of - self._load() # all members, we first have to - # scan the whole archive. - return self.members - - def getnames(self): - """Return the members of the archive as a list of their names. It has - the same order as the list returned by getmembers(). - """ - return [tarinfo.name for tarinfo in self.getmembers()] - - def gettarinfo(self, name=None, arcname=None, fileobj=None): - """Create a TarInfo object for either the file `name' or the file - object `fileobj' (using os.fstat on its file descriptor). You can - modify some of the TarInfo's attributes before you add it using - addfile(). If given, `arcname' specifies an alternative name for the - file in the archive. - """ - self._check("aw") - - # When fileobj is given, replace name by - # fileobj's real name. - if fileobj is not None: - name = fileobj.name - - # Building the name of the member in the archive. - # Backward slashes are converted to forward slashes, - # Absolute paths are turned to relative paths. - if arcname is None: - arcname = name - drv, arcname = os.path.splitdrive(arcname) - arcname = arcname.replace(os.sep, "/") - arcname = arcname.lstrip("/") - - # Now, fill the TarInfo object with - # information specific for the file. - tarinfo = self.tarinfo() - tarinfo.tarfile = self - - # Use os.stat or os.lstat, depending on platform - # and if symlinks shall be resolved. - if fileobj is None: - if hasattr(os, "lstat") and not self.dereference: - statres = os.lstat(name) - else: - statres = os.stat(name) - else: - statres = os.fstat(fileobj.fileno()) - linkname = "" - - stmd = statres.st_mode - if stat.S_ISREG(stmd): - inode = (statres.st_ino, statres.st_dev) - if not self.dereference and statres.st_nlink > 1 and \ - inode in self.inodes and arcname != self.inodes[inode]: - # Is it a hardlink to an already - # archived file? - type = LNKTYPE - linkname = self.inodes[inode] - else: - # The inode is added only if its valid. - # For win32 it is always 0. - type = REGTYPE - if inode[0]: - self.inodes[inode] = arcname - elif stat.S_ISDIR(stmd): - type = DIRTYPE - elif stat.S_ISFIFO(stmd): - type = FIFOTYPE - elif stat.S_ISLNK(stmd): - type = SYMTYPE - linkname = os.readlink(name) - elif stat.S_ISCHR(stmd): - type = CHRTYPE - elif stat.S_ISBLK(stmd): - type = BLKTYPE - else: - return None - - # Fill the TarInfo object with all - # information we can get. - tarinfo.name = arcname - tarinfo.mode = stmd - tarinfo.uid = statres.st_uid - tarinfo.gid = statres.st_gid - if type == REGTYPE: - tarinfo.size = statres.st_size - else: - tarinfo.size = 0 - tarinfo.mtime = statres.st_mtime - tarinfo.type = type - tarinfo.linkname = linkname - if pwd: - try: - tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0] - except KeyError: - pass - if grp: - try: - tarinfo.gname = grp.getgrgid(tarinfo.gid)[0] - except KeyError: - pass - - if type in (CHRTYPE, BLKTYPE): - if hasattr(os, "major") and hasattr(os, "minor"): - tarinfo.devmajor = os.major(statres.st_rdev) - tarinfo.devminor = os.minor(statres.st_rdev) - return tarinfo - - def list(self, verbose=True): - """Print a table of contents to sys.stdout. If `verbose' is False, only - the names of the members are printed. If it is True, an `ls -l'-like - output is produced. - """ - self._check() - - for tarinfo in self: - if verbose: - print(filemode(tarinfo.mode), end=' ') - print("%s/%s" % (tarinfo.uname or tarinfo.uid, - tarinfo.gname or tarinfo.gid), end=' ') - if tarinfo.ischr() or tarinfo.isblk(): - print("%10s" % ("%d,%d" \ - % (tarinfo.devmajor, tarinfo.devminor)), end=' ') - else: - print("%10d" % tarinfo.size, end=' ') - print("%d-%02d-%02d %02d:%02d:%02d" \ - % time.localtime(tarinfo.mtime)[:6], end=' ') - - print(tarinfo.name + ("/" if tarinfo.isdir() else ""), end=' ') - - if verbose: - if tarinfo.issym(): - print("->", tarinfo.linkname, end=' ') - if tarinfo.islnk(): - print("link to", tarinfo.linkname, end=' ') - print() - - def add(self, name, arcname=None, recursive=True, exclude=None, filter=None): - """Add the file `name' to the archive. `name' may be any type of file - (directory, fifo, symbolic link, etc.). If given, `arcname' - specifies an alternative name for the file in the archive. - Directories are added recursively by default. This can be avoided by - setting `recursive' to False. `exclude' is a function that should - return True for each filename to be excluded. `filter' is a function - that expects a TarInfo object argument and returns the changed - TarInfo object, if it returns None the TarInfo object will be - excluded from the archive. - """ - self._check("aw") - - if arcname is None: - arcname = name - - # Exclude pathnames. - if exclude is not None: - import warnings - warnings.warn("use the filter argument instead", - DeprecationWarning, 2) - if exclude(name): - self._dbg(2, "tarfile: Excluded %r" % name) - return - - # Skip if somebody tries to archive the archive... - if self.name is not None and os.path.abspath(name) == self.name: - self._dbg(2, "tarfile: Skipped %r" % name) - return - - self._dbg(1, name) - - # Create a TarInfo object from the file. - tarinfo = self.gettarinfo(name, arcname) - - if tarinfo is None: - self._dbg(1, "tarfile: Unsupported type %r" % name) - return - - # Change or exclude the TarInfo object. - if filter is not None: - tarinfo = filter(tarinfo) - if tarinfo is None: - self._dbg(2, "tarfile: Excluded %r" % name) - return - - # Append the tar header and data to the archive. - if tarinfo.isreg(): - f = bltn_open(name, "rb") - self.addfile(tarinfo, f) - f.close() - - elif tarinfo.isdir(): - self.addfile(tarinfo) - if recursive: - for f in os.listdir(name): - self.add(os.path.join(name, f), os.path.join(arcname, f), - recursive, exclude, filter=filter) - - else: - self.addfile(tarinfo) - - def addfile(self, tarinfo, fileobj=None): - """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is - given, tarinfo.size bytes are read from it and added to the archive. - You can create TarInfo objects using gettarinfo(). - On Windows platforms, `fileobj' should always be opened with mode - 'rb' to avoid irritation about the file size. - """ - self._check("aw") - - tarinfo = copy.copy(tarinfo) - - buf = tarinfo.tobuf(self.format, self.encoding, self.errors) - self.fileobj.write(buf) - self.offset += len(buf) - - # If there's data to follow, append it. - if fileobj is not None: - copyfileobj(fileobj, self.fileobj, tarinfo.size) - blocks, remainder = divmod(tarinfo.size, BLOCKSIZE) - if remainder > 0: - self.fileobj.write(NUL * (BLOCKSIZE - remainder)) - blocks += 1 - self.offset += blocks * BLOCKSIZE - - self.members.append(tarinfo) - - def extractall(self, path=".", members=None): - """Extract all members from the archive to the current working - directory and set owner, modification time and permissions on - directories afterwards. `path' specifies a different directory - to extract to. `members' is optional and must be a subset of the - list returned by getmembers(). - """ - directories = [] - - if members is None: - members = self - - for tarinfo in members: - if tarinfo.isdir(): - # Extract directories with a safe mode. - directories.append(tarinfo) - tarinfo = copy.copy(tarinfo) - tarinfo.mode = 0o700 - # Do not set_attrs directories, as we will do that further down - self.extract(tarinfo, path, set_attrs=not tarinfo.isdir()) - - # Reverse sort directories. - directories.sort(key=lambda a: a.name) - directories.reverse() - - # Set correct owner, mtime and filemode on directories. - for tarinfo in directories: - dirpath = os.path.join(path, tarinfo.name) - try: - self.chown(tarinfo, dirpath) - self.utime(tarinfo, dirpath) - self.chmod(tarinfo, dirpath) - except ExtractError as e: - if self.errorlevel > 1: - raise - else: - self._dbg(1, "tarfile: %s" % e) - - def extract(self, member, path="", set_attrs=True): - """Extract a member from the archive to the current working directory, - using its full name. Its file information is extracted as accurately - as possible. `member' may be a filename or a TarInfo object. You can - specify a different directory using `path'. File attributes (owner, - mtime, mode) are set unless `set_attrs' is False. - """ - self._check("r") - - if isinstance(member, str): - tarinfo = self.getmember(member) - else: - tarinfo = member - - # Prepare the link target for makelink(). - if tarinfo.islnk(): - tarinfo._link_target = os.path.join(path, tarinfo.linkname) - - try: - self._extract_member(tarinfo, os.path.join(path, tarinfo.name), - set_attrs=set_attrs) - except EnvironmentError as e: - if self.errorlevel > 0: - raise - else: - if e.filename is None: - self._dbg(1, "tarfile: %s" % e.strerror) - else: - self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename)) - except ExtractError as e: - if self.errorlevel > 1: - raise - else: - self._dbg(1, "tarfile: %s" % e) - - def extractfile(self, member): - """Extract a member from the archive as a file object. `member' may be - a filename or a TarInfo object. If `member' is a regular file, a - file-like object is returned. If `member' is a link, a file-like - object is constructed from the link's target. If `member' is none of - the above, None is returned. - The file-like object is read-only and provides the following - methods: read(), readline(), readlines(), seek() and tell() - """ - self._check("r") - - if isinstance(member, str): - tarinfo = self.getmember(member) - else: - tarinfo = member - - if tarinfo.isreg(): - return self.fileobject(self, tarinfo) - - elif tarinfo.type not in SUPPORTED_TYPES: - # If a member's type is unknown, it is treated as a - # regular file. - return self.fileobject(self, tarinfo) - - elif tarinfo.islnk() or tarinfo.issym(): - if isinstance(self.fileobj, _Stream): - # A small but ugly workaround for the case that someone tries - # to extract a (sym)link as a file-object from a non-seekable - # stream of tar blocks. - raise StreamError("cannot extract (sym)link as file object") - else: - # A (sym)link's file object is its target's file object. - return self.extractfile(self._find_link_target(tarinfo)) - else: - # If there's no data associated with the member (directory, chrdev, - # blkdev, etc.), return None instead of a file object. - return None - - def _extract_member(self, tarinfo, targetpath, set_attrs=True): - """Extract the TarInfo object tarinfo to a physical - file called targetpath. - """ - # Fetch the TarInfo object for the given name - # and build the destination pathname, replacing - # forward slashes to platform specific separators. - targetpath = targetpath.rstrip("/") - targetpath = targetpath.replace("/", os.sep) - - # Create all upper directories. - upperdirs = os.path.dirname(targetpath) - if upperdirs and not os.path.exists(upperdirs): - # Create directories that are not part of the archive with - # default permissions. - os.makedirs(upperdirs) - - if tarinfo.islnk() or tarinfo.issym(): - self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname)) - else: - self._dbg(1, tarinfo.name) - - if tarinfo.isreg(): - self.makefile(tarinfo, targetpath) - elif tarinfo.isdir(): - self.makedir(tarinfo, targetpath) - elif tarinfo.isfifo(): - self.makefifo(tarinfo, targetpath) - elif tarinfo.ischr() or tarinfo.isblk(): - self.makedev(tarinfo, targetpath) - elif tarinfo.islnk() or tarinfo.issym(): - self.makelink(tarinfo, targetpath) - elif tarinfo.type not in SUPPORTED_TYPES: - self.makeunknown(tarinfo, targetpath) - else: - self.makefile(tarinfo, targetpath) - - if set_attrs: - self.chown(tarinfo, targetpath) - if not tarinfo.issym(): - self.chmod(tarinfo, targetpath) - self.utime(tarinfo, targetpath) - - #-------------------------------------------------------------------------- - # Below are the different file methods. They are called via - # _extract_member() when extract() is called. They can be replaced in a - # subclass to implement other functionality. - - def makedir(self, tarinfo, targetpath): - """Make a directory called targetpath. - """ - try: - # Use a safe mode for the directory, the real mode is set - # later in _extract_member(). - os.mkdir(targetpath, 0o700) - except EnvironmentError as e: - if e.errno != errno.EEXIST: - raise - - def makefile(self, tarinfo, targetpath): - """Make a file called targetpath. - """ - source = self.fileobj - source.seek(tarinfo.offset_data) - target = bltn_open(targetpath, "wb") - if tarinfo.sparse is not None: - for offset, size in tarinfo.sparse: - target.seek(offset) - copyfileobj(source, target, size) - else: - copyfileobj(source, target, tarinfo.size) - target.seek(tarinfo.size) - target.truncate() - target.close() - - def makeunknown(self, tarinfo, targetpath): - """Make a file from a TarInfo object with an unknown type - at targetpath. - """ - self.makefile(tarinfo, targetpath) - self._dbg(1, "tarfile: Unknown file type %r, " \ - "extracted as regular file." % tarinfo.type) - - def makefifo(self, tarinfo, targetpath): - """Make a fifo called targetpath. - """ - if hasattr(os, "mkfifo"): - os.mkfifo(targetpath) - else: - raise ExtractError("fifo not supported by system") - - def makedev(self, tarinfo, targetpath): - """Make a character or block device called targetpath. - """ - if not hasattr(os, "mknod") or not hasattr(os, "makedev"): - raise ExtractError("special devices not supported by system") - - mode = tarinfo.mode - if tarinfo.isblk(): - mode |= stat.S_IFBLK - else: - mode |= stat.S_IFCHR - - os.mknod(targetpath, mode, - os.makedev(tarinfo.devmajor, tarinfo.devminor)) - - def makelink(self, tarinfo, targetpath): - """Make a (symbolic) link called targetpath. If it cannot be created - (platform limitation), we try to make a copy of the referenced file - instead of a link. - """ - try: - # For systems that support symbolic and hard links. - if tarinfo.issym(): - os.symlink(tarinfo.linkname, targetpath) - else: - # See extract(). - if os.path.exists(tarinfo._link_target): - os.link(tarinfo._link_target, targetpath) - else: - self._extract_member(self._find_link_target(tarinfo), - targetpath) - except symlink_exception: - if tarinfo.issym(): - linkpath = os.path.join(os.path.dirname(tarinfo.name), - tarinfo.linkname) - else: - linkpath = tarinfo.linkname - else: - try: - self._extract_member(self._find_link_target(tarinfo), - targetpath) - except KeyError: - raise ExtractError("unable to resolve link inside archive") - - def chown(self, tarinfo, targetpath): - """Set owner of targetpath according to tarinfo. - """ - if pwd and hasattr(os, "geteuid") and os.geteuid() == 0: - # We have to be root to do so. - try: - g = grp.getgrnam(tarinfo.gname)[2] - except KeyError: - g = tarinfo.gid - try: - u = pwd.getpwnam(tarinfo.uname)[2] - except KeyError: - u = tarinfo.uid - try: - if tarinfo.issym() and hasattr(os, "lchown"): - os.lchown(targetpath, u, g) - else: - if sys.platform != "os2emx": - os.chown(targetpath, u, g) - except EnvironmentError as e: - raise ExtractError("could not change owner") - - def chmod(self, tarinfo, targetpath): - """Set file permissions of targetpath according to tarinfo. - """ - if hasattr(os, 'chmod'): - try: - os.chmod(targetpath, tarinfo.mode) - except EnvironmentError as e: - raise ExtractError("could not change mode") - - def utime(self, tarinfo, targetpath): - """Set modification time of targetpath according to tarinfo. - """ - if not hasattr(os, 'utime'): - return - try: - os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime)) - except EnvironmentError as e: - raise ExtractError("could not change modification time") - - #-------------------------------------------------------------------------- - def next(self): - """Return the next member of the archive as a TarInfo object, when - TarFile is opened for reading. Return None if there is no more - available. - """ - self._check("ra") - if self.firstmember is not None: - m = self.firstmember - self.firstmember = None - return m - - # Read the next block. - self.fileobj.seek(self.offset) - tarinfo = None - while True: - try: - tarinfo = self.tarinfo.fromtarfile(self) - except EOFHeaderError as e: - if self.ignore_zeros: - self._dbg(2, "0x%X: %s" % (self.offset, e)) - self.offset += BLOCKSIZE - continue - except InvalidHeaderError as e: - if self.ignore_zeros: - self._dbg(2, "0x%X: %s" % (self.offset, e)) - self.offset += BLOCKSIZE - continue - elif self.offset == 0: - raise ReadError(str(e)) - except EmptyHeaderError: - if self.offset == 0: - raise ReadError("empty file") - except TruncatedHeaderError as e: - if self.offset == 0: - raise ReadError(str(e)) - except SubsequentHeaderError as e: - raise ReadError(str(e)) - break - - if tarinfo is not None: - self.members.append(tarinfo) - else: - self._loaded = True - - return tarinfo - - #-------------------------------------------------------------------------- - # Little helper methods: - - def _getmember(self, name, tarinfo=None, normalize=False): - """Find an archive member by name from bottom to top. - If tarinfo is given, it is used as the starting point. - """ - # Ensure that all members have been loaded. - members = self.getmembers() - - # Limit the member search list up to tarinfo. - if tarinfo is not None: - members = members[:members.index(tarinfo)] - - if normalize: - name = os.path.normpath(name) - - for member in reversed(members): - if normalize: - member_name = os.path.normpath(member.name) - else: - member_name = member.name - - if name == member_name: - return member - - def _load(self): - """Read through the entire archive file and look for readable - members. - """ - while True: - tarinfo = self.next() - if tarinfo is None: - break - self._loaded = True - - def _check(self, mode=None): - """Check if TarFile is still open, and if the operation's mode - corresponds to TarFile's mode. - """ - if self.closed: - raise IOError("%s is closed" % self.__class__.__name__) - if mode is not None and self.mode not in mode: - raise IOError("bad operation for mode %r" % self.mode) - - def _find_link_target(self, tarinfo): - """Find the target member of a symlink or hardlink member in the - archive. - """ - if tarinfo.issym(): - # Always search the entire archive. - linkname = os.path.dirname(tarinfo.name) + "/" + tarinfo.linkname - limit = None - else: - # Search the archive before the link, because a hard link is - # just a reference to an already archived file. - linkname = tarinfo.linkname - limit = tarinfo - - member = self._getmember(linkname, tarinfo=limit, normalize=True) - if member is None: - raise KeyError("linkname %r not found" % linkname) - return member - - def __iter__(self): - """Provide an iterator object. - """ - if self._loaded: - return iter(self.members) - else: - return TarIter(self) - - def _dbg(self, level, msg): - """Write debugging output to sys.stderr. - """ - if level <= self.debug: - print(msg, file=sys.stderr) - - def __enter__(self): - self._check() - return self - - def __exit__(self, type, value, traceback): - if type is None: - self.close() - else: - # An exception occurred. We must not call close() because - # it would try to write end-of-archive blocks and padding. - if not self._extfileobj: - self.fileobj.close() - self.closed = True -# class TarFile - -class TarIter(object): - """Iterator Class. - - for tarinfo in TarFile(...): - suite... - """ - - def __init__(self, tarfile): - """Construct a TarIter object. - """ - self.tarfile = tarfile - self.index = 0 - def __iter__(self): - """Return iterator object. - """ - return self - - def __next__(self): - """Return the next item using TarFile's next() method. - When all members have been read, set TarFile as _loaded. - """ - # Fix for SF #1100429: Under rare circumstances it can - # happen that getmembers() is called during iteration, - # which will cause TarIter to stop prematurely. - if not self.tarfile._loaded: - tarinfo = self.tarfile.next() - if not tarinfo: - self.tarfile._loaded = True - raise StopIteration - else: - try: - tarinfo = self.tarfile.members[self.index] - except IndexError: - raise StopIteration - self.index += 1 - return tarinfo - - next = __next__ # for Python 2.x - -#-------------------- -# exported functions -#-------------------- -def is_tarfile(name): - """Return True if name points to a tar archive that we - are able to handle, else return False. - """ - try: - t = open(name) - t.close() - return True - except TarError: - return False - -bltn_open = open -open = TarFile.open diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/compat.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/compat.py deleted file mode 100644 index ff328c8..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/compat.py +++ /dev/null @@ -1,1120 +0,0 @@ -# -*- 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<prefix>[a-z]+)://(?P<suffix>.*)$') - - 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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/database.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/database.py deleted file mode 100644 index b13cdac..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/database.py +++ /dev/null @@ -1,1339 +0,0 @@ -# -*- 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 '<Distribution %s (%s)%s>' % (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 '<InstalledDistribution %r %s at %r>' % ( - 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 '<EggInfoDistribution %r %s at %r>' % ( - 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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/index.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/index.py deleted file mode 100644 index 2406be2..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/index.py +++ /dev/null @@ -1,516 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2013 Vinay Sajip. -# Licensed to the Python Software Foundation under a contributor agreement. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -import hashlib -import logging -import os -import shutil -import subprocess -import tempfile -try: - from threading import Thread -except ImportError: - from dummy_threading import Thread - -from . import DistlibException -from .compat import (HTTPBasicAuthHandler, Request, HTTPPasswordMgr, - urlparse, build_opener, string_types) -from .util import cached_property, zip_dir, ServerProxy - -logger = logging.getLogger(__name__) - -DEFAULT_INDEX = 'https://pypi.python.org/pypi' -DEFAULT_REALM = 'pypi' - -class PackageIndex(object): - """ - This class represents a package index compatible with PyPI, the Python - Package Index. - """ - - boundary = b'----------ThIs_Is_tHe_distlib_index_bouNdaRY_$' - - def __init__(self, url=None): - """ - Initialise an instance. - - :param url: The URL of the index. If not specified, the URL for PyPI is - used. - """ - self.url = url or DEFAULT_INDEX - self.read_configuration() - scheme, netloc, path, params, query, frag = urlparse(self.url) - if params or query or frag or scheme not in ('http', 'https'): - raise DistlibException('invalid repository: %s' % self.url) - self.password_handler = None - self.ssl_verifier = None - self.gpg = None - self.gpg_home = None - with open(os.devnull, 'w') as sink: - # Use gpg by default rather than gpg2, as gpg2 insists on - # prompting for passwords - for s in ('gpg', 'gpg2'): - try: - rc = subprocess.check_call([s, '--version'], stdout=sink, - stderr=sink) - if rc == 0: - self.gpg = s - break - except OSError: - pass - - def _get_pypirc_command(self): - """ - Get the distutils command for interacting with PyPI configurations. - :return: the command. - """ - from distutils.core import Distribution - from distutils.config import PyPIRCCommand - d = Distribution() - return PyPIRCCommand(d) - - def read_configuration(self): - """ - 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. - """ - # get distutils to do the work - c = self._get_pypirc_command() - c.repository = self.url - cfg = c._read_pypirc() - self.username = cfg.get('username') - self.password = cfg.get('password') - self.realm = cfg.get('realm', 'pypi') - self.url = cfg.get('repository', self.url) - - def save_configuration(self): - """ - 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. - """ - self.check_credentials() - # get distutils to do the work - c = self._get_pypirc_command() - c._store_pypirc(self.username, self.password) - - def check_credentials(self): - """ - Check that ``username`` and ``password`` have been set, and raise an - exception if not. - """ - if self.username is None or self.password is None: - raise DistlibException('username and password must be set') - pm = HTTPPasswordMgr() - _, netloc, _, _, _, _ = urlparse(self.url) - pm.add_password(self.realm, netloc, self.username, self.password) - self.password_handler = HTTPBasicAuthHandler(pm) - - def register(self, metadata): - """ - 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. - """ - self.check_credentials() - metadata.validate() - d = metadata.todict() - d[':action'] = 'verify' - request = self.encode_request(d.items(), []) - response = self.send_request(request) - d[':action'] = 'submit' - request = self.encode_request(d.items(), []) - return self.send_request(request) - - def _reader(self, name, stream, outbuf): - """ - 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. - """ - while True: - s = stream.readline() - if not s: - break - s = s.decode('utf-8').rstrip() - outbuf.append(s) - logger.debug('%s: %s' % (name, s)) - stream.close() - - def get_sign_command(self, filename, signer, sign_password, - keystore=None): - """ - 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`. - """ - cmd = [self.gpg, '--status-fd', '2', '--no-tty'] - if keystore is None: - keystore = self.gpg_home - if keystore: - cmd.extend(['--homedir', keystore]) - if sign_password is not None: - cmd.extend(['--batch', '--passphrase-fd', '0']) - td = tempfile.mkdtemp() - sf = os.path.join(td, os.path.basename(filename) + '.asc') - cmd.extend(['--detach-sign', '--armor', '--local-user', - signer, '--output', sf, filename]) - logger.debug('invoking: %s', ' '.join(cmd)) - return cmd, sf - - def run_command(self, cmd, input_data=None): - """ - 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``. - """ - kwargs = { - 'stdout': subprocess.PIPE, - 'stderr': subprocess.PIPE, - } - if input_data is not None: - kwargs['stdin'] = subprocess.PIPE - stdout = [] - stderr = [] - p = subprocess.Popen(cmd, **kwargs) - # We don't use communicate() here because we may need to - # get clever with interacting with the command - t1 = Thread(target=self._reader, args=('stdout', p.stdout, stdout)) - t1.start() - t2 = Thread(target=self._reader, args=('stderr', p.stderr, stderr)) - t2.start() - if input_data is not None: - p.stdin.write(input_data) - p.stdin.close() - - p.wait() - t1.join() - t2.join() - return p.returncode, stdout, stderr - - def sign_file(self, filename, signer, sign_password, keystore=None): - """ - 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. - """ - cmd, sig_file = self.get_sign_command(filename, signer, sign_password, - keystore) - rc, stdout, stderr = self.run_command(cmd, - sign_password.encode('utf-8')) - if rc != 0: - raise DistlibException('sign command failed with error ' - 'code %s' % rc) - return sig_file - - def upload_file(self, metadata, filename, signer=None, sign_password=None, - filetype='sdist', pyversion='source', keystore=None): - """ - 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. - """ - self.check_credentials() - if not os.path.exists(filename): - raise DistlibException('not found: %s' % filename) - metadata.validate() - d = metadata.todict() - sig_file = None - if signer: - if not self.gpg: - logger.warning('no signing program available - not signed') - else: - sig_file = self.sign_file(filename, signer, sign_password, - keystore) - with open(filename, 'rb') as f: - file_data = f.read() - md5_digest = hashlib.md5(file_data).hexdigest() - sha256_digest = hashlib.sha256(file_data).hexdigest() - d.update({ - ':action': 'file_upload', - 'protocol_version': '1', - 'filetype': filetype, - 'pyversion': pyversion, - 'md5_digest': md5_digest, - 'sha256_digest': sha256_digest, - }) - files = [('content', os.path.basename(filename), file_data)] - if sig_file: - with open(sig_file, 'rb') as f: - sig_data = f.read() - files.append(('gpg_signature', os.path.basename(sig_file), - sig_data)) - shutil.rmtree(os.path.dirname(sig_file)) - request = self.encode_request(d.items(), files) - return self.send_request(request) - - def upload_documentation(self, metadata, doc_dir): - """ - 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. - """ - self.check_credentials() - if not os.path.isdir(doc_dir): - raise DistlibException('not a directory: %r' % doc_dir) - fn = os.path.join(doc_dir, 'index.html') - if not os.path.exists(fn): - raise DistlibException('not found: %r' % fn) - metadata.validate() - name, version = metadata.name, metadata.version - zip_data = zip_dir(doc_dir).getvalue() - fields = [(':action', 'doc_upload'), - ('name', name), ('version', version)] - files = [('content', name, zip_data)] - request = self.encode_request(fields, files) - return self.send_request(request) - - def get_verify_command(self, signature_filename, data_filename, - keystore=None): - """ - 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`. - """ - cmd = [self.gpg, '--status-fd', '2', '--no-tty'] - if keystore is None: - keystore = self.gpg_home - if keystore: - cmd.extend(['--homedir', keystore]) - cmd.extend(['--verify', signature_filename, data_filename]) - logger.debug('invoking: %s', ' '.join(cmd)) - return cmd - - def verify_signature(self, signature_filename, data_filename, - keystore=None): - """ - 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. - """ - if not self.gpg: - raise DistlibException('verification unavailable because gpg ' - 'unavailable') - cmd = self.get_verify_command(signature_filename, data_filename, - keystore) - rc, stdout, stderr = self.run_command(cmd) - if rc not in (0, 1): - raise DistlibException('verify command failed with error ' - 'code %s' % rc) - return rc == 0 - - def download_file(self, url, destfile, digest=None, reporthook=None): - """ - 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. - """ - if digest is None: - digester = None - logger.debug('No digest specified') - else: - if isinstance(digest, (list, tuple)): - hasher, digest = digest - else: - hasher = 'md5' - digester = getattr(hashlib, hasher)() - logger.debug('Digest specified: %s' % digest) - # The following code is equivalent to urlretrieve. - # We need to do it this way so that we can compute the - # digest of the file as we go. - with open(destfile, 'wb') as dfp: - # addinfourl is not a context manager on 2.x - # so we have to use try/finally - sfp = self.send_request(Request(url)) - try: - headers = sfp.info() - blocksize = 8192 - size = -1 - read = 0 - blocknum = 0 - if "content-length" in headers: - size = int(headers["Content-Length"]) - if reporthook: - reporthook(blocknum, blocksize, size) - while True: - block = sfp.read(blocksize) - if not block: - break - read += len(block) - dfp.write(block) - if digester: - digester.update(block) - blocknum += 1 - if reporthook: - reporthook(blocknum, blocksize, size) - finally: - sfp.close() - - # check that we got the whole file, if we can - if size >= 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')() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/locators.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/locators.py deleted file mode 100644 index 5c655c3..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/locators.py +++ /dev/null @@ -1,1295 +0,0 @@ -# -*- 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.python.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.python.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<rel1>[^"]*)"|'(?P<rel2>[^']*)'|(?P<rel3>[^>\\s\n]*))\\s+)? -href\\s*=\\s*(?:"(?P<url1>[^"]*)"|'(?P<url2>[^']*)'|(?P<url3>[^>\\s\n]*)) -(\\s+rel\\s*=\\s*(?:"(?P<rel4>[^"]*)"|'(?P<rel5>[^']*)'|(?P<rel6>[^>\\s\n]*)))? -""", re.I | re.S | re.X) - _base = re.compile(r"""<base\s+href\s*=\s*['"]?([^'">]+)""", 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('<a href=[^>]*>([^<]+)<') - - 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.python.org/simple/', - timeout=3.0), - scheme='legacy') - -locate = default_locator.locate - -NAME_VERSION_RE = re.compile(r'(?P<name>[\w-]+)\s*' - r'\(\s*(==\s*)?(?P<ver>[^)]+)\)$') - -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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/manifest.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/manifest.py deleted file mode 100644 index ca0fe44..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/manifest.py +++ /dev/null @@ -1,393 +0,0 @@ -# -*- 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 <pattern1> <pattern2> ...' % 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 <dir> <pattern1> <pattern2> ...' % 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 <dir_pattern>' % 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'((?<!\\)(\\\\)*)\.', escaped, pattern_re) - return pattern_re diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/markers.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/markers.py deleted file mode 100644 index ee1f3e2..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/markers.py +++ /dev/null @@ -1,131 +0,0 @@ -# -*- 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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/metadata.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/metadata.py deleted file mode 100644 index 77eed7f..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/metadata.py +++ /dev/null @@ -1,1094 +0,0 @@ -# -*- 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' occurs wrongly in the metadata. Include -# it in the tuple literal below to allow it (for now) -_566_FIELDS = _426_FIELDS + ('Description-Content-Type', 'Requires') - -_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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/resources.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/resources.py deleted file mode 100644 index 1884016..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/resources.py +++ /dev/null @@ -1,355 +0,0 @@ -# -*- 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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/scripts.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/scripts.py deleted file mode 100644 index 8e22cb9..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/scripts.py +++ /dev/null @@ -1,417 +0,0 @@ -# -*- 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 = ''' -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> - <assemblyIdentity version="1.0.0.0" - processorArchitecture="X86" - name="%s" - type="win32"/> - - <!-- Identify the application security requirements. --> - <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> - <security> - <requestedPrivileges> - <requestedExecutionLevel level="asInvoker" uiAccess="false"/> - </requestedPrivileges> - </security> - </trustInfo> -</assembly>'''.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 -*- -if __name__ == '__main__': - import sys, re - - def _resolve(module, func): - __import__(module) - mod = sys.modules[module] - parts = func.split('.') - result = getattr(mod, parts.pop(0)) - for p in parts: - result = getattr(result, p) - return result - - try: - sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) - - func = _resolve('%(module)s', '%(func)s') - rc = func() # None interpreted as 0 - except Exception as e: # only supporting Python >= 2.6 - sys.stderr.write('%%s\n' %% e) - rc = 1 - sys.exit(rc) -''' - - -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, - 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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/t32.exe b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/t32.exe deleted file mode 100644 index a09d926872d84ae22a617dfe9ebb560d420b37de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 92672 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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/t64.exe b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/t64.exe deleted file mode 100644 index 9da9b40de922fb203df6b9a1d0ad4139af536850..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102400 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�vlnW`{LoXpTySn$@;x8yoz96jn?+Kk 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�?dYNUd4WaURX_A__M4W}D0!0n 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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/util.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/util.py deleted file mode 100644 index 9d4bfd3..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/util.py +++ /dev/null @@ -1,1756 +0,0 @@ -# -# 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 '<ExportEntry %s = %s:%s %s>' % (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<name>(\w|[-.+])+) - \s*=\s*(?P<callable>(\w+)([:\.]\w+)*) - \s*(\[\s*(?P<flags>\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.split('@', 1) - if ':' not in prefix: - username = prefix - else: - username, password = prefix.split(':', 1) - 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<name>[\w .-]+)\s*' - r'\(\s*(?P<ver>[^\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') - 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() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/version.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/version.py deleted file mode 100644 index 3eebe18..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/version.py +++ /dev/null @@ -1,736 +0,0 @@ -# -*- 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] diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/w32.exe b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/w32.exe deleted file mode 100644 index 732215a9d34ccb7b417d637a7646d9b843ecafa8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89088 zcmeFae|S?>wm*FGqitH!CO`{C3REl(SahnPNDYM`O{q#T7)Xdvz$<hz5gjb&0FD$| zPs=nt#$jgk-tk`NUb*PJIy$3wMg@OiORy=5PEkZ0P^;6cyPm2=Y8#~Xyq~pC(iU~@ z_dd`2ywCg3TS)e=wSTX@_S$Q$y;FJf9>F9Cf*Bu86NCeB>CeT#|L3nblC!40kR?2m z{>H@z3`^g*ct!B1Tk<#8{Ol(+x7?n8>n(TO@iQ_1pEl;#NO$D_^p5<p8@>6r|7^p? zD>5@P3KB)%InlPUc<U{5lb_$uJ2!U@!dIxT&CTYnHuoCtzCL#`-1%8w%`JjkymkHD zpYr&>Cg9H}+(GW%^wV2|ROUbGfyXTfOART)i?<!WISJD#7!6|#8G`TvV*Xu^z32+K zc6>T0?9%;4K}Zn{6fx`yPa}*$9C+R!7zI~72c&$InY+UdMGBkF3c`HyxD3K09`bzW z?_q;rO&5ec#{?noJ4vI19bbHBt~vx^h2FH$V8i|^#EsiUg#JboP3@w-(&Uf&%NK<8 zSJZ5{MZ852W)~s>WeT(LIf&1wKNqULLI)GN_(-E-D)X~ZK=1;t<%*guHMhdg`-(mb zHzDv1KBN9zR9?--O+N$ReOXAr81V9z!X5SJ5`=3<1^<8V|AP@&sr2}Qvp;hQT24iW zOHg|EiZd1ojV;oo#(r^ba2`^8T22{~_UQ@YMZp7O1R*2@?SerFE~TuJB_wDaYC0h8 zfONF1t%{=H`W`bdYp+>YBsg9Ty9ec3iy+O3xa}TIvPK#Q&udyx1MvwG0(#iaGC|N| zJ#3?<Y4YLRkU`54s9BYRjyISA>){9$tW;Y34lPnX=&>D4X~|k7c$TwEfOzs@Yh#Nz z`FV;`(w!E`sKg@`2E}bDY>ku^4XS@tV(WO*<eu67;0Clk;vRHp!Qf<+5w0B!*Y>g? zYH=KK#%%Yu1~&m>IlB^#2^syGG|2AB1(}4aOcaC%!)}%`I7AIC2(Ro3yW`GSttng^ z_xb=ECor!L{-PNO>_ulJ3%fm=O0X!s%)$GZ?~I94l-^KEAX0n$?4wGpr7&i4#~)OB zQD%2NrWUKtZuYT1Vnu}AeF`cSgx>Rkk@}Lg{WltgT76VeA2aic`cTnpXrt2WXmJkM z9%u<Rp-*9{$HQ)>Xm?McyDyZ28Ux7mpxy?mnmvzMMr-85vkRrJLaDRx>|I7je+cM+ zj{RJ(3Vrgke;W@#D!y%U%fQLtlPKTAzWtVuOQdXpwsy6eRjt^cZ%0D4bF7$F;f!th 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ð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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/w64.exe b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/w64.exe deleted file mode 100644 index c41bd0a011fd760ce20ba795d9e535e0d2c39876..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 99328 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 B=L-M; diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/wheel.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/wheel.py deleted file mode 100644 index b04bfae..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distlib/wheel.py +++ /dev/null @@ -1,988 +0,0 @@ -# -*- 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<nm>[^-]+) --(?P<vn>\d+[^-]*) -(-(?P<bn>\d+[^-]*))? --(?P<py>\w+\d+(\.\w+\d+)*) --(?P<bi>\w+) --(?P<ar>\w+(\.\w+)*) -\.whl$ -''', re.IGNORECASE | re.VERBOSE) - -NAME_VERSION_RE = re.compile(r''' -(?P<nm>[^-]+) --(?P<vn>\d+[^-]*) -(-(?P<bn>\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 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') - # The signature file won't be in RECORD, - # and we don't currently don't do anything with it - if u_arcname.endswith('/RECORD.jws'): - 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') - if '..' in u_arcname: - raise DistlibException('invalid entry in ' - 'wheel: %r' % u_arcname) - - # The signature file won't be in RECORD, - # and we don't currently don't do anything with it - if u_arcname.endswith('/RECORD.jws'): - 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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/distro.py b/venv2/lib/python2.7/site-packages/pip/_vendor/distro.py deleted file mode 100644 index 3306163..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/distro.py +++ /dev/null @@ -1,1216 +0,0 @@ -# Copyright 2015,2016,2017 Nir Cohen -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -The ``distro`` package (``distro`` stands for Linux Distribution) provides -information about the Linux distribution it runs on, such as a reliable -machine-readable distro ID, or version information. - -It is the recommended replacement for Python's original -:py:func:`platform.linux_distribution` function, but it provides much more -functionality. An alternative implementation became necessary because Python -3.5 deprecated this function, and Python 3.8 will remove it altogether. -Its predecessor function :py:func:`platform.dist` was already -deprecated since Python 2.6 and will also be removed in Python 3.8. -Still, there are many cases in which access to OS distribution information -is needed. See `Python issue 1322 <https://bugs.python.org/issue1322>`_ for -more information. -""" - -import os -import re -import sys -import json -import shlex -import logging -import argparse -import subprocess - - -_UNIXCONFDIR = os.environ.get('UNIXCONFDIR', '/etc') -_OS_RELEASE_BASENAME = 'os-release' - -#: Translation table for normalizing the "ID" attribute defined in os-release -#: files, for use by the :func:`distro.id` method. -#: -#: * Key: Value as defined in the os-release file, translated to lower case, -#: with blanks translated to underscores. -#: -#: * Value: Normalized value. -NORMALIZED_OS_ID = { - 'ol': 'oracle', # Oracle Enterprise Linux -} - -#: Translation table for normalizing the "Distributor ID" attribute returned by -#: the lsb_release command, for use by the :func:`distro.id` method. -#: -#: * Key: Value as returned by the lsb_release command, translated to lower -#: case, with blanks translated to underscores. -#: -#: * Value: Normalized value. -NORMALIZED_LSB_ID = { - 'enterpriseenterprise': 'oracle', # Oracle Enterprise Linux - 'redhatenterpriseworkstation': 'rhel', # RHEL 6, 7 Workstation - 'redhatenterpriseserver': 'rhel', # RHEL 6, 7 Server -} - -#: Translation table for normalizing the distro ID derived from the file name -#: of distro release files, for use by the :func:`distro.id` method. -#: -#: * Key: Value as derived from the file name of a distro release file, -#: translated to lower case, with blanks translated to underscores. -#: -#: * Value: Normalized value. -NORMALIZED_DISTRO_ID = { - 'redhat': 'rhel', # RHEL 6.x, 7.x -} - -# Pattern for content of distro release file (reversed) -_DISTRO_RELEASE_CONTENT_REVERSED_PATTERN = re.compile( - r'(?:[^)]*\)(.*)\()? *(?:STL )?([\d.+\-a-z]*\d) *(?:esaeler *)?(.+)') - -# Pattern for base file name of distro release file -_DISTRO_RELEASE_BASENAME_PATTERN = re.compile( - r'(\w+)[-_](release|version)$') - -# Base file names to be ignored when searching for distro release file -_DISTRO_RELEASE_IGNORE_BASENAMES = ( - 'debian_version', - 'lsb-release', - 'oem-release', - _OS_RELEASE_BASENAME, - 'system-release' -) - - -def linux_distribution(full_distribution_name=True): - """ - Return information about the current OS distribution as a tuple - ``(id_name, version, codename)`` with items as follows: - - * ``id_name``: If *full_distribution_name* is false, the result of - :func:`distro.id`. Otherwise, the result of :func:`distro.name`. - - * ``version``: The result of :func:`distro.version`. - - * ``codename``: The result of :func:`distro.codename`. - - The interface of this function is compatible with the original - :py:func:`platform.linux_distribution` function, supporting a subset of - its parameters. - - The data it returns may not exactly be the same, because it uses more data - sources than the original function, and that may lead to different data if - the OS distribution is not consistent across multiple data sources it - provides (there are indeed such distributions ...). - - Another reason for differences is the fact that the :func:`distro.id` - method normalizes the distro ID string to a reliable machine-readable value - for a number of popular OS distributions. - """ - return _distro.linux_distribution(full_distribution_name) - - -def id(): - """ - Return the distro ID of the current distribution, as a - machine-readable string. - - For a number of OS distributions, the returned distro ID value is - *reliable*, in the sense that it is documented and that it does not change - across releases of the distribution. - - This package maintains the following reliable distro ID values: - - ============== ========================================= - Distro ID Distribution - ============== ========================================= - "ubuntu" Ubuntu - "debian" Debian - "rhel" RedHat Enterprise Linux - "centos" CentOS - "fedora" Fedora - "sles" SUSE Linux Enterprise Server - "opensuse" openSUSE - "amazon" Amazon Linux - "arch" Arch Linux - "cloudlinux" CloudLinux OS - "exherbo" Exherbo Linux - "gentoo" GenToo Linux - "ibm_powerkvm" IBM PowerKVM - "kvmibm" KVM for IBM z Systems - "linuxmint" Linux Mint - "mageia" Mageia - "mandriva" Mandriva Linux - "parallels" Parallels - "pidora" Pidora - "raspbian" Raspbian - "oracle" Oracle Linux (and Oracle Enterprise Linux) - "scientific" Scientific Linux - "slackware" Slackware - "xenserver" XenServer - "openbsd" OpenBSD - "netbsd" NetBSD - "freebsd" FreeBSD - ============== ========================================= - - If you have a need to get distros for reliable IDs added into this set, - or if you find that the :func:`distro.id` function returns a different - distro ID for one of the listed distros, please create an issue in the - `distro issue tracker`_. - - **Lookup hierarchy and transformations:** - - First, the ID is obtained from the following sources, in the specified - order. The first available and non-empty value is used: - - * the value of the "ID" attribute of the os-release file, - - * the value of the "Distributor ID" attribute returned by the lsb_release - command, - - * the first part of the file name of the distro release file, - - The so determined ID value then passes the following transformations, - before it is returned by this method: - - * it is translated to lower case, - - * blanks (which should not be there anyway) are translated to underscores, - - * a normalization of the ID is performed, based upon - `normalization tables`_. The purpose of this normalization is to ensure - that the ID is as reliable as possible, even across incompatible changes - in the OS distributions. A common reason for an incompatible change is - the addition of an os-release file, or the addition of the lsb_release - command, with ID values that differ from what was previously determined - from the distro release file name. - """ - return _distro.id() - - -def name(pretty=False): - """ - Return the name of the current OS distribution, as a human-readable - string. - - If *pretty* is false, the name is returned without version or codename. - (e.g. "CentOS Linux") - - If *pretty* is true, the version and codename are appended. - (e.g. "CentOS Linux 7.1.1503 (Core)") - - **Lookup hierarchy:** - - The name is obtained from the following sources, in the specified order. - The first available and non-empty value is used: - - * If *pretty* is false: - - - the value of the "NAME" attribute of the os-release file, - - - the value of the "Distributor ID" attribute returned by the lsb_release - command, - - - the value of the "<name>" field of the distro release file. - - * If *pretty* is true: - - - the value of the "PRETTY_NAME" attribute of the os-release file, - - - the value of the "Description" attribute returned by the lsb_release - command, - - - the value of the "<name>" field of the distro release file, appended - with the value of the pretty version ("<version_id>" and "<codename>" - fields) of the distro release file, if available. - """ - return _distro.name(pretty) - - -def version(pretty=False, best=False): - """ - Return the version of the current OS distribution, as a human-readable - string. - - If *pretty* is false, the version is returned without codename (e.g. - "7.0"). - - If *pretty* is true, the codename in parenthesis is appended, if the - codename is non-empty (e.g. "7.0 (Maipo)"). - - Some distributions provide version numbers with different precisions in - the different sources of distribution information. Examining the different - sources in a fixed priority order does not always yield the most precise - version (e.g. for Debian 8.2, or CentOS 7.1). - - The *best* parameter can be used to control the approach for the returned - version: - - If *best* is false, the first non-empty version number in priority order of - the examined sources is returned. - - If *best* is true, the most precise version number out of all examined - sources is returned. - - **Lookup hierarchy:** - - In all cases, the version number is obtained from the following sources. - If *best* is false, this order represents the priority order: - - * the value of the "VERSION_ID" attribute of the os-release file, - * the value of the "Release" attribute returned by the lsb_release - command, - * the version number parsed from the "<version_id>" field of the first line - of the distro release file, - * the version number parsed from the "PRETTY_NAME" attribute of the - os-release file, if it follows the format of the distro release files. - * the version number parsed from the "Description" attribute returned by - the lsb_release command, if it follows the format of the distro release - files. - """ - return _distro.version(pretty, best) - - -def version_parts(best=False): - """ - Return the version of the current OS distribution as a tuple - ``(major, minor, build_number)`` with items as follows: - - * ``major``: The result of :func:`distro.major_version`. - - * ``minor``: The result of :func:`distro.minor_version`. - - * ``build_number``: The result of :func:`distro.build_number`. - - For a description of the *best* parameter, see the :func:`distro.version` - method. - """ - return _distro.version_parts(best) - - -def major_version(best=False): - """ - Return the major version of the current OS distribution, as a string, - if provided. - Otherwise, the empty string is returned. The major version is the first - part of the dot-separated version string. - - For a description of the *best* parameter, see the :func:`distro.version` - method. - """ - return _distro.major_version(best) - - -def minor_version(best=False): - """ - Return the minor version of the current OS distribution, as a string, - if provided. - Otherwise, the empty string is returned. The minor version is the second - part of the dot-separated version string. - - For a description of the *best* parameter, see the :func:`distro.version` - method. - """ - return _distro.minor_version(best) - - -def build_number(best=False): - """ - Return the build number of the current OS distribution, as a string, - if provided. - Otherwise, the empty string is returned. The build number is the third part - of the dot-separated version string. - - For a description of the *best* parameter, see the :func:`distro.version` - method. - """ - return _distro.build_number(best) - - -def like(): - """ - Return a space-separated list of distro IDs of distributions that are - closely related to the current OS distribution in regards to packaging - and programming interfaces, for example distributions the current - distribution is a derivative from. - - **Lookup hierarchy:** - - This information item is only provided by the os-release file. - For details, see the description of the "ID_LIKE" attribute in the - `os-release man page - <http://www.freedesktop.org/software/systemd/man/os-release.html>`_. - """ - return _distro.like() - - -def codename(): - """ - Return the codename for the release of the current OS distribution, - as a string. - - If the distribution does not have a codename, an empty string is returned. - - Note that the returned codename is not always really a codename. For - example, openSUSE returns "x86_64". This function does not handle such - cases in any special way and just returns the string it finds, if any. - - **Lookup hierarchy:** - - * the codename within the "VERSION" attribute of the os-release file, if - provided, - - * the value of the "Codename" attribute returned by the lsb_release - command, - - * the value of the "<codename>" field of the distro release file. - """ - return _distro.codename() - - -def info(pretty=False, best=False): - """ - Return certain machine-readable information items about the current OS - distribution in a dictionary, as shown in the following example: - - .. sourcecode:: python - - { - 'id': 'rhel', - 'version': '7.0', - 'version_parts': { - 'major': '7', - 'minor': '0', - 'build_number': '' - }, - 'like': 'fedora', - 'codename': 'Maipo' - } - - The dictionary structure and keys are always the same, regardless of which - information items are available in the underlying data sources. The values - for the various keys are as follows: - - * ``id``: The result of :func:`distro.id`. - - * ``version``: The result of :func:`distro.version`. - - * ``version_parts -> major``: The result of :func:`distro.major_version`. - - * ``version_parts -> minor``: The result of :func:`distro.minor_version`. - - * ``version_parts -> build_number``: The result of - :func:`distro.build_number`. - - * ``like``: The result of :func:`distro.like`. - - * ``codename``: The result of :func:`distro.codename`. - - For a description of the *pretty* and *best* parameters, see the - :func:`distro.version` method. - """ - return _distro.info(pretty, best) - - -def os_release_info(): - """ - Return a dictionary containing key-value pairs for the information items - from the os-release file data source of the current OS distribution. - - See `os-release file`_ for details about these information items. - """ - return _distro.os_release_info() - - -def lsb_release_info(): - """ - Return a dictionary containing key-value pairs for the information items - from the lsb_release command data source of the current OS distribution. - - See `lsb_release command output`_ for details about these information - items. - """ - return _distro.lsb_release_info() - - -def distro_release_info(): - """ - Return a dictionary containing key-value pairs for the information items - from the distro release file data source of the current OS distribution. - - See `distro release file`_ for details about these information items. - """ - return _distro.distro_release_info() - - -def uname_info(): - """ - Return a dictionary containing key-value pairs for the information items - from the distro release file data source of the current OS distribution. - """ - return _distro.uname_info() - - -def os_release_attr(attribute): - """ - Return a single named information item from the os-release file data source - of the current OS distribution. - - Parameters: - - * ``attribute`` (string): Key of the information item. - - Returns: - - * (string): Value of the information item, if the item exists. - The empty string, if the item does not exist. - - See `os-release file`_ for details about these information items. - """ - return _distro.os_release_attr(attribute) - - -def lsb_release_attr(attribute): - """ - Return a single named information item from the lsb_release command output - data source of the current OS distribution. - - Parameters: - - * ``attribute`` (string): Key of the information item. - - Returns: - - * (string): Value of the information item, if the item exists. - The empty string, if the item does not exist. - - See `lsb_release command output`_ for details about these information - items. - """ - return _distro.lsb_release_attr(attribute) - - -def distro_release_attr(attribute): - """ - Return a single named information item from the distro release file - data source of the current OS distribution. - - Parameters: - - * ``attribute`` (string): Key of the information item. - - Returns: - - * (string): Value of the information item, if the item exists. - The empty string, if the item does not exist. - - See `distro release file`_ for details about these information items. - """ - return _distro.distro_release_attr(attribute) - - -def uname_attr(attribute): - """ - Return a single named information item from the distro release file - data source of the current OS distribution. - - Parameters: - - * ``attribute`` (string): Key of the information item. - - Returns: - - * (string): Value of the information item, if the item exists. - The empty string, if the item does not exist. - """ - return _distro.uname_attr(attribute) - - -class cached_property(object): - """A version of @property which caches the value. On access, it calls the - underlying function and sets the value in `__dict__` so future accesses - will not re-call the property. - """ - def __init__(self, f): - self._fname = f.__name__ - self._f = f - - def __get__(self, obj, owner): - assert obj is not None, 'call {} on an instance'.format(self._fname) - ret = obj.__dict__[self._fname] = self._f(obj) - return ret - - -class LinuxDistribution(object): - """ - Provides information about a OS distribution. - - This package creates a private module-global instance of this class with - default initialization arguments, that is used by the - `consolidated accessor functions`_ and `single source accessor functions`_. - By using default initialization arguments, that module-global instance - returns data about the current OS distribution (i.e. the distro this - package runs on). - - Normally, it is not necessary to create additional instances of this class. - However, in situations where control is needed over the exact data sources - that are used, instances of this class can be created with a specific - distro release file, or a specific os-release file, or without invoking the - lsb_release command. - """ - - def __init__(self, - include_lsb=True, - os_release_file='', - distro_release_file='', - include_uname=True): - """ - The initialization method of this class gathers information from the - available data sources, and stores that in private instance attributes. - Subsequent access to the information items uses these private instance - attributes, so that the data sources are read only once. - - Parameters: - - * ``include_lsb`` (bool): Controls whether the - `lsb_release command output`_ is included as a data source. - - If the lsb_release command is not available in the program execution - path, the data source for the lsb_release command will be empty. - - * ``os_release_file`` (string): The path name of the - `os-release file`_ that is to be used as a data source. - - An empty string (the default) will cause the default path name to - be used (see `os-release file`_ for details). - - If the specified or defaulted os-release file does not exist, the - data source for the os-release file will be empty. - - * ``distro_release_file`` (string): The path name of the - `distro release file`_ that is to be used as a data source. - - An empty string (the default) will cause a default search algorithm - to be used (see `distro release file`_ for details). - - If the specified distro release file does not exist, or if no default - distro release file can be found, the data source for the distro - release file will be empty. - - * ``include_name`` (bool): Controls whether uname command output is - included as a data source. If the uname command is not available in - the program execution path the data source for the uname command will - be empty. - - Public instance attributes: - - * ``os_release_file`` (string): The path name of the - `os-release file`_ that is actually used as a data source. The - empty string if no distro release file is used as a data source. - - * ``distro_release_file`` (string): The path name of the - `distro release file`_ that is actually used as a data source. The - empty string if no distro release file is used as a data source. - - * ``include_lsb`` (bool): The result of the ``include_lsb`` parameter. - This controls whether the lsb information will be loaded. - - * ``include_uname`` (bool): The result of the ``include_uname`` - parameter. This controls whether the uname information will - be loaded. - - Raises: - - * :py:exc:`IOError`: Some I/O issue with an os-release file or distro - release file. - - * :py:exc:`subprocess.CalledProcessError`: The lsb_release command had - some issue (other than not being available in the program execution - path). - - * :py:exc:`UnicodeError`: A data source has unexpected characters or - uses an unexpected encoding. - """ - self.os_release_file = os_release_file or \ - os.path.join(_UNIXCONFDIR, _OS_RELEASE_BASENAME) - self.distro_release_file = distro_release_file or '' # updated later - self.include_lsb = include_lsb - self.include_uname = include_uname - - def __repr__(self): - """Return repr of all info - """ - return \ - "LinuxDistribution(" \ - "os_release_file={self.os_release_file!r}, " \ - "distro_release_file={self.distro_release_file!r}, " \ - "include_lsb={self.include_lsb!r}, " \ - "include_uname={self.include_uname!r}, " \ - "_os_release_info={self._os_release_info!r}, " \ - "_lsb_release_info={self._lsb_release_info!r}, " \ - "_distro_release_info={self._distro_release_info!r}, " \ - "_uname_info={self._uname_info!r})".format( - self=self) - - def linux_distribution(self, full_distribution_name=True): - """ - Return information about the OS distribution that is compatible - with Python's :func:`platform.linux_distribution`, supporting a subset - of its parameters. - - For details, see :func:`distro.linux_distribution`. - """ - return ( - self.name() if full_distribution_name else self.id(), - self.version(), - self.codename() - ) - - def id(self): - """Return the distro ID of the OS distribution, as a string. - - For details, see :func:`distro.id`. - """ - def normalize(distro_id, table): - distro_id = distro_id.lower().replace(' ', '_') - return table.get(distro_id, distro_id) - - distro_id = self.os_release_attr('id') - if distro_id: - return normalize(distro_id, NORMALIZED_OS_ID) - - distro_id = self.lsb_release_attr('distributor_id') - if distro_id: - return normalize(distro_id, NORMALIZED_LSB_ID) - - distro_id = self.distro_release_attr('id') - if distro_id: - return normalize(distro_id, NORMALIZED_DISTRO_ID) - - distro_id = self.uname_attr('id') - if distro_id: - return normalize(distro_id, NORMALIZED_DISTRO_ID) - - return '' - - def name(self, pretty=False): - """ - Return the name of the OS distribution, as a string. - - For details, see :func:`distro.name`. - """ - name = self.os_release_attr('name') \ - or self.lsb_release_attr('distributor_id') \ - or self.distro_release_attr('name') \ - or self.uname_attr('name') - if pretty: - name = self.os_release_attr('pretty_name') \ - or self.lsb_release_attr('description') - if not name: - name = self.distro_release_attr('name') \ - or self.uname_attr('name') - version = self.version(pretty=True) - if version: - name = name + ' ' + version - return name or '' - - def version(self, pretty=False, best=False): - """ - Return the version of the OS distribution, as a string. - - For details, see :func:`distro.version`. - """ - versions = [ - self.os_release_attr('version_id'), - self.lsb_release_attr('release'), - self.distro_release_attr('version_id'), - self._parse_distro_release_content( - self.os_release_attr('pretty_name')).get('version_id', ''), - self._parse_distro_release_content( - self.lsb_release_attr('description')).get('version_id', ''), - self.uname_attr('release') - ] - version = '' - if best: - # This algorithm uses the last version in priority order that has - # the best precision. If the versions are not in conflict, that - # does not matter; otherwise, using the last one instead of the - # first one might be considered a surprise. - for v in versions: - if v.count(".") > version.count(".") or version == '': - version = v - else: - for v in versions: - if v != '': - version = v - break - if pretty and version and self.codename(): - version = u'{0} ({1})'.format(version, self.codename()) - return version - - def version_parts(self, best=False): - """ - Return the version of the OS distribution, as a tuple of version - numbers. - - For details, see :func:`distro.version_parts`. - """ - version_str = self.version(best=best) - if version_str: - version_regex = re.compile(r'(\d+)\.?(\d+)?\.?(\d+)?') - matches = version_regex.match(version_str) - if matches: - major, minor, build_number = matches.groups() - return major, minor or '', build_number or '' - return '', '', '' - - def major_version(self, best=False): - """ - Return the major version number of the current distribution. - - For details, see :func:`distro.major_version`. - """ - return self.version_parts(best)[0] - - def minor_version(self, best=False): - """ - Return the minor version number of the current distribution. - - For details, see :func:`distro.minor_version`. - """ - return self.version_parts(best)[1] - - def build_number(self, best=False): - """ - Return the build number of the current distribution. - - For details, see :func:`distro.build_number`. - """ - return self.version_parts(best)[2] - - def like(self): - """ - Return the IDs of distributions that are like the OS distribution. - - For details, see :func:`distro.like`. - """ - return self.os_release_attr('id_like') or '' - - def codename(self): - """ - Return the codename of the OS distribution. - - For details, see :func:`distro.codename`. - """ - try: - # Handle os_release specially since distros might purposefully set - # this to empty string to have no codename - return self._os_release_info['codename'] - except KeyError: - return self.lsb_release_attr('codename') \ - or self.distro_release_attr('codename') \ - or '' - - def info(self, pretty=False, best=False): - """ - Return certain machine-readable information about the OS - distribution. - - For details, see :func:`distro.info`. - """ - return dict( - id=self.id(), - version=self.version(pretty, best), - version_parts=dict( - major=self.major_version(best), - minor=self.minor_version(best), - build_number=self.build_number(best) - ), - like=self.like(), - codename=self.codename(), - ) - - def os_release_info(self): - """ - Return a dictionary containing key-value pairs for the information - items from the os-release file data source of the OS distribution. - - For details, see :func:`distro.os_release_info`. - """ - return self._os_release_info - - def lsb_release_info(self): - """ - Return a dictionary containing key-value pairs for the information - items from the lsb_release command data source of the OS - distribution. - - For details, see :func:`distro.lsb_release_info`. - """ - return self._lsb_release_info - - def distro_release_info(self): - """ - Return a dictionary containing key-value pairs for the information - items from the distro release file data source of the OS - distribution. - - For details, see :func:`distro.distro_release_info`. - """ - return self._distro_release_info - - def uname_info(self): - """ - Return a dictionary containing key-value pairs for the information - items from the uname command data source of the OS distribution. - - For details, see :func:`distro.uname_info`. - """ - return self._uname_info - - def os_release_attr(self, attribute): - """ - Return a single named information item from the os-release file data - source of the OS distribution. - - For details, see :func:`distro.os_release_attr`. - """ - return self._os_release_info.get(attribute, '') - - def lsb_release_attr(self, attribute): - """ - Return a single named information item from the lsb_release command - output data source of the OS distribution. - - For details, see :func:`distro.lsb_release_attr`. - """ - return self._lsb_release_info.get(attribute, '') - - def distro_release_attr(self, attribute): - """ - Return a single named information item from the distro release file - data source of the OS distribution. - - For details, see :func:`distro.distro_release_attr`. - """ - return self._distro_release_info.get(attribute, '') - - def uname_attr(self, attribute): - """ - Return a single named information item from the uname command - output data source of the OS distribution. - - For details, see :func:`distro.uname_release_attr`. - """ - return self._uname_info.get(attribute, '') - - @cached_property - def _os_release_info(self): - """ - Get the information items from the specified os-release file. - - Returns: - A dictionary containing all information items. - """ - if os.path.isfile(self.os_release_file): - with open(self.os_release_file) as release_file: - return self._parse_os_release_content(release_file) - return {} - - @staticmethod - def _parse_os_release_content(lines): - """ - Parse the lines of an os-release file. - - Parameters: - - * lines: Iterable through the lines in the os-release file. - Each line must be a unicode string or a UTF-8 encoded byte - string. - - Returns: - A dictionary containing all information items. - """ - props = {} - lexer = shlex.shlex(lines, posix=True) - lexer.whitespace_split = True - - # The shlex module defines its `wordchars` variable using literals, - # making it dependent on the encoding of the Python source file. - # In Python 2.6 and 2.7, the shlex source file is encoded in - # 'iso-8859-1', and the `wordchars` variable is defined as a byte - # string. This causes a UnicodeDecodeError to be raised when the - # parsed content is a unicode object. The following fix resolves that - # (... but it should be fixed in shlex...): - if sys.version_info[0] == 2 and isinstance(lexer.wordchars, bytes): - lexer.wordchars = lexer.wordchars.decode('iso-8859-1') - - tokens = list(lexer) - for token in tokens: - # At this point, all shell-like parsing has been done (i.e. - # comments processed, quotes and backslash escape sequences - # processed, multi-line values assembled, trailing newlines - # stripped, etc.), so the tokens are now either: - # * variable assignments: var=value - # * commands or their arguments (not allowed in os-release) - if '=' in token: - k, v = token.split('=', 1) - if isinstance(v, bytes): - v = v.decode('utf-8') - props[k.lower()] = v - else: - # Ignore any tokens that are not variable assignments - pass - - if 'version_codename' in props: - # os-release added a version_codename field. Use that in - # preference to anything else Note that some distros purposefully - # do not have code names. They should be setting - # version_codename="" - props['codename'] = props['version_codename'] - elif 'ubuntu_codename' in props: - # Same as above but a non-standard field name used on older Ubuntus - props['codename'] = props['ubuntu_codename'] - elif 'version' in props: - # If there is no version_codename, parse it from the version - codename = re.search(r'(\(\D+\))|,(\s+)?\D+', props['version']) - if codename: - codename = codename.group() - codename = codename.strip('()') - codename = codename.strip(',') - codename = codename.strip() - # codename appears within paranthese. - props['codename'] = codename - - return props - - @cached_property - def _lsb_release_info(self): - """ - Get the information items from the lsb_release command output. - - Returns: - A dictionary containing all information items. - """ - if not self.include_lsb: - return {} - with open(os.devnull, 'w') as devnull: - try: - cmd = ('lsb_release', '-a') - stdout = subprocess.check_output(cmd, stderr=devnull) - except OSError: # Command not found - return {} - content = stdout.decode(sys.getfilesystemencoding()).splitlines() - return self._parse_lsb_release_content(content) - - @staticmethod - def _parse_lsb_release_content(lines): - """ - Parse the output of the lsb_release command. - - Parameters: - - * lines: Iterable through the lines of the lsb_release output. - Each line must be a unicode string or a UTF-8 encoded byte - string. - - Returns: - A dictionary containing all information items. - """ - props = {} - for line in lines: - kv = line.strip('\n').split(':', 1) - if len(kv) != 2: - # Ignore lines without colon. - continue - k, v = kv - props.update({k.replace(' ', '_').lower(): v.strip()}) - return props - - @cached_property - def _uname_info(self): - with open(os.devnull, 'w') as devnull: - try: - cmd = ('uname', '-rs') - stdout = subprocess.check_output(cmd, stderr=devnull) - except OSError: - return {} - content = stdout.decode(sys.getfilesystemencoding()).splitlines() - return self._parse_uname_content(content) - - @staticmethod - def _parse_uname_content(lines): - props = {} - match = re.search(r'^([^\s]+)\s+([\d\.]+)', lines[0].strip()) - if match: - name, version = match.groups() - - # This is to prevent the Linux kernel version from - # appearing as the 'best' version on otherwise - # identifiable distributions. - if name == 'Linux': - return {} - props['id'] = name.lower() - props['name'] = name - props['release'] = version - return props - - @cached_property - def _distro_release_info(self): - """ - Get the information items from the specified distro release file. - - Returns: - A dictionary containing all information items. - """ - if self.distro_release_file: - # If it was specified, we use it and parse what we can, even if - # its file name or content does not match the expected pattern. - distro_info = self._parse_distro_release_file( - self.distro_release_file) - basename = os.path.basename(self.distro_release_file) - # The file name pattern for user-specified distro release files - # is somewhat more tolerant (compared to when searching for the - # file), because we want to use what was specified as best as - # possible. - match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename) - if 'name' in distro_info \ - and 'cloudlinux' in distro_info['name'].lower(): - distro_info['id'] = 'cloudlinux' - elif match: - distro_info['id'] = match.group(1) - return distro_info - else: - try: - basenames = os.listdir(_UNIXCONFDIR) - # We sort for repeatability in cases where there are multiple - # distro specific files; e.g. CentOS, Oracle, Enterprise all - # containing `redhat-release` on top of their own. - basenames.sort() - except OSError: - # This may occur when /etc is not readable but we can't be - # sure about the *-release files. Check common entries of - # /etc for information. If they turn out to not be there the - # error is handled in `_parse_distro_release_file()`. - basenames = ['SuSE-release', - 'arch-release', - 'base-release', - 'centos-release', - 'fedora-release', - 'gentoo-release', - 'mageia-release', - 'mandrake-release', - 'mandriva-release', - 'mandrivalinux-release', - 'manjaro-release', - 'oracle-release', - 'redhat-release', - 'sl-release', - 'slackware-version'] - for basename in basenames: - if basename in _DISTRO_RELEASE_IGNORE_BASENAMES: - continue - match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename) - if match: - filepath = os.path.join(_UNIXCONFDIR, basename) - distro_info = self._parse_distro_release_file(filepath) - if 'name' in distro_info: - # The name is always present if the pattern matches - self.distro_release_file = filepath - distro_info['id'] = match.group(1) - if 'cloudlinux' in distro_info['name'].lower(): - distro_info['id'] = 'cloudlinux' - return distro_info - return {} - - def _parse_distro_release_file(self, filepath): - """ - Parse a distro release file. - - Parameters: - - * filepath: Path name of the distro release file. - - Returns: - A dictionary containing all information items. - """ - try: - with open(filepath) as fp: - # Only parse the first line. For instance, on SLES there - # are multiple lines. We don't want them... - return self._parse_distro_release_content(fp.readline()) - except (OSError, IOError): - # Ignore not being able to read a specific, seemingly version - # related file. - # See https://github.com/nir0s/distro/issues/162 - return {} - - @staticmethod - def _parse_distro_release_content(line): - """ - Parse a line from a distro release file. - - Parameters: - * line: Line from the distro release file. Must be a unicode string - or a UTF-8 encoded byte string. - - Returns: - A dictionary containing all information items. - """ - if isinstance(line, bytes): - line = line.decode('utf-8') - matches = _DISTRO_RELEASE_CONTENT_REVERSED_PATTERN.match( - line.strip()[::-1]) - distro_info = {} - if matches: - # regexp ensures non-None - distro_info['name'] = matches.group(3)[::-1] - if matches.group(2): - distro_info['version_id'] = matches.group(2)[::-1] - if matches.group(1): - distro_info['codename'] = matches.group(1)[::-1] - elif line: - distro_info['name'] = line.strip() - return distro_info - - -_distro = LinuxDistribution() - - -def main(): - logger = logging.getLogger(__name__) - logger.setLevel(logging.DEBUG) - logger.addHandler(logging.StreamHandler(sys.stdout)) - - parser = argparse.ArgumentParser(description="OS distro info tool") - parser.add_argument( - '--json', - '-j', - help="Output in machine readable format", - action="store_true") - args = parser.parse_args() - - if args.json: - logger.info(json.dumps(info(), indent=4, sort_keys=True)) - else: - logger.info('Name: %s', name(pretty=True)) - distribution_version = version(pretty=True) - logger.info('Version: %s', distribution_version) - distribution_codename = codename() - logger.info('Codename: %s', distribution_codename) - - -if __name__ == '__main__': - main() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/__init__.py deleted file mode 100644 index 0491234..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/__init__.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -HTML parsing library based on the `WHATWG HTML specification -<https://whatwg.org/html>`_. The parser is designed to be compatible with -existing HTML found in the wild and implements well-defined error recovery that -is largely compatible with modern desktop web browsers. - -Example usage:: - - from pip._vendor import html5lib - with open("my_document.html", "rb") as f: - tree = html5lib.parse(f) - -For convenience, this module re-exports the following names: - -* :func:`~.html5parser.parse` -* :func:`~.html5parser.parseFragment` -* :class:`~.html5parser.HTMLParser` -* :func:`~.treebuilders.getTreeBuilder` -* :func:`~.treewalkers.getTreeWalker` -* :func:`~.serializer.serialize` -""" - -from __future__ import absolute_import, division, unicode_literals - -from .html5parser import HTMLParser, parse, parseFragment -from .treebuilders import getTreeBuilder -from .treewalkers import getTreeWalker -from .serializer import serialize - -__all__ = ["HTMLParser", "parse", "parseFragment", "getTreeBuilder", - "getTreeWalker", "serialize"] - -# this has to be at the top level, see how setup.py parses this -#: Distribution version number. -__version__ = "1.0.1" diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_ihatexml.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_ihatexml.py deleted file mode 100644 index 4c77717..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_ihatexml.py +++ /dev/null @@ -1,288 +0,0 @@ -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)) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_inputstream.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_inputstream.py deleted file mode 100644 index a65e55f..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_inputstream.py +++ /dev/null @@ -1,923 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from pip._vendor.six import text_type, binary_type -from pip._vendor.six.moves import http_client, urllib - -import codecs -import re - -from pip._vendor import webencodings - -from .constants import EOF, spaceCharacters, asciiLetters, asciiUppercase -from .constants import _ReparseException -from . import _utils - -from io import StringIO - -try: - from io import BytesIO -except ImportError: - BytesIO = StringIO - -# Non-unicode versions of constants for use in the pre-parser -spaceCharactersBytes = frozenset([item.encode("ascii") for item in spaceCharacters]) -asciiLettersBytes = frozenset([item.encode("ascii") for item in asciiLetters]) -asciiUppercaseBytes = frozenset([item.encode("ascii") for item in asciiUppercase]) -spacesAngleBrackets = spaceCharactersBytes | frozenset([b">", b"<"]) - - -invalid_unicode_no_surrogate = "[\u0001-\u0008\u000B\u000E-\u001F\u007F-\u009F\uFDD0-\uFDEF\uFFFE\uFFFF\U0001FFFE\U0001FFFF\U0002FFFE\U0002FFFF\U0003FFFE\U0003FFFF\U0004FFFE\U0004FFFF\U0005FFFE\U0005FFFF\U0006FFFE\U0006FFFF\U0007FFFE\U0007FFFF\U0008FFFE\U0008FFFF\U0009FFFE\U0009FFFF\U000AFFFE\U000AFFFF\U000BFFFE\U000BFFFF\U000CFFFE\U000CFFFF\U000DFFFE\U000DFFFF\U000EFFFE\U000EFFFF\U000FFFFE\U000FFFFF\U0010FFFE\U0010FFFF]" # noqa - -if _utils.supports_lone_surrogates: - # Use one extra step of indirection and create surrogates with - # eval. Not using this indirection would introduce an illegal - # unicode literal on platforms not supporting such lone - # surrogates. - assert invalid_unicode_no_surrogate[-1] == "]" and invalid_unicode_no_surrogate.count("]") == 1 - invalid_unicode_re = re.compile(invalid_unicode_no_surrogate[:-1] + - eval('"\\uD800-\\uDFFF"') + # pylint:disable=eval-used - "]") -else: - invalid_unicode_re = re.compile(invalid_unicode_no_surrogate) - -non_bmp_invalid_codepoints = set([0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, - 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, - 0x6FFFE, 0x6FFFF, 0x7FFFE, 0x7FFFF, 0x8FFFE, - 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF, - 0xBFFFE, 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, - 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, 0xFFFFF, - 0x10FFFE, 0x10FFFF]) - -ascii_punctuation_re = re.compile("[\u0009-\u000D\u0020-\u002F\u003A-\u0040\u005C\u005B-\u0060\u007B-\u007E]") - -# Cache for charsUntil() -charsUntilRegEx = {} - - -class BufferedStream(object): - """Buffering for streams that do not have buffering of their own - - The buffer is implemented as a list of chunks on the assumption that - joining many strings will be slow since it is O(n**2) - """ - - def __init__(self, stream): - self.stream = stream - self.buffer = [] - self.position = [-1, 0] # chunk number, offset - - def tell(self): - pos = 0 - for chunk in self.buffer[:self.position[0]]: - pos += len(chunk) - pos += self.position[1] - return pos - - def seek(self, pos): - assert pos <= self._bufferedBytes() - offset = pos - i = 0 - while len(self.buffer[i]) < offset: - offset -= len(self.buffer[i]) - i += 1 - self.position = [i, offset] - - def read(self, bytes): - if not self.buffer: - return self._readStream(bytes) - elif (self.position[0] == len(self.buffer) and - self.position[1] == len(self.buffer[-1])): - return self._readStream(bytes) - else: - return self._readFromBuffer(bytes) - - def _bufferedBytes(self): - return sum([len(item) for item in self.buffer]) - - def _readStream(self, bytes): - data = self.stream.read(bytes) - self.buffer.append(data) - self.position[0] += 1 - self.position[1] = len(data) - return data - - def _readFromBuffer(self, bytes): - remainingBytes = bytes - rv = [] - bufferIndex = self.position[0] - bufferOffset = self.position[1] - while bufferIndex < len(self.buffer) and remainingBytes != 0: - assert remainingBytes > 0 - bufferedData = self.buffer[bufferIndex] - - if remainingBytes <= len(bufferedData) - bufferOffset: - bytesToRead = remainingBytes - self.position = [bufferIndex, bufferOffset + bytesToRead] - else: - bytesToRead = len(bufferedData) - bufferOffset - self.position = [bufferIndex, len(bufferedData)] - bufferIndex += 1 - rv.append(bufferedData[bufferOffset:bufferOffset + bytesToRead]) - remainingBytes -= bytesToRead - - bufferOffset = 0 - - if remainingBytes: - rv.append(self._readStream(remainingBytes)) - - return b"".join(rv) - - -def HTMLInputStream(source, **kwargs): - # Work around Python bug #20007: read(0) closes the connection. - # http://bugs.python.org/issue20007 - if (isinstance(source, http_client.HTTPResponse) or - # Also check for addinfourl wrapping HTTPResponse - (isinstance(source, urllib.response.addbase) and - isinstance(source.fp, http_client.HTTPResponse))): - isUnicode = False - elif hasattr(source, "read"): - isUnicode = isinstance(source.read(0), text_type) - else: - isUnicode = isinstance(source, text_type) - - if isUnicode: - encodings = [x for x in kwargs if x.endswith("_encoding")] - if encodings: - raise TypeError("Cannot set an encoding with a unicode input, set %r" % encodings) - - return HTMLUnicodeInputStream(source, **kwargs) - else: - return HTMLBinaryInputStream(source, **kwargs) - - -class HTMLUnicodeInputStream(object): - """Provides a unicode stream of characters to the HTMLTokenizer. - - This class takes care of character encoding and removing or replacing - incorrect byte-sequences and also provides column and line tracking. - - """ - - _defaultChunkSize = 10240 - - def __init__(self, source): - """Initialises the HTMLInputStream. - - HTMLInputStream(source, [encoding]) -> Normalized stream from source - for use by html5lib. - - source can be either a file-object, local filename or a string. - - The optional encoding parameter must be a string that indicates - the encoding. If specified, that encoding will be used, - regardless of any BOM or later declaration (such as in a meta - element) - - """ - - if not _utils.supports_lone_surrogates: - # Such platforms will have already checked for such - # surrogate errors, so no need to do this checking. - self.reportCharacterErrors = None - elif len("\U0010FFFF") == 1: - self.reportCharacterErrors = self.characterErrorsUCS4 - else: - self.reportCharacterErrors = self.characterErrorsUCS2 - - # List of where new lines occur - self.newLines = [0] - - self.charEncoding = (lookupEncoding("utf-8"), "certain") - self.dataStream = self.openStream(source) - - self.reset() - - def reset(self): - self.chunk = "" - self.chunkSize = 0 - self.chunkOffset = 0 - self.errors = [] - - # number of (complete) lines in previous chunks - self.prevNumLines = 0 - # number of columns in the last line of the previous chunk - self.prevNumCols = 0 - - # Deal with CR LF and surrogates split over chunk boundaries - self._bufferedCharacter = None - - def openStream(self, source): - """Produces a file object from source. - - source can be either a file object, local filename or a string. - - """ - # Already a file object - if hasattr(source, 'read'): - stream = source - else: - stream = StringIO(source) - - return stream - - def _position(self, offset): - chunk = self.chunk - nLines = chunk.count('\n', 0, offset) - positionLine = self.prevNumLines + nLines - lastLinePos = chunk.rfind('\n', 0, offset) - if lastLinePos == -1: - positionColumn = self.prevNumCols + offset - else: - positionColumn = offset - (lastLinePos + 1) - return (positionLine, positionColumn) - - def position(self): - """Returns (line, col) of the current position in the stream.""" - line, col = self._position(self.chunkOffset) - return (line + 1, col) - - def char(self): - """ Read one character from the stream or queue if available. Return - EOF when EOF is reached. - """ - # Read a new chunk from the input stream if necessary - if self.chunkOffset >= self.chunkSize: - if not self.readChunk(): - return EOF - - chunkOffset = self.chunkOffset - char = self.chunk[chunkOffset] - self.chunkOffset = chunkOffset + 1 - - return char - - def readChunk(self, chunkSize=None): - if chunkSize is None: - chunkSize = self._defaultChunkSize - - self.prevNumLines, self.prevNumCols = self._position(self.chunkSize) - - self.chunk = "" - self.chunkSize = 0 - self.chunkOffset = 0 - - data = self.dataStream.read(chunkSize) - - # Deal with CR LF and surrogates broken across chunks - if self._bufferedCharacter: - data = self._bufferedCharacter + data - self._bufferedCharacter = None - elif not data: - # We have no more data, bye-bye stream - return False - - if len(data) > 1: - lastv = ord(data[-1]) - if lastv == 0x0D or 0xD800 <= lastv <= 0xDBFF: - self._bufferedCharacter = data[-1] - data = data[:-1] - - if self.reportCharacterErrors: - self.reportCharacterErrors(data) - - # Replace invalid characters - data = data.replace("\r\n", "\n") - data = data.replace("\r", "\n") - - self.chunk = data - self.chunkSize = len(data) - - return True - - def characterErrorsUCS4(self, data): - for _ in range(len(invalid_unicode_re.findall(data))): - self.errors.append("invalid-codepoint") - - def characterErrorsUCS2(self, data): - # Someone picked the wrong compile option - # You lose - skip = False - for match in invalid_unicode_re.finditer(data): - if skip: - continue - codepoint = ord(match.group()) - pos = match.start() - # Pretty sure there should be endianness issues here - if _utils.isSurrogatePair(data[pos:pos + 2]): - # We have a surrogate pair! - char_val = _utils.surrogatePairToCodepoint(data[pos:pos + 2]) - if char_val in non_bmp_invalid_codepoints: - self.errors.append("invalid-codepoint") - skip = True - elif (codepoint >= 0xD800 and codepoint <= 0xDFFF and - pos == len(data) - 1): - self.errors.append("invalid-codepoint") - else: - skip = False - self.errors.append("invalid-codepoint") - - def charsUntil(self, characters, opposite=False): - """ Returns a string of characters from the stream up to but not - including any character in 'characters' or EOF. 'characters' must be - a container that supports the 'in' method and iteration over its - characters. - """ - - # Use a cache of regexps to find the required characters - try: - chars = charsUntilRegEx[(characters, opposite)] - except KeyError: - if __debug__: - for c in characters: - assert(ord(c) < 128) - regex = "".join(["\\x%02x" % ord(c) for c in characters]) - if not opposite: - regex = "^%s" % regex - chars = charsUntilRegEx[(characters, opposite)] = re.compile("[%s]+" % regex) - - rv = [] - - while True: - # Find the longest matching prefix - m = chars.match(self.chunk, self.chunkOffset) - if m is None: - # If nothing matched, and it wasn't because we ran out of chunk, - # then stop - if self.chunkOffset != self.chunkSize: - break - else: - end = m.end() - # If not the whole chunk matched, return everything - # up to the part that didn't match - if end != self.chunkSize: - rv.append(self.chunk[self.chunkOffset:end]) - self.chunkOffset = end - break - # If the whole remainder of the chunk matched, - # use it all and read the next chunk - rv.append(self.chunk[self.chunkOffset:]) - if not self.readChunk(): - # Reached EOF - break - - r = "".join(rv) - return r - - def unget(self, char): - # Only one character is allowed to be ungotten at once - it must - # be consumed again before any further call to unget - if char is not None: - if self.chunkOffset == 0: - # unget is called quite rarely, so it's a good idea to do - # more work here if it saves a bit of work in the frequently - # called char and charsUntil. - # So, just prepend the ungotten character onto the current - # chunk: - self.chunk = char + self.chunk - self.chunkSize += 1 - else: - self.chunkOffset -= 1 - assert self.chunk[self.chunkOffset] == char - - -class HTMLBinaryInputStream(HTMLUnicodeInputStream): - """Provides a unicode stream of characters to the HTMLTokenizer. - - This class takes care of character encoding and removing or replacing - incorrect byte-sequences and also provides column and line tracking. - - """ - - def __init__(self, source, override_encoding=None, transport_encoding=None, - same_origin_parent_encoding=None, likely_encoding=None, - default_encoding="windows-1252", useChardet=True): - """Initialises the HTMLInputStream. - - HTMLInputStream(source, [encoding]) -> Normalized stream from source - for use by html5lib. - - source can be either a file-object, local filename or a string. - - The optional encoding parameter must be a string that indicates - the encoding. If specified, that encoding will be used, - regardless of any BOM or later declaration (such as in a meta - element) - - """ - # Raw Stream - for unicode objects this will encode to utf-8 and set - # self.charEncoding as appropriate - self.rawStream = self.openStream(source) - - HTMLUnicodeInputStream.__init__(self, self.rawStream) - - # Encoding Information - # Number of bytes to use when looking for a meta element with - # encoding information - self.numBytesMeta = 1024 - # Number of bytes to use when using detecting encoding using chardet - self.numBytesChardet = 100 - # Things from args - self.override_encoding = override_encoding - self.transport_encoding = transport_encoding - self.same_origin_parent_encoding = same_origin_parent_encoding - self.likely_encoding = likely_encoding - self.default_encoding = default_encoding - - # Determine encoding - self.charEncoding = self.determineEncoding(useChardet) - assert self.charEncoding[0] is not None - - # Call superclass - self.reset() - - def reset(self): - self.dataStream = self.charEncoding[0].codec_info.streamreader(self.rawStream, 'replace') - HTMLUnicodeInputStream.reset(self) - - def openStream(self, source): - """Produces a file object from source. - - source can be either a file object, local filename or a string. - - """ - # Already a file object - if hasattr(source, 'read'): - stream = source - else: - stream = BytesIO(source) - - try: - stream.seek(stream.tell()) - except: # pylint:disable=bare-except - stream = BufferedStream(stream) - - return stream - - def determineEncoding(self, chardet=True): - # BOMs take precedence over everything - # This will also read past the BOM if present - charEncoding = self.detectBOM(), "certain" - if charEncoding[0] is not None: - return charEncoding - - # If we've been overriden, we've been overriden - charEncoding = lookupEncoding(self.override_encoding), "certain" - if charEncoding[0] is not None: - return charEncoding - - # Now check the transport layer - charEncoding = lookupEncoding(self.transport_encoding), "certain" - if charEncoding[0] is not None: - return charEncoding - - # Look for meta elements with encoding information - charEncoding = self.detectEncodingMeta(), "tentative" - if charEncoding[0] is not None: - return charEncoding - - # Parent document encoding - charEncoding = lookupEncoding(self.same_origin_parent_encoding), "tentative" - if charEncoding[0] is not None and not charEncoding[0].name.startswith("utf-16"): - return charEncoding - - # "likely" encoding - charEncoding = lookupEncoding(self.likely_encoding), "tentative" - if charEncoding[0] is not None: - return charEncoding - - # Guess with chardet, if available - if chardet: - try: - from pip._vendor.chardet.universaldetector import UniversalDetector - except ImportError: - pass - else: - buffers = [] - detector = UniversalDetector() - while not detector.done: - buffer = self.rawStream.read(self.numBytesChardet) - assert isinstance(buffer, bytes) - if not buffer: - break - buffers.append(buffer) - detector.feed(buffer) - detector.close() - encoding = lookupEncoding(detector.result['encoding']) - self.rawStream.seek(0) - if encoding is not None: - return encoding, "tentative" - - # Try the default encoding - charEncoding = lookupEncoding(self.default_encoding), "tentative" - if charEncoding[0] is not None: - return charEncoding - - # Fallback to html5lib's default if even that hasn't worked - return lookupEncoding("windows-1252"), "tentative" - - def changeEncoding(self, newEncoding): - assert self.charEncoding[1] != "certain" - newEncoding = lookupEncoding(newEncoding) - if newEncoding is None: - return - if newEncoding.name in ("utf-16be", "utf-16le"): - newEncoding = lookupEncoding("utf-8") - assert newEncoding is not None - elif newEncoding == self.charEncoding[0]: - self.charEncoding = (self.charEncoding[0], "certain") - else: - self.rawStream.seek(0) - self.charEncoding = (newEncoding, "certain") - self.reset() - raise _ReparseException("Encoding changed from %s to %s" % (self.charEncoding[0], newEncoding)) - - def detectBOM(self): - """Attempts to detect at BOM at the start of the stream. If - an encoding can be determined from the BOM return the name of the - encoding otherwise return None""" - bomDict = { - codecs.BOM_UTF8: 'utf-8', - codecs.BOM_UTF16_LE: 'utf-16le', codecs.BOM_UTF16_BE: 'utf-16be', - codecs.BOM_UTF32_LE: 'utf-32le', codecs.BOM_UTF32_BE: 'utf-32be' - } - - # Go to beginning of file and read in 4 bytes - string = self.rawStream.read(4) - assert isinstance(string, bytes) - - # Try detecting the BOM using bytes from the string - encoding = bomDict.get(string[:3]) # UTF-8 - seek = 3 - if not encoding: - # Need to detect UTF-32 before UTF-16 - encoding = bomDict.get(string) # UTF-32 - seek = 4 - if not encoding: - encoding = bomDict.get(string[:2]) # UTF-16 - seek = 2 - - # Set the read position past the BOM if one was found, otherwise - # set it to the start of the stream - if encoding: - self.rawStream.seek(seek) - return lookupEncoding(encoding) - else: - self.rawStream.seek(0) - return None - - def detectEncodingMeta(self): - """Report the encoding declared by the meta element - """ - buffer = self.rawStream.read(self.numBytesMeta) - assert isinstance(buffer, bytes) - parser = EncodingParser(buffer) - self.rawStream.seek(0) - encoding = parser.getEncoding() - - if encoding is not None and encoding.name in ("utf-16be", "utf-16le"): - encoding = lookupEncoding("utf-8") - - return encoding - - -class EncodingBytes(bytes): - """String-like object with an associated position and various extra methods - If the position is ever greater than the string length then an exception is - raised""" - def __new__(self, value): - assert isinstance(value, bytes) - return bytes.__new__(self, value.lower()) - - def __init__(self, value): - # pylint:disable=unused-argument - self._position = -1 - - def __iter__(self): - return self - - def __next__(self): - p = self._position = self._position + 1 - if p >= len(self): - raise StopIteration - elif p < 0: - raise TypeError - return self[p:p + 1] - - def next(self): - # Py2 compat - return self.__next__() - - def previous(self): - p = self._position - if p >= len(self): - raise StopIteration - elif p < 0: - raise TypeError - self._position = p = p - 1 - return self[p:p + 1] - - def setPosition(self, position): - if self._position >= len(self): - raise StopIteration - self._position = position - - def getPosition(self): - if self._position >= len(self): - raise StopIteration - if self._position >= 0: - return self._position - else: - return None - - position = property(getPosition, setPosition) - - def getCurrentByte(self): - return self[self.position:self.position + 1] - - currentByte = property(getCurrentByte) - - def skip(self, chars=spaceCharactersBytes): - """Skip past a list of characters""" - p = self.position # use property for the error-checking - while p < len(self): - c = self[p:p + 1] - if c not in chars: - self._position = p - return c - p += 1 - self._position = p - return None - - def skipUntil(self, chars): - p = self.position - while p < len(self): - c = self[p:p + 1] - if c in chars: - self._position = p - return c - p += 1 - self._position = p - return None - - def matchBytes(self, bytes): - """Look for a sequence of bytes at the start of a string. If the bytes - are found return True and advance the position to the byte after the - match. Otherwise return False and leave the position alone""" - p = self.position - data = self[p:p + len(bytes)] - rv = data.startswith(bytes) - if rv: - self.position += len(bytes) - return rv - - def jumpTo(self, bytes): - """Look for the next sequence of bytes matching a given sequence. If - a match is found advance the position to the last byte of the match""" - newPosition = self[self.position:].find(bytes) - if newPosition > -1: - # XXX: This is ugly, but I can't see a nicer way to fix this. - if self._position == -1: - self._position = 0 - self._position += (newPosition + len(bytes) - 1) - return True - else: - raise StopIteration - - -class EncodingParser(object): - """Mini parser for detecting character encoding from meta elements""" - - def __init__(self, data): - """string - the data to work on for encoding detection""" - self.data = EncodingBytes(data) - self.encoding = None - - def getEncoding(self): - methodDispatch = ( - (b"<!--", self.handleComment), - (b"<meta", self.handleMeta), - (b"</", self.handlePossibleEndTag), - (b"<!", self.handleOther), - (b"<?", self.handleOther), - (b"<", self.handlePossibleStartTag)) - for _ in self.data: - keepParsing = True - for key, method in methodDispatch: - if self.data.matchBytes(key): - try: - keepParsing = method() - break - except StopIteration: - keepParsing = False - break - if not keepParsing: - break - - return self.encoding - - def handleComment(self): - """Skip over comments""" - return self.data.jumpTo(b"-->") - - def handleMeta(self): - if self.data.currentByte not in spaceCharactersBytes: - # if we have <meta not followed by a space so just keep going - return True - # We have a valid meta element we want to search for attributes - hasPragma = False - pendingEncoding = None - while True: - # Try to find the next attribute after the current position - attr = self.getAttribute() - if attr is None: - return True - else: - if attr[0] == b"http-equiv": - hasPragma = attr[1] == b"content-type" - if hasPragma and pendingEncoding is not None: - self.encoding = pendingEncoding - return False - elif attr[0] == b"charset": - tentativeEncoding = attr[1] - codec = lookupEncoding(tentativeEncoding) - if codec is not None: - self.encoding = codec - return False - elif attr[0] == b"content": - contentParser = ContentAttrParser(EncodingBytes(attr[1])) - tentativeEncoding = contentParser.parse() - if tentativeEncoding is not None: - codec = lookupEncoding(tentativeEncoding) - if codec is not None: - if hasPragma: - self.encoding = codec - return False - else: - pendingEncoding = codec - - def handlePossibleStartTag(self): - return self.handlePossibleTag(False) - - def handlePossibleEndTag(self): - next(self.data) - return self.handlePossibleTag(True) - - def handlePossibleTag(self, endTag): - data = self.data - if data.currentByte not in asciiLettersBytes: - # If the next byte is not an ascii letter either ignore this - # fragment (possible start tag case) or treat it according to - # handleOther - if endTag: - data.previous() - self.handleOther() - return True - - c = data.skipUntil(spacesAngleBrackets) - if c == b"<": - # return to the first step in the overall "two step" algorithm - # reprocessing the < byte - data.previous() - else: - # Read all attributes - attr = self.getAttribute() - while attr is not None: - attr = self.getAttribute() - return True - - def handleOther(self): - return self.data.jumpTo(b">") - - def getAttribute(self): - """Return a name,value pair for the next attribute in the stream, - if one is found, or None""" - data = self.data - # Step 1 (skip chars) - c = data.skip(spaceCharactersBytes | frozenset([b"/"])) - assert c is None or len(c) == 1 - # Step 2 - if c in (b">", None): - return None - # Step 3 - attrName = [] - attrValue = [] - # Step 4 attribute name - while True: - if c == b"=" and attrName: - break - elif c in spaceCharactersBytes: - # Step 6! - c = data.skip() - break - elif c in (b"/", b">"): - return b"".join(attrName), b"" - elif c in asciiUppercaseBytes: - attrName.append(c.lower()) - elif c is None: - return None - else: - attrName.append(c) - # Step 5 - c = next(data) - # Step 7 - if c != b"=": - data.previous() - return b"".join(attrName), b"" - # Step 8 - next(data) - # Step 9 - c = data.skip() - # Step 10 - if c in (b"'", b'"'): - # 10.1 - quoteChar = c - while True: - # 10.2 - c = next(data) - # 10.3 - if c == quoteChar: - next(data) - return b"".join(attrName), b"".join(attrValue) - # 10.4 - elif c in asciiUppercaseBytes: - attrValue.append(c.lower()) - # 10.5 - else: - attrValue.append(c) - elif c == b">": - return b"".join(attrName), b"" - elif c in asciiUppercaseBytes: - attrValue.append(c.lower()) - elif c is None: - return None - else: - attrValue.append(c) - # Step 11 - while True: - c = next(data) - if c in spacesAngleBrackets: - return b"".join(attrName), b"".join(attrValue) - elif c in asciiUppercaseBytes: - attrValue.append(c.lower()) - elif c is None: - return None - else: - attrValue.append(c) - - -class ContentAttrParser(object): - def __init__(self, data): - assert isinstance(data, bytes) - self.data = data - - def parse(self): - try: - # Check if the attr name is charset - # otherwise return - self.data.jumpTo(b"charset") - self.data.position += 1 - self.data.skip() - if not self.data.currentByte == b"=": - # If there is no = sign keep looking for attrs - return None - self.data.position += 1 - self.data.skip() - # Look for an encoding between matching quote marks - if self.data.currentByte in (b'"', b"'"): - quoteMark = self.data.currentByte - self.data.position += 1 - oldPosition = self.data.position - if self.data.jumpTo(quoteMark): - return self.data[oldPosition:self.data.position] - else: - return None - else: - # Unquoted value - oldPosition = self.data.position - try: - self.data.skipUntil(spaceCharactersBytes) - return self.data[oldPosition:self.data.position] - except StopIteration: - # Return the whole remaining value - return self.data[oldPosition:] - except StopIteration: - return None - - -def lookupEncoding(encoding): - """Return the python codec name corresponding to an encoding or None if the - string doesn't correspond to a valid encoding.""" - if isinstance(encoding, binary_type): - try: - encoding = encoding.decode("ascii") - except UnicodeDecodeError: - return None - - if encoding is not None: - try: - return webencodings.lookup(encoding) - except AttributeError: - return None - else: - return None diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_tokenizer.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_tokenizer.py deleted file mode 100644 index 178f6e7..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_tokenizer.py +++ /dev/null @@ -1,1721 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from pip._vendor.six import unichr as chr - -from collections import deque - -from .constants import spaceCharacters -from .constants import entities -from .constants import asciiLetters, asciiUpper2Lower -from .constants import digits, hexDigits, EOF -from .constants import tokenTypes, tagTokenTypes -from .constants import replacementCharacters - -from ._inputstream import HTMLInputStream - -from ._trie import Trie - -entitiesTrie = Trie(entities) - - -class HTMLTokenizer(object): - """ This class takes care of tokenizing HTML. - - * self.currentToken - Holds the token that is currently being processed. - - * self.state - Holds a reference to the method to be invoked... XXX - - * self.stream - Points to HTMLInputStream object. - """ - - def __init__(self, stream, parser=None, **kwargs): - - self.stream = HTMLInputStream(stream, **kwargs) - self.parser = parser - - # Setup the initial tokenizer state - self.escapeFlag = False - self.lastFourChars = [] - self.state = self.dataState - self.escape = False - - # The current token being created - self.currentToken = None - super(HTMLTokenizer, self).__init__() - - def __iter__(self): - """ This is where the magic happens. - - We do our usually processing through the states and when we have a token - to return we yield the token which pauses processing until the next token - is requested. - """ - self.tokenQueue = deque([]) - # Start processing. When EOF is reached self.state will return False - # instead of True and the loop will terminate. - while self.state(): - while self.stream.errors: - yield {"type": tokenTypes["ParseError"], "data": self.stream.errors.pop(0)} - while self.tokenQueue: - yield self.tokenQueue.popleft() - - def consumeNumberEntity(self, isHex): - """This function returns either U+FFFD or the character based on the - decimal or hexadecimal representation. It also discards ";" if present. - If not present self.tokenQueue.append({"type": tokenTypes["ParseError"]}) is invoked. - """ - - allowed = digits - radix = 10 - if isHex: - allowed = hexDigits - radix = 16 - - charStack = [] - - # Consume all the characters that are in range while making sure we - # don't hit an EOF. - c = self.stream.char() - while c in allowed and c is not EOF: - charStack.append(c) - c = self.stream.char() - - # Convert the set of characters consumed to an int. - charAsInt = int("".join(charStack), radix) - - # Certain characters get replaced with others - if charAsInt in replacementCharacters: - char = replacementCharacters[charAsInt] - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "illegal-codepoint-for-numeric-entity", - "datavars": {"charAsInt": charAsInt}}) - elif ((0xD800 <= charAsInt <= 0xDFFF) or - (charAsInt > 0x10FFFF)): - char = "\uFFFD" - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "illegal-codepoint-for-numeric-entity", - "datavars": {"charAsInt": charAsInt}}) - else: - # Should speed up this check somehow (e.g. move the set to a constant) - if ((0x0001 <= charAsInt <= 0x0008) or - (0x000E <= charAsInt <= 0x001F) or - (0x007F <= charAsInt <= 0x009F) or - (0xFDD0 <= charAsInt <= 0xFDEF) or - charAsInt in frozenset([0x000B, 0xFFFE, 0xFFFF, 0x1FFFE, - 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, - 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE, - 0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE, - 0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, - 0x9FFFF, 0xAFFFE, 0xAFFFF, 0xBFFFE, - 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, - 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, - 0xFFFFF, 0x10FFFE, 0x10FFFF])): - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": - "illegal-codepoint-for-numeric-entity", - "datavars": {"charAsInt": charAsInt}}) - try: - # Try/except needed as UCS-2 Python builds' unichar only works - # within the BMP. - char = chr(charAsInt) - except ValueError: - v = charAsInt - 0x10000 - char = chr(0xD800 | (v >> 10)) + chr(0xDC00 | (v & 0x3FF)) - - # Discard the ; if present. Otherwise, put it back on the queue and - # invoke parseError on parser. - if c != ";": - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "numeric-entity-without-semicolon"}) - self.stream.unget(c) - - return char - - def consumeEntity(self, allowedChar=None, fromAttribute=False): - # Initialise to the default output for when no entity is matched - output = "&" - - charStack = [self.stream.char()] - if (charStack[0] in spaceCharacters or charStack[0] in (EOF, "<", "&") or - (allowedChar is not None and allowedChar == charStack[0])): - self.stream.unget(charStack[0]) - - elif charStack[0] == "#": - # Read the next character to see if it's hex or decimal - hex = False - charStack.append(self.stream.char()) - if charStack[-1] in ("x", "X"): - hex = True - charStack.append(self.stream.char()) - - # charStack[-1] should be the first digit - if (hex and charStack[-1] in hexDigits) \ - or (not hex and charStack[-1] in digits): - # At least one digit found, so consume the whole number - self.stream.unget(charStack[-1]) - output = self.consumeNumberEntity(hex) - else: - # No digits found - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "expected-numeric-entity"}) - self.stream.unget(charStack.pop()) - output = "&" + "".join(charStack) - - else: - # At this point in the process might have named entity. Entities - # are stored in the global variable "entities". - # - # Consume characters and compare to these to a substring of the - # entity names in the list until the substring no longer matches. - while (charStack[-1] is not EOF): - if not entitiesTrie.has_keys_with_prefix("".join(charStack)): - break - charStack.append(self.stream.char()) - - # At this point we have a string that starts with some characters - # that may match an entity - # Try to find the longest entity the string will match to take care - # of ¬i for instance. - try: - entityName = entitiesTrie.longest_prefix("".join(charStack[:-1])) - entityLength = len(entityName) - except KeyError: - entityName = None - - if entityName is not None: - if entityName[-1] != ";": - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "named-entity-without-semicolon"}) - if (entityName[-1] != ";" and fromAttribute and - (charStack[entityLength] in asciiLetters or - charStack[entityLength] in digits or - charStack[entityLength] == "=")): - self.stream.unget(charStack.pop()) - output = "&" + "".join(charStack) - else: - output = entities[entityName] - self.stream.unget(charStack.pop()) - output += "".join(charStack[entityLength:]) - else: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "expected-named-entity"}) - self.stream.unget(charStack.pop()) - output = "&" + "".join(charStack) - - if fromAttribute: - self.currentToken["data"][-1][1] += output - else: - if output in spaceCharacters: - tokenType = "SpaceCharacters" - else: - tokenType = "Characters" - self.tokenQueue.append({"type": tokenTypes[tokenType], "data": output}) - - def processEntityInAttribute(self, allowedChar): - """This method replaces the need for "entityInAttributeValueState". - """ - self.consumeEntity(allowedChar=allowedChar, fromAttribute=True) - - def emitCurrentToken(self): - """This method is a generic handler for emitting the tags. It also sets - the state to "data" because that's what's needed after a token has been - emitted. - """ - token = self.currentToken - # Add token to the queue to be yielded - if (token["type"] in tagTokenTypes): - token["name"] = token["name"].translate(asciiUpper2Lower) - if token["type"] == tokenTypes["EndTag"]: - if token["data"]: - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "attributes-in-end-tag"}) - if token["selfClosing"]: - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "self-closing-flag-on-end-tag"}) - self.tokenQueue.append(token) - self.state = self.dataState - - # Below are the various tokenizer states worked out. - def dataState(self): - data = self.stream.char() - if data == "&": - self.state = self.entityDataState - elif data == "<": - self.state = self.tagOpenState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.tokenQueue.append({"type": tokenTypes["Characters"], - "data": "\u0000"}) - elif data is EOF: - # Tokenization ends. - return False - elif data in spaceCharacters: - # Directly after emitting a token you switch back to the "data - # state". At that point spaceCharacters are important so they are - # emitted separately. - self.tokenQueue.append({"type": tokenTypes["SpaceCharacters"], "data": - data + self.stream.charsUntil(spaceCharacters, True)}) - # No need to update lastFourChars here, since the first space will - # have already been appended to lastFourChars and will have broken - # any <!-- or --> sequences - else: - chars = self.stream.charsUntil(("&", "<", "\u0000")) - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": - data + chars}) - return True - - def entityDataState(self): - self.consumeEntity() - self.state = self.dataState - return True - - def rcdataState(self): - data = self.stream.char() - if data == "&": - self.state = self.characterReferenceInRcdata - elif data == "<": - self.state = self.rcdataLessThanSignState - elif data == EOF: - # Tokenization ends. - return False - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.tokenQueue.append({"type": tokenTypes["Characters"], - "data": "\uFFFD"}) - elif data in spaceCharacters: - # Directly after emitting a token you switch back to the "data - # state". At that point spaceCharacters are important so they are - # emitted separately. - self.tokenQueue.append({"type": tokenTypes["SpaceCharacters"], "data": - data + self.stream.charsUntil(spaceCharacters, True)}) - # No need to update lastFourChars here, since the first space will - # have already been appended to lastFourChars and will have broken - # any <!-- or --> sequences - else: - chars = self.stream.charsUntil(("&", "<", "\u0000")) - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": - data + chars}) - return True - - def characterReferenceInRcdata(self): - self.consumeEntity() - self.state = self.rcdataState - return True - - def rawtextState(self): - data = self.stream.char() - if data == "<": - self.state = self.rawtextLessThanSignState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.tokenQueue.append({"type": tokenTypes["Characters"], - "data": "\uFFFD"}) - elif data == EOF: - # Tokenization ends. - return False - else: - chars = self.stream.charsUntil(("<", "\u0000")) - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": - data + chars}) - return True - - def scriptDataState(self): - data = self.stream.char() - if data == "<": - self.state = self.scriptDataLessThanSignState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.tokenQueue.append({"type": tokenTypes["Characters"], - "data": "\uFFFD"}) - elif data == EOF: - # Tokenization ends. - return False - else: - chars = self.stream.charsUntil(("<", "\u0000")) - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": - data + chars}) - return True - - def plaintextState(self): - data = self.stream.char() - if data == EOF: - # Tokenization ends. - return False - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.tokenQueue.append({"type": tokenTypes["Characters"], - "data": "\uFFFD"}) - else: - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": - data + self.stream.charsUntil("\u0000")}) - return True - - def tagOpenState(self): - data = self.stream.char() - if data == "!": - self.state = self.markupDeclarationOpenState - elif data == "/": - self.state = self.closeTagOpenState - elif data in asciiLetters: - self.currentToken = {"type": tokenTypes["StartTag"], - "name": data, "data": [], - "selfClosing": False, - "selfClosingAcknowledged": False} - self.state = self.tagNameState - elif data == ">": - # XXX In theory it could be something besides a tag name. But - # do we really care? - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "expected-tag-name-but-got-right-bracket"}) - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<>"}) - self.state = self.dataState - elif data == "?": - # XXX In theory it could be something besides a tag name. But - # do we really care? - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "expected-tag-name-but-got-question-mark"}) - self.stream.unget(data) - self.state = self.bogusCommentState - else: - # XXX - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "expected-tag-name"}) - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) - self.stream.unget(data) - self.state = self.dataState - return True - - def closeTagOpenState(self): - data = self.stream.char() - if data in asciiLetters: - self.currentToken = {"type": tokenTypes["EndTag"], "name": data, - "data": [], "selfClosing": False} - self.state = self.tagNameState - elif data == ">": - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "expected-closing-tag-but-got-right-bracket"}) - self.state = self.dataState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "expected-closing-tag-but-got-eof"}) - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) - self.state = self.dataState - else: - # XXX data can be _'_... - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "expected-closing-tag-but-got-char", - "datavars": {"data": data}}) - self.stream.unget(data) - self.state = self.bogusCommentState - return True - - def tagNameState(self): - data = self.stream.char() - if data in spaceCharacters: - self.state = self.beforeAttributeNameState - elif data == ">": - self.emitCurrentToken() - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-tag-name"}) - self.state = self.dataState - elif data == "/": - self.state = self.selfClosingStartTagState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["name"] += "\uFFFD" - else: - self.currentToken["name"] += data - # (Don't use charsUntil here, because tag names are - # very short and it's faster to not do anything fancy) - return True - - def rcdataLessThanSignState(self): - data = self.stream.char() - if data == "/": - self.temporaryBuffer = "" - self.state = self.rcdataEndTagOpenState - else: - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) - self.stream.unget(data) - self.state = self.rcdataState - return True - - def rcdataEndTagOpenState(self): - data = self.stream.char() - if data in asciiLetters: - self.temporaryBuffer += data - self.state = self.rcdataEndTagNameState - else: - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) - self.stream.unget(data) - self.state = self.rcdataState - return True - - def rcdataEndTagNameState(self): - appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower() - data = self.stream.char() - if data in spaceCharacters and appropriate: - self.currentToken = {"type": tokenTypes["EndTag"], - "name": self.temporaryBuffer, - "data": [], "selfClosing": False} - self.state = self.beforeAttributeNameState - elif data == "/" and appropriate: - self.currentToken = {"type": tokenTypes["EndTag"], - "name": self.temporaryBuffer, - "data": [], "selfClosing": False} - self.state = self.selfClosingStartTagState - elif data == ">" and appropriate: - self.currentToken = {"type": tokenTypes["EndTag"], - "name": self.temporaryBuffer, - "data": [], "selfClosing": False} - self.emitCurrentToken() - self.state = self.dataState - elif data in asciiLetters: - self.temporaryBuffer += data - else: - self.tokenQueue.append({"type": tokenTypes["Characters"], - "data": "</" + self.temporaryBuffer}) - self.stream.unget(data) - self.state = self.rcdataState - return True - - def rawtextLessThanSignState(self): - data = self.stream.char() - if data == "/": - self.temporaryBuffer = "" - self.state = self.rawtextEndTagOpenState - else: - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) - self.stream.unget(data) - self.state = self.rawtextState - return True - - def rawtextEndTagOpenState(self): - data = self.stream.char() - if data in asciiLetters: - self.temporaryBuffer += data - self.state = self.rawtextEndTagNameState - else: - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) - self.stream.unget(data) - self.state = self.rawtextState - return True - - def rawtextEndTagNameState(self): - appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower() - data = self.stream.char() - if data in spaceCharacters and appropriate: - self.currentToken = {"type": tokenTypes["EndTag"], - "name": self.temporaryBuffer, - "data": [], "selfClosing": False} - self.state = self.beforeAttributeNameState - elif data == "/" and appropriate: - self.currentToken = {"type": tokenTypes["EndTag"], - "name": self.temporaryBuffer, - "data": [], "selfClosing": False} - self.state = self.selfClosingStartTagState - elif data == ">" and appropriate: - self.currentToken = {"type": tokenTypes["EndTag"], - "name": self.temporaryBuffer, - "data": [], "selfClosing": False} - self.emitCurrentToken() - self.state = self.dataState - elif data in asciiLetters: - self.temporaryBuffer += data - else: - self.tokenQueue.append({"type": tokenTypes["Characters"], - "data": "</" + self.temporaryBuffer}) - self.stream.unget(data) - self.state = self.rawtextState - return True - - def scriptDataLessThanSignState(self): - data = self.stream.char() - if data == "/": - self.temporaryBuffer = "" - self.state = self.scriptDataEndTagOpenState - elif data == "!": - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<!"}) - self.state = self.scriptDataEscapeStartState - else: - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) - self.stream.unget(data) - self.state = self.scriptDataState - return True - - def scriptDataEndTagOpenState(self): - data = self.stream.char() - if data in asciiLetters: - self.temporaryBuffer += data - self.state = self.scriptDataEndTagNameState - else: - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) - self.stream.unget(data) - self.state = self.scriptDataState - return True - - def scriptDataEndTagNameState(self): - appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower() - data = self.stream.char() - if data in spaceCharacters and appropriate: - self.currentToken = {"type": tokenTypes["EndTag"], - "name": self.temporaryBuffer, - "data": [], "selfClosing": False} - self.state = self.beforeAttributeNameState - elif data == "/" and appropriate: - self.currentToken = {"type": tokenTypes["EndTag"], - "name": self.temporaryBuffer, - "data": [], "selfClosing": False} - self.state = self.selfClosingStartTagState - elif data == ">" and appropriate: - self.currentToken = {"type": tokenTypes["EndTag"], - "name": self.temporaryBuffer, - "data": [], "selfClosing": False} - self.emitCurrentToken() - self.state = self.dataState - elif data in asciiLetters: - self.temporaryBuffer += data - else: - self.tokenQueue.append({"type": tokenTypes["Characters"], - "data": "</" + self.temporaryBuffer}) - self.stream.unget(data) - self.state = self.scriptDataState - return True - - def scriptDataEscapeStartState(self): - data = self.stream.char() - if data == "-": - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) - self.state = self.scriptDataEscapeStartDashState - else: - self.stream.unget(data) - self.state = self.scriptDataState - return True - - def scriptDataEscapeStartDashState(self): - data = self.stream.char() - if data == "-": - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) - self.state = self.scriptDataEscapedDashDashState - else: - self.stream.unget(data) - self.state = self.scriptDataState - return True - - def scriptDataEscapedState(self): - data = self.stream.char() - if data == "-": - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) - self.state = self.scriptDataEscapedDashState - elif data == "<": - self.state = self.scriptDataEscapedLessThanSignState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.tokenQueue.append({"type": tokenTypes["Characters"], - "data": "\uFFFD"}) - elif data == EOF: - self.state = self.dataState - else: - chars = self.stream.charsUntil(("<", "-", "\u0000")) - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": - data + chars}) - return True - - def scriptDataEscapedDashState(self): - data = self.stream.char() - if data == "-": - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) - self.state = self.scriptDataEscapedDashDashState - elif data == "<": - self.state = self.scriptDataEscapedLessThanSignState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.tokenQueue.append({"type": tokenTypes["Characters"], - "data": "\uFFFD"}) - self.state = self.scriptDataEscapedState - elif data == EOF: - self.state = self.dataState - else: - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) - self.state = self.scriptDataEscapedState - return True - - def scriptDataEscapedDashDashState(self): - data = self.stream.char() - if data == "-": - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) - elif data == "<": - self.state = self.scriptDataEscapedLessThanSignState - elif data == ">": - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": ">"}) - self.state = self.scriptDataState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.tokenQueue.append({"type": tokenTypes["Characters"], - "data": "\uFFFD"}) - self.state = self.scriptDataEscapedState - elif data == EOF: - self.state = self.dataState - else: - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) - self.state = self.scriptDataEscapedState - return True - - def scriptDataEscapedLessThanSignState(self): - data = self.stream.char() - if data == "/": - self.temporaryBuffer = "" - self.state = self.scriptDataEscapedEndTagOpenState - elif data in asciiLetters: - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<" + data}) - self.temporaryBuffer = data - self.state = self.scriptDataDoubleEscapeStartState - else: - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) - self.stream.unget(data) - self.state = self.scriptDataEscapedState - return True - - def scriptDataEscapedEndTagOpenState(self): - data = self.stream.char() - if data in asciiLetters: - self.temporaryBuffer = data - self.state = self.scriptDataEscapedEndTagNameState - else: - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) - self.stream.unget(data) - self.state = self.scriptDataEscapedState - return True - - def scriptDataEscapedEndTagNameState(self): - appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower() - data = self.stream.char() - if data in spaceCharacters and appropriate: - self.currentToken = {"type": tokenTypes["EndTag"], - "name": self.temporaryBuffer, - "data": [], "selfClosing": False} - self.state = self.beforeAttributeNameState - elif data == "/" and appropriate: - self.currentToken = {"type": tokenTypes["EndTag"], - "name": self.temporaryBuffer, - "data": [], "selfClosing": False} - self.state = self.selfClosingStartTagState - elif data == ">" and appropriate: - self.currentToken = {"type": tokenTypes["EndTag"], - "name": self.temporaryBuffer, - "data": [], "selfClosing": False} - self.emitCurrentToken() - self.state = self.dataState - elif data in asciiLetters: - self.temporaryBuffer += data - else: - self.tokenQueue.append({"type": tokenTypes["Characters"], - "data": "</" + self.temporaryBuffer}) - self.stream.unget(data) - self.state = self.scriptDataEscapedState - return True - - def scriptDataDoubleEscapeStartState(self): - data = self.stream.char() - if data in (spaceCharacters | frozenset(("/", ">"))): - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) - if self.temporaryBuffer.lower() == "script": - self.state = self.scriptDataDoubleEscapedState - else: - self.state = self.scriptDataEscapedState - elif data in asciiLetters: - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) - self.temporaryBuffer += data - else: - self.stream.unget(data) - self.state = self.scriptDataEscapedState - return True - - def scriptDataDoubleEscapedState(self): - data = self.stream.char() - if data == "-": - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) - self.state = self.scriptDataDoubleEscapedDashState - elif data == "<": - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) - self.state = self.scriptDataDoubleEscapedLessThanSignState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.tokenQueue.append({"type": tokenTypes["Characters"], - "data": "\uFFFD"}) - elif data == EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-script-in-script"}) - self.state = self.dataState - else: - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) - return True - - def scriptDataDoubleEscapedDashState(self): - data = self.stream.char() - if data == "-": - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) - self.state = self.scriptDataDoubleEscapedDashDashState - elif data == "<": - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) - self.state = self.scriptDataDoubleEscapedLessThanSignState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.tokenQueue.append({"type": tokenTypes["Characters"], - "data": "\uFFFD"}) - self.state = self.scriptDataDoubleEscapedState - elif data == EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-script-in-script"}) - self.state = self.dataState - else: - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) - self.state = self.scriptDataDoubleEscapedState - return True - - def scriptDataDoubleEscapedDashDashState(self): - data = self.stream.char() - if data == "-": - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) - elif data == "<": - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) - self.state = self.scriptDataDoubleEscapedLessThanSignState - elif data == ">": - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": ">"}) - self.state = self.scriptDataState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.tokenQueue.append({"type": tokenTypes["Characters"], - "data": "\uFFFD"}) - self.state = self.scriptDataDoubleEscapedState - elif data == EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-script-in-script"}) - self.state = self.dataState - else: - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) - self.state = self.scriptDataDoubleEscapedState - return True - - def scriptDataDoubleEscapedLessThanSignState(self): - data = self.stream.char() - if data == "/": - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "/"}) - self.temporaryBuffer = "" - self.state = self.scriptDataDoubleEscapeEndState - else: - self.stream.unget(data) - self.state = self.scriptDataDoubleEscapedState - return True - - def scriptDataDoubleEscapeEndState(self): - data = self.stream.char() - if data in (spaceCharacters | frozenset(("/", ">"))): - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) - if self.temporaryBuffer.lower() == "script": - self.state = self.scriptDataEscapedState - else: - self.state = self.scriptDataDoubleEscapedState - elif data in asciiLetters: - self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) - self.temporaryBuffer += data - else: - self.stream.unget(data) - self.state = self.scriptDataDoubleEscapedState - return True - - def beforeAttributeNameState(self): - data = self.stream.char() - if data in spaceCharacters: - self.stream.charsUntil(spaceCharacters, True) - elif data in asciiLetters: - self.currentToken["data"].append([data, ""]) - self.state = self.attributeNameState - elif data == ">": - self.emitCurrentToken() - elif data == "/": - self.state = self.selfClosingStartTagState - elif data in ("'", '"', "=", "<"): - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "invalid-character-in-attribute-name"}) - self.currentToken["data"].append([data, ""]) - self.state = self.attributeNameState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["data"].append(["\uFFFD", ""]) - self.state = self.attributeNameState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "expected-attribute-name-but-got-eof"}) - self.state = self.dataState - else: - self.currentToken["data"].append([data, ""]) - self.state = self.attributeNameState - return True - - def attributeNameState(self): - data = self.stream.char() - leavingThisState = True - emitToken = False - if data == "=": - self.state = self.beforeAttributeValueState - elif data in asciiLetters: - self.currentToken["data"][-1][0] += data +\ - self.stream.charsUntil(asciiLetters, True) - leavingThisState = False - elif data == ">": - # XXX If we emit here the attributes are converted to a dict - # without being checked and when the code below runs we error - # because data is a dict not a list - emitToken = True - elif data in spaceCharacters: - self.state = self.afterAttributeNameState - elif data == "/": - self.state = self.selfClosingStartTagState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["data"][-1][0] += "\uFFFD" - leavingThisState = False - elif data in ("'", '"', "<"): - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": - "invalid-character-in-attribute-name"}) - self.currentToken["data"][-1][0] += data - leavingThisState = False - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "eof-in-attribute-name"}) - self.state = self.dataState - else: - self.currentToken["data"][-1][0] += data - leavingThisState = False - - if leavingThisState: - # Attributes are not dropped at this stage. That happens when the - # start tag token is emitted so values can still be safely appended - # to attributes, but we do want to report the parse error in time. - self.currentToken["data"][-1][0] = ( - self.currentToken["data"][-1][0].translate(asciiUpper2Lower)) - for name, _ in self.currentToken["data"][:-1]: - if self.currentToken["data"][-1][0] == name: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "duplicate-attribute"}) - break - # XXX Fix for above XXX - if emitToken: - self.emitCurrentToken() - return True - - def afterAttributeNameState(self): - data = self.stream.char() - if data in spaceCharacters: - self.stream.charsUntil(spaceCharacters, True) - elif data == "=": - self.state = self.beforeAttributeValueState - elif data == ">": - self.emitCurrentToken() - elif data in asciiLetters: - self.currentToken["data"].append([data, ""]) - self.state = self.attributeNameState - elif data == "/": - self.state = self.selfClosingStartTagState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["data"].append(["\uFFFD", ""]) - self.state = self.attributeNameState - elif data in ("'", '"', "<"): - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "invalid-character-after-attribute-name"}) - self.currentToken["data"].append([data, ""]) - self.state = self.attributeNameState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "expected-end-of-tag-but-got-eof"}) - self.state = self.dataState - else: - self.currentToken["data"].append([data, ""]) - self.state = self.attributeNameState - return True - - def beforeAttributeValueState(self): - data = self.stream.char() - if data in spaceCharacters: - self.stream.charsUntil(spaceCharacters, True) - elif data == "\"": - self.state = self.attributeValueDoubleQuotedState - elif data == "&": - self.state = self.attributeValueUnQuotedState - self.stream.unget(data) - elif data == "'": - self.state = self.attributeValueSingleQuotedState - elif data == ">": - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "expected-attribute-value-but-got-right-bracket"}) - self.emitCurrentToken() - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["data"][-1][1] += "\uFFFD" - self.state = self.attributeValueUnQuotedState - elif data in ("=", "<", "`"): - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "equals-in-unquoted-attribute-value"}) - self.currentToken["data"][-1][1] += data - self.state = self.attributeValueUnQuotedState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "expected-attribute-value-but-got-eof"}) - self.state = self.dataState - else: - self.currentToken["data"][-1][1] += data - self.state = self.attributeValueUnQuotedState - return True - - def attributeValueDoubleQuotedState(self): - data = self.stream.char() - if data == "\"": - self.state = self.afterAttributeValueState - elif data == "&": - self.processEntityInAttribute('"') - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["data"][-1][1] += "\uFFFD" - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-attribute-value-double-quote"}) - self.state = self.dataState - else: - self.currentToken["data"][-1][1] += data +\ - self.stream.charsUntil(("\"", "&", "\u0000")) - return True - - def attributeValueSingleQuotedState(self): - data = self.stream.char() - if data == "'": - self.state = self.afterAttributeValueState - elif data == "&": - self.processEntityInAttribute("'") - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["data"][-1][1] += "\uFFFD" - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-attribute-value-single-quote"}) - self.state = self.dataState - else: - self.currentToken["data"][-1][1] += data +\ - self.stream.charsUntil(("'", "&", "\u0000")) - return True - - def attributeValueUnQuotedState(self): - data = self.stream.char() - if data in spaceCharacters: - self.state = self.beforeAttributeNameState - elif data == "&": - self.processEntityInAttribute(">") - elif data == ">": - self.emitCurrentToken() - elif data in ('"', "'", "=", "<", "`"): - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-character-in-unquoted-attribute-value"}) - self.currentToken["data"][-1][1] += data - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["data"][-1][1] += "\uFFFD" - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-attribute-value-no-quotes"}) - self.state = self.dataState - else: - self.currentToken["data"][-1][1] += data + self.stream.charsUntil( - frozenset(("&", ">", '"', "'", "=", "<", "`", "\u0000")) | spaceCharacters) - return True - - def afterAttributeValueState(self): - data = self.stream.char() - if data in spaceCharacters: - self.state = self.beforeAttributeNameState - elif data == ">": - self.emitCurrentToken() - elif data == "/": - self.state = self.selfClosingStartTagState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-EOF-after-attribute-value"}) - self.stream.unget(data) - self.state = self.dataState - else: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-character-after-attribute-value"}) - self.stream.unget(data) - self.state = self.beforeAttributeNameState - return True - - def selfClosingStartTagState(self): - data = self.stream.char() - if data == ">": - self.currentToken["selfClosing"] = True - self.emitCurrentToken() - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": - "unexpected-EOF-after-solidus-in-tag"}) - self.stream.unget(data) - self.state = self.dataState - else: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-character-after-solidus-in-tag"}) - self.stream.unget(data) - self.state = self.beforeAttributeNameState - return True - - def bogusCommentState(self): - # Make a new comment token and give it as value all the characters - # until the first > or EOF (charsUntil checks for EOF automatically) - # and emit it. - data = self.stream.charsUntil(">") - data = data.replace("\u0000", "\uFFFD") - self.tokenQueue.append( - {"type": tokenTypes["Comment"], "data": data}) - - # Eat the character directly after the bogus comment which is either a - # ">" or an EOF. - self.stream.char() - self.state = self.dataState - return True - - def markupDeclarationOpenState(self): - charStack = [self.stream.char()] - if charStack[-1] == "-": - charStack.append(self.stream.char()) - if charStack[-1] == "-": - self.currentToken = {"type": tokenTypes["Comment"], "data": ""} - self.state = self.commentStartState - return True - elif charStack[-1] in ('d', 'D'): - matched = True - for expected in (('o', 'O'), ('c', 'C'), ('t', 'T'), - ('y', 'Y'), ('p', 'P'), ('e', 'E')): - charStack.append(self.stream.char()) - if charStack[-1] not in expected: - matched = False - break - if matched: - self.currentToken = {"type": tokenTypes["Doctype"], - "name": "", - "publicId": None, "systemId": None, - "correct": True} - self.state = self.doctypeState - return True - elif (charStack[-1] == "[" and - self.parser is not None and - self.parser.tree.openElements and - self.parser.tree.openElements[-1].namespace != self.parser.tree.defaultNamespace): - matched = True - for expected in ["C", "D", "A", "T", "A", "["]: - charStack.append(self.stream.char()) - if charStack[-1] != expected: - matched = False - break - if matched: - self.state = self.cdataSectionState - return True - - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "expected-dashes-or-doctype"}) - - while charStack: - self.stream.unget(charStack.pop()) - self.state = self.bogusCommentState - return True - - def commentStartState(self): - data = self.stream.char() - if data == "-": - self.state = self.commentStartDashState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["data"] += "\uFFFD" - elif data == ">": - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "incorrect-comment"}) - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-comment"}) - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.currentToken["data"] += data - self.state = self.commentState - return True - - def commentStartDashState(self): - data = self.stream.char() - if data == "-": - self.state = self.commentEndState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["data"] += "-\uFFFD" - elif data == ">": - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "incorrect-comment"}) - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-comment"}) - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.currentToken["data"] += "-" + data - self.state = self.commentState - return True - - def commentState(self): - data = self.stream.char() - if data == "-": - self.state = self.commentEndDashState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["data"] += "\uFFFD" - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "eof-in-comment"}) - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.currentToken["data"] += data + \ - self.stream.charsUntil(("-", "\u0000")) - return True - - def commentEndDashState(self): - data = self.stream.char() - if data == "-": - self.state = self.commentEndState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["data"] += "-\uFFFD" - self.state = self.commentState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-comment-end-dash"}) - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.currentToken["data"] += "-" + data - self.state = self.commentState - return True - - def commentEndState(self): - data = self.stream.char() - if data == ">": - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["data"] += "--\uFFFD" - self.state = self.commentState - elif data == "!": - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-bang-after-double-dash-in-comment"}) - self.state = self.commentEndBangState - elif data == "-": - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-dash-after-double-dash-in-comment"}) - self.currentToken["data"] += data - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-comment-double-dash"}) - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - # XXX - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-char-in-comment"}) - self.currentToken["data"] += "--" + data - self.state = self.commentState - return True - - def commentEndBangState(self): - data = self.stream.char() - if data == ">": - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - elif data == "-": - self.currentToken["data"] += "--!" - self.state = self.commentEndDashState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["data"] += "--!\uFFFD" - self.state = self.commentState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-comment-end-bang-state"}) - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.currentToken["data"] += "--!" + data - self.state = self.commentState - return True - - def doctypeState(self): - data = self.stream.char() - if data in spaceCharacters: - self.state = self.beforeDoctypeNameState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "expected-doctype-name-but-got-eof"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "need-space-after-doctype"}) - self.stream.unget(data) - self.state = self.beforeDoctypeNameState - return True - - def beforeDoctypeNameState(self): - data = self.stream.char() - if data in spaceCharacters: - pass - elif data == ">": - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "expected-doctype-name-but-got-right-bracket"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["name"] = "\uFFFD" - self.state = self.doctypeNameState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "expected-doctype-name-but-got-eof"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.currentToken["name"] = data - self.state = self.doctypeNameState - return True - - def doctypeNameState(self): - data = self.stream.char() - if data in spaceCharacters: - self.currentToken["name"] = self.currentToken["name"].translate(asciiUpper2Lower) - self.state = self.afterDoctypeNameState - elif data == ">": - self.currentToken["name"] = self.currentToken["name"].translate(asciiUpper2Lower) - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["name"] += "\uFFFD" - self.state = self.doctypeNameState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-doctype-name"}) - self.currentToken["correct"] = False - self.currentToken["name"] = self.currentToken["name"].translate(asciiUpper2Lower) - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.currentToken["name"] += data - return True - - def afterDoctypeNameState(self): - data = self.stream.char() - if data in spaceCharacters: - pass - elif data == ">": - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - elif data is EOF: - self.currentToken["correct"] = False - self.stream.unget(data) - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-doctype"}) - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - if data in ("p", "P"): - matched = True - for expected in (("u", "U"), ("b", "B"), ("l", "L"), - ("i", "I"), ("c", "C")): - data = self.stream.char() - if data not in expected: - matched = False - break - if matched: - self.state = self.afterDoctypePublicKeywordState - return True - elif data in ("s", "S"): - matched = True - for expected in (("y", "Y"), ("s", "S"), ("t", "T"), - ("e", "E"), ("m", "M")): - data = self.stream.char() - if data not in expected: - matched = False - break - if matched: - self.state = self.afterDoctypeSystemKeywordState - return True - - # All the characters read before the current 'data' will be - # [a-zA-Z], so they're garbage in the bogus doctype and can be - # discarded; only the latest character might be '>' or EOF - # and needs to be ungetted - self.stream.unget(data) - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "expected-space-or-right-bracket-in-doctype", "datavars": - {"data": data}}) - self.currentToken["correct"] = False - self.state = self.bogusDoctypeState - - return True - - def afterDoctypePublicKeywordState(self): - data = self.stream.char() - if data in spaceCharacters: - self.state = self.beforeDoctypePublicIdentifierState - elif data in ("'", '"'): - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-char-in-doctype"}) - self.stream.unget(data) - self.state = self.beforeDoctypePublicIdentifierState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-doctype"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.stream.unget(data) - self.state = self.beforeDoctypePublicIdentifierState - return True - - def beforeDoctypePublicIdentifierState(self): - data = self.stream.char() - if data in spaceCharacters: - pass - elif data == "\"": - self.currentToken["publicId"] = "" - self.state = self.doctypePublicIdentifierDoubleQuotedState - elif data == "'": - self.currentToken["publicId"] = "" - self.state = self.doctypePublicIdentifierSingleQuotedState - elif data == ">": - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-end-of-doctype"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-doctype"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-char-in-doctype"}) - self.currentToken["correct"] = False - self.state = self.bogusDoctypeState - return True - - def doctypePublicIdentifierDoubleQuotedState(self): - data = self.stream.char() - if data == "\"": - self.state = self.afterDoctypePublicIdentifierState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["publicId"] += "\uFFFD" - elif data == ">": - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-end-of-doctype"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-doctype"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.currentToken["publicId"] += data - return True - - def doctypePublicIdentifierSingleQuotedState(self): - data = self.stream.char() - if data == "'": - self.state = self.afterDoctypePublicIdentifierState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["publicId"] += "\uFFFD" - elif data == ">": - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-end-of-doctype"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-doctype"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.currentToken["publicId"] += data - return True - - def afterDoctypePublicIdentifierState(self): - data = self.stream.char() - if data in spaceCharacters: - self.state = self.betweenDoctypePublicAndSystemIdentifiersState - elif data == ">": - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - elif data == '"': - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-char-in-doctype"}) - self.currentToken["systemId"] = "" - self.state = self.doctypeSystemIdentifierDoubleQuotedState - elif data == "'": - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-char-in-doctype"}) - self.currentToken["systemId"] = "" - self.state = self.doctypeSystemIdentifierSingleQuotedState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-doctype"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-char-in-doctype"}) - self.currentToken["correct"] = False - self.state = self.bogusDoctypeState - return True - - def betweenDoctypePublicAndSystemIdentifiersState(self): - data = self.stream.char() - if data in spaceCharacters: - pass - elif data == ">": - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - elif data == '"': - self.currentToken["systemId"] = "" - self.state = self.doctypeSystemIdentifierDoubleQuotedState - elif data == "'": - self.currentToken["systemId"] = "" - self.state = self.doctypeSystemIdentifierSingleQuotedState - elif data == EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-doctype"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-char-in-doctype"}) - self.currentToken["correct"] = False - self.state = self.bogusDoctypeState - return True - - def afterDoctypeSystemKeywordState(self): - data = self.stream.char() - if data in spaceCharacters: - self.state = self.beforeDoctypeSystemIdentifierState - elif data in ("'", '"'): - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-char-in-doctype"}) - self.stream.unget(data) - self.state = self.beforeDoctypeSystemIdentifierState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-doctype"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.stream.unget(data) - self.state = self.beforeDoctypeSystemIdentifierState - return True - - def beforeDoctypeSystemIdentifierState(self): - data = self.stream.char() - if data in spaceCharacters: - pass - elif data == "\"": - self.currentToken["systemId"] = "" - self.state = self.doctypeSystemIdentifierDoubleQuotedState - elif data == "'": - self.currentToken["systemId"] = "" - self.state = self.doctypeSystemIdentifierSingleQuotedState - elif data == ">": - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-char-in-doctype"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-doctype"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-char-in-doctype"}) - self.currentToken["correct"] = False - self.state = self.bogusDoctypeState - return True - - def doctypeSystemIdentifierDoubleQuotedState(self): - data = self.stream.char() - if data == "\"": - self.state = self.afterDoctypeSystemIdentifierState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["systemId"] += "\uFFFD" - elif data == ">": - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-end-of-doctype"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-doctype"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.currentToken["systemId"] += data - return True - - def doctypeSystemIdentifierSingleQuotedState(self): - data = self.stream.char() - if data == "'": - self.state = self.afterDoctypeSystemIdentifierState - elif data == "\u0000": - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - self.currentToken["systemId"] += "\uFFFD" - elif data == ">": - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-end-of-doctype"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-doctype"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.currentToken["systemId"] += data - return True - - def afterDoctypeSystemIdentifierState(self): - data = self.stream.char() - if data in spaceCharacters: - pass - elif data == ">": - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - elif data is EOF: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "eof-in-doctype"}) - self.currentToken["correct"] = False - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": - "unexpected-char-in-doctype"}) - self.state = self.bogusDoctypeState - return True - - def bogusDoctypeState(self): - data = self.stream.char() - if data == ">": - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - elif data is EOF: - # XXX EMIT - self.stream.unget(data) - self.tokenQueue.append(self.currentToken) - self.state = self.dataState - else: - pass - return True - - def cdataSectionState(self): - data = [] - while True: - data.append(self.stream.charsUntil("]")) - data.append(self.stream.charsUntil(">")) - char = self.stream.char() - if char == EOF: - break - else: - assert char == ">" - if data[-1][-2:] == "]]": - data[-1] = data[-1][:-2] - break - else: - data.append(char) - - data = "".join(data) # pylint:disable=redefined-variable-type - # Deal with null here rather than in the parser - nullCount = data.count("\u0000") - if nullCount > 0: - for _ in range(nullCount): - self.tokenQueue.append({"type": tokenTypes["ParseError"], - "data": "invalid-codepoint"}) - data = data.replace("\u0000", "\uFFFD") - if data: - self.tokenQueue.append({"type": tokenTypes["Characters"], - "data": data}) - self.state = self.dataState - return True diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_trie/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_trie/__init__.py deleted file mode 100644 index a5ba4bf..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_trie/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from .py import Trie as PyTrie - -Trie = PyTrie - -# pylint:disable=wrong-import-position -try: - from .datrie import Trie as DATrie -except ImportError: - pass -else: - Trie = DATrie -# pylint:enable=wrong-import-position diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_trie/_base.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_trie/_base.py deleted file mode 100644 index a1158bb..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_trie/_base.py +++ /dev/null @@ -1,37 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from collections import Mapping - - -class Trie(Mapping): - """Abstract base class for tries""" - - def keys(self, prefix=None): - # pylint:disable=arguments-differ - keys = super(Trie, self).keys() - - if prefix is None: - return set(keys) - - return {x for x in keys if x.startswith(prefix)} - - def has_keys_with_prefix(self, prefix): - for key in self.keys(): - if key.startswith(prefix): - return True - - return False - - def longest_prefix(self, prefix): - if prefix in self: - return prefix - - for i in range(1, len(prefix) + 1): - if prefix[:-i] in self: - return prefix[:-i] - - raise KeyError(prefix) - - def longest_prefix_item(self, prefix): - lprefix = self.longest_prefix(prefix) - return (lprefix, self[lprefix]) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_trie/datrie.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_trie/datrie.py deleted file mode 100644 index e2e5f86..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_trie/datrie.py +++ /dev/null @@ -1,44 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from datrie import Trie as DATrie -from pip._vendor.six import text_type - -from ._base import Trie as ABCTrie - - -class Trie(ABCTrie): - def __init__(self, data): - chars = set() - for key in data.keys(): - if not isinstance(key, text_type): - raise TypeError("All keys must be strings") - for char in key: - chars.add(char) - - self._data = DATrie("".join(chars)) - for key, value in data.items(): - self._data[key] = value - - def __contains__(self, key): - return key in self._data - - def __len__(self): - return len(self._data) - - def __iter__(self): - raise NotImplementedError() - - def __getitem__(self, key): - return self._data[key] - - def keys(self, prefix=None): - return self._data.keys(prefix) - - def has_keys_with_prefix(self, prefix): - return self._data.has_keys_with_prefix(prefix) - - def longest_prefix(self, prefix): - return self._data.longest_prefix(prefix) - - def longest_prefix_item(self, prefix): - return self._data.longest_prefix_item(prefix) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_trie/py.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_trie/py.py deleted file mode 100644 index c178b21..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_trie/py.py +++ /dev/null @@ -1,67 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals -from pip._vendor.six import text_type - -from bisect import bisect_left - -from ._base import Trie as ABCTrie - - -class Trie(ABCTrie): - def __init__(self, data): - if not all(isinstance(x, text_type) for x in data.keys()): - raise TypeError("All keys must be strings") - - self._data = data - self._keys = sorted(data.keys()) - self._cachestr = "" - self._cachepoints = (0, len(data)) - - def __contains__(self, key): - return key in self._data - - def __len__(self): - return len(self._data) - - def __iter__(self): - return iter(self._data) - - def __getitem__(self, key): - return self._data[key] - - def keys(self, prefix=None): - if prefix is None or prefix == "" or not self._keys: - return set(self._keys) - - if prefix.startswith(self._cachestr): - lo, hi = self._cachepoints - start = i = bisect_left(self._keys, prefix, lo, hi) - else: - start = i = bisect_left(self._keys, prefix) - - keys = set() - if start == len(self._keys): - return keys - - while self._keys[i].startswith(prefix): - keys.add(self._keys[i]) - i += 1 - - self._cachestr = prefix - self._cachepoints = (start, i) - - return keys - - def has_keys_with_prefix(self, prefix): - if prefix in self._data: - return True - - if prefix.startswith(self._cachestr): - lo, hi = self._cachepoints - i = bisect_left(self._keys, prefix, lo, hi) - else: - i = bisect_left(self._keys, prefix) - - if i == len(self._keys): - return False - - return self._keys[i].startswith(prefix) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_utils.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_utils.py deleted file mode 100644 index 0703afb..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/_utils.py +++ /dev/null @@ -1,124 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from types import ModuleType - -from pip._vendor.six import text_type - -try: - import xml.etree.cElementTree as default_etree -except ImportError: - import xml.etree.ElementTree as default_etree - - -__all__ = ["default_etree", "MethodDispatcher", "isSurrogatePair", - "surrogatePairToCodepoint", "moduleFactoryFactory", - "supports_lone_surrogates"] - - -# Platforms not supporting lone surrogates (\uD800-\uDFFF) should be -# caught by the below test. In general this would be any platform -# using UTF-16 as its encoding of unicode strings, such as -# Jython. This is because UTF-16 itself is based on the use of such -# surrogates, and there is no mechanism to further escape such -# escapes. -try: - _x = eval('"\\uD800"') # pylint:disable=eval-used - if not isinstance(_x, text_type): - # We need this with u"" because of http://bugs.jython.org/issue2039 - _x = eval('u"\\uD800"') # pylint:disable=eval-used - assert isinstance(_x, text_type) -except: # pylint:disable=bare-except - supports_lone_surrogates = False -else: - supports_lone_surrogates = True - - -class MethodDispatcher(dict): - """Dict with 2 special properties: - - On initiation, keys that are lists, sets or tuples are converted to - multiple keys so accessing any one of the items in the original - list-like object returns the matching value - - md = MethodDispatcher({("foo", "bar"):"baz"}) - md["foo"] == "baz" - - A default value which can be set through the default attribute. - """ - - def __init__(self, items=()): - # Using _dictEntries instead of directly assigning to self is about - # twice as fast. Please do careful performance testing before changing - # anything here. - _dictEntries = [] - for name, value in items: - if isinstance(name, (list, tuple, frozenset, set)): - for item in name: - _dictEntries.append((item, value)) - else: - _dictEntries.append((name, value)) - dict.__init__(self, _dictEntries) - assert len(self) == len(_dictEntries) - self.default = None - - def __getitem__(self, key): - return dict.get(self, key, self.default) - - -# Some utility functions to deal with weirdness around UCS2 vs UCS4 -# python builds - -def isSurrogatePair(data): - return (len(data) == 2 and - ord(data[0]) >= 0xD800 and ord(data[0]) <= 0xDBFF and - ord(data[1]) >= 0xDC00 and ord(data[1]) <= 0xDFFF) - - -def surrogatePairToCodepoint(data): - char_val = (0x10000 + (ord(data[0]) - 0xD800) * 0x400 + - (ord(data[1]) - 0xDC00)) - return char_val - -# Module Factory Factory (no, this isn't Java, I know) -# Here to stop this being duplicated all over the place. - - -def moduleFactoryFactory(factory): - moduleCache = {} - - def moduleFactory(baseModule, *args, **kwargs): - if isinstance(ModuleType.__name__, type("")): - name = "_%s_factory" % baseModule.__name__ - else: - name = b"_%s_factory" % baseModule.__name__ - - kwargs_tuple = tuple(kwargs.items()) - - try: - return moduleCache[name][args][kwargs_tuple] - except KeyError: - mod = ModuleType(name) - objs = factory(baseModule, *args, **kwargs) - mod.__dict__.update(objs) - if "name" not in moduleCache: - moduleCache[name] = {} - if "args" not in moduleCache[name]: - moduleCache[name][args] = {} - if "kwargs" not in moduleCache[name][args]: - moduleCache[name][args][kwargs_tuple] = {} - moduleCache[name][args][kwargs_tuple] = mod - return mod - - return moduleFactory - - -def memoize(func): - cache = {} - - def wrapped(*args, **kwargs): - key = (tuple(args), tuple(kwargs.items())) - if key not in cache: - cache[key] = func(*args, **kwargs) - return cache[key] - - return wrapped diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/constants.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/constants.py deleted file mode 100644 index 1ff8041..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/constants.py +++ /dev/null @@ -1,2947 +0,0 @@ -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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py deleted file mode 100644 index 5ba926e..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py +++ /dev/null @@ -1,29 +0,0 @@ -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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/base.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/base.py deleted file mode 100644 index c7dbaed..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/base.py +++ /dev/null @@ -1,12 +0,0 @@ -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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py deleted file mode 100644 index aefb5c8..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py +++ /dev/null @@ -1,73 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from . import base - - -class Filter(base.Filter): - """Injects ``<meta charset=ENCODING>`` 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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/lint.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/lint.py deleted file mode 100644 index fcc07ee..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/lint.py +++ /dev/null @@ -1,93 +0,0 @@ -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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/optionaltags.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/optionaltags.py deleted file mode 100644 index 4a86501..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/optionaltags.py +++ /dev/null @@ -1,207 +0,0 @@ -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 <code>optgroup</code> - # 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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/sanitizer.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/sanitizer.py deleted file mode 100644 index af8e77b..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/sanitizer.py +++ /dev/null @@ -1,896 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -import re -from xml.sax.saxutils import escape, unescape - -from pip._vendor.six.moves import urllib_parse as urlparse - -from . import base -from ..constants import namespaces, prefixes - -__all__ = ["Filter"] - - -allowed_elements = frozenset(( - (namespaces['html'], 'a'), - (namespaces['html'], 'abbr'), - (namespaces['html'], 'acronym'), - (namespaces['html'], 'address'), - (namespaces['html'], 'area'), - (namespaces['html'], 'article'), - (namespaces['html'], 'aside'), - (namespaces['html'], 'audio'), - (namespaces['html'], 'b'), - (namespaces['html'], 'big'), - (namespaces['html'], 'blockquote'), - (namespaces['html'], 'br'), - (namespaces['html'], 'button'), - (namespaces['html'], 'canvas'), - (namespaces['html'], 'caption'), - (namespaces['html'], 'center'), - (namespaces['html'], 'cite'), - (namespaces['html'], 'code'), - (namespaces['html'], 'col'), - (namespaces['html'], 'colgroup'), - (namespaces['html'], 'command'), - (namespaces['html'], 'datagrid'), - (namespaces['html'], 'datalist'), - (namespaces['html'], 'dd'), - (namespaces['html'], 'del'), - (namespaces['html'], 'details'), - (namespaces['html'], 'dfn'), - (namespaces['html'], 'dialog'), - (namespaces['html'], 'dir'), - (namespaces['html'], 'div'), - (namespaces['html'], 'dl'), - (namespaces['html'], 'dt'), - (namespaces['html'], 'em'), - (namespaces['html'], 'event-source'), - (namespaces['html'], 'fieldset'), - (namespaces['html'], 'figcaption'), - (namespaces['html'], 'figure'), - (namespaces['html'], 'footer'), - (namespaces['html'], 'font'), - (namespaces['html'], 'form'), - (namespaces['html'], 'header'), - (namespaces['html'], 'h1'), - (namespaces['html'], 'h2'), - (namespaces['html'], 'h3'), - (namespaces['html'], 'h4'), - (namespaces['html'], 'h5'), - (namespaces['html'], 'h6'), - (namespaces['html'], 'hr'), - (namespaces['html'], 'i'), - (namespaces['html'], 'img'), - (namespaces['html'], 'input'), - (namespaces['html'], 'ins'), - (namespaces['html'], 'keygen'), - (namespaces['html'], 'kbd'), - (namespaces['html'], 'label'), - (namespaces['html'], 'legend'), - (namespaces['html'], 'li'), - (namespaces['html'], 'm'), - (namespaces['html'], 'map'), - (namespaces['html'], 'menu'), - (namespaces['html'], 'meter'), - (namespaces['html'], 'multicol'), - (namespaces['html'], 'nav'), - (namespaces['html'], 'nextid'), - (namespaces['html'], 'ol'), - (namespaces['html'], 'output'), - (namespaces['html'], 'optgroup'), - (namespaces['html'], 'option'), - (namespaces['html'], 'p'), - (namespaces['html'], 'pre'), - (namespaces['html'], 'progress'), - (namespaces['html'], 'q'), - (namespaces['html'], 's'), - (namespaces['html'], 'samp'), - (namespaces['html'], 'section'), - (namespaces['html'], 'select'), - (namespaces['html'], 'small'), - (namespaces['html'], 'sound'), - (namespaces['html'], 'source'), - (namespaces['html'], 'spacer'), - (namespaces['html'], 'span'), - (namespaces['html'], 'strike'), - (namespaces['html'], 'strong'), - (namespaces['html'], 'sub'), - (namespaces['html'], 'sup'), - (namespaces['html'], 'table'), - (namespaces['html'], 'tbody'), - (namespaces['html'], 'td'), - (namespaces['html'], 'textarea'), - (namespaces['html'], 'time'), - (namespaces['html'], 'tfoot'), - (namespaces['html'], 'th'), - (namespaces['html'], 'thead'), - (namespaces['html'], 'tr'), - (namespaces['html'], 'tt'), - (namespaces['html'], 'u'), - (namespaces['html'], 'ul'), - (namespaces['html'], 'var'), - (namespaces['html'], 'video'), - (namespaces['mathml'], 'maction'), - (namespaces['mathml'], 'math'), - (namespaces['mathml'], 'merror'), - (namespaces['mathml'], 'mfrac'), - (namespaces['mathml'], 'mi'), - (namespaces['mathml'], 'mmultiscripts'), - (namespaces['mathml'], 'mn'), - (namespaces['mathml'], 'mo'), - (namespaces['mathml'], 'mover'), - (namespaces['mathml'], 'mpadded'), - (namespaces['mathml'], 'mphantom'), - (namespaces['mathml'], 'mprescripts'), - (namespaces['mathml'], 'mroot'), - (namespaces['mathml'], 'mrow'), - (namespaces['mathml'], 'mspace'), - (namespaces['mathml'], 'msqrt'), - (namespaces['mathml'], 'mstyle'), - (namespaces['mathml'], 'msub'), - (namespaces['mathml'], 'msubsup'), - (namespaces['mathml'], 'msup'), - (namespaces['mathml'], 'mtable'), - (namespaces['mathml'], 'mtd'), - (namespaces['mathml'], 'mtext'), - (namespaces['mathml'], 'mtr'), - (namespaces['mathml'], 'munder'), - (namespaces['mathml'], 'munderover'), - (namespaces['mathml'], 'none'), - (namespaces['svg'], 'a'), - (namespaces['svg'], 'animate'), - (namespaces['svg'], 'animateColor'), - (namespaces['svg'], 'animateMotion'), - (namespaces['svg'], 'animateTransform'), - (namespaces['svg'], 'clipPath'), - (namespaces['svg'], 'circle'), - (namespaces['svg'], 'defs'), - (namespaces['svg'], 'desc'), - (namespaces['svg'], 'ellipse'), - (namespaces['svg'], 'font-face'), - (namespaces['svg'], 'font-face-name'), - (namespaces['svg'], 'font-face-src'), - (namespaces['svg'], 'g'), - (namespaces['svg'], 'glyph'), - (namespaces['svg'], 'hkern'), - (namespaces['svg'], 'linearGradient'), - (namespaces['svg'], 'line'), - (namespaces['svg'], 'marker'), - (namespaces['svg'], 'metadata'), - (namespaces['svg'], 'missing-glyph'), - (namespaces['svg'], 'mpath'), - (namespaces['svg'], 'path'), - (namespaces['svg'], 'polygon'), - (namespaces['svg'], 'polyline'), - (namespaces['svg'], 'radialGradient'), - (namespaces['svg'], 'rect'), - (namespaces['svg'], 'set'), - (namespaces['svg'], 'stop'), - (namespaces['svg'], 'svg'), - (namespaces['svg'], 'switch'), - (namespaces['svg'], 'text'), - (namespaces['svg'], 'title'), - (namespaces['svg'], 'tspan'), - (namespaces['svg'], 'use'), -)) - -allowed_attributes = frozenset(( - # HTML attributes - (None, 'abbr'), - (None, 'accept'), - (None, 'accept-charset'), - (None, 'accesskey'), - (None, 'action'), - (None, 'align'), - (None, 'alt'), - (None, 'autocomplete'), - (None, 'autofocus'), - (None, 'axis'), - (None, 'background'), - (None, 'balance'), - (None, 'bgcolor'), - (None, 'bgproperties'), - (None, 'border'), - (None, 'bordercolor'), - (None, 'bordercolordark'), - (None, 'bordercolorlight'), - (None, 'bottompadding'), - (None, 'cellpadding'), - (None, 'cellspacing'), - (None, 'ch'), - (None, 'challenge'), - (None, 'char'), - (None, 'charoff'), - (None, 'choff'), - (None, 'charset'), - (None, 'checked'), - (None, 'cite'), - (None, 'class'), - (None, 'clear'), - (None, 'color'), - (None, 'cols'), - (None, 'colspan'), - (None, 'compact'), - (None, 'contenteditable'), - (None, 'controls'), - (None, 'coords'), - (None, 'data'), - (None, 'datafld'), - (None, 'datapagesize'), - (None, 'datasrc'), - (None, 'datetime'), - (None, 'default'), - (None, 'delay'), - (None, 'dir'), - (None, 'disabled'), - (None, 'draggable'), - (None, 'dynsrc'), - (None, 'enctype'), - (None, 'end'), - (None, 'face'), - (None, 'for'), - (None, 'form'), - (None, 'frame'), - (None, 'galleryimg'), - (None, 'gutter'), - (None, 'headers'), - (None, 'height'), - (None, 'hidefocus'), - (None, 'hidden'), - (None, 'high'), - (None, 'href'), - (None, 'hreflang'), - (None, 'hspace'), - (None, 'icon'), - (None, 'id'), - (None, 'inputmode'), - (None, 'ismap'), - (None, 'keytype'), - (None, 'label'), - (None, 'leftspacing'), - (None, 'lang'), - (None, 'list'), - (None, 'longdesc'), - (None, 'loop'), - (None, 'loopcount'), - (None, 'loopend'), - (None, 'loopstart'), - (None, 'low'), - (None, 'lowsrc'), - (None, 'max'), - (None, 'maxlength'), - (None, 'media'), - (None, 'method'), - (None, 'min'), - (None, 'multiple'), - (None, 'name'), - (None, 'nohref'), - (None, 'noshade'), - (None, 'nowrap'), - (None, 'open'), - (None, 'optimum'), - (None, 'pattern'), - (None, 'ping'), - (None, 'point-size'), - (None, 'poster'), - (None, 'pqg'), - (None, 'preload'), - (None, 'prompt'), - (None, 'radiogroup'), - (None, 'readonly'), - (None, 'rel'), - (None, 'repeat-max'), - (None, 'repeat-min'), - (None, 'replace'), - (None, 'required'), - (None, 'rev'), - (None, 'rightspacing'), - (None, 'rows'), - (None, 'rowspan'), - (None, 'rules'), - (None, 'scope'), - (None, 'selected'), - (None, 'shape'), - (None, 'size'), - (None, 'span'), - (None, 'src'), - (None, 'start'), - (None, 'step'), - (None, 'style'), - (None, 'summary'), - (None, 'suppress'), - (None, 'tabindex'), - (None, 'target'), - (None, 'template'), - (None, 'title'), - (None, 'toppadding'), - (None, 'type'), - (None, 'unselectable'), - (None, 'usemap'), - (None, 'urn'), - (None, 'valign'), - (None, 'value'), - (None, 'variable'), - (None, 'volume'), - (None, 'vspace'), - (None, 'vrml'), - (None, 'width'), - (None, 'wrap'), - (namespaces['xml'], 'lang'), - # MathML attributes - (None, 'actiontype'), - (None, 'align'), - (None, 'columnalign'), - (None, 'columnalign'), - (None, 'columnalign'), - (None, 'columnlines'), - (None, 'columnspacing'), - (None, 'columnspan'), - (None, 'depth'), - (None, 'display'), - (None, 'displaystyle'), - (None, 'equalcolumns'), - (None, 'equalrows'), - (None, 'fence'), - (None, 'fontstyle'), - (None, 'fontweight'), - (None, 'frame'), - (None, 'height'), - (None, 'linethickness'), - (None, 'lspace'), - (None, 'mathbackground'), - (None, 'mathcolor'), - (None, 'mathvariant'), - (None, 'mathvariant'), - (None, 'maxsize'), - (None, 'minsize'), - (None, 'other'), - (None, 'rowalign'), - (None, 'rowalign'), - (None, 'rowalign'), - (None, 'rowlines'), - (None, 'rowspacing'), - (None, 'rowspan'), - (None, 'rspace'), - (None, 'scriptlevel'), - (None, 'selection'), - (None, 'separator'), - (None, 'stretchy'), - (None, 'width'), - (None, 'width'), - (namespaces['xlink'], 'href'), - (namespaces['xlink'], 'show'), - (namespaces['xlink'], 'type'), - # SVG attributes - (None, 'accent-height'), - (None, 'accumulate'), - (None, 'additive'), - (None, 'alphabetic'), - (None, 'arabic-form'), - (None, 'ascent'), - (None, 'attributeName'), - (None, 'attributeType'), - (None, 'baseProfile'), - (None, 'bbox'), - (None, 'begin'), - (None, 'by'), - (None, 'calcMode'), - (None, 'cap-height'), - (None, 'class'), - (None, 'clip-path'), - (None, 'color'), - (None, 'color-rendering'), - (None, 'content'), - (None, 'cx'), - (None, 'cy'), - (None, 'd'), - (None, 'dx'), - (None, 'dy'), - (None, 'descent'), - (None, 'display'), - (None, 'dur'), - (None, 'end'), - (None, 'fill'), - (None, 'fill-opacity'), - (None, 'fill-rule'), - (None, 'font-family'), - (None, 'font-size'), - (None, 'font-stretch'), - (None, 'font-style'), - (None, 'font-variant'), - (None, 'font-weight'), - (None, 'from'), - (None, 'fx'), - (None, 'fy'), - (None, 'g1'), - (None, 'g2'), - (None, 'glyph-name'), - (None, 'gradientUnits'), - (None, 'hanging'), - (None, 'height'), - (None, 'horiz-adv-x'), - (None, 'horiz-origin-x'), - (None, 'id'), - (None, 'ideographic'), - (None, 'k'), - (None, 'keyPoints'), - (None, 'keySplines'), - (None, 'keyTimes'), - (None, 'lang'), - (None, 'marker-end'), - (None, 'marker-mid'), - (None, 'marker-start'), - (None, 'markerHeight'), - (None, 'markerUnits'), - (None, 'markerWidth'), - (None, 'mathematical'), - (None, 'max'), - (None, 'min'), - (None, 'name'), - (None, 'offset'), - (None, 'opacity'), - (None, 'orient'), - (None, 'origin'), - (None, 'overline-position'), - (None, 'overline-thickness'), - (None, 'panose-1'), - (None, 'path'), - (None, 'pathLength'), - (None, 'points'), - (None, 'preserveAspectRatio'), - (None, 'r'), - (None, 'refX'), - (None, 'refY'), - (None, 'repeatCount'), - (None, 'repeatDur'), - (None, 'requiredExtensions'), - (None, 'requiredFeatures'), - (None, 'restart'), - (None, 'rotate'), - (None, 'rx'), - (None, 'ry'), - (None, 'slope'), - (None, 'stemh'), - (None, 'stemv'), - (None, 'stop-color'), - (None, 'stop-opacity'), - (None, 'strikethrough-position'), - (None, 'strikethrough-thickness'), - (None, 'stroke'), - (None, 'stroke-dasharray'), - (None, 'stroke-dashoffset'), - (None, 'stroke-linecap'), - (None, 'stroke-linejoin'), - (None, 'stroke-miterlimit'), - (None, 'stroke-opacity'), - (None, 'stroke-width'), - (None, 'systemLanguage'), - (None, 'target'), - (None, 'text-anchor'), - (None, 'to'), - (None, 'transform'), - (None, 'type'), - (None, 'u1'), - (None, 'u2'), - (None, 'underline-position'), - (None, 'underline-thickness'), - (None, 'unicode'), - (None, 'unicode-range'), - (None, 'units-per-em'), - (None, 'values'), - (None, 'version'), - (None, 'viewBox'), - (None, 'visibility'), - (None, 'width'), - (None, 'widths'), - (None, 'x'), - (None, 'x-height'), - (None, 'x1'), - (None, 'x2'), - (namespaces['xlink'], 'actuate'), - (namespaces['xlink'], 'arcrole'), - (namespaces['xlink'], 'href'), - (namespaces['xlink'], 'role'), - (namespaces['xlink'], 'show'), - (namespaces['xlink'], 'title'), - (namespaces['xlink'], 'type'), - (namespaces['xml'], 'base'), - (namespaces['xml'], 'lang'), - (namespaces['xml'], 'space'), - (None, 'y'), - (None, 'y1'), - (None, 'y2'), - (None, 'zoomAndPan'), -)) - -attr_val_is_uri = frozenset(( - (None, 'href'), - (None, 'src'), - (None, 'cite'), - (None, 'action'), - (None, 'longdesc'), - (None, 'poster'), - (None, 'background'), - (None, 'datasrc'), - (None, 'dynsrc'), - (None, 'lowsrc'), - (None, 'ping'), - (namespaces['xlink'], 'href'), - (namespaces['xml'], 'base'), -)) - -svg_attr_val_allows_ref = frozenset(( - (None, 'clip-path'), - (None, 'color-profile'), - (None, 'cursor'), - (None, 'fill'), - (None, 'filter'), - (None, 'marker'), - (None, 'marker-start'), - (None, 'marker-mid'), - (None, 'marker-end'), - (None, 'mask'), - (None, 'stroke'), -)) - -svg_allow_local_href = frozenset(( - (None, 'altGlyph'), - (None, 'animate'), - (None, 'animateColor'), - (None, 'animateMotion'), - (None, 'animateTransform'), - (None, 'cursor'), - (None, 'feImage'), - (None, 'filter'), - (None, 'linearGradient'), - (None, 'pattern'), - (None, 'radialGradient'), - (None, 'textpath'), - (None, 'tref'), - (None, 'set'), - (None, 'use') -)) - -allowed_css_properties = frozenset(( - 'azimuth', - 'background-color', - 'border-bottom-color', - 'border-collapse', - 'border-color', - 'border-left-color', - 'border-right-color', - 'border-top-color', - 'clear', - 'color', - 'cursor', - 'direction', - 'display', - 'elevation', - 'float', - 'font', - 'font-family', - 'font-size', - 'font-style', - 'font-variant', - 'font-weight', - 'height', - 'letter-spacing', - 'line-height', - 'overflow', - 'pause', - 'pause-after', - 'pause-before', - 'pitch', - 'pitch-range', - 'richness', - 'speak', - 'speak-header', - 'speak-numeral', - 'speak-punctuation', - 'speech-rate', - 'stress', - 'text-align', - 'text-decoration', - 'text-indent', - 'unicode-bidi', - 'vertical-align', - 'voice-family', - 'volume', - 'white-space', - 'width', -)) - -allowed_css_keywords = frozenset(( - 'auto', - 'aqua', - 'black', - 'block', - 'blue', - 'bold', - 'both', - 'bottom', - 'brown', - 'center', - 'collapse', - 'dashed', - 'dotted', - 'fuchsia', - 'gray', - 'green', - '!important', - 'italic', - 'left', - 'lime', - 'maroon', - 'medium', - 'none', - 'navy', - 'normal', - 'nowrap', - 'olive', - 'pointer', - 'purple', - 'red', - 'right', - 'solid', - 'silver', - 'teal', - 'top', - 'transparent', - 'underline', - 'white', - 'yellow', -)) - -allowed_svg_properties = frozenset(( - 'fill', - 'fill-opacity', - 'fill-rule', - 'stroke', - 'stroke-width', - 'stroke-linecap', - 'stroke-linejoin', - 'stroke-opacity', -)) - -allowed_protocols = frozenset(( - 'ed2k', - 'ftp', - 'http', - 'https', - 'irc', - 'mailto', - 'news', - 'gopher', - 'nntp', - 'telnet', - 'webcal', - 'xmpp', - 'callto', - 'feed', - 'urn', - 'aim', - 'rsync', - 'tag', - 'ssh', - 'sftp', - 'rtsp', - 'afs', - 'data', -)) - -allowed_content_types = frozenset(( - 'image/png', - 'image/jpeg', - 'image/gif', - 'image/webp', - 'image/bmp', - 'text/plain', -)) - - -data_content_type = re.compile(r''' - ^ - # Match a content type <application>/<type> - (?P<content_type>[-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 - ,.* - $ - ''', - re.VERBOSE) - - -class Filter(base.Filter): - """Sanitizes token stream of XHTML+MathML+SVG and of inline style attributes""" - def __init__(self, - source, - allowed_elements=allowed_elements, - allowed_attributes=allowed_attributes, - allowed_css_properties=allowed_css_properties, - allowed_css_keywords=allowed_css_keywords, - allowed_svg_properties=allowed_svg_properties, - allowed_protocols=allowed_protocols, - allowed_content_types=allowed_content_types, - attr_val_is_uri=attr_val_is_uri, - svg_attr_val_allows_ref=svg_attr_val_allows_ref, - svg_allow_local_href=svg_allow_local_href): - """Creates 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 - - """ - super(Filter, self).__init__(source) - self.allowed_elements = allowed_elements - self.allowed_attributes = allowed_attributes - self.allowed_css_properties = allowed_css_properties - self.allowed_css_keywords = allowed_css_keywords - self.allowed_svg_properties = allowed_svg_properties - self.allowed_protocols = allowed_protocols - self.allowed_content_types = allowed_content_types - self.attr_val_is_uri = attr_val_is_uri - self.svg_attr_val_allows_ref = svg_attr_val_allows_ref - self.svg_allow_local_href = svg_allow_local_href - - def __iter__(self): - for token in base.Filter.__iter__(self): - token = self.sanitize_token(token) - if token: - yield token - - # Sanitize the +html+, escaping all elements not in ALLOWED_ELEMENTS, and - # stripping out all attributes not in ALLOWED_ATTRIBUTES. Style attributes - # are parsed, and a restricted set, specified by ALLOWED_CSS_PROPERTIES and - # ALLOWED_CSS_KEYWORDS, are allowed through. attributes in ATTR_VAL_IS_URI - # are scanned, and only URI schemes specified in ALLOWED_PROTOCOLS are - # allowed. - # - # sanitize_html('<script> do_nasty_stuff() </script>') - # => <script> do_nasty_stuff() </script> - # sanitize_html('<a href="javascript: sucker();">Click here for $100</a>') - # => <a>Click here for $100</a> - 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"] = "</%s>" % 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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/whitespace.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/whitespace.py deleted file mode 100644 index 0d12584..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/filters/whitespace.py +++ /dev/null @@ -1,38 +0,0 @@ -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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/html5parser.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/html5parser.py deleted file mode 100644 index ae41a13..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/html5parser.py +++ /dev/null @@ -1,2791 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals -from pip._vendor.six import with_metaclass, viewkeys - -import types -from collections import OrderedDict - -from . import _inputstream -from . import _tokenizer - -from . import treebuilders -from .treebuilders.base import Marker - -from . import _utils -from .constants import ( - spaceCharacters, asciiUpper2Lower, - specialElements, headingElements, cdataElements, rcdataElements, - tokenTypes, tagTokenTypes, - namespaces, - htmlIntegrationPointElements, mathmlTextIntegrationPointElements, - adjustForeignAttributes as adjustForeignAttributesMap, - adjustMathMLAttributes, adjustSVGAttributes, - E, - _ReparseException -) - - -def parse(doc, treebuilder="etree", namespaceHTMLElements=True, **kwargs): - """Parse an HTML document as a string or file-like object into a tree - - :arg doc: the document to parse as a string or file-like object - - :arg treebuilder: the treebuilder to use when parsing - - :arg namespaceHTMLElements: whether or not to namespace HTML elements - - :returns: parsed tree - - Example: - - >>> from html5lib.html5parser import parse - >>> parse('<html><body><p>This is a doc</p></body></html>') - <Element u'{http://www.w3.org/1999/xhtml}html' at 0x7feac4909db0> - - """ - tb = treebuilders.getTreeBuilder(treebuilder) - p = HTMLParser(tb, namespaceHTMLElements=namespaceHTMLElements) - return p.parse(doc, **kwargs) - - -def parseFragment(doc, container="div", treebuilder="etree", namespaceHTMLElements=True, **kwargs): - """Parse an HTML fragment as a string or file-like object into a tree - - :arg doc: the fragment to parse as a string or file-like object - - :arg container: the container context to parse the fragment in - - :arg treebuilder: the treebuilder to use when parsing - - :arg namespaceHTMLElements: whether or not to namespace HTML elements - - :returns: parsed tree - - Example: - - >>> from html5lib.html5libparser import parseFragment - >>> parseFragment('<b>this is a fragment</b>') - <Element u'DOCUMENT_FRAGMENT' at 0x7feac484b090> - - """ - tb = treebuilders.getTreeBuilder(treebuilder) - p = HTMLParser(tb, namespaceHTMLElements=namespaceHTMLElements) - return p.parseFragment(doc, container=container, **kwargs) - - -def method_decorator_metaclass(function): - class Decorated(type): - def __new__(meta, classname, bases, classDict): - for attributeName, attribute in classDict.items(): - if isinstance(attribute, types.FunctionType): - attribute = function(attribute) - - classDict[attributeName] = attribute - return type.__new__(meta, classname, bases, classDict) - return Decorated - - -class HTMLParser(object): - """HTML parser - - Generates a tree structure from a stream of (possibly malformed) HTML. - - """ - - def __init__(self, tree=None, strict=False, namespaceHTMLElements=True, debug=False): - """ - :arg tree: a treebuilder class controlling the type of tree that will be - returned. Built in treebuilders can be accessed through - html5lib.treebuilders.getTreeBuilder(treeType) - - :arg strict: raise an exception when a parse error is encountered - - :arg namespaceHTMLElements: whether or not to namespace HTML elements - - :arg debug: whether or not to enable debug mode which logs things - - Example: - - >>> from html5lib.html5parser import HTMLParser - >>> parser = HTMLParser() # generates parser with etree builder - >>> parser = HTMLParser('lxml', strict=True) # generates parser with lxml builder which is strict - - """ - - # Raise an exception on the first error encountered - self.strict = strict - - if tree is None: - tree = treebuilders.getTreeBuilder("etree") - self.tree = tree(namespaceHTMLElements) - self.errors = [] - - self.phases = dict([(name, cls(self, self.tree)) for name, cls in - getPhases(debug).items()]) - - def _parse(self, stream, innerHTML=False, container="div", scripting=False, **kwargs): - - self.innerHTMLMode = innerHTML - self.container = container - self.scripting = scripting - self.tokenizer = _tokenizer.HTMLTokenizer(stream, parser=self, **kwargs) - self.reset() - - try: - self.mainLoop() - except _ReparseException: - self.reset() - self.mainLoop() - - def reset(self): - self.tree.reset() - self.firstStartTag = False - self.errors = [] - self.log = [] # only used with debug mode - # "quirks" / "limited quirks" / "no quirks" - self.compatMode = "no quirks" - - if self.innerHTMLMode: - self.innerHTML = self.container.lower() - - if self.innerHTML in cdataElements: - self.tokenizer.state = self.tokenizer.rcdataState - elif self.innerHTML in rcdataElements: - self.tokenizer.state = self.tokenizer.rawtextState - elif self.innerHTML == 'plaintext': - self.tokenizer.state = self.tokenizer.plaintextState - else: - # state already is data state - # self.tokenizer.state = self.tokenizer.dataState - pass - self.phase = self.phases["beforeHtml"] - self.phase.insertHtmlElement() - self.resetInsertionMode() - else: - self.innerHTML = False # pylint:disable=redefined-variable-type - self.phase = self.phases["initial"] - - self.lastPhase = None - - self.beforeRCDataPhase = None - - self.framesetOK = True - - @property - def documentEncoding(self): - """Name of the character encoding that was used to decode the input stream, or - :obj:`None` if that is not determined yet - - """ - if not hasattr(self, 'tokenizer'): - return None - return self.tokenizer.stream.charEncoding[0].name - - def isHTMLIntegrationPoint(self, element): - if (element.name == "annotation-xml" and - element.namespace == namespaces["mathml"]): - return ("encoding" in element.attributes and - element.attributes["encoding"].translate( - asciiUpper2Lower) in - ("text/html", "application/xhtml+xml")) - else: - return (element.namespace, element.name) in htmlIntegrationPointElements - - def isMathMLTextIntegrationPoint(self, element): - return (element.namespace, element.name) in mathmlTextIntegrationPointElements - - def mainLoop(self): - CharactersToken = tokenTypes["Characters"] - SpaceCharactersToken = tokenTypes["SpaceCharacters"] - StartTagToken = tokenTypes["StartTag"] - EndTagToken = tokenTypes["EndTag"] - CommentToken = tokenTypes["Comment"] - DoctypeToken = tokenTypes["Doctype"] - ParseErrorToken = tokenTypes["ParseError"] - - for token in self.normalizedTokens(): - prev_token = None - new_token = token - while new_token is not None: - prev_token = new_token - currentNode = self.tree.openElements[-1] if self.tree.openElements else None - currentNodeNamespace = currentNode.namespace if currentNode else None - currentNodeName = currentNode.name if currentNode else None - - type = new_token["type"] - - if type == ParseErrorToken: - self.parseError(new_token["data"], new_token.get("datavars", {})) - new_token = None - else: - if (len(self.tree.openElements) == 0 or - currentNodeNamespace == self.tree.defaultNamespace or - (self.isMathMLTextIntegrationPoint(currentNode) and - ((type == StartTagToken and - token["name"] not in frozenset(["mglyph", "malignmark"])) or - type in (CharactersToken, SpaceCharactersToken))) or - (currentNodeNamespace == namespaces["mathml"] and - currentNodeName == "annotation-xml" and - type == StartTagToken and - token["name"] == "svg") or - (self.isHTMLIntegrationPoint(currentNode) and - type in (StartTagToken, CharactersToken, SpaceCharactersToken))): - phase = self.phase - else: - phase = self.phases["inForeignContent"] - - if type == CharactersToken: - new_token = phase.processCharacters(new_token) - elif type == SpaceCharactersToken: - new_token = phase.processSpaceCharacters(new_token) - elif type == StartTagToken: - new_token = phase.processStartTag(new_token) - elif type == EndTagToken: - new_token = phase.processEndTag(new_token) - elif type == CommentToken: - new_token = phase.processComment(new_token) - elif type == DoctypeToken: - new_token = phase.processDoctype(new_token) - - if (type == StartTagToken and prev_token["selfClosing"] and - not prev_token["selfClosingAcknowledged"]): - self.parseError("non-void-element-with-trailing-solidus", - {"name": prev_token["name"]}) - - # When the loop finishes it's EOF - reprocess = True - phases = [] - while reprocess: - phases.append(self.phase) - reprocess = self.phase.processEOF() - if reprocess: - assert self.phase not in phases - - def normalizedTokens(self): - for token in self.tokenizer: - yield self.normalizeToken(token) - - def parse(self, stream, *args, **kwargs): - """Parse a HTML document into a well-formed tree - - :arg stream: a file-like object or string containing the HTML to be parsed - - The optional encoding parameter must be a string that indicates - the encoding. If specified, that encoding will be used, - regardless of any BOM or later declaration (such as in a meta - element). - - :arg scripting: treat noscript elements as if JavaScript was turned on - - :returns: parsed tree - - Example: - - >>> from html5lib.html5parser import HTMLParser - >>> parser = HTMLParser() - >>> parser.parse('<html><body><p>This is a doc</p></body></html>') - <Element u'{http://www.w3.org/1999/xhtml}html' at 0x7feac4909db0> - - """ - self._parse(stream, False, None, *args, **kwargs) - return self.tree.getDocument() - - def parseFragment(self, stream, *args, **kwargs): - """Parse a HTML fragment into a well-formed tree fragment - - :arg container: name of the element we're setting the innerHTML - property if set to None, default to 'div' - - :arg stream: a file-like object or string containing the HTML to be parsed - - The optional encoding parameter must be a string that indicates - the encoding. If specified, that encoding will be used, - regardless of any BOM or later declaration (such as in a meta - element) - - :arg scripting: treat noscript elements as if JavaScript was turned on - - :returns: parsed tree - - Example: - - >>> from html5lib.html5libparser import HTMLParser - >>> parser = HTMLParser() - >>> parser.parseFragment('<b>this is a fragment</b>') - <Element u'DOCUMENT_FRAGMENT' at 0x7feac484b090> - - """ - self._parse(stream, True, *args, **kwargs) - return self.tree.getFragment() - - def parseError(self, errorcode="XXX-undefined-error", datavars=None): - # XXX The idea is to make errorcode mandatory. - if datavars is None: - datavars = {} - self.errors.append((self.tokenizer.stream.position(), errorcode, datavars)) - if self.strict: - raise ParseError(E[errorcode] % datavars) - - def normalizeToken(self, token): - # HTML5 specific normalizations to the token stream - if token["type"] == tokenTypes["StartTag"]: - raw = token["data"] - token["data"] = OrderedDict(raw) - if len(raw) > len(token["data"]): - # we had some duplicated attribute, fix so first wins - token["data"].update(raw[::-1]) - - return token - - def adjustMathMLAttributes(self, token): - adjust_attributes(token, adjustMathMLAttributes) - - def adjustSVGAttributes(self, token): - adjust_attributes(token, adjustSVGAttributes) - - def adjustForeignAttributes(self, token): - adjust_attributes(token, adjustForeignAttributesMap) - - def reparseTokenNormal(self, token): - # pylint:disable=unused-argument - self.parser.phase() - - def resetInsertionMode(self): - # The name of this method is mostly historical. (It's also used in the - # specification.) - last = False - newModes = { - "select": "inSelect", - "td": "inCell", - "th": "inCell", - "tr": "inRow", - "tbody": "inTableBody", - "thead": "inTableBody", - "tfoot": "inTableBody", - "caption": "inCaption", - "colgroup": "inColumnGroup", - "table": "inTable", - "head": "inBody", - "body": "inBody", - "frameset": "inFrameset", - "html": "beforeHead" - } - for node in self.tree.openElements[::-1]: - nodeName = node.name - new_phase = None - if node == self.tree.openElements[0]: - assert self.innerHTML - last = True - nodeName = self.innerHTML - # Check for conditions that should only happen in the innerHTML - # case - if nodeName in ("select", "colgroup", "head", "html"): - assert self.innerHTML - - if not last and node.namespace != self.tree.defaultNamespace: - continue - - if nodeName in newModes: - new_phase = self.phases[newModes[nodeName]] - break - elif last: - new_phase = self.phases["inBody"] - break - - self.phase = new_phase - - def parseRCDataRawtext(self, token, contentType): - # Generic RCDATA/RAWTEXT Parsing algorithm - assert contentType in ("RAWTEXT", "RCDATA") - - self.tree.insertElement(token) - - if contentType == "RAWTEXT": - self.tokenizer.state = self.tokenizer.rawtextState - else: - self.tokenizer.state = self.tokenizer.rcdataState - - self.originalPhase = self.phase - - self.phase = self.phases["text"] - - -@_utils.memoize -def getPhases(debug): - def log(function): - """Logger that records which phase processes each token""" - type_names = dict((value, key) for key, value in - tokenTypes.items()) - - def wrapped(self, *args, **kwargs): - if function.__name__.startswith("process") and len(args) > 0: - token = args[0] - try: - info = {"type": type_names[token['type']]} - except: - raise - if token['type'] in tagTokenTypes: - info["name"] = token['name'] - - self.parser.log.append((self.parser.tokenizer.state.__name__, - self.parser.phase.__class__.__name__, - self.__class__.__name__, - function.__name__, - info)) - return function(self, *args, **kwargs) - else: - return function(self, *args, **kwargs) - return wrapped - - def getMetaclass(use_metaclass, metaclass_func): - if use_metaclass: - return method_decorator_metaclass(metaclass_func) - else: - return type - - # pylint:disable=unused-argument - class Phase(with_metaclass(getMetaclass(debug, log))): - """Base class for helper object that implements each phase of processing - """ - - def __init__(self, parser, tree): - self.parser = parser - self.tree = tree - - def processEOF(self): - raise NotImplementedError - - def processComment(self, token): - # For most phases the following is correct. Where it's not it will be - # overridden. - self.tree.insertComment(token, self.tree.openElements[-1]) - - def processDoctype(self, token): - self.parser.parseError("unexpected-doctype") - - def processCharacters(self, token): - self.tree.insertText(token["data"]) - - def processSpaceCharacters(self, token): - self.tree.insertText(token["data"]) - - def processStartTag(self, token): - return self.startTagHandler[token["name"]](token) - - def startTagHtml(self, token): - if not self.parser.firstStartTag and token["name"] == "html": - self.parser.parseError("non-html-root") - # XXX Need a check here to see if the first start tag token emitted is - # this token... If it's not, invoke self.parser.parseError(). - for attr, value in token["data"].items(): - if attr not in self.tree.openElements[0].attributes: - self.tree.openElements[0].attributes[attr] = value - self.parser.firstStartTag = False - - def processEndTag(self, token): - return self.endTagHandler[token["name"]](token) - - class InitialPhase(Phase): - def processSpaceCharacters(self, token): - pass - - def processComment(self, token): - self.tree.insertComment(token, self.tree.document) - - def processDoctype(self, token): - name = token["name"] - publicId = token["publicId"] - systemId = token["systemId"] - correct = token["correct"] - - if (name != "html" or publicId is not None or - systemId is not None and systemId != "about:legacy-compat"): - self.parser.parseError("unknown-doctype") - - if publicId is None: - publicId = "" - - self.tree.insertDoctype(token) - - if publicId != "": - publicId = publicId.translate(asciiUpper2Lower) - - if (not correct or token["name"] != "html" or - publicId.startswith( - ("+//silmaril//dtd html pro v0r11 19970101//", - "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", - "-//as//dtd html 3.0 aswedit + extensions//", - "-//ietf//dtd html 2.0 level 1//", - "-//ietf//dtd html 2.0 level 2//", - "-//ietf//dtd html 2.0 strict level 1//", - "-//ietf//dtd html 2.0 strict level 2//", - "-//ietf//dtd html 2.0 strict//", - "-//ietf//dtd html 2.0//", - "-//ietf//dtd html 2.1e//", - "-//ietf//dtd html 3.0//", - "-//ietf//dtd html 3.2 final//", - "-//ietf//dtd html 3.2//", - "-//ietf//dtd html 3//", - "-//ietf//dtd html level 0//", - "-//ietf//dtd html level 1//", - "-//ietf//dtd html level 2//", - "-//ietf//dtd html level 3//", - "-//ietf//dtd html strict level 0//", - "-//ietf//dtd html strict level 1//", - "-//ietf//dtd html strict level 2//", - "-//ietf//dtd html strict level 3//", - "-//ietf//dtd html strict//", - "-//ietf//dtd html//", - "-//metrius//dtd metrius presentational//", - "-//microsoft//dtd internet explorer 2.0 html strict//", - "-//microsoft//dtd internet explorer 2.0 html//", - "-//microsoft//dtd internet explorer 2.0 tables//", - "-//microsoft//dtd internet explorer 3.0 html strict//", - "-//microsoft//dtd internet explorer 3.0 html//", - "-//microsoft//dtd internet explorer 3.0 tables//", - "-//netscape comm. corp.//dtd html//", - "-//netscape comm. corp.//dtd strict html//", - "-//o'reilly and associates//dtd html 2.0//", - "-//o'reilly and associates//dtd html extended 1.0//", - "-//o'reilly and associates//dtd html extended relaxed 1.0//", - "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", - "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", - "-//spyglass//dtd html 2.0 extended//", - "-//sq//dtd html 2.0 hotmetal + extensions//", - "-//sun microsystems corp.//dtd hotjava html//", - "-//sun microsystems corp.//dtd hotjava strict html//", - "-//w3c//dtd html 3 1995-03-24//", - "-//w3c//dtd html 3.2 draft//", - "-//w3c//dtd html 3.2 final//", - "-//w3c//dtd html 3.2//", - "-//w3c//dtd html 3.2s draft//", - "-//w3c//dtd html 4.0 frameset//", - "-//w3c//dtd html 4.0 transitional//", - "-//w3c//dtd html experimental 19960712//", - "-//w3c//dtd html experimental 970421//", - "-//w3c//dtd w3 html//", - "-//w3o//dtd w3 html 3.0//", - "-//webtechs//dtd mozilla html 2.0//", - "-//webtechs//dtd mozilla html//")) or - publicId in ("-//w3o//dtd w3 html strict 3.0//en//", - "-/w3c/dtd html 4.0 transitional/en", - "html") or - publicId.startswith( - ("-//w3c//dtd html 4.01 frameset//", - "-//w3c//dtd html 4.01 transitional//")) and - systemId is None or - systemId and systemId.lower() == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"): - self.parser.compatMode = "quirks" - elif (publicId.startswith( - ("-//w3c//dtd xhtml 1.0 frameset//", - "-//w3c//dtd xhtml 1.0 transitional//")) or - publicId.startswith( - ("-//w3c//dtd html 4.01 frameset//", - "-//w3c//dtd html 4.01 transitional//")) and - systemId is not None): - self.parser.compatMode = "limited quirks" - - self.parser.phase = self.parser.phases["beforeHtml"] - - def anythingElse(self): - self.parser.compatMode = "quirks" - self.parser.phase = self.parser.phases["beforeHtml"] - - def processCharacters(self, token): - self.parser.parseError("expected-doctype-but-got-chars") - self.anythingElse() - return token - - def processStartTag(self, token): - self.parser.parseError("expected-doctype-but-got-start-tag", - {"name": token["name"]}) - self.anythingElse() - return token - - def processEndTag(self, token): - self.parser.parseError("expected-doctype-but-got-end-tag", - {"name": token["name"]}) - self.anythingElse() - return token - - def processEOF(self): - self.parser.parseError("expected-doctype-but-got-eof") - self.anythingElse() - return True - - class BeforeHtmlPhase(Phase): - # helper methods - def insertHtmlElement(self): - self.tree.insertRoot(impliedTagToken("html", "StartTag")) - self.parser.phase = self.parser.phases["beforeHead"] - - # other - def processEOF(self): - self.insertHtmlElement() - return True - - def processComment(self, token): - self.tree.insertComment(token, self.tree.document) - - def processSpaceCharacters(self, token): - pass - - def processCharacters(self, token): - self.insertHtmlElement() - return token - - def processStartTag(self, token): - if token["name"] == "html": - self.parser.firstStartTag = True - self.insertHtmlElement() - return token - - def processEndTag(self, token): - if token["name"] not in ("head", "body", "html", "br"): - self.parser.parseError("unexpected-end-tag-before-html", - {"name": token["name"]}) - else: - self.insertHtmlElement() - return token - - class BeforeHeadPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("head", self.startTagHead) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([ - (("head", "body", "html", "br"), self.endTagImplyHead) - ]) - self.endTagHandler.default = self.endTagOther - - def processEOF(self): - self.startTagHead(impliedTagToken("head", "StartTag")) - return True - - def processSpaceCharacters(self, token): - pass - - def processCharacters(self, token): - self.startTagHead(impliedTagToken("head", "StartTag")) - return token - - def startTagHtml(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def startTagHead(self, token): - self.tree.insertElement(token) - self.tree.headPointer = self.tree.openElements[-1] - self.parser.phase = self.parser.phases["inHead"] - - def startTagOther(self, token): - self.startTagHead(impliedTagToken("head", "StartTag")) - return token - - def endTagImplyHead(self, token): - self.startTagHead(impliedTagToken("head", "StartTag")) - return token - - def endTagOther(self, token): - self.parser.parseError("end-tag-after-implied-root", - {"name": token["name"]}) - - class InHeadPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("title", self.startTagTitle), - (("noframes", "style"), self.startTagNoFramesStyle), - ("noscript", self.startTagNoscript), - ("script", self.startTagScript), - (("base", "basefont", "bgsound", "command", "link"), - self.startTagBaseLinkCommand), - ("meta", self.startTagMeta), - ("head", self.startTagHead) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([ - ("head", self.endTagHead), - (("br", "html", "body"), self.endTagHtmlBodyBr) - ]) - self.endTagHandler.default = self.endTagOther - - # the real thing - def processEOF(self): - self.anythingElse() - return True - - def processCharacters(self, token): - self.anythingElse() - return token - - def startTagHtml(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def startTagHead(self, token): - self.parser.parseError("two-heads-are-not-better-than-one") - - def startTagBaseLinkCommand(self, token): - self.tree.insertElement(token) - self.tree.openElements.pop() - token["selfClosingAcknowledged"] = True - - def startTagMeta(self, token): - self.tree.insertElement(token) - self.tree.openElements.pop() - token["selfClosingAcknowledged"] = True - - attributes = token["data"] - if self.parser.tokenizer.stream.charEncoding[1] == "tentative": - if "charset" in attributes: - self.parser.tokenizer.stream.changeEncoding(attributes["charset"]) - elif ("content" in attributes and - "http-equiv" in attributes and - attributes["http-equiv"].lower() == "content-type"): - # Encoding it as UTF-8 here is a hack, as really we should pass - # the abstract Unicode string, and just use the - # ContentAttrParser on that, but using UTF-8 allows all chars - # to be encoded and as a ASCII-superset works. - data = _inputstream.EncodingBytes(attributes["content"].encode("utf-8")) - parser = _inputstream.ContentAttrParser(data) - codec = parser.parse() - self.parser.tokenizer.stream.changeEncoding(codec) - - def startTagTitle(self, token): - self.parser.parseRCDataRawtext(token, "RCDATA") - - def startTagNoFramesStyle(self, token): - # Need to decide whether to implement the scripting-disabled case - self.parser.parseRCDataRawtext(token, "RAWTEXT") - - def startTagNoscript(self, token): - if self.parser.scripting: - self.parser.parseRCDataRawtext(token, "RAWTEXT") - else: - self.tree.insertElement(token) - self.parser.phase = self.parser.phases["inHeadNoscript"] - - def startTagScript(self, token): - self.tree.insertElement(token) - self.parser.tokenizer.state = self.parser.tokenizer.scriptDataState - self.parser.originalPhase = self.parser.phase - self.parser.phase = self.parser.phases["text"] - - def startTagOther(self, token): - self.anythingElse() - return token - - def endTagHead(self, token): - node = self.parser.tree.openElements.pop() - assert node.name == "head", "Expected head got %s" % node.name - self.parser.phase = self.parser.phases["afterHead"] - - def endTagHtmlBodyBr(self, token): - self.anythingElse() - return token - - def endTagOther(self, token): - self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) - - def anythingElse(self): - self.endTagHead(impliedTagToken("head")) - - class InHeadNoscriptPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - (("basefont", "bgsound", "link", "meta", "noframes", "style"), self.startTagBaseLinkCommand), - (("head", "noscript"), self.startTagHeadNoscript), - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([ - ("noscript", self.endTagNoscript), - ("br", self.endTagBr), - ]) - self.endTagHandler.default = self.endTagOther - - def processEOF(self): - self.parser.parseError("eof-in-head-noscript") - self.anythingElse() - return True - - def processComment(self, token): - return self.parser.phases["inHead"].processComment(token) - - def processCharacters(self, token): - self.parser.parseError("char-in-head-noscript") - self.anythingElse() - return token - - def processSpaceCharacters(self, token): - return self.parser.phases["inHead"].processSpaceCharacters(token) - - def startTagHtml(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def startTagBaseLinkCommand(self, token): - return self.parser.phases["inHead"].processStartTag(token) - - def startTagHeadNoscript(self, token): - self.parser.parseError("unexpected-start-tag", {"name": token["name"]}) - - def startTagOther(self, token): - self.parser.parseError("unexpected-inhead-noscript-tag", {"name": token["name"]}) - self.anythingElse() - return token - - def endTagNoscript(self, token): - node = self.parser.tree.openElements.pop() - assert node.name == "noscript", "Expected noscript got %s" % node.name - self.parser.phase = self.parser.phases["inHead"] - - def endTagBr(self, token): - self.parser.parseError("unexpected-inhead-noscript-tag", {"name": token["name"]}) - self.anythingElse() - return token - - def endTagOther(self, token): - self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) - - def anythingElse(self): - # Caller must raise parse error first! - self.endTagNoscript(impliedTagToken("noscript")) - - class AfterHeadPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("body", self.startTagBody), - ("frameset", self.startTagFrameset), - (("base", "basefont", "bgsound", "link", "meta", "noframes", "script", - "style", "title"), - self.startTagFromHead), - ("head", self.startTagHead) - ]) - self.startTagHandler.default = self.startTagOther - self.endTagHandler = _utils.MethodDispatcher([(("body", "html", "br"), - self.endTagHtmlBodyBr)]) - self.endTagHandler.default = self.endTagOther - - def processEOF(self): - self.anythingElse() - return True - - def processCharacters(self, token): - self.anythingElse() - return token - - def startTagHtml(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def startTagBody(self, token): - self.parser.framesetOK = False - self.tree.insertElement(token) - self.parser.phase = self.parser.phases["inBody"] - - def startTagFrameset(self, token): - self.tree.insertElement(token) - self.parser.phase = self.parser.phases["inFrameset"] - - def startTagFromHead(self, token): - self.parser.parseError("unexpected-start-tag-out-of-my-head", - {"name": token["name"]}) - self.tree.openElements.append(self.tree.headPointer) - self.parser.phases["inHead"].processStartTag(token) - for node in self.tree.openElements[::-1]: - if node.name == "head": - self.tree.openElements.remove(node) - break - - def startTagHead(self, token): - self.parser.parseError("unexpected-start-tag", {"name": token["name"]}) - - def startTagOther(self, token): - self.anythingElse() - return token - - def endTagHtmlBodyBr(self, token): - self.anythingElse() - return token - - def endTagOther(self, token): - self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) - - def anythingElse(self): - self.tree.insertElement(impliedTagToken("body", "StartTag")) - self.parser.phase = self.parser.phases["inBody"] - self.parser.framesetOK = True - - class InBodyPhase(Phase): - # http://www.whatwg.org/specs/web-apps/current-work/#parsing-main-inbody - # the really-really-really-very crazy mode - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - # Set this to the default handler - self.processSpaceCharacters = self.processSpaceCharactersNonPre - - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - (("base", "basefont", "bgsound", "command", "link", "meta", - "script", "style", "title"), - self.startTagProcessInHead), - ("body", self.startTagBody), - ("frameset", self.startTagFrameset), - (("address", "article", "aside", "blockquote", "center", "details", - "dir", "div", "dl", "fieldset", "figcaption", "figure", - "footer", "header", "hgroup", "main", "menu", "nav", "ol", "p", - "section", "summary", "ul"), - self.startTagCloseP), - (headingElements, self.startTagHeading), - (("pre", "listing"), self.startTagPreListing), - ("form", self.startTagForm), - (("li", "dd", "dt"), self.startTagListItem), - ("plaintext", self.startTagPlaintext), - ("a", self.startTagA), - (("b", "big", "code", "em", "font", "i", "s", "small", "strike", - "strong", "tt", "u"), self.startTagFormatting), - ("nobr", self.startTagNobr), - ("button", self.startTagButton), - (("applet", "marquee", "object"), self.startTagAppletMarqueeObject), - ("xmp", self.startTagXmp), - ("table", self.startTagTable), - (("area", "br", "embed", "img", "keygen", "wbr"), - self.startTagVoidFormatting), - (("param", "source", "track"), self.startTagParamSource), - ("input", self.startTagInput), - ("hr", self.startTagHr), - ("image", self.startTagImage), - ("isindex", self.startTagIsIndex), - ("textarea", self.startTagTextarea), - ("iframe", self.startTagIFrame), - ("noscript", self.startTagNoscript), - (("noembed", "noframes"), self.startTagRawtext), - ("select", self.startTagSelect), - (("rp", "rt"), self.startTagRpRt), - (("option", "optgroup"), self.startTagOpt), - (("math"), self.startTagMath), - (("svg"), self.startTagSvg), - (("caption", "col", "colgroup", "frame", "head", - "tbody", "td", "tfoot", "th", "thead", - "tr"), self.startTagMisplaced) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([ - ("body", self.endTagBody), - ("html", self.endTagHtml), - (("address", "article", "aside", "blockquote", "button", "center", - "details", "dialog", "dir", "div", "dl", "fieldset", "figcaption", "figure", - "footer", "header", "hgroup", "listing", "main", "menu", "nav", "ol", "pre", - "section", "summary", "ul"), self.endTagBlock), - ("form", self.endTagForm), - ("p", self.endTagP), - (("dd", "dt", "li"), self.endTagListItem), - (headingElements, self.endTagHeading), - (("a", "b", "big", "code", "em", "font", "i", "nobr", "s", "small", - "strike", "strong", "tt", "u"), self.endTagFormatting), - (("applet", "marquee", "object"), self.endTagAppletMarqueeObject), - ("br", self.endTagBr), - ]) - self.endTagHandler.default = self.endTagOther - - def isMatchingFormattingElement(self, node1, node2): - return (node1.name == node2.name and - node1.namespace == node2.namespace and - node1.attributes == node2.attributes) - - # helper - def addFormattingElement(self, token): - self.tree.insertElement(token) - element = self.tree.openElements[-1] - - matchingElements = [] - for node in self.tree.activeFormattingElements[::-1]: - if node is Marker: - break - elif self.isMatchingFormattingElement(node, element): - matchingElements.append(node) - - assert len(matchingElements) <= 3 - if len(matchingElements) == 3: - self.tree.activeFormattingElements.remove(matchingElements[-1]) - self.tree.activeFormattingElements.append(element) - - # the real deal - def processEOF(self): - allowed_elements = frozenset(("dd", "dt", "li", "p", "tbody", "td", - "tfoot", "th", "thead", "tr", "body", - "html")) - for node in self.tree.openElements[::-1]: - if node.name not in allowed_elements: - self.parser.parseError("expected-closing-tag-but-got-eof") - break - # Stop parsing - - def processSpaceCharactersDropNewline(self, token): - # Sometimes (start of <pre>, <listing>, and <textarea> blocks) we - # want to drop leading newlines - data = token["data"] - self.processSpaceCharacters = self.processSpaceCharactersNonPre - if (data.startswith("\n") and - self.tree.openElements[-1].name in ("pre", "listing", "textarea") and - not self.tree.openElements[-1].hasContent()): - data = data[1:] - if data: - self.tree.reconstructActiveFormattingElements() - self.tree.insertText(data) - - def processCharacters(self, token): - if token["data"] == "\u0000": - # The tokenizer should always emit null on its own - return - self.tree.reconstructActiveFormattingElements() - self.tree.insertText(token["data"]) - # This must be bad for performance - if (self.parser.framesetOK and - any([char not in spaceCharacters - for char in token["data"]])): - self.parser.framesetOK = False - - def processSpaceCharactersNonPre(self, token): - self.tree.reconstructActiveFormattingElements() - self.tree.insertText(token["data"]) - - def startTagProcessInHead(self, token): - return self.parser.phases["inHead"].processStartTag(token) - - def startTagBody(self, token): - self.parser.parseError("unexpected-start-tag", {"name": "body"}) - if (len(self.tree.openElements) == 1 or - self.tree.openElements[1].name != "body"): - assert self.parser.innerHTML - else: - self.parser.framesetOK = False - for attr, value in token["data"].items(): - if attr not in self.tree.openElements[1].attributes: - self.tree.openElements[1].attributes[attr] = value - - def startTagFrameset(self, token): - self.parser.parseError("unexpected-start-tag", {"name": "frameset"}) - if (len(self.tree.openElements) == 1 or self.tree.openElements[1].name != "body"): - assert self.parser.innerHTML - elif not self.parser.framesetOK: - pass - else: - if self.tree.openElements[1].parent: - self.tree.openElements[1].parent.removeChild(self.tree.openElements[1]) - while self.tree.openElements[-1].name != "html": - self.tree.openElements.pop() - self.tree.insertElement(token) - self.parser.phase = self.parser.phases["inFrameset"] - - def startTagCloseP(self, token): - if self.tree.elementInScope("p", variant="button"): - self.endTagP(impliedTagToken("p")) - self.tree.insertElement(token) - - def startTagPreListing(self, token): - if self.tree.elementInScope("p", variant="button"): - self.endTagP(impliedTagToken("p")) - self.tree.insertElement(token) - self.parser.framesetOK = False - self.processSpaceCharacters = self.processSpaceCharactersDropNewline - - def startTagForm(self, token): - if self.tree.formPointer: - self.parser.parseError("unexpected-start-tag", {"name": "form"}) - else: - if self.tree.elementInScope("p", variant="button"): - self.endTagP(impliedTagToken("p")) - self.tree.insertElement(token) - self.tree.formPointer = self.tree.openElements[-1] - - def startTagListItem(self, token): - self.parser.framesetOK = False - - stopNamesMap = {"li": ["li"], - "dt": ["dt", "dd"], - "dd": ["dt", "dd"]} - stopNames = stopNamesMap[token["name"]] - for node in reversed(self.tree.openElements): - if node.name in stopNames: - self.parser.phase.processEndTag( - impliedTagToken(node.name, "EndTag")) - break - if (node.nameTuple in specialElements and - node.name not in ("address", "div", "p")): - break - - if self.tree.elementInScope("p", variant="button"): - self.parser.phase.processEndTag( - impliedTagToken("p", "EndTag")) - - self.tree.insertElement(token) - - def startTagPlaintext(self, token): - if self.tree.elementInScope("p", variant="button"): - self.endTagP(impliedTagToken("p")) - self.tree.insertElement(token) - self.parser.tokenizer.state = self.parser.tokenizer.plaintextState - - def startTagHeading(self, token): - if self.tree.elementInScope("p", variant="button"): - self.endTagP(impliedTagToken("p")) - if self.tree.openElements[-1].name in headingElements: - self.parser.parseError("unexpected-start-tag", {"name": token["name"]}) - self.tree.openElements.pop() - self.tree.insertElement(token) - - def startTagA(self, token): - afeAElement = self.tree.elementInActiveFormattingElements("a") - if afeAElement: - self.parser.parseError("unexpected-start-tag-implies-end-tag", - {"startName": "a", "endName": "a"}) - self.endTagFormatting(impliedTagToken("a")) - if afeAElement in self.tree.openElements: - self.tree.openElements.remove(afeAElement) - if afeAElement in self.tree.activeFormattingElements: - self.tree.activeFormattingElements.remove(afeAElement) - self.tree.reconstructActiveFormattingElements() - self.addFormattingElement(token) - - def startTagFormatting(self, token): - self.tree.reconstructActiveFormattingElements() - self.addFormattingElement(token) - - def startTagNobr(self, token): - self.tree.reconstructActiveFormattingElements() - if self.tree.elementInScope("nobr"): - self.parser.parseError("unexpected-start-tag-implies-end-tag", - {"startName": "nobr", "endName": "nobr"}) - self.processEndTag(impliedTagToken("nobr")) - # XXX Need tests that trigger the following - self.tree.reconstructActiveFormattingElements() - self.addFormattingElement(token) - - def startTagButton(self, token): - if self.tree.elementInScope("button"): - self.parser.parseError("unexpected-start-tag-implies-end-tag", - {"startName": "button", "endName": "button"}) - self.processEndTag(impliedTagToken("button")) - return token - else: - self.tree.reconstructActiveFormattingElements() - self.tree.insertElement(token) - self.parser.framesetOK = False - - def startTagAppletMarqueeObject(self, token): - self.tree.reconstructActiveFormattingElements() - self.tree.insertElement(token) - self.tree.activeFormattingElements.append(Marker) - self.parser.framesetOK = False - - def startTagXmp(self, token): - if self.tree.elementInScope("p", variant="button"): - self.endTagP(impliedTagToken("p")) - self.tree.reconstructActiveFormattingElements() - self.parser.framesetOK = False - self.parser.parseRCDataRawtext(token, "RAWTEXT") - - def startTagTable(self, token): - if self.parser.compatMode != "quirks": - if self.tree.elementInScope("p", variant="button"): - self.processEndTag(impliedTagToken("p")) - self.tree.insertElement(token) - self.parser.framesetOK = False - self.parser.phase = self.parser.phases["inTable"] - - def startTagVoidFormatting(self, token): - self.tree.reconstructActiveFormattingElements() - self.tree.insertElement(token) - self.tree.openElements.pop() - token["selfClosingAcknowledged"] = True - self.parser.framesetOK = False - - def startTagInput(self, token): - framesetOK = self.parser.framesetOK - self.startTagVoidFormatting(token) - if ("type" in token["data"] and - token["data"]["type"].translate(asciiUpper2Lower) == "hidden"): - # input type=hidden doesn't change framesetOK - self.parser.framesetOK = framesetOK - - def startTagParamSource(self, token): - self.tree.insertElement(token) - self.tree.openElements.pop() - token["selfClosingAcknowledged"] = True - - def startTagHr(self, token): - if self.tree.elementInScope("p", variant="button"): - self.endTagP(impliedTagToken("p")) - self.tree.insertElement(token) - self.tree.openElements.pop() - token["selfClosingAcknowledged"] = True - self.parser.framesetOK = False - - def startTagImage(self, token): - # No really... - self.parser.parseError("unexpected-start-tag-treated-as", - {"originalName": "image", "newName": "img"}) - self.processStartTag(impliedTagToken("img", "StartTag", - attributes=token["data"], - selfClosing=token["selfClosing"])) - - def startTagIsIndex(self, token): - self.parser.parseError("deprecated-tag", {"name": "isindex"}) - if self.tree.formPointer: - return - form_attrs = {} - if "action" in token["data"]: - form_attrs["action"] = token["data"]["action"] - self.processStartTag(impliedTagToken("form", "StartTag", - attributes=form_attrs)) - self.processStartTag(impliedTagToken("hr", "StartTag")) - self.processStartTag(impliedTagToken("label", "StartTag")) - # XXX Localization ... - if "prompt" in token["data"]: - prompt = token["data"]["prompt"] - else: - prompt = "This is a searchable index. Enter search keywords: " - self.processCharacters( - {"type": tokenTypes["Characters"], "data": prompt}) - attributes = token["data"].copy() - if "action" in attributes: - del attributes["action"] - if "prompt" in attributes: - del attributes["prompt"] - attributes["name"] = "isindex" - self.processStartTag(impliedTagToken("input", "StartTag", - attributes=attributes, - selfClosing=token["selfClosing"])) - self.processEndTag(impliedTagToken("label")) - self.processStartTag(impliedTagToken("hr", "StartTag")) - self.processEndTag(impliedTagToken("form")) - - def startTagTextarea(self, token): - self.tree.insertElement(token) - self.parser.tokenizer.state = self.parser.tokenizer.rcdataState - self.processSpaceCharacters = self.processSpaceCharactersDropNewline - self.parser.framesetOK = False - - def startTagIFrame(self, token): - self.parser.framesetOK = False - self.startTagRawtext(token) - - def startTagNoscript(self, token): - if self.parser.scripting: - self.startTagRawtext(token) - else: - self.startTagOther(token) - - def startTagRawtext(self, token): - """iframe, noembed noframes, noscript(if scripting enabled)""" - self.parser.parseRCDataRawtext(token, "RAWTEXT") - - def startTagOpt(self, token): - if self.tree.openElements[-1].name == "option": - self.parser.phase.processEndTag(impliedTagToken("option")) - self.tree.reconstructActiveFormattingElements() - self.parser.tree.insertElement(token) - - def startTagSelect(self, token): - self.tree.reconstructActiveFormattingElements() - self.tree.insertElement(token) - self.parser.framesetOK = False - if self.parser.phase in (self.parser.phases["inTable"], - self.parser.phases["inCaption"], - self.parser.phases["inColumnGroup"], - self.parser.phases["inTableBody"], - self.parser.phases["inRow"], - self.parser.phases["inCell"]): - self.parser.phase = self.parser.phases["inSelectInTable"] - else: - self.parser.phase = self.parser.phases["inSelect"] - - def startTagRpRt(self, token): - if self.tree.elementInScope("ruby"): - self.tree.generateImpliedEndTags() - if self.tree.openElements[-1].name != "ruby": - self.parser.parseError() - self.tree.insertElement(token) - - def startTagMath(self, token): - self.tree.reconstructActiveFormattingElements() - self.parser.adjustMathMLAttributes(token) - self.parser.adjustForeignAttributes(token) - token["namespace"] = namespaces["mathml"] - self.tree.insertElement(token) - # Need to get the parse error right for the case where the token - # has a namespace not equal to the xmlns attribute - if token["selfClosing"]: - self.tree.openElements.pop() - token["selfClosingAcknowledged"] = True - - def startTagSvg(self, token): - self.tree.reconstructActiveFormattingElements() - self.parser.adjustSVGAttributes(token) - self.parser.adjustForeignAttributes(token) - token["namespace"] = namespaces["svg"] - self.tree.insertElement(token) - # Need to get the parse error right for the case where the token - # has a namespace not equal to the xmlns attribute - if token["selfClosing"]: - self.tree.openElements.pop() - token["selfClosingAcknowledged"] = True - - def startTagMisplaced(self, token): - """ Elements that should be children of other elements that have a - different insertion mode; here they are ignored - "caption", "col", "colgroup", "frame", "frameset", "head", - "option", "optgroup", "tbody", "td", "tfoot", "th", "thead", - "tr", "noscript" - """ - self.parser.parseError("unexpected-start-tag-ignored", {"name": token["name"]}) - - def startTagOther(self, token): - self.tree.reconstructActiveFormattingElements() - self.tree.insertElement(token) - - def endTagP(self, token): - if not self.tree.elementInScope("p", variant="button"): - self.startTagCloseP(impliedTagToken("p", "StartTag")) - self.parser.parseError("unexpected-end-tag", {"name": "p"}) - self.endTagP(impliedTagToken("p", "EndTag")) - else: - self.tree.generateImpliedEndTags("p") - if self.tree.openElements[-1].name != "p": - self.parser.parseError("unexpected-end-tag", {"name": "p"}) - node = self.tree.openElements.pop() - while node.name != "p": - node = self.tree.openElements.pop() - - def endTagBody(self, token): - if not self.tree.elementInScope("body"): - self.parser.parseError() - return - elif self.tree.openElements[-1].name != "body": - for node in self.tree.openElements[2:]: - if node.name not in frozenset(("dd", "dt", "li", "optgroup", - "option", "p", "rp", "rt", - "tbody", "td", "tfoot", - "th", "thead", "tr", "body", - "html")): - # Not sure this is the correct name for the parse error - self.parser.parseError( - "expected-one-end-tag-but-got-another", - {"gotName": "body", "expectedName": node.name}) - break - self.parser.phase = self.parser.phases["afterBody"] - - def endTagHtml(self, token): - # We repeat the test for the body end tag token being ignored here - if self.tree.elementInScope("body"): - self.endTagBody(impliedTagToken("body")) - return token - - def endTagBlock(self, token): - # Put us back in the right whitespace handling mode - if token["name"] == "pre": - self.processSpaceCharacters = self.processSpaceCharactersNonPre - inScope = self.tree.elementInScope(token["name"]) - if inScope: - self.tree.generateImpliedEndTags() - if self.tree.openElements[-1].name != token["name"]: - self.parser.parseError("end-tag-too-early", {"name": token["name"]}) - if inScope: - node = self.tree.openElements.pop() - while node.name != token["name"]: - node = self.tree.openElements.pop() - - def endTagForm(self, token): - node = self.tree.formPointer - self.tree.formPointer = None - if node is None or not self.tree.elementInScope(node): - self.parser.parseError("unexpected-end-tag", - {"name": "form"}) - else: - self.tree.generateImpliedEndTags() - if self.tree.openElements[-1] != node: - self.parser.parseError("end-tag-too-early-ignored", - {"name": "form"}) - self.tree.openElements.remove(node) - - def endTagListItem(self, token): - if token["name"] == "li": - variant = "list" - else: - variant = None - if not self.tree.elementInScope(token["name"], variant=variant): - self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) - else: - self.tree.generateImpliedEndTags(exclude=token["name"]) - if self.tree.openElements[-1].name != token["name"]: - self.parser.parseError( - "end-tag-too-early", - {"name": token["name"]}) - node = self.tree.openElements.pop() - while node.name != token["name"]: - node = self.tree.openElements.pop() - - def endTagHeading(self, token): - for item in headingElements: - if self.tree.elementInScope(item): - self.tree.generateImpliedEndTags() - break - if self.tree.openElements[-1].name != token["name"]: - self.parser.parseError("end-tag-too-early", {"name": token["name"]}) - - for item in headingElements: - if self.tree.elementInScope(item): - item = self.tree.openElements.pop() - while item.name not in headingElements: - item = self.tree.openElements.pop() - break - - def endTagFormatting(self, token): - """The much-feared adoption agency algorithm""" - # http://svn.whatwg.org/webapps/complete.html#adoptionAgency revision 7867 - # XXX Better parseError messages appreciated. - - # Step 1 - outerLoopCounter = 0 - - # Step 2 - while outerLoopCounter < 8: - - # Step 3 - outerLoopCounter += 1 - - # Step 4: - - # Let the formatting element be the last element in - # the list of active formatting elements that: - # - is between the end of the list and the last scope - # marker in the list, if any, or the start of the list - # otherwise, and - # - has the same tag name as the token. - formattingElement = self.tree.elementInActiveFormattingElements( - token["name"]) - if (not formattingElement or - (formattingElement in self.tree.openElements and - not self.tree.elementInScope(formattingElement.name))): - # If there is no such node, then abort these steps - # and instead act as described in the "any other - # end tag" entry below. - self.endTagOther(token) - return - - # Otherwise, if there is such a node, but that node is - # not in the stack of open elements, then this is a - # parse error; remove the element from the list, and - # abort these steps. - elif formattingElement not in self.tree.openElements: - self.parser.parseError("adoption-agency-1.2", {"name": token["name"]}) - self.tree.activeFormattingElements.remove(formattingElement) - return - - # Otherwise, if there is such a node, and that node is - # also in the stack of open elements, but the element - # is not in scope, then this is a parse error; ignore - # the token, and abort these steps. - elif not self.tree.elementInScope(formattingElement.name): - self.parser.parseError("adoption-agency-4.4", {"name": token["name"]}) - return - - # Otherwise, there is a formatting element and that - # element is in the stack and is in scope. If the - # element is not the current node, this is a parse - # error. In any case, proceed with the algorithm as - # written in the following steps. - else: - if formattingElement != self.tree.openElements[-1]: - self.parser.parseError("adoption-agency-1.3", {"name": token["name"]}) - - # Step 5: - - # Let the furthest block be the topmost node in the - # stack of open elements that is lower in the stack - # than the formatting element, and is an element in - # the special category. There might not be one. - afeIndex = self.tree.openElements.index(formattingElement) - furthestBlock = None - for element in self.tree.openElements[afeIndex:]: - if element.nameTuple in specialElements: - furthestBlock = element - break - - # Step 6: - - # If there is no furthest block, then the UA must - # first pop all the nodes from the bottom of the stack - # of open elements, from the current node up to and - # including the formatting element, then remove the - # formatting element from the list of active - # formatting elements, and finally abort these steps. - if furthestBlock is None: - element = self.tree.openElements.pop() - while element != formattingElement: - element = self.tree.openElements.pop() - self.tree.activeFormattingElements.remove(element) - return - - # Step 7 - commonAncestor = self.tree.openElements[afeIndex - 1] - - # Step 8: - # The bookmark is supposed to help us identify where to reinsert - # nodes in step 15. We have to ensure that we reinsert nodes after - # the node before the active formatting element. Note the bookmark - # can move in step 9.7 - bookmark = self.tree.activeFormattingElements.index(formattingElement) - - # Step 9 - lastNode = node = furthestBlock - innerLoopCounter = 0 - - index = self.tree.openElements.index(node) - while innerLoopCounter < 3: - innerLoopCounter += 1 - # Node is element before node in open elements - index -= 1 - node = self.tree.openElements[index] - if node not in self.tree.activeFormattingElements: - self.tree.openElements.remove(node) - continue - # Step 9.6 - if node == formattingElement: - break - # Step 9.7 - if lastNode == furthestBlock: - bookmark = self.tree.activeFormattingElements.index(node) + 1 - # Step 9.8 - clone = node.cloneNode() - # Replace node with clone - self.tree.activeFormattingElements[ - self.tree.activeFormattingElements.index(node)] = clone - self.tree.openElements[ - self.tree.openElements.index(node)] = clone - node = clone - # Step 9.9 - # Remove lastNode from its parents, if any - if lastNode.parent: - lastNode.parent.removeChild(lastNode) - node.appendChild(lastNode) - # Step 9.10 - lastNode = node - - # Step 10 - # Foster parent lastNode if commonAncestor is a - # table, tbody, tfoot, thead, or tr we need to foster - # parent the lastNode - if lastNode.parent: - lastNode.parent.removeChild(lastNode) - - if commonAncestor.name in frozenset(("table", "tbody", "tfoot", "thead", "tr")): - parent, insertBefore = self.tree.getTableMisnestedNodePosition() - parent.insertBefore(lastNode, insertBefore) - else: - commonAncestor.appendChild(lastNode) - - # Step 11 - clone = formattingElement.cloneNode() - - # Step 12 - furthestBlock.reparentChildren(clone) - - # Step 13 - furthestBlock.appendChild(clone) - - # Step 14 - self.tree.activeFormattingElements.remove(formattingElement) - self.tree.activeFormattingElements.insert(bookmark, clone) - - # Step 15 - self.tree.openElements.remove(formattingElement) - self.tree.openElements.insert( - self.tree.openElements.index(furthestBlock) + 1, clone) - - def endTagAppletMarqueeObject(self, token): - if self.tree.elementInScope(token["name"]): - self.tree.generateImpliedEndTags() - if self.tree.openElements[-1].name != token["name"]: - self.parser.parseError("end-tag-too-early", {"name": token["name"]}) - - if self.tree.elementInScope(token["name"]): - element = self.tree.openElements.pop() - while element.name != token["name"]: - element = self.tree.openElements.pop() - self.tree.clearActiveFormattingElements() - - def endTagBr(self, token): - self.parser.parseError("unexpected-end-tag-treated-as", - {"originalName": "br", "newName": "br element"}) - self.tree.reconstructActiveFormattingElements() - self.tree.insertElement(impliedTagToken("br", "StartTag")) - self.tree.openElements.pop() - - def endTagOther(self, token): - for node in self.tree.openElements[::-1]: - if node.name == token["name"]: - self.tree.generateImpliedEndTags(exclude=token["name"]) - if self.tree.openElements[-1].name != token["name"]: - self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) - while self.tree.openElements.pop() != node: - pass - break - else: - if node.nameTuple in specialElements: - self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) - break - - class TextPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - self.startTagHandler = _utils.MethodDispatcher([]) - self.startTagHandler.default = self.startTagOther - self.endTagHandler = _utils.MethodDispatcher([ - ("script", self.endTagScript)]) - self.endTagHandler.default = self.endTagOther - - def processCharacters(self, token): - self.tree.insertText(token["data"]) - - def processEOF(self): - self.parser.parseError("expected-named-closing-tag-but-got-eof", - {"name": self.tree.openElements[-1].name}) - self.tree.openElements.pop() - self.parser.phase = self.parser.originalPhase - return True - - def startTagOther(self, token): - assert False, "Tried to process start tag %s in RCDATA/RAWTEXT mode" % token['name'] - - def endTagScript(self, token): - node = self.tree.openElements.pop() - assert node.name == "script" - self.parser.phase = self.parser.originalPhase - # The rest of this method is all stuff that only happens if - # document.write works - - def endTagOther(self, token): - self.tree.openElements.pop() - self.parser.phase = self.parser.originalPhase - - class InTablePhase(Phase): - # http://www.whatwg.org/specs/web-apps/current-work/#in-table - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("caption", self.startTagCaption), - ("colgroup", self.startTagColgroup), - ("col", self.startTagCol), - (("tbody", "tfoot", "thead"), self.startTagRowGroup), - (("td", "th", "tr"), self.startTagImplyTbody), - ("table", self.startTagTable), - (("style", "script"), self.startTagStyleScript), - ("input", self.startTagInput), - ("form", self.startTagForm) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([ - ("table", self.endTagTable), - (("body", "caption", "col", "colgroup", "html", "tbody", "td", - "tfoot", "th", "thead", "tr"), self.endTagIgnore) - ]) - self.endTagHandler.default = self.endTagOther - - # helper methods - def clearStackToTableContext(self): - # "clear the stack back to a table context" - while self.tree.openElements[-1].name not in ("table", "html"): - # self.parser.parseError("unexpected-implied-end-tag-in-table", - # {"name": self.tree.openElements[-1].name}) - self.tree.openElements.pop() - # When the current node is <html> it's an innerHTML case - - # processing methods - def processEOF(self): - if self.tree.openElements[-1].name != "html": - self.parser.parseError("eof-in-table") - else: - assert self.parser.innerHTML - # Stop parsing - - def processSpaceCharacters(self, token): - originalPhase = self.parser.phase - self.parser.phase = self.parser.phases["inTableText"] - self.parser.phase.originalPhase = originalPhase - self.parser.phase.processSpaceCharacters(token) - - def processCharacters(self, token): - originalPhase = self.parser.phase - self.parser.phase = self.parser.phases["inTableText"] - self.parser.phase.originalPhase = originalPhase - self.parser.phase.processCharacters(token) - - def insertText(self, token): - # If we get here there must be at least one non-whitespace character - # Do the table magic! - self.tree.insertFromTable = True - self.parser.phases["inBody"].processCharacters(token) - self.tree.insertFromTable = False - - def startTagCaption(self, token): - self.clearStackToTableContext() - self.tree.activeFormattingElements.append(Marker) - self.tree.insertElement(token) - self.parser.phase = self.parser.phases["inCaption"] - - def startTagColgroup(self, token): - self.clearStackToTableContext() - self.tree.insertElement(token) - self.parser.phase = self.parser.phases["inColumnGroup"] - - def startTagCol(self, token): - self.startTagColgroup(impliedTagToken("colgroup", "StartTag")) - return token - - def startTagRowGroup(self, token): - self.clearStackToTableContext() - self.tree.insertElement(token) - self.parser.phase = self.parser.phases["inTableBody"] - - def startTagImplyTbody(self, token): - self.startTagRowGroup(impliedTagToken("tbody", "StartTag")) - return token - - def startTagTable(self, token): - self.parser.parseError("unexpected-start-tag-implies-end-tag", - {"startName": "table", "endName": "table"}) - self.parser.phase.processEndTag(impliedTagToken("table")) - if not self.parser.innerHTML: - return token - - def startTagStyleScript(self, token): - return self.parser.phases["inHead"].processStartTag(token) - - def startTagInput(self, token): - if ("type" in token["data"] and - token["data"]["type"].translate(asciiUpper2Lower) == "hidden"): - self.parser.parseError("unexpected-hidden-input-in-table") - self.tree.insertElement(token) - # XXX associate with form - self.tree.openElements.pop() - else: - self.startTagOther(token) - - def startTagForm(self, token): - self.parser.parseError("unexpected-form-in-table") - if self.tree.formPointer is None: - self.tree.insertElement(token) - self.tree.formPointer = self.tree.openElements[-1] - self.tree.openElements.pop() - - def startTagOther(self, token): - self.parser.parseError("unexpected-start-tag-implies-table-voodoo", {"name": token["name"]}) - # Do the table magic! - self.tree.insertFromTable = True - self.parser.phases["inBody"].processStartTag(token) - self.tree.insertFromTable = False - - def endTagTable(self, token): - if self.tree.elementInScope("table", variant="table"): - self.tree.generateImpliedEndTags() - if self.tree.openElements[-1].name != "table": - self.parser.parseError("end-tag-too-early-named", - {"gotName": "table", - "expectedName": self.tree.openElements[-1].name}) - while self.tree.openElements[-1].name != "table": - self.tree.openElements.pop() - self.tree.openElements.pop() - self.parser.resetInsertionMode() - else: - # innerHTML case - assert self.parser.innerHTML - self.parser.parseError() - - def endTagIgnore(self, token): - self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) - - def endTagOther(self, token): - self.parser.parseError("unexpected-end-tag-implies-table-voodoo", {"name": token["name"]}) - # Do the table magic! - self.tree.insertFromTable = True - self.parser.phases["inBody"].processEndTag(token) - self.tree.insertFromTable = False - - class InTableTextPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - self.originalPhase = None - self.characterTokens = [] - - def flushCharacters(self): - data = "".join([item["data"] for item in self.characterTokens]) - if any([item not in spaceCharacters for item in data]): - token = {"type": tokenTypes["Characters"], "data": data} - self.parser.phases["inTable"].insertText(token) - elif data: - self.tree.insertText(data) - self.characterTokens = [] - - def processComment(self, token): - self.flushCharacters() - self.parser.phase = self.originalPhase - return token - - def processEOF(self): - self.flushCharacters() - self.parser.phase = self.originalPhase - return True - - def processCharacters(self, token): - if token["data"] == "\u0000": - return - self.characterTokens.append(token) - - def processSpaceCharacters(self, token): - # pretty sure we should never reach here - self.characterTokens.append(token) - # assert False - - def processStartTag(self, token): - self.flushCharacters() - self.parser.phase = self.originalPhase - return token - - def processEndTag(self, token): - self.flushCharacters() - self.parser.phase = self.originalPhase - return token - - class InCaptionPhase(Phase): - # http://www.whatwg.org/specs/web-apps/current-work/#in-caption - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - (("caption", "col", "colgroup", "tbody", "td", "tfoot", "th", - "thead", "tr"), self.startTagTableElement) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([ - ("caption", self.endTagCaption), - ("table", self.endTagTable), - (("body", "col", "colgroup", "html", "tbody", "td", "tfoot", "th", - "thead", "tr"), self.endTagIgnore) - ]) - self.endTagHandler.default = self.endTagOther - - def ignoreEndTagCaption(self): - return not self.tree.elementInScope("caption", variant="table") - - def processEOF(self): - self.parser.phases["inBody"].processEOF() - - def processCharacters(self, token): - return self.parser.phases["inBody"].processCharacters(token) - - def startTagTableElement(self, token): - self.parser.parseError() - # XXX Have to duplicate logic here to find out if the tag is ignored - ignoreEndTag = self.ignoreEndTagCaption() - self.parser.phase.processEndTag(impliedTagToken("caption")) - if not ignoreEndTag: - return token - - def startTagOther(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def endTagCaption(self, token): - if not self.ignoreEndTagCaption(): - # AT this code is quite similar to endTagTable in "InTable" - self.tree.generateImpliedEndTags() - if self.tree.openElements[-1].name != "caption": - self.parser.parseError("expected-one-end-tag-but-got-another", - {"gotName": "caption", - "expectedName": self.tree.openElements[-1].name}) - while self.tree.openElements[-1].name != "caption": - self.tree.openElements.pop() - self.tree.openElements.pop() - self.tree.clearActiveFormattingElements() - self.parser.phase = self.parser.phases["inTable"] - else: - # innerHTML case - assert self.parser.innerHTML - self.parser.parseError() - - def endTagTable(self, token): - self.parser.parseError() - ignoreEndTag = self.ignoreEndTagCaption() - self.parser.phase.processEndTag(impliedTagToken("caption")) - if not ignoreEndTag: - return token - - def endTagIgnore(self, token): - self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) - - def endTagOther(self, token): - return self.parser.phases["inBody"].processEndTag(token) - - class InColumnGroupPhase(Phase): - # http://www.whatwg.org/specs/web-apps/current-work/#in-column - - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("col", self.startTagCol) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([ - ("colgroup", self.endTagColgroup), - ("col", self.endTagCol) - ]) - self.endTagHandler.default = self.endTagOther - - def ignoreEndTagColgroup(self): - return self.tree.openElements[-1].name == "html" - - def processEOF(self): - if self.tree.openElements[-1].name == "html": - assert self.parser.innerHTML - return - else: - ignoreEndTag = self.ignoreEndTagColgroup() - self.endTagColgroup(impliedTagToken("colgroup")) - if not ignoreEndTag: - return True - - def processCharacters(self, token): - ignoreEndTag = self.ignoreEndTagColgroup() - self.endTagColgroup(impliedTagToken("colgroup")) - if not ignoreEndTag: - return token - - def startTagCol(self, token): - self.tree.insertElement(token) - self.tree.openElements.pop() - token["selfClosingAcknowledged"] = True - - def startTagOther(self, token): - ignoreEndTag = self.ignoreEndTagColgroup() - self.endTagColgroup(impliedTagToken("colgroup")) - if not ignoreEndTag: - return token - - def endTagColgroup(self, token): - if self.ignoreEndTagColgroup(): - # innerHTML case - assert self.parser.innerHTML - self.parser.parseError() - else: - self.tree.openElements.pop() - self.parser.phase = self.parser.phases["inTable"] - - def endTagCol(self, token): - self.parser.parseError("no-end-tag", {"name": "col"}) - - def endTagOther(self, token): - ignoreEndTag = self.ignoreEndTagColgroup() - self.endTagColgroup(impliedTagToken("colgroup")) - if not ignoreEndTag: - return token - - class InTableBodyPhase(Phase): - # http://www.whatwg.org/specs/web-apps/current-work/#in-table0 - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("tr", self.startTagTr), - (("td", "th"), self.startTagTableCell), - (("caption", "col", "colgroup", "tbody", "tfoot", "thead"), - self.startTagTableOther) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([ - (("tbody", "tfoot", "thead"), self.endTagTableRowGroup), - ("table", self.endTagTable), - (("body", "caption", "col", "colgroup", "html", "td", "th", - "tr"), self.endTagIgnore) - ]) - self.endTagHandler.default = self.endTagOther - - # helper methods - def clearStackToTableBodyContext(self): - while self.tree.openElements[-1].name not in ("tbody", "tfoot", - "thead", "html"): - # self.parser.parseError("unexpected-implied-end-tag-in-table", - # {"name": self.tree.openElements[-1].name}) - self.tree.openElements.pop() - if self.tree.openElements[-1].name == "html": - assert self.parser.innerHTML - - # the rest - def processEOF(self): - self.parser.phases["inTable"].processEOF() - - def processSpaceCharacters(self, token): - return self.parser.phases["inTable"].processSpaceCharacters(token) - - def processCharacters(self, token): - return self.parser.phases["inTable"].processCharacters(token) - - def startTagTr(self, token): - self.clearStackToTableBodyContext() - self.tree.insertElement(token) - self.parser.phase = self.parser.phases["inRow"] - - def startTagTableCell(self, token): - self.parser.parseError("unexpected-cell-in-table-body", - {"name": token["name"]}) - self.startTagTr(impliedTagToken("tr", "StartTag")) - return token - - def startTagTableOther(self, token): - # XXX AT Any ideas on how to share this with endTagTable? - if (self.tree.elementInScope("tbody", variant="table") or - self.tree.elementInScope("thead", variant="table") or - self.tree.elementInScope("tfoot", variant="table")): - self.clearStackToTableBodyContext() - self.endTagTableRowGroup( - impliedTagToken(self.tree.openElements[-1].name)) - return token - else: - # innerHTML case - assert self.parser.innerHTML - self.parser.parseError() - - def startTagOther(self, token): - return self.parser.phases["inTable"].processStartTag(token) - - def endTagTableRowGroup(self, token): - if self.tree.elementInScope(token["name"], variant="table"): - self.clearStackToTableBodyContext() - self.tree.openElements.pop() - self.parser.phase = self.parser.phases["inTable"] - else: - self.parser.parseError("unexpected-end-tag-in-table-body", - {"name": token["name"]}) - - def endTagTable(self, token): - if (self.tree.elementInScope("tbody", variant="table") or - self.tree.elementInScope("thead", variant="table") or - self.tree.elementInScope("tfoot", variant="table")): - self.clearStackToTableBodyContext() - self.endTagTableRowGroup( - impliedTagToken(self.tree.openElements[-1].name)) - return token - else: - # innerHTML case - assert self.parser.innerHTML - self.parser.parseError() - - def endTagIgnore(self, token): - self.parser.parseError("unexpected-end-tag-in-table-body", - {"name": token["name"]}) - - def endTagOther(self, token): - return self.parser.phases["inTable"].processEndTag(token) - - class InRowPhase(Phase): - # http://www.whatwg.org/specs/web-apps/current-work/#in-row - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - (("td", "th"), self.startTagTableCell), - (("caption", "col", "colgroup", "tbody", "tfoot", "thead", - "tr"), self.startTagTableOther) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([ - ("tr", self.endTagTr), - ("table", self.endTagTable), - (("tbody", "tfoot", "thead"), self.endTagTableRowGroup), - (("body", "caption", "col", "colgroup", "html", "td", "th"), - self.endTagIgnore) - ]) - self.endTagHandler.default = self.endTagOther - - # helper methods (XXX unify this with other table helper methods) - def clearStackToTableRowContext(self): - while self.tree.openElements[-1].name not in ("tr", "html"): - self.parser.parseError("unexpected-implied-end-tag-in-table-row", - {"name": self.tree.openElements[-1].name}) - self.tree.openElements.pop() - - def ignoreEndTagTr(self): - return not self.tree.elementInScope("tr", variant="table") - - # the rest - def processEOF(self): - self.parser.phases["inTable"].processEOF() - - def processSpaceCharacters(self, token): - return self.parser.phases["inTable"].processSpaceCharacters(token) - - def processCharacters(self, token): - return self.parser.phases["inTable"].processCharacters(token) - - def startTagTableCell(self, token): - self.clearStackToTableRowContext() - self.tree.insertElement(token) - self.parser.phase = self.parser.phases["inCell"] - self.tree.activeFormattingElements.append(Marker) - - def startTagTableOther(self, token): - ignoreEndTag = self.ignoreEndTagTr() - self.endTagTr(impliedTagToken("tr")) - # XXX how are we sure it's always ignored in the innerHTML case? - if not ignoreEndTag: - return token - - def startTagOther(self, token): - return self.parser.phases["inTable"].processStartTag(token) - - def endTagTr(self, token): - if not self.ignoreEndTagTr(): - self.clearStackToTableRowContext() - self.tree.openElements.pop() - self.parser.phase = self.parser.phases["inTableBody"] - else: - # innerHTML case - assert self.parser.innerHTML - self.parser.parseError() - - def endTagTable(self, token): - ignoreEndTag = self.ignoreEndTagTr() - self.endTagTr(impliedTagToken("tr")) - # Reprocess the current tag if the tr end tag was not ignored - # XXX how are we sure it's always ignored in the innerHTML case? - if not ignoreEndTag: - return token - - def endTagTableRowGroup(self, token): - if self.tree.elementInScope(token["name"], variant="table"): - self.endTagTr(impliedTagToken("tr")) - return token - else: - self.parser.parseError() - - def endTagIgnore(self, token): - self.parser.parseError("unexpected-end-tag-in-table-row", - {"name": token["name"]}) - - def endTagOther(self, token): - return self.parser.phases["inTable"].processEndTag(token) - - class InCellPhase(Phase): - # http://www.whatwg.org/specs/web-apps/current-work/#in-cell - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - (("caption", "col", "colgroup", "tbody", "td", "tfoot", "th", - "thead", "tr"), self.startTagTableOther) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([ - (("td", "th"), self.endTagTableCell), - (("body", "caption", "col", "colgroup", "html"), self.endTagIgnore), - (("table", "tbody", "tfoot", "thead", "tr"), self.endTagImply) - ]) - self.endTagHandler.default = self.endTagOther - - # helper - def closeCell(self): - if self.tree.elementInScope("td", variant="table"): - self.endTagTableCell(impliedTagToken("td")) - elif self.tree.elementInScope("th", variant="table"): - self.endTagTableCell(impliedTagToken("th")) - - # the rest - def processEOF(self): - self.parser.phases["inBody"].processEOF() - - def processCharacters(self, token): - return self.parser.phases["inBody"].processCharacters(token) - - def startTagTableOther(self, token): - if (self.tree.elementInScope("td", variant="table") or - self.tree.elementInScope("th", variant="table")): - self.closeCell() - return token - else: - # innerHTML case - assert self.parser.innerHTML - self.parser.parseError() - - def startTagOther(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def endTagTableCell(self, token): - if self.tree.elementInScope(token["name"], variant="table"): - self.tree.generateImpliedEndTags(token["name"]) - if self.tree.openElements[-1].name != token["name"]: - self.parser.parseError("unexpected-cell-end-tag", - {"name": token["name"]}) - while True: - node = self.tree.openElements.pop() - if node.name == token["name"]: - break - else: - self.tree.openElements.pop() - self.tree.clearActiveFormattingElements() - self.parser.phase = self.parser.phases["inRow"] - else: - self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) - - def endTagIgnore(self, token): - self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) - - def endTagImply(self, token): - if self.tree.elementInScope(token["name"], variant="table"): - self.closeCell() - return token - else: - # sometimes innerHTML case - self.parser.parseError() - - def endTagOther(self, token): - return self.parser.phases["inBody"].processEndTag(token) - - class InSelectPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("option", self.startTagOption), - ("optgroup", self.startTagOptgroup), - ("select", self.startTagSelect), - (("input", "keygen", "textarea"), self.startTagInput), - ("script", self.startTagScript) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([ - ("option", self.endTagOption), - ("optgroup", self.endTagOptgroup), - ("select", self.endTagSelect) - ]) - self.endTagHandler.default = self.endTagOther - - # http://www.whatwg.org/specs/web-apps/current-work/#in-select - def processEOF(self): - if self.tree.openElements[-1].name != "html": - self.parser.parseError("eof-in-select") - else: - assert self.parser.innerHTML - - def processCharacters(self, token): - if token["data"] == "\u0000": - return - self.tree.insertText(token["data"]) - - def startTagOption(self, token): - # We need to imply </option> if <option> is the current node. - if self.tree.openElements[-1].name == "option": - self.tree.openElements.pop() - self.tree.insertElement(token) - - def startTagOptgroup(self, token): - if self.tree.openElements[-1].name == "option": - self.tree.openElements.pop() - if self.tree.openElements[-1].name == "optgroup": - self.tree.openElements.pop() - self.tree.insertElement(token) - - def startTagSelect(self, token): - self.parser.parseError("unexpected-select-in-select") - self.endTagSelect(impliedTagToken("select")) - - def startTagInput(self, token): - self.parser.parseError("unexpected-input-in-select") - if self.tree.elementInScope("select", variant="select"): - self.endTagSelect(impliedTagToken("select")) - return token - else: - assert self.parser.innerHTML - - def startTagScript(self, token): - return self.parser.phases["inHead"].processStartTag(token) - - def startTagOther(self, token): - self.parser.parseError("unexpected-start-tag-in-select", - {"name": token["name"]}) - - def endTagOption(self, token): - if self.tree.openElements[-1].name == "option": - self.tree.openElements.pop() - else: - self.parser.parseError("unexpected-end-tag-in-select", - {"name": "option"}) - - def endTagOptgroup(self, token): - # </optgroup> implicitly closes <option> - if (self.tree.openElements[-1].name == "option" and - self.tree.openElements[-2].name == "optgroup"): - self.tree.openElements.pop() - # It also closes </optgroup> - if self.tree.openElements[-1].name == "optgroup": - self.tree.openElements.pop() - # But nothing else - else: - self.parser.parseError("unexpected-end-tag-in-select", - {"name": "optgroup"}) - - def endTagSelect(self, token): - if self.tree.elementInScope("select", variant="select"): - node = self.tree.openElements.pop() - while node.name != "select": - node = self.tree.openElements.pop() - self.parser.resetInsertionMode() - else: - # innerHTML case - assert self.parser.innerHTML - self.parser.parseError() - - def endTagOther(self, token): - self.parser.parseError("unexpected-end-tag-in-select", - {"name": token["name"]}) - - class InSelectInTablePhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = _utils.MethodDispatcher([ - (("caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th"), - self.startTagTable) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([ - (("caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th"), - self.endTagTable) - ]) - self.endTagHandler.default = self.endTagOther - - def processEOF(self): - self.parser.phases["inSelect"].processEOF() - - def processCharacters(self, token): - return self.parser.phases["inSelect"].processCharacters(token) - - def startTagTable(self, token): - self.parser.parseError("unexpected-table-element-start-tag-in-select-in-table", {"name": token["name"]}) - self.endTagOther(impliedTagToken("select")) - return token - - def startTagOther(self, token): - return self.parser.phases["inSelect"].processStartTag(token) - - def endTagTable(self, token): - self.parser.parseError("unexpected-table-element-end-tag-in-select-in-table", {"name": token["name"]}) - if self.tree.elementInScope(token["name"], variant="table"): - self.endTagOther(impliedTagToken("select")) - return token - - def endTagOther(self, token): - return self.parser.phases["inSelect"].processEndTag(token) - - class InForeignContentPhase(Phase): - breakoutElements = frozenset(["b", "big", "blockquote", "body", "br", - "center", "code", "dd", "div", "dl", "dt", - "em", "embed", "h1", "h2", "h3", - "h4", "h5", "h6", "head", "hr", "i", "img", - "li", "listing", "menu", "meta", "nobr", - "ol", "p", "pre", "ruby", "s", "small", - "span", "strong", "strike", "sub", "sup", - "table", "tt", "u", "ul", "var"]) - - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - def adjustSVGTagNames(self, token): - replacements = {"altglyph": "altGlyph", - "altglyphdef": "altGlyphDef", - "altglyphitem": "altGlyphItem", - "animatecolor": "animateColor", - "animatemotion": "animateMotion", - "animatetransform": "animateTransform", - "clippath": "clipPath", - "feblend": "feBlend", - "fecolormatrix": "feColorMatrix", - "fecomponenttransfer": "feComponentTransfer", - "fecomposite": "feComposite", - "feconvolvematrix": "feConvolveMatrix", - "fediffuselighting": "feDiffuseLighting", - "fedisplacementmap": "feDisplacementMap", - "fedistantlight": "feDistantLight", - "feflood": "feFlood", - "fefunca": "feFuncA", - "fefuncb": "feFuncB", - "fefuncg": "feFuncG", - "fefuncr": "feFuncR", - "fegaussianblur": "feGaussianBlur", - "feimage": "feImage", - "femerge": "feMerge", - "femergenode": "feMergeNode", - "femorphology": "feMorphology", - "feoffset": "feOffset", - "fepointlight": "fePointLight", - "fespecularlighting": "feSpecularLighting", - "fespotlight": "feSpotLight", - "fetile": "feTile", - "feturbulence": "feTurbulence", - "foreignobject": "foreignObject", - "glyphref": "glyphRef", - "lineargradient": "linearGradient", - "radialgradient": "radialGradient", - "textpath": "textPath"} - - if token["name"] in replacements: - token["name"] = replacements[token["name"]] - - def processCharacters(self, token): - if token["data"] == "\u0000": - token["data"] = "\uFFFD" - elif (self.parser.framesetOK and - any(char not in spaceCharacters for char in token["data"])): - self.parser.framesetOK = False - Phase.processCharacters(self, token) - - def processStartTag(self, token): - currentNode = self.tree.openElements[-1] - if (token["name"] in self.breakoutElements or - (token["name"] == "font" and - set(token["data"].keys()) & set(["color", "face", "size"]))): - self.parser.parseError("unexpected-html-element-in-foreign-content", - {"name": token["name"]}) - while (self.tree.openElements[-1].namespace != - self.tree.defaultNamespace and - not self.parser.isHTMLIntegrationPoint(self.tree.openElements[-1]) and - not self.parser.isMathMLTextIntegrationPoint(self.tree.openElements[-1])): - self.tree.openElements.pop() - return token - - else: - if currentNode.namespace == namespaces["mathml"]: - self.parser.adjustMathMLAttributes(token) - elif currentNode.namespace == namespaces["svg"]: - self.adjustSVGTagNames(token) - self.parser.adjustSVGAttributes(token) - self.parser.adjustForeignAttributes(token) - token["namespace"] = currentNode.namespace - self.tree.insertElement(token) - if token["selfClosing"]: - self.tree.openElements.pop() - token["selfClosingAcknowledged"] = True - - def processEndTag(self, token): - nodeIndex = len(self.tree.openElements) - 1 - node = self.tree.openElements[-1] - if node.name.translate(asciiUpper2Lower) != token["name"]: - self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) - - while True: - if node.name.translate(asciiUpper2Lower) == token["name"]: - # XXX this isn't in the spec but it seems necessary - if self.parser.phase == self.parser.phases["inTableText"]: - self.parser.phase.flushCharacters() - self.parser.phase = self.parser.phase.originalPhase - while self.tree.openElements.pop() != node: - assert self.tree.openElements - new_token = None - break - nodeIndex -= 1 - - node = self.tree.openElements[nodeIndex] - if node.namespace != self.tree.defaultNamespace: - continue - else: - new_token = self.parser.phase.processEndTag(token) - break - return new_token - - class AfterBodyPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([("html", self.endTagHtml)]) - self.endTagHandler.default = self.endTagOther - - def processEOF(self): - # Stop parsing - pass - - def processComment(self, token): - # This is needed because data is to be appended to the <html> element - # here and not to whatever is currently open. - self.tree.insertComment(token, self.tree.openElements[0]) - - def processCharacters(self, token): - self.parser.parseError("unexpected-char-after-body") - self.parser.phase = self.parser.phases["inBody"] - return token - - def startTagHtml(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def startTagOther(self, token): - self.parser.parseError("unexpected-start-tag-after-body", - {"name": token["name"]}) - self.parser.phase = self.parser.phases["inBody"] - return token - - def endTagHtml(self, name): - if self.parser.innerHTML: - self.parser.parseError("unexpected-end-tag-after-body-innerhtml") - else: - self.parser.phase = self.parser.phases["afterAfterBody"] - - def endTagOther(self, token): - self.parser.parseError("unexpected-end-tag-after-body", - {"name": token["name"]}) - self.parser.phase = self.parser.phases["inBody"] - return token - - class InFramesetPhase(Phase): - # http://www.whatwg.org/specs/web-apps/current-work/#in-frameset - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("frameset", self.startTagFrameset), - ("frame", self.startTagFrame), - ("noframes", self.startTagNoframes) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([ - ("frameset", self.endTagFrameset) - ]) - self.endTagHandler.default = self.endTagOther - - def processEOF(self): - if self.tree.openElements[-1].name != "html": - self.parser.parseError("eof-in-frameset") - else: - assert self.parser.innerHTML - - def processCharacters(self, token): - self.parser.parseError("unexpected-char-in-frameset") - - def startTagFrameset(self, token): - self.tree.insertElement(token) - - def startTagFrame(self, token): - self.tree.insertElement(token) - self.tree.openElements.pop() - - def startTagNoframes(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def startTagOther(self, token): - self.parser.parseError("unexpected-start-tag-in-frameset", - {"name": token["name"]}) - - def endTagFrameset(self, token): - if self.tree.openElements[-1].name == "html": - # innerHTML case - self.parser.parseError("unexpected-frameset-in-frameset-innerhtml") - else: - self.tree.openElements.pop() - if (not self.parser.innerHTML and - self.tree.openElements[-1].name != "frameset"): - # If we're not in innerHTML mode and the current node is not a - # "frameset" element (anymore) then switch. - self.parser.phase = self.parser.phases["afterFrameset"] - - def endTagOther(self, token): - self.parser.parseError("unexpected-end-tag-in-frameset", - {"name": token["name"]}) - - class AfterFramesetPhase(Phase): - # http://www.whatwg.org/specs/web-apps/current-work/#after3 - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("noframes", self.startTagNoframes) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = _utils.MethodDispatcher([ - ("html", self.endTagHtml) - ]) - self.endTagHandler.default = self.endTagOther - - def processEOF(self): - # Stop parsing - pass - - def processCharacters(self, token): - self.parser.parseError("unexpected-char-after-frameset") - - def startTagNoframes(self, token): - return self.parser.phases["inHead"].processStartTag(token) - - def startTagOther(self, token): - self.parser.parseError("unexpected-start-tag-after-frameset", - {"name": token["name"]}) - - def endTagHtml(self, token): - self.parser.phase = self.parser.phases["afterAfterFrameset"] - - def endTagOther(self, token): - self.parser.parseError("unexpected-end-tag-after-frameset", - {"name": token["name"]}) - - class AfterAfterBodyPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml) - ]) - self.startTagHandler.default = self.startTagOther - - def processEOF(self): - pass - - def processComment(self, token): - self.tree.insertComment(token, self.tree.document) - - def processSpaceCharacters(self, token): - return self.parser.phases["inBody"].processSpaceCharacters(token) - - def processCharacters(self, token): - self.parser.parseError("expected-eof-but-got-char") - self.parser.phase = self.parser.phases["inBody"] - return token - - def startTagHtml(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def startTagOther(self, token): - self.parser.parseError("expected-eof-but-got-start-tag", - {"name": token["name"]}) - self.parser.phase = self.parser.phases["inBody"] - return token - - def processEndTag(self, token): - self.parser.parseError("expected-eof-but-got-end-tag", - {"name": token["name"]}) - self.parser.phase = self.parser.phases["inBody"] - return token - - class AfterAfterFramesetPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = _utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("noframes", self.startTagNoFrames) - ]) - self.startTagHandler.default = self.startTagOther - - def processEOF(self): - pass - - def processComment(self, token): - self.tree.insertComment(token, self.tree.document) - - def processSpaceCharacters(self, token): - return self.parser.phases["inBody"].processSpaceCharacters(token) - - def processCharacters(self, token): - self.parser.parseError("expected-eof-but-got-char") - - def startTagHtml(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def startTagNoFrames(self, token): - return self.parser.phases["inHead"].processStartTag(token) - - def startTagOther(self, token): - self.parser.parseError("expected-eof-but-got-start-tag", - {"name": token["name"]}) - - def processEndTag(self, token): - self.parser.parseError("expected-eof-but-got-end-tag", - {"name": token["name"]}) - # pylint:enable=unused-argument - - return { - "initial": InitialPhase, - "beforeHtml": BeforeHtmlPhase, - "beforeHead": BeforeHeadPhase, - "inHead": InHeadPhase, - "inHeadNoscript": InHeadNoscriptPhase, - "afterHead": AfterHeadPhase, - "inBody": InBodyPhase, - "text": TextPhase, - "inTable": InTablePhase, - "inTableText": InTableTextPhase, - "inCaption": InCaptionPhase, - "inColumnGroup": InColumnGroupPhase, - "inTableBody": InTableBodyPhase, - "inRow": InRowPhase, - "inCell": InCellPhase, - "inSelect": InSelectPhase, - "inSelectInTable": InSelectInTablePhase, - "inForeignContent": InForeignContentPhase, - "afterBody": AfterBodyPhase, - "inFrameset": InFramesetPhase, - "afterFrameset": AfterFramesetPhase, - "afterAfterBody": AfterAfterBodyPhase, - "afterAfterFrameset": AfterAfterFramesetPhase, - # XXX after after frameset - } - - -def adjust_attributes(token, replacements): - needs_adjustment = viewkeys(token['data']) & viewkeys(replacements) - if needs_adjustment: - token['data'] = OrderedDict((replacements.get(k, k), v) - for k, v in token['data'].items()) - - -def impliedTagToken(name, type="EndTag", attributes=None, - selfClosing=False): - if attributes is None: - attributes = {} - return {"type": tokenTypes[type], "name": name, "data": attributes, - "selfClosing": selfClosing} - - -class ParseError(Exception): - """Error in parsed document""" - pass diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/serializer.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/serializer.py deleted file mode 100644 index 53f4d44..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/serializer.py +++ /dev/null @@ -1,409 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals -from pip._vendor.six import text_type - -import re - -from codecs import register_error, xmlcharrefreplace_errors - -from .constants import voidElements, booleanAttributes, spaceCharacters -from .constants import rcdataElements, entities, xmlEntities -from . import treewalkers, _utils -from xml.sax.saxutils import escape - -_quoteAttributeSpecChars = "".join(spaceCharacters) + "\"'=<>`" -_quoteAttributeSpec = re.compile("[" + _quoteAttributeSpecChars + "]") -_quoteAttributeLegacy = re.compile("[" + _quoteAttributeSpecChars + - "\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" - "\x20\x2f\x60\xa0\u1680\u180e\u180f\u2000" - "\u2001\u2002\u2003\u2004\u2005\u2006\u2007" - "\u2008\u2009\u200a\u2028\u2029\u202f\u205f" - "\u3000]") - - -_encode_entity_map = {} -_is_ucs4 = len("\U0010FFFF") == 1 -for k, v in list(entities.items()): - # skip multi-character entities - if ((_is_ucs4 and len(v) > 1) or - (not _is_ucs4 and len(v) > 2)): - continue - if v != "&": - if len(v) == 2: - v = _utils.surrogatePairToCodepoint(v) - else: - v = ord(v) - if v not in _encode_entity_map or k.islower(): - # prefer < over < and similarly for &, >, etc. - _encode_entity_map[v] = k - - -def htmlentityreplace_errors(exc): - if isinstance(exc, (UnicodeEncodeError, UnicodeTranslateError)): - res = [] - codepoints = [] - skip = False - for i, c in enumerate(exc.object[exc.start:exc.end]): - if skip: - skip = False - continue - index = i + exc.start - if _utils.isSurrogatePair(exc.object[index:min([exc.end, index + 2])]): - codepoint = _utils.surrogatePairToCodepoint(exc.object[index:index + 2]) - skip = True - else: - codepoint = ord(c) - codepoints.append(codepoint) - for cp in codepoints: - e = _encode_entity_map.get(cp) - if e: - res.append("&") - res.append(e) - if not e.endswith(";"): - res.append(";") - else: - res.append("&#x%s;" % (hex(cp)[2:])) - return ("".join(res), exc.end) - else: - return xmlcharrefreplace_errors(exc) - - -register_error("htmlentityreplace", htmlentityreplace_errors) - - -def serialize(input, tree="etree", encoding=None, **serializer_opts): - """Serializes the input token stream using the specified treewalker - - :arg input: the token stream to serialize - - :arg tree: the treewalker to use - - :arg encoding: the encoding to use - - :arg serializer_opts: any options to pass to the - :py:class:`html5lib.serializer.HTMLSerializer` that gets created - - :returns: the tree serialized as a string - - Example: - - >>> from html5lib.html5parser import parse - >>> from html5lib.serializer import serialize - >>> token_stream = parse('<html><body><p>Hi!</p></body></html>') - >>> serialize(token_stream, omit_optional_tags=False) - '<html><head></head><body><p>Hi!</p></body></html>' - - """ - # XXX: Should we cache this? - walker = treewalkers.getTreeWalker(tree) - s = HTMLSerializer(**serializer_opts) - return s.render(walker(input), encoding) - - -class HTMLSerializer(object): - - # attribute quoting options - quote_attr_values = "legacy" # be secure by default - quote_char = '"' - use_best_quote_char = True - - # tag syntax options - omit_optional_tags = True - minimize_boolean_attributes = True - use_trailing_solidus = False - space_before_trailing_solidus = True - - # escaping options - escape_lt_in_attrs = False - escape_rcdata = False - resolve_entities = True - - # miscellaneous options - alphabetical_attributes = False - inject_meta_charset = True - strip_whitespace = False - sanitize = False - - options = ("quote_attr_values", "quote_char", "use_best_quote_char", - "omit_optional_tags", "minimize_boolean_attributes", - "use_trailing_solidus", "space_before_trailing_solidus", - "escape_lt_in_attrs", "escape_rcdata", "resolve_entities", - "alphabetical_attributes", "inject_meta_charset", - "strip_whitespace", "sanitize") - - def __init__(self, **kwargs): - """Initialize HTMLSerializer - - :arg inject_meta_charset: Whether or not to inject the meta charset. - - Defaults to ``True``. - - :arg quote_attr_values: Whether to quote attribute values that don't - require quoting per legacy browser behavior (``"legacy"``), when - required by the standard (``"spec"``), or always (``"always"``). - - Defaults to ``"legacy"``. - - :arg quote_char: Use given quote character for attribute quoting. - - Defaults to ``"`` which will use double quotes unless attribute - value contains a double quote, in which case single quotes are - used. - - :arg escape_lt_in_attrs: Whether or not to escape ``<`` in attribute - values. - - Defaults to ``False``. - - :arg escape_rcdata: Whether to escape characters that need to be - escaped within normal elements within rcdata elements such as - style. - - Defaults to ``False``. - - :arg resolve_entities: Whether to resolve named character entities that - appear in the source tree. The XML predefined entities < > - & " ' are unaffected by this setting. - - Defaults to ``True``. - - :arg strip_whitespace: Whether to remove semantically meaningless - whitespace. (This compresses all whitespace to a single space - except within ``pre``.) - - Defaults to ``False``. - - :arg minimize_boolean_attributes: Shortens boolean attributes to give - just the attribute value, for example:: - - <input disabled="disabled"> - - becomes:: - - <input disabled> - - Defaults to ``True``. - - :arg use_trailing_solidus: Includes a close-tag slash at the end of the - start tag of void elements (empty elements whose end tag is - forbidden). E.g. ``<hr/>``. - - Defaults to ``False``. - - :arg space_before_trailing_solidus: Places a space immediately before - the closing slash in a tag using a trailing solidus. E.g. - ``<hr />``. Requires ``use_trailing_solidus=True``. - - Defaults to ``True``. - - :arg sanitize: Strip all unsafe or unknown constructs from output. - See :py:class:`html5lib.filters.sanitizer.Filter`. - - Defaults to ``False``. - - :arg omit_optional_tags: Omit start/end tags that are optional. - - Defaults to ``True``. - - :arg alphabetical_attributes: Reorder attributes to be in alphabetical order. - - Defaults to ``False``. - - """ - unexpected_args = frozenset(kwargs) - frozenset(self.options) - if len(unexpected_args) > 0: - raise TypeError("__init__() got an unexpected keyword argument '%s'" % next(iter(unexpected_args))) - if 'quote_char' in kwargs: - self.use_best_quote_char = False - for attr in self.options: - setattr(self, attr, kwargs.get(attr, getattr(self, attr))) - self.errors = [] - self.strict = False - - def encode(self, string): - assert(isinstance(string, text_type)) - if self.encoding: - return string.encode(self.encoding, "htmlentityreplace") - else: - return string - - def encodeStrict(self, string): - assert(isinstance(string, text_type)) - if self.encoding: - return string.encode(self.encoding, "strict") - else: - return string - - def serialize(self, treewalker, encoding=None): - # pylint:disable=too-many-nested-blocks - self.encoding = encoding - in_cdata = False - self.errors = [] - - if encoding and self.inject_meta_charset: - from .filters.inject_meta_charset import Filter - treewalker = Filter(treewalker, encoding) - # Alphabetical attributes is here under the assumption that none of - # the later filters add or change order of attributes; it needs to be - # before the sanitizer so escaped elements come out correctly - if self.alphabetical_attributes: - from .filters.alphabeticalattributes import Filter - treewalker = Filter(treewalker) - # WhitespaceFilter should be used before OptionalTagFilter - # for maximum efficiently of this latter filter - if self.strip_whitespace: - from .filters.whitespace import Filter - treewalker = Filter(treewalker) - if self.sanitize: - from .filters.sanitizer import Filter - treewalker = Filter(treewalker) - if self.omit_optional_tags: - from .filters.optionaltags import Filter - treewalker = Filter(treewalker) - - for token in treewalker: - type = token["type"] - if type == "Doctype": - doctype = "<!DOCTYPE %s" % token["name"] - - if token["publicId"]: - doctype += ' PUBLIC "%s"' % token["publicId"] - elif token["systemId"]: - doctype += " SYSTEM" - if token["systemId"]: - if token["systemId"].find('"') >= 0: - if token["systemId"].find("'") >= 0: - self.serializeError("System identifer contains both single and double quote characters") - quote_char = "'" - else: - quote_char = '"' - doctype += " %s%s%s" % (quote_char, token["systemId"], quote_char) - - doctype += ">" - yield self.encodeStrict(doctype) - - elif type in ("Characters", "SpaceCharacters"): - if type == "SpaceCharacters" or in_cdata: - if in_cdata and token["data"].find("</") >= 0: - self.serializeError("Unexpected </ in CDATA") - yield self.encode(token["data"]) - else: - yield self.encode(escape(token["data"])) - - elif type in ("StartTag", "EmptyTag"): - name = token["name"] - yield self.encodeStrict("<%s" % name) - if name in rcdataElements and not self.escape_rcdata: - in_cdata = True - elif in_cdata: - self.serializeError("Unexpected child element of a CDATA element") - for (_, attr_name), attr_value in token["data"].items(): - # TODO: Add namespace support here - k = attr_name - v = attr_value - yield self.encodeStrict(' ') - - yield self.encodeStrict(k) - if not self.minimize_boolean_attributes or \ - (k not in booleanAttributes.get(name, tuple()) and - k not in booleanAttributes.get("", tuple())): - yield self.encodeStrict("=") - if self.quote_attr_values == "always" or len(v) == 0: - quote_attr = True - elif self.quote_attr_values == "spec": - quote_attr = _quoteAttributeSpec.search(v) is not None - elif self.quote_attr_values == "legacy": - quote_attr = _quoteAttributeLegacy.search(v) is not None - else: - raise ValueError("quote_attr_values must be one of: " - "'always', 'spec', or 'legacy'") - v = v.replace("&", "&") - if self.escape_lt_in_attrs: - v = v.replace("<", "<") - if quote_attr: - quote_char = self.quote_char - if self.use_best_quote_char: - if "'" in v and '"' not in v: - quote_char = '"' - elif '"' in v and "'" not in v: - quote_char = "'" - if quote_char == "'": - v = v.replace("'", "'") - else: - v = v.replace('"', """) - yield self.encodeStrict(quote_char) - yield self.encode(v) - yield self.encodeStrict(quote_char) - else: - yield self.encode(v) - if name in voidElements and self.use_trailing_solidus: - if self.space_before_trailing_solidus: - yield self.encodeStrict(" /") - else: - yield self.encodeStrict("/") - yield self.encode(">") - - elif type == "EndTag": - name = token["name"] - if name in rcdataElements: - in_cdata = False - elif in_cdata: - self.serializeError("Unexpected child element of a CDATA element") - yield self.encodeStrict("</%s>" % name) - - elif type == "Comment": - data = token["data"] - if data.find("--") >= 0: - self.serializeError("Comment contains --") - yield self.encodeStrict("<!--%s-->" % token["data"]) - - elif type == "Entity": - name = token["name"] - key = name + ";" - if key not in entities: - self.serializeError("Entity %s not recognized" % name) - if self.resolve_entities and key not in xmlEntities: - data = entities[key] - else: - data = "&%s;" % name - yield self.encodeStrict(data) - - else: - self.serializeError(token["data"]) - - def render(self, treewalker, encoding=None): - """Serializes the stream from the treewalker into a string - - :arg treewalker: the treewalker to serialize - - :arg encoding: the string encoding to use - - :returns: the serialized tree - - Example: - - >>> from html5lib import parse, getTreeWalker - >>> from html5lib.serializer import HTMLSerializer - >>> token_stream = parse('<html><body>Hi!</body></html>') - >>> walker = getTreeWalker('etree') - >>> serializer = HTMLSerializer(omit_optional_tags=False) - >>> serializer.render(walker(token_stream)) - '<html><head></head><body>Hi!</body></html>' - - """ - if encoding: - return b"".join(list(self.serialize(treewalker, encoding))) - else: - return "".join(list(self.serialize(treewalker))) - - def serializeError(self, data="XXX ERROR MESSAGE NEEDED"): - # XXX The idea is to make data mandatory. - self.errors.append(data) - if self.strict: - raise SerializeError - - -class SerializeError(Exception): - """Error in serialized tree""" - pass diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py deleted file mode 100644 index 7ef5959..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -"""Tree adapters let you convert from one tree structure to another - -Example: - -.. code-block:: python - - from pip._vendor import html5lib - from pip._vendor.html5lib.treeadapters import genshi - - doc = '<html><body>Hi!</body></html>' - treebuilder = html5lib.getTreeBuilder('etree') - parser = html5lib.HTMLParser(tree=treebuilder) - tree = parser.parse(doc) - TreeWalker = html5lib.getTreeWalker('etree') - - genshi_tree = genshi.to_genshi(TreeWalker(tree)) - -""" -from __future__ import absolute_import, division, unicode_literals - -from . import sax - -__all__ = ["sax"] - -try: - from . import genshi # noqa -except ImportError: - pass -else: - __all__.append("genshi") diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treeadapters/genshi.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treeadapters/genshi.py deleted file mode 100644 index 61d5fb6..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treeadapters/genshi.py +++ /dev/null @@ -1,54 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from genshi.core import QName, Attrs -from genshi.core import START, END, TEXT, COMMENT, DOCTYPE - - -def to_genshi(walker): - """Convert a tree to a genshi tree - - :arg walker: the treewalker to use to walk the tree to convert it - - :returns: generator of genshi nodes - - """ - text = [] - for token in walker: - type = token["type"] - if type in ("Characters", "SpaceCharacters"): - text.append(token["data"]) - elif text: - yield TEXT, "".join(text), (None, -1, -1) - text = [] - - if type in ("StartTag", "EmptyTag"): - if token["namespace"]: - name = "{%s}%s" % (token["namespace"], token["name"]) - else: - name = token["name"] - attrs = Attrs([(QName("{%s}%s" % attr if attr[0] is not None else attr[1]), value) - for attr, value in token["data"].items()]) - yield (START, (QName(name), attrs), (None, -1, -1)) - if type == "EmptyTag": - type = "EndTag" - - if type == "EndTag": - if token["namespace"]: - name = "{%s}%s" % (token["namespace"], token["name"]) - else: - name = token["name"] - - yield END, QName(name), (None, -1, -1) - - elif type == "Comment": - yield COMMENT, token["data"], (None, -1, -1) - - elif type == "Doctype": - yield DOCTYPE, (token["name"], token["publicId"], - token["systemId"]), (None, -1, -1) - - else: - pass # FIXME: What to do? - - if text: - yield TEXT, "".join(text), (None, -1, -1) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treeadapters/sax.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treeadapters/sax.py deleted file mode 100644 index f4ccea5..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treeadapters/sax.py +++ /dev/null @@ -1,50 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from xml.sax.xmlreader import AttributesNSImpl - -from ..constants import adjustForeignAttributes, unadjustForeignAttributes - -prefix_mapping = {} -for prefix, localName, namespace in adjustForeignAttributes.values(): - if prefix is not None: - prefix_mapping[prefix] = namespace - - -def to_sax(walker, handler): - """Call SAX-like content handler based on treewalker walker - - :arg walker: the treewalker to use to walk the tree to convert it - - :arg handler: SAX handler to use - - """ - handler.startDocument() - for prefix, namespace in prefix_mapping.items(): - handler.startPrefixMapping(prefix, namespace) - - for token in walker: - type = token["type"] - if type == "Doctype": - continue - elif type in ("StartTag", "EmptyTag"): - attrs = AttributesNSImpl(token["data"], - unadjustForeignAttributes) - handler.startElementNS((token["namespace"], token["name"]), - token["name"], - attrs) - if type == "EmptyTag": - handler.endElementNS((token["namespace"], token["name"]), - token["name"]) - elif type == "EndTag": - handler.endElementNS((token["namespace"], token["name"]), - token["name"]) - elif type in ("Characters", "SpaceCharacters"): - handler.characters(token["data"]) - elif type == "Comment": - pass - else: - assert False, "Unknown token type" - - for prefix, namespace in prefix_mapping.items(): - handler.endPrefixMapping(prefix) - handler.endDocument() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py deleted file mode 100644 index d44447e..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py +++ /dev/null @@ -1,88 +0,0 @@ -"""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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/base.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/base.py deleted file mode 100644 index 73973db..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/base.py +++ /dev/null @@ -1,417 +0,0 @@ -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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/dom.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/dom.py deleted file mode 100644 index dcfac22..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/dom.py +++ /dev/null @@ -1,236 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - - -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<!DOCTYPE %s "%s" "%s">""" % - (' ' * indent, element.name, publicId, systemId)) - else: - rv.append("|%s<!DOCTYPE %s>" % (' ' * indent, element.name)) - else: - rv.append("|%s<!DOCTYPE >" % (' ' * 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<!-- %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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/etree.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/etree.py deleted file mode 100644 index 0dedf44..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/etree.py +++ /dev/null @@ -1,340 +0,0 @@ -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, "<!DOCTYPE>") - 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 == "<!DOCTYPE>": - if element.get("publicId") or element.get("systemId"): - publicId = element.get("publicId") or "" - systemId = element.get("systemId") or "" - rv.append("""<!DOCTYPE %s "%s" "%s">""" % - (element.text, publicId, systemId)) - else: - rv.append("<!DOCTYPE %s>" % (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<!-- %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 == "<!DOCTYPE>": - if element.get("publicId") or element.get("systemId"): - publicId = element.get("publicId") or "" - systemId = element.get("systemId") or "" - rv.append("""<!DOCTYPE %s PUBLIC "%s" "%s">""" % - (element.text, publicId, systemId)) - else: - rv.append("<!DOCTYPE %s>" % (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("<!--%s-->" % (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("</%s>" % (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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py deleted file mode 100644 index ca12a99..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py +++ /dev/null @@ -1,366 +0,0 @@ -"""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 = "<!DOCTYPE %s>" % element.docinfo.root_name - else: - dtd_str = """<!DOCTYPE %s "%s" "%s">""" % ( - 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<!-- %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 = "<!DOCTYPE %s>" % element.docinfo.root_name - rv.append(dtd_str) - serializeElement(element.getroot()) - - elif element.tag == comment_type: - rv.append("<!--%s-->" % (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("</%s>" % (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 += "<!DOCTYPE %s" % self.doctype.name - if (self.doctype.publicId is not None or - self.doctype.systemId is not None): - docStr += (' PUBLIC "%s" ' % - (self.infosetFilter.coercePubid(self.doctype.publicId or ""))) - if self.doctype.systemId: - sysid = self.doctype.systemId - if sysid.find("'") >= 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 += "<THIS_SHOULD_NEVER_APPEAR_PUBLICLY/>" - 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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py deleted file mode 100644 index 9bec207..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py +++ /dev/null @@ -1,154 +0,0 @@ -"""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<!-- %s -->" % (" " * indent, token["data"])) - - elif type == "Doctype": - if token["name"]: - if token["publicId"]: - output.append("""%s<!DOCTYPE %s "%s" "%s">""" % - (" " * indent, - token["name"], - token["publicId"], - token["systemId"] if token["systemId"] else "")) - elif token["systemId"]: - output.append("""%s<!DOCTYPE %s "" "%s">""" % - (" " * indent, - token["name"], - token["systemId"])) - else: - output.append("%s<!DOCTYPE %s>" % (" " * indent, - token["name"])) - else: - output.append("%s<!DOCTYPE >" % (" " * 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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/base.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/base.py deleted file mode 100644 index 80c474c..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/base.py +++ /dev/null @@ -1,252 +0,0 @@ -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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/dom.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/dom.py deleted file mode 100644 index b0c89b0..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/dom.py +++ /dev/null @@ -1,43 +0,0 @@ -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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/etree.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/etree.py deleted file mode 100644 index 95fc0c1..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/etree.py +++ /dev/null @@ -1,130 +0,0 @@ -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 == "<!DOCTYPE>": - 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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.py deleted file mode 100644 index e81ddf3..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.py +++ /dev/null @@ -1,213 +0,0 @@ -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() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/genshi.py b/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/genshi.py deleted file mode 100644 index 7483be2..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/html5lib/treewalkers/genshi.py +++ /dev/null @@ -1,69 +0,0 @@ -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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/idna/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/idna/__init__.py deleted file mode 100644 index 847bf93..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/idna/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .package_data import __version__ -from .core import * diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/idna/codec.py b/venv2/lib/python2.7/site-packages/pip/_vendor/idna/codec.py deleted file mode 100644 index 98c65ea..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/idna/codec.py +++ /dev/null @@ -1,118 +0,0 @@ -from .core import encode, decode, alabel, ulabel, IDNAError -import codecs -import re - -_unicode_dots_re = re.compile(u'[\u002e\u3002\uff0e\uff61]') - -class Codec(codecs.Codec): - - def encode(self, data, errors='strict'): - - if errors != 'strict': - raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) - - if not data: - return "", 0 - - return encode(data), len(data) - - def decode(self, data, errors='strict'): - - if errors != 'strict': - raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) - - if not data: - return u"", 0 - - return decode(data), len(data) - -class IncrementalEncoder(codecs.BufferedIncrementalEncoder): - def _buffer_encode(self, data, errors, final): - if errors != 'strict': - raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) - - if not data: - return ("", 0) - - labels = _unicode_dots_re.split(data) - trailing_dot = u'' - if labels: - if not labels[-1]: - trailing_dot = '.' - del labels[-1] - elif not final: - # Keep potentially unfinished label until the next call - del labels[-1] - if labels: - trailing_dot = '.' - - result = [] - size = 0 - for label in labels: - result.append(alabel(label)) - if size: - size += 1 - size += len(label) - - # Join with U+002E - result = ".".join(result) + trailing_dot - size += len(trailing_dot) - return (result, size) - -class IncrementalDecoder(codecs.BufferedIncrementalDecoder): - def _buffer_decode(self, data, errors, final): - if errors != 'strict': - raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) - - if not data: - return (u"", 0) - - # IDNA allows decoding to operate on Unicode strings, too. - if isinstance(data, unicode): - labels = _unicode_dots_re.split(data) - else: - # Must be ASCII string - data = str(data) - unicode(data, "ascii") - labels = data.split(".") - - trailing_dot = u'' - if labels: - if not labels[-1]: - trailing_dot = u'.' - del labels[-1] - elif not final: - # Keep potentially unfinished label until the next call - del labels[-1] - if labels: - trailing_dot = u'.' - - result = [] - size = 0 - for label in labels: - result.append(ulabel(label)) - if size: - size += 1 - size += len(label) - - result = u".".join(result) + trailing_dot - size += len(trailing_dot) - return (result, size) - - -class StreamWriter(Codec, codecs.StreamWriter): - pass - -class StreamReader(Codec, codecs.StreamReader): - pass - -def getregentry(): - return codecs.CodecInfo( - name='idna', - encode=Codec().encode, - decode=Codec().decode, - incrementalencoder=IncrementalEncoder, - incrementaldecoder=IncrementalDecoder, - streamwriter=StreamWriter, - streamreader=StreamReader, - ) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/idna/compat.py b/venv2/lib/python2.7/site-packages/pip/_vendor/idna/compat.py deleted file mode 100644 index 4d47f33..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/idna/compat.py +++ /dev/null @@ -1,12 +0,0 @@ -from .core import * -from .codec import * - -def ToASCII(label): - return encode(label) - -def ToUnicode(label): - return decode(label) - -def nameprep(s): - raise NotImplementedError("IDNA 2008 does not utilise nameprep protocol") - diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/idna/core.py b/venv2/lib/python2.7/site-packages/pip/_vendor/idna/core.py deleted file mode 100644 index 104624a..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/idna/core.py +++ /dev/null @@ -1,396 +0,0 @@ -from . import idnadata -import bisect -import unicodedata -import re -import sys -from .intranges import intranges_contain - -_virama_combining_class = 9 -_alabel_prefix = b'xn--' -_unicode_dots_re = re.compile(u'[\u002e\u3002\uff0e\uff61]') - -if sys.version_info[0] == 3: - unicode = str - unichr = chr - -class IDNAError(UnicodeError): - """ Base exception for all IDNA-encoding related problems """ - pass - - -class IDNABidiError(IDNAError): - """ Exception when bidirectional requirements are not satisfied """ - pass - - -class InvalidCodepoint(IDNAError): - """ Exception when a disallowed or unallocated codepoint is used """ - pass - - -class InvalidCodepointContext(IDNAError): - """ Exception when the codepoint is not valid in the context it is used """ - pass - - -def _combining_class(cp): - v = unicodedata.combining(unichr(cp)) - if v == 0: - if not unicodedata.name(unichr(cp)): - raise ValueError("Unknown character in unicodedata") - return v - -def _is_script(cp, script): - return intranges_contain(ord(cp), idnadata.scripts[script]) - -def _punycode(s): - return s.encode('punycode') - -def _unot(s): - return 'U+{0:04X}'.format(s) - - -def valid_label_length(label): - - if len(label) > 63: - return False - return True - - -def valid_string_length(label, trailing_dot): - - if len(label) > (254 if trailing_dot else 253): - return False - return True - - -def check_bidi(label, check_ltr=False): - - # Bidi rules should only be applied if string contains RTL characters - bidi_label = False - for (idx, cp) in enumerate(label, 1): - direction = unicodedata.bidirectional(cp) - if direction == '': - # String likely comes from a newer version of Unicode - raise IDNABidiError('Unknown directionality in label {0} at position {1}'.format(repr(label), idx)) - if direction in ['R', 'AL', 'AN']: - bidi_label = True - if not bidi_label and not check_ltr: - return True - - # Bidi rule 1 - direction = unicodedata.bidirectional(label[0]) - if direction in ['R', 'AL']: - rtl = True - elif direction == 'L': - rtl = False - else: - raise IDNABidiError('First codepoint in label {0} must be directionality L, R or AL'.format(repr(label))) - - valid_ending = False - number_type = False - for (idx, cp) in enumerate(label, 1): - direction = unicodedata.bidirectional(cp) - - if rtl: - # Bidi rule 2 - if not direction in ['R', 'AL', 'AN', 'EN', 'ES', 'CS', 'ET', 'ON', 'BN', 'NSM']: - raise IDNABidiError('Invalid direction for codepoint at position {0} in a right-to-left label'.format(idx)) - # Bidi rule 3 - if direction in ['R', 'AL', 'EN', 'AN']: - valid_ending = True - elif direction != 'NSM': - valid_ending = False - # Bidi rule 4 - if direction in ['AN', 'EN']: - if not number_type: - number_type = direction - else: - if number_type != direction: - raise IDNABidiError('Can not mix numeral types in a right-to-left label') - else: - # Bidi rule 5 - if not direction in ['L', 'EN', 'ES', 'CS', 'ET', 'ON', 'BN', 'NSM']: - raise IDNABidiError('Invalid direction for codepoint at position {0} in a left-to-right label'.format(idx)) - # Bidi rule 6 - if direction in ['L', 'EN']: - valid_ending = True - elif direction != 'NSM': - valid_ending = False - - if not valid_ending: - raise IDNABidiError('Label ends with illegal codepoint directionality') - - return True - - -def check_initial_combiner(label): - - if unicodedata.category(label[0])[0] == 'M': - raise IDNAError('Label begins with an illegal combining character') - return True - - -def check_hyphen_ok(label): - - if label[2:4] == '--': - raise IDNAError('Label has disallowed hyphens in 3rd and 4th position') - if label[0] == '-' or label[-1] == '-': - raise IDNAError('Label must not start or end with a hyphen') - return True - - -def check_nfc(label): - - if unicodedata.normalize('NFC', label) != label: - raise IDNAError('Label must be in Normalization Form C') - - -def valid_contextj(label, pos): - - cp_value = ord(label[pos]) - - if cp_value == 0x200c: - - if pos > 0: - if _combining_class(ord(label[pos - 1])) == _virama_combining_class: - return True - - ok = False - for i in range(pos-1, -1, -1): - joining_type = idnadata.joining_types.get(ord(label[i])) - if joining_type == ord('T'): - continue - if joining_type in [ord('L'), ord('D')]: - ok = True - break - - if not ok: - return False - - ok = False - for i in range(pos+1, len(label)): - joining_type = idnadata.joining_types.get(ord(label[i])) - if joining_type == ord('T'): - continue - if joining_type in [ord('R'), ord('D')]: - ok = True - break - return ok - - if cp_value == 0x200d: - - if pos > 0: - if _combining_class(ord(label[pos - 1])) == _virama_combining_class: - return True - return False - - else: - - return False - - -def valid_contexto(label, pos, exception=False): - - cp_value = ord(label[pos]) - - if cp_value == 0x00b7: - if 0 < pos < len(label)-1: - if ord(label[pos - 1]) == 0x006c and ord(label[pos + 1]) == 0x006c: - return True - return False - - elif cp_value == 0x0375: - if pos < len(label)-1 and len(label) > 1: - return _is_script(label[pos + 1], 'Greek') - return False - - elif cp_value == 0x05f3 or cp_value == 0x05f4: - if pos > 0: - return _is_script(label[pos - 1], 'Hebrew') - return False - - elif cp_value == 0x30fb: - for cp in label: - if cp == u'\u30fb': - continue - if _is_script(cp, 'Hiragana') or _is_script(cp, 'Katakana') or _is_script(cp, 'Han'): - return True - return False - - elif 0x660 <= cp_value <= 0x669: - for cp in label: - if 0x6f0 <= ord(cp) <= 0x06f9: - return False - return True - - elif 0x6f0 <= cp_value <= 0x6f9: - for cp in label: - if 0x660 <= ord(cp) <= 0x0669: - return False - return True - - -def check_label(label): - - if isinstance(label, (bytes, bytearray)): - label = label.decode('utf-8') - if len(label) == 0: - raise IDNAError('Empty Label') - - check_nfc(label) - check_hyphen_ok(label) - check_initial_combiner(label) - - for (pos, cp) in enumerate(label): - cp_value = ord(cp) - if intranges_contain(cp_value, idnadata.codepoint_classes['PVALID']): - continue - elif intranges_contain(cp_value, idnadata.codepoint_classes['CONTEXTJ']): - try: - if not valid_contextj(label, pos): - raise InvalidCodepointContext('Joiner {0} not allowed at position {1} in {2}'.format( - _unot(cp_value), pos+1, repr(label))) - except ValueError: - raise IDNAError('Unknown codepoint adjacent to joiner {0} at position {1} in {2}'.format( - _unot(cp_value), pos+1, repr(label))) - elif intranges_contain(cp_value, idnadata.codepoint_classes['CONTEXTO']): - if not valid_contexto(label, pos): - raise InvalidCodepointContext('Codepoint {0} not allowed at position {1} in {2}'.format(_unot(cp_value), pos+1, repr(label))) - else: - raise InvalidCodepoint('Codepoint {0} at position {1} of {2} not allowed'.format(_unot(cp_value), pos+1, repr(label))) - - check_bidi(label) - - -def alabel(label): - - try: - label = label.encode('ascii') - ulabel(label) - if not valid_label_length(label): - raise IDNAError('Label too long') - return label - except UnicodeEncodeError: - pass - - if not label: - raise IDNAError('No Input') - - label = unicode(label) - check_label(label) - label = _punycode(label) - label = _alabel_prefix + label - - if not valid_label_length(label): - raise IDNAError('Label too long') - - return label - - -def ulabel(label): - - if not isinstance(label, (bytes, bytearray)): - try: - label = label.encode('ascii') - except UnicodeEncodeError: - check_label(label) - return label - - label = label.lower() - if label.startswith(_alabel_prefix): - label = label[len(_alabel_prefix):] - else: - check_label(label) - return label.decode('ascii') - - label = label.decode('punycode') - check_label(label) - return label - - -def uts46_remap(domain, std3_rules=True, transitional=False): - """Re-map the characters in the string according to UTS46 processing.""" - from .uts46data import uts46data - output = u"" - try: - for pos, char in enumerate(domain): - code_point = ord(char) - uts46row = uts46data[code_point if code_point < 256 else - bisect.bisect_left(uts46data, (code_point, "Z")) - 1] - status = uts46row[1] - replacement = uts46row[2] if len(uts46row) == 3 else None - if (status == "V" or - (status == "D" and not transitional) or - (status == "3" and not std3_rules and replacement is None)): - output += char - elif replacement is not None and (status == "M" or - (status == "3" and not std3_rules) or - (status == "D" and transitional)): - output += replacement - elif status != "I": - raise IndexError() - return unicodedata.normalize("NFC", output) - except IndexError: - raise InvalidCodepoint( - "Codepoint {0} not allowed at position {1} in {2}".format( - _unot(code_point), pos + 1, repr(domain))) - - -def encode(s, strict=False, uts46=False, std3_rules=False, transitional=False): - - if isinstance(s, (bytes, bytearray)): - s = s.decode("ascii") - if uts46: - s = uts46_remap(s, std3_rules, transitional) - trailing_dot = False - result = [] - if strict: - labels = s.split('.') - else: - labels = _unicode_dots_re.split(s) - if not labels or labels == ['']: - raise IDNAError('Empty domain') - if labels[-1] == '': - del labels[-1] - trailing_dot = True - for label in labels: - s = alabel(label) - if s: - result.append(s) - else: - raise IDNAError('Empty label') - if trailing_dot: - result.append(b'') - s = b'.'.join(result) - if not valid_string_length(s, trailing_dot): - raise IDNAError('Domain too long') - return s - - -def decode(s, strict=False, uts46=False, std3_rules=False): - - if isinstance(s, (bytes, bytearray)): - s = s.decode("ascii") - if uts46: - s = uts46_remap(s, std3_rules, False) - trailing_dot = False - result = [] - if not strict: - labels = _unicode_dots_re.split(s) - else: - labels = s.split(u'.') - if not labels or labels == ['']: - raise IDNAError('Empty domain') - if not labels[-1]: - del labels[-1] - trailing_dot = True - for label in labels: - s = ulabel(label) - if s: - result.append(s) - else: - raise IDNAError('Empty label') - if trailing_dot: - result.append(u'') - return u'.'.join(result) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/idna/idnadata.py b/venv2/lib/python2.7/site-packages/pip/_vendor/idna/idnadata.py deleted file mode 100644 index a80c959..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/idna/idnadata.py +++ /dev/null @@ -1,1979 +0,0 @@ -# This file is automatically generated by tools/idna-data - -__version__ = "11.0.0" -scripts = { - 'Greek': ( - 0x37000000374, - 0x37500000378, - 0x37a0000037e, - 0x37f00000380, - 0x38400000385, - 0x38600000387, - 0x3880000038b, - 0x38c0000038d, - 0x38e000003a2, - 0x3a3000003e2, - 0x3f000000400, - 0x1d2600001d2b, - 0x1d5d00001d62, - 0x1d6600001d6b, - 0x1dbf00001dc0, - 0x1f0000001f16, - 0x1f1800001f1e, - 0x1f2000001f46, - 0x1f4800001f4e, - 0x1f5000001f58, - 0x1f5900001f5a, - 0x1f5b00001f5c, - 0x1f5d00001f5e, - 0x1f5f00001f7e, - 0x1f8000001fb5, - 0x1fb600001fc5, - 0x1fc600001fd4, - 0x1fd600001fdc, - 0x1fdd00001ff0, - 0x1ff200001ff5, - 0x1ff600001fff, - 0x212600002127, - 0xab650000ab66, - 0x101400001018f, - 0x101a0000101a1, - 0x1d2000001d246, - ), - 'Han': ( - 0x2e8000002e9a, - 0x2e9b00002ef4, - 0x2f0000002fd6, - 0x300500003006, - 0x300700003008, - 0x30210000302a, - 0x30380000303c, - 0x340000004db6, - 0x4e0000009ff0, - 0xf9000000fa6e, - 0xfa700000fada, - 0x200000002a6d7, - 0x2a7000002b735, - 0x2b7400002b81e, - 0x2b8200002cea2, - 0x2ceb00002ebe1, - 0x2f8000002fa1e, - ), - 'Hebrew': ( - 0x591000005c8, - 0x5d0000005eb, - 0x5ef000005f5, - 0xfb1d0000fb37, - 0xfb380000fb3d, - 0xfb3e0000fb3f, - 0xfb400000fb42, - 0xfb430000fb45, - 0xfb460000fb50, - ), - 'Hiragana': ( - 0x304100003097, - 0x309d000030a0, - 0x1b0010001b11f, - 0x1f2000001f201, - ), - 'Katakana': ( - 0x30a1000030fb, - 0x30fd00003100, - 0x31f000003200, - 0x32d0000032ff, - 0x330000003358, - 0xff660000ff70, - 0xff710000ff9e, - 0x1b0000001b001, - ), -} -joining_types = { - 0x600: 85, - 0x601: 85, - 0x602: 85, - 0x603: 85, - 0x604: 85, - 0x605: 85, - 0x608: 85, - 0x60b: 85, - 0x620: 68, - 0x621: 85, - 0x622: 82, - 0x623: 82, - 0x624: 82, - 0x625: 82, - 0x626: 68, - 0x627: 82, - 0x628: 68, - 0x629: 82, - 0x62a: 68, - 0x62b: 68, - 0x62c: 68, - 0x62d: 68, - 0x62e: 68, - 0x62f: 82, - 0x630: 82, - 0x631: 82, - 0x632: 82, - 0x633: 68, - 0x634: 68, - 0x635: 68, - 0x636: 68, - 0x637: 68, - 0x638: 68, - 0x639: 68, - 0x63a: 68, - 0x63b: 68, - 0x63c: 68, - 0x63d: 68, - 0x63e: 68, - 0x63f: 68, - 0x640: 67, - 0x641: 68, - 0x642: 68, - 0x643: 68, - 0x644: 68, - 0x645: 68, - 0x646: 68, - 0x647: 68, - 0x648: 82, - 0x649: 68, - 0x64a: 68, - 0x66e: 68, - 0x66f: 68, - 0x671: 82, - 0x672: 82, - 0x673: 82, - 0x674: 85, - 0x675: 82, - 0x676: 82, - 0x677: 82, - 0x678: 68, - 0x679: 68, - 0x67a: 68, - 0x67b: 68, - 0x67c: 68, - 0x67d: 68, - 0x67e: 68, - 0x67f: 68, - 0x680: 68, - 0x681: 68, - 0x682: 68, - 0x683: 68, - 0x684: 68, - 0x685: 68, - 0x686: 68, - 0x687: 68, - 0x688: 82, - 0x689: 82, - 0x68a: 82, - 0x68b: 82, - 0x68c: 82, - 0x68d: 82, - 0x68e: 82, - 0x68f: 82, - 0x690: 82, - 0x691: 82, - 0x692: 82, - 0x693: 82, - 0x694: 82, - 0x695: 82, - 0x696: 82, - 0x697: 82, - 0x698: 82, - 0x699: 82, - 0x69a: 68, - 0x69b: 68, - 0x69c: 68, - 0x69d: 68, - 0x69e: 68, - 0x69f: 68, - 0x6a0: 68, - 0x6a1: 68, - 0x6a2: 68, - 0x6a3: 68, - 0x6a4: 68, - 0x6a5: 68, - 0x6a6: 68, - 0x6a7: 68, - 0x6a8: 68, - 0x6a9: 68, - 0x6aa: 68, - 0x6ab: 68, - 0x6ac: 68, - 0x6ad: 68, - 0x6ae: 68, - 0x6af: 68, - 0x6b0: 68, - 0x6b1: 68, - 0x6b2: 68, - 0x6b3: 68, - 0x6b4: 68, - 0x6b5: 68, - 0x6b6: 68, - 0x6b7: 68, - 0x6b8: 68, - 0x6b9: 68, - 0x6ba: 68, - 0x6bb: 68, - 0x6bc: 68, - 0x6bd: 68, - 0x6be: 68, - 0x6bf: 68, - 0x6c0: 82, - 0x6c1: 68, - 0x6c2: 68, - 0x6c3: 82, - 0x6c4: 82, - 0x6c5: 82, - 0x6c6: 82, - 0x6c7: 82, - 0x6c8: 82, - 0x6c9: 82, - 0x6ca: 82, - 0x6cb: 82, - 0x6cc: 68, - 0x6cd: 82, - 0x6ce: 68, - 0x6cf: 82, - 0x6d0: 68, - 0x6d1: 68, - 0x6d2: 82, - 0x6d3: 82, - 0x6d5: 82, - 0x6dd: 85, - 0x6ee: 82, - 0x6ef: 82, - 0x6fa: 68, - 0x6fb: 68, - 0x6fc: 68, - 0x6ff: 68, - 0x70f: 84, - 0x710: 82, - 0x712: 68, - 0x713: 68, - 0x714: 68, - 0x715: 82, - 0x716: 82, - 0x717: 82, - 0x718: 82, - 0x719: 82, - 0x71a: 68, - 0x71b: 68, - 0x71c: 68, - 0x71d: 68, - 0x71e: 82, - 0x71f: 68, - 0x720: 68, - 0x721: 68, - 0x722: 68, - 0x723: 68, - 0x724: 68, - 0x725: 68, - 0x726: 68, - 0x727: 68, - 0x728: 82, - 0x729: 68, - 0x72a: 82, - 0x72b: 68, - 0x72c: 82, - 0x72d: 68, - 0x72e: 68, - 0x72f: 82, - 0x74d: 82, - 0x74e: 68, - 0x74f: 68, - 0x750: 68, - 0x751: 68, - 0x752: 68, - 0x753: 68, - 0x754: 68, - 0x755: 68, - 0x756: 68, - 0x757: 68, - 0x758: 68, - 0x759: 82, - 0x75a: 82, - 0x75b: 82, - 0x75c: 68, - 0x75d: 68, - 0x75e: 68, - 0x75f: 68, - 0x760: 68, - 0x761: 68, - 0x762: 68, - 0x763: 68, - 0x764: 68, - 0x765: 68, - 0x766: 68, - 0x767: 68, - 0x768: 68, - 0x769: 68, - 0x76a: 68, - 0x76b: 82, - 0x76c: 82, - 0x76d: 68, - 0x76e: 68, - 0x76f: 68, - 0x770: 68, - 0x771: 82, - 0x772: 68, - 0x773: 82, - 0x774: 82, - 0x775: 68, - 0x776: 68, - 0x777: 68, - 0x778: 82, - 0x779: 82, - 0x77a: 68, - 0x77b: 68, - 0x77c: 68, - 0x77d: 68, - 0x77e: 68, - 0x77f: 68, - 0x7ca: 68, - 0x7cb: 68, - 0x7cc: 68, - 0x7cd: 68, - 0x7ce: 68, - 0x7cf: 68, - 0x7d0: 68, - 0x7d1: 68, - 0x7d2: 68, - 0x7d3: 68, - 0x7d4: 68, - 0x7d5: 68, - 0x7d6: 68, - 0x7d7: 68, - 0x7d8: 68, - 0x7d9: 68, - 0x7da: 68, - 0x7db: 68, - 0x7dc: 68, - 0x7dd: 68, - 0x7de: 68, - 0x7df: 68, - 0x7e0: 68, - 0x7e1: 68, - 0x7e2: 68, - 0x7e3: 68, - 0x7e4: 68, - 0x7e5: 68, - 0x7e6: 68, - 0x7e7: 68, - 0x7e8: 68, - 0x7e9: 68, - 0x7ea: 68, - 0x7fa: 67, - 0x840: 82, - 0x841: 68, - 0x842: 68, - 0x843: 68, - 0x844: 68, - 0x845: 68, - 0x846: 82, - 0x847: 82, - 0x848: 68, - 0x849: 82, - 0x84a: 68, - 0x84b: 68, - 0x84c: 68, - 0x84d: 68, - 0x84e: 68, - 0x84f: 68, - 0x850: 68, - 0x851: 68, - 0x852: 68, - 0x853: 68, - 0x854: 82, - 0x855: 68, - 0x856: 85, - 0x857: 85, - 0x858: 85, - 0x860: 68, - 0x861: 85, - 0x862: 68, - 0x863: 68, - 0x864: 68, - 0x865: 68, - 0x866: 85, - 0x867: 82, - 0x868: 68, - 0x869: 82, - 0x86a: 82, - 0x8a0: 68, - 0x8a1: 68, - 0x8a2: 68, - 0x8a3: 68, - 0x8a4: 68, - 0x8a5: 68, - 0x8a6: 68, - 0x8a7: 68, - 0x8a8: 68, - 0x8a9: 68, - 0x8aa: 82, - 0x8ab: 82, - 0x8ac: 82, - 0x8ad: 85, - 0x8ae: 82, - 0x8af: 68, - 0x8b0: 68, - 0x8b1: 82, - 0x8b2: 82, - 0x8b3: 68, - 0x8b4: 68, - 0x8b6: 68, - 0x8b7: 68, - 0x8b8: 68, - 0x8b9: 82, - 0x8ba: 68, - 0x8bb: 68, - 0x8bc: 68, - 0x8bd: 68, - 0x8e2: 85, - 0x1806: 85, - 0x1807: 68, - 0x180a: 67, - 0x180e: 85, - 0x1820: 68, - 0x1821: 68, - 0x1822: 68, - 0x1823: 68, - 0x1824: 68, - 0x1825: 68, - 0x1826: 68, - 0x1827: 68, - 0x1828: 68, - 0x1829: 68, - 0x182a: 68, - 0x182b: 68, - 0x182c: 68, - 0x182d: 68, - 0x182e: 68, - 0x182f: 68, - 0x1830: 68, - 0x1831: 68, - 0x1832: 68, - 0x1833: 68, - 0x1834: 68, - 0x1835: 68, - 0x1836: 68, - 0x1837: 68, - 0x1838: 68, - 0x1839: 68, - 0x183a: 68, - 0x183b: 68, - 0x183c: 68, - 0x183d: 68, - 0x183e: 68, - 0x183f: 68, - 0x1840: 68, - 0x1841: 68, - 0x1842: 68, - 0x1843: 68, - 0x1844: 68, - 0x1845: 68, - 0x1846: 68, - 0x1847: 68, - 0x1848: 68, - 0x1849: 68, - 0x184a: 68, - 0x184b: 68, - 0x184c: 68, - 0x184d: 68, - 0x184e: 68, - 0x184f: 68, - 0x1850: 68, - 0x1851: 68, - 0x1852: 68, - 0x1853: 68, - 0x1854: 68, - 0x1855: 68, - 0x1856: 68, - 0x1857: 68, - 0x1858: 68, - 0x1859: 68, - 0x185a: 68, - 0x185b: 68, - 0x185c: 68, - 0x185d: 68, - 0x185e: 68, - 0x185f: 68, - 0x1860: 68, - 0x1861: 68, - 0x1862: 68, - 0x1863: 68, - 0x1864: 68, - 0x1865: 68, - 0x1866: 68, - 0x1867: 68, - 0x1868: 68, - 0x1869: 68, - 0x186a: 68, - 0x186b: 68, - 0x186c: 68, - 0x186d: 68, - 0x186e: 68, - 0x186f: 68, - 0x1870: 68, - 0x1871: 68, - 0x1872: 68, - 0x1873: 68, - 0x1874: 68, - 0x1875: 68, - 0x1876: 68, - 0x1877: 68, - 0x1878: 68, - 0x1880: 85, - 0x1881: 85, - 0x1882: 85, - 0x1883: 85, - 0x1884: 85, - 0x1885: 84, - 0x1886: 84, - 0x1887: 68, - 0x1888: 68, - 0x1889: 68, - 0x188a: 68, - 0x188b: 68, - 0x188c: 68, - 0x188d: 68, - 0x188e: 68, - 0x188f: 68, - 0x1890: 68, - 0x1891: 68, - 0x1892: 68, - 0x1893: 68, - 0x1894: 68, - 0x1895: 68, - 0x1896: 68, - 0x1897: 68, - 0x1898: 68, - 0x1899: 68, - 0x189a: 68, - 0x189b: 68, - 0x189c: 68, - 0x189d: 68, - 0x189e: 68, - 0x189f: 68, - 0x18a0: 68, - 0x18a1: 68, - 0x18a2: 68, - 0x18a3: 68, - 0x18a4: 68, - 0x18a5: 68, - 0x18a6: 68, - 0x18a7: 68, - 0x18a8: 68, - 0x18aa: 68, - 0x200c: 85, - 0x200d: 67, - 0x202f: 85, - 0x2066: 85, - 0x2067: 85, - 0x2068: 85, - 0x2069: 85, - 0xa840: 68, - 0xa841: 68, - 0xa842: 68, - 0xa843: 68, - 0xa844: 68, - 0xa845: 68, - 0xa846: 68, - 0xa847: 68, - 0xa848: 68, - 0xa849: 68, - 0xa84a: 68, - 0xa84b: 68, - 0xa84c: 68, - 0xa84d: 68, - 0xa84e: 68, - 0xa84f: 68, - 0xa850: 68, - 0xa851: 68, - 0xa852: 68, - 0xa853: 68, - 0xa854: 68, - 0xa855: 68, - 0xa856: 68, - 0xa857: 68, - 0xa858: 68, - 0xa859: 68, - 0xa85a: 68, - 0xa85b: 68, - 0xa85c: 68, - 0xa85d: 68, - 0xa85e: 68, - 0xa85f: 68, - 0xa860: 68, - 0xa861: 68, - 0xa862: 68, - 0xa863: 68, - 0xa864: 68, - 0xa865: 68, - 0xa866: 68, - 0xa867: 68, - 0xa868: 68, - 0xa869: 68, - 0xa86a: 68, - 0xa86b: 68, - 0xa86c: 68, - 0xa86d: 68, - 0xa86e: 68, - 0xa86f: 68, - 0xa870: 68, - 0xa871: 68, - 0xa872: 76, - 0xa873: 85, - 0x10ac0: 68, - 0x10ac1: 68, - 0x10ac2: 68, - 0x10ac3: 68, - 0x10ac4: 68, - 0x10ac5: 82, - 0x10ac6: 85, - 0x10ac7: 82, - 0x10ac8: 85, - 0x10ac9: 82, - 0x10aca: 82, - 0x10acb: 85, - 0x10acc: 85, - 0x10acd: 76, - 0x10ace: 82, - 0x10acf: 82, - 0x10ad0: 82, - 0x10ad1: 82, - 0x10ad2: 82, - 0x10ad3: 68, - 0x10ad4: 68, - 0x10ad5: 68, - 0x10ad6: 68, - 0x10ad7: 76, - 0x10ad8: 68, - 0x10ad9: 68, - 0x10ada: 68, - 0x10adb: 68, - 0x10adc: 68, - 0x10add: 82, - 0x10ade: 68, - 0x10adf: 68, - 0x10ae0: 68, - 0x10ae1: 82, - 0x10ae2: 85, - 0x10ae3: 85, - 0x10ae4: 82, - 0x10aeb: 68, - 0x10aec: 68, - 0x10aed: 68, - 0x10aee: 68, - 0x10aef: 82, - 0x10b80: 68, - 0x10b81: 82, - 0x10b82: 68, - 0x10b83: 82, - 0x10b84: 82, - 0x10b85: 82, - 0x10b86: 68, - 0x10b87: 68, - 0x10b88: 68, - 0x10b89: 82, - 0x10b8a: 68, - 0x10b8b: 68, - 0x10b8c: 82, - 0x10b8d: 68, - 0x10b8e: 82, - 0x10b8f: 82, - 0x10b90: 68, - 0x10b91: 82, - 0x10ba9: 82, - 0x10baa: 82, - 0x10bab: 82, - 0x10bac: 82, - 0x10bad: 68, - 0x10bae: 68, - 0x10baf: 85, - 0x10d00: 76, - 0x10d01: 68, - 0x10d02: 68, - 0x10d03: 68, - 0x10d04: 68, - 0x10d05: 68, - 0x10d06: 68, - 0x10d07: 68, - 0x10d08: 68, - 0x10d09: 68, - 0x10d0a: 68, - 0x10d0b: 68, - 0x10d0c: 68, - 0x10d0d: 68, - 0x10d0e: 68, - 0x10d0f: 68, - 0x10d10: 68, - 0x10d11: 68, - 0x10d12: 68, - 0x10d13: 68, - 0x10d14: 68, - 0x10d15: 68, - 0x10d16: 68, - 0x10d17: 68, - 0x10d18: 68, - 0x10d19: 68, - 0x10d1a: 68, - 0x10d1b: 68, - 0x10d1c: 68, - 0x10d1d: 68, - 0x10d1e: 68, - 0x10d1f: 68, - 0x10d20: 68, - 0x10d21: 68, - 0x10d22: 82, - 0x10d23: 68, - 0x10f30: 68, - 0x10f31: 68, - 0x10f32: 68, - 0x10f33: 82, - 0x10f34: 68, - 0x10f35: 68, - 0x10f36: 68, - 0x10f37: 68, - 0x10f38: 68, - 0x10f39: 68, - 0x10f3a: 68, - 0x10f3b: 68, - 0x10f3c: 68, - 0x10f3d: 68, - 0x10f3e: 68, - 0x10f3f: 68, - 0x10f40: 68, - 0x10f41: 68, - 0x10f42: 68, - 0x10f43: 68, - 0x10f44: 68, - 0x10f45: 85, - 0x10f51: 68, - 0x10f52: 68, - 0x10f53: 68, - 0x10f54: 82, - 0x110bd: 85, - 0x110cd: 85, - 0x1e900: 68, - 0x1e901: 68, - 0x1e902: 68, - 0x1e903: 68, - 0x1e904: 68, - 0x1e905: 68, - 0x1e906: 68, - 0x1e907: 68, - 0x1e908: 68, - 0x1e909: 68, - 0x1e90a: 68, - 0x1e90b: 68, - 0x1e90c: 68, - 0x1e90d: 68, - 0x1e90e: 68, - 0x1e90f: 68, - 0x1e910: 68, - 0x1e911: 68, - 0x1e912: 68, - 0x1e913: 68, - 0x1e914: 68, - 0x1e915: 68, - 0x1e916: 68, - 0x1e917: 68, - 0x1e918: 68, - 0x1e919: 68, - 0x1e91a: 68, - 0x1e91b: 68, - 0x1e91c: 68, - 0x1e91d: 68, - 0x1e91e: 68, - 0x1e91f: 68, - 0x1e920: 68, - 0x1e921: 68, - 0x1e922: 68, - 0x1e923: 68, - 0x1e924: 68, - 0x1e925: 68, - 0x1e926: 68, - 0x1e927: 68, - 0x1e928: 68, - 0x1e929: 68, - 0x1e92a: 68, - 0x1e92b: 68, - 0x1e92c: 68, - 0x1e92d: 68, - 0x1e92e: 68, - 0x1e92f: 68, - 0x1e930: 68, - 0x1e931: 68, - 0x1e932: 68, - 0x1e933: 68, - 0x1e934: 68, - 0x1e935: 68, - 0x1e936: 68, - 0x1e937: 68, - 0x1e938: 68, - 0x1e939: 68, - 0x1e93a: 68, - 0x1e93b: 68, - 0x1e93c: 68, - 0x1e93d: 68, - 0x1e93e: 68, - 0x1e93f: 68, - 0x1e940: 68, - 0x1e941: 68, - 0x1e942: 68, - 0x1e943: 68, -} -codepoint_classes = { - 'PVALID': ( - 0x2d0000002e, - 0x300000003a, - 0x610000007b, - 0xdf000000f7, - 0xf800000100, - 0x10100000102, - 0x10300000104, - 0x10500000106, - 0x10700000108, - 0x1090000010a, - 0x10b0000010c, - 0x10d0000010e, - 0x10f00000110, - 0x11100000112, - 0x11300000114, - 0x11500000116, - 0x11700000118, - 0x1190000011a, - 0x11b0000011c, - 0x11d0000011e, - 0x11f00000120, - 0x12100000122, - 0x12300000124, - 0x12500000126, - 0x12700000128, - 0x1290000012a, - 0x12b0000012c, - 0x12d0000012e, - 0x12f00000130, - 0x13100000132, - 0x13500000136, - 0x13700000139, - 0x13a0000013b, - 0x13c0000013d, - 0x13e0000013f, - 0x14200000143, - 0x14400000145, - 0x14600000147, - 0x14800000149, - 0x14b0000014c, - 0x14d0000014e, - 0x14f00000150, - 0x15100000152, - 0x15300000154, - 0x15500000156, - 0x15700000158, - 0x1590000015a, - 0x15b0000015c, - 0x15d0000015e, - 0x15f00000160, - 0x16100000162, - 0x16300000164, - 0x16500000166, - 0x16700000168, - 0x1690000016a, - 0x16b0000016c, - 0x16d0000016e, - 0x16f00000170, - 0x17100000172, - 0x17300000174, - 0x17500000176, - 0x17700000178, - 0x17a0000017b, - 0x17c0000017d, - 0x17e0000017f, - 0x18000000181, - 0x18300000184, - 0x18500000186, - 0x18800000189, - 0x18c0000018e, - 0x19200000193, - 0x19500000196, - 0x1990000019c, - 0x19e0000019f, - 0x1a1000001a2, - 0x1a3000001a4, - 0x1a5000001a6, - 0x1a8000001a9, - 0x1aa000001ac, - 0x1ad000001ae, - 0x1b0000001b1, - 0x1b4000001b5, - 0x1b6000001b7, - 0x1b9000001bc, - 0x1bd000001c4, - 0x1ce000001cf, - 0x1d0000001d1, - 0x1d2000001d3, - 0x1d4000001d5, - 0x1d6000001d7, - 0x1d8000001d9, - 0x1da000001db, - 0x1dc000001de, - 0x1df000001e0, - 0x1e1000001e2, - 0x1e3000001e4, - 0x1e5000001e6, - 0x1e7000001e8, - 0x1e9000001ea, - 0x1eb000001ec, - 0x1ed000001ee, - 0x1ef000001f1, - 0x1f5000001f6, - 0x1f9000001fa, - 0x1fb000001fc, - 0x1fd000001fe, - 0x1ff00000200, - 0x20100000202, - 0x20300000204, - 0x20500000206, - 0x20700000208, - 0x2090000020a, - 0x20b0000020c, - 0x20d0000020e, - 0x20f00000210, - 0x21100000212, - 0x21300000214, - 0x21500000216, - 0x21700000218, - 0x2190000021a, - 0x21b0000021c, - 0x21d0000021e, - 0x21f00000220, - 0x22100000222, - 0x22300000224, - 0x22500000226, - 0x22700000228, - 0x2290000022a, - 0x22b0000022c, - 0x22d0000022e, - 0x22f00000230, - 0x23100000232, - 0x2330000023a, - 0x23c0000023d, - 0x23f00000241, - 0x24200000243, - 0x24700000248, - 0x2490000024a, - 0x24b0000024c, - 0x24d0000024e, - 0x24f000002b0, - 0x2b9000002c2, - 0x2c6000002d2, - 0x2ec000002ed, - 0x2ee000002ef, - 0x30000000340, - 0x34200000343, - 0x3460000034f, - 0x35000000370, - 0x37100000372, - 0x37300000374, - 0x37700000378, - 0x37b0000037e, - 0x39000000391, - 0x3ac000003cf, - 0x3d7000003d8, - 0x3d9000003da, - 0x3db000003dc, - 0x3dd000003de, - 0x3df000003e0, - 0x3e1000003e2, - 0x3e3000003e4, - 0x3e5000003e6, - 0x3e7000003e8, - 0x3e9000003ea, - 0x3eb000003ec, - 0x3ed000003ee, - 0x3ef000003f0, - 0x3f3000003f4, - 0x3f8000003f9, - 0x3fb000003fd, - 0x43000000460, - 0x46100000462, - 0x46300000464, - 0x46500000466, - 0x46700000468, - 0x4690000046a, - 0x46b0000046c, - 0x46d0000046e, - 0x46f00000470, - 0x47100000472, - 0x47300000474, - 0x47500000476, - 0x47700000478, - 0x4790000047a, - 0x47b0000047c, - 0x47d0000047e, - 0x47f00000480, - 0x48100000482, - 0x48300000488, - 0x48b0000048c, - 0x48d0000048e, - 0x48f00000490, - 0x49100000492, - 0x49300000494, - 0x49500000496, - 0x49700000498, - 0x4990000049a, - 0x49b0000049c, - 0x49d0000049e, - 0x49f000004a0, - 0x4a1000004a2, - 0x4a3000004a4, - 0x4a5000004a6, - 0x4a7000004a8, - 0x4a9000004aa, - 0x4ab000004ac, - 0x4ad000004ae, - 0x4af000004b0, - 0x4b1000004b2, - 0x4b3000004b4, - 0x4b5000004b6, - 0x4b7000004b8, - 0x4b9000004ba, - 0x4bb000004bc, - 0x4bd000004be, - 0x4bf000004c0, - 0x4c2000004c3, - 0x4c4000004c5, - 0x4c6000004c7, - 0x4c8000004c9, - 0x4ca000004cb, - 0x4cc000004cd, - 0x4ce000004d0, - 0x4d1000004d2, - 0x4d3000004d4, - 0x4d5000004d6, - 0x4d7000004d8, - 0x4d9000004da, - 0x4db000004dc, - 0x4dd000004de, - 0x4df000004e0, - 0x4e1000004e2, - 0x4e3000004e4, - 0x4e5000004e6, - 0x4e7000004e8, - 0x4e9000004ea, - 0x4eb000004ec, - 0x4ed000004ee, - 0x4ef000004f0, - 0x4f1000004f2, - 0x4f3000004f4, - 0x4f5000004f6, - 0x4f7000004f8, - 0x4f9000004fa, - 0x4fb000004fc, - 0x4fd000004fe, - 0x4ff00000500, - 0x50100000502, - 0x50300000504, - 0x50500000506, - 0x50700000508, - 0x5090000050a, - 0x50b0000050c, - 0x50d0000050e, - 0x50f00000510, - 0x51100000512, - 0x51300000514, - 0x51500000516, - 0x51700000518, - 0x5190000051a, - 0x51b0000051c, - 0x51d0000051e, - 0x51f00000520, - 0x52100000522, - 0x52300000524, - 0x52500000526, - 0x52700000528, - 0x5290000052a, - 0x52b0000052c, - 0x52d0000052e, - 0x52f00000530, - 0x5590000055a, - 0x56000000587, - 0x58800000589, - 0x591000005be, - 0x5bf000005c0, - 0x5c1000005c3, - 0x5c4000005c6, - 0x5c7000005c8, - 0x5d0000005eb, - 0x5ef000005f3, - 0x6100000061b, - 0x62000000640, - 0x64100000660, - 0x66e00000675, - 0x679000006d4, - 0x6d5000006dd, - 0x6df000006e9, - 0x6ea000006f0, - 0x6fa00000700, - 0x7100000074b, - 0x74d000007b2, - 0x7c0000007f6, - 0x7fd000007fe, - 0x8000000082e, - 0x8400000085c, - 0x8600000086b, - 0x8a0000008b5, - 0x8b6000008be, - 0x8d3000008e2, - 0x8e300000958, - 0x96000000964, - 0x96600000970, - 0x97100000984, - 0x9850000098d, - 0x98f00000991, - 0x993000009a9, - 0x9aa000009b1, - 0x9b2000009b3, - 0x9b6000009ba, - 0x9bc000009c5, - 0x9c7000009c9, - 0x9cb000009cf, - 0x9d7000009d8, - 0x9e0000009e4, - 0x9e6000009f2, - 0x9fc000009fd, - 0x9fe000009ff, - 0xa0100000a04, - 0xa0500000a0b, - 0xa0f00000a11, - 0xa1300000a29, - 0xa2a00000a31, - 0xa3200000a33, - 0xa3500000a36, - 0xa3800000a3a, - 0xa3c00000a3d, - 0xa3e00000a43, - 0xa4700000a49, - 0xa4b00000a4e, - 0xa5100000a52, - 0xa5c00000a5d, - 0xa6600000a76, - 0xa8100000a84, - 0xa8500000a8e, - 0xa8f00000a92, - 0xa9300000aa9, - 0xaaa00000ab1, - 0xab200000ab4, - 0xab500000aba, - 0xabc00000ac6, - 0xac700000aca, - 0xacb00000ace, - 0xad000000ad1, - 0xae000000ae4, - 0xae600000af0, - 0xaf900000b00, - 0xb0100000b04, - 0xb0500000b0d, - 0xb0f00000b11, - 0xb1300000b29, - 0xb2a00000b31, - 0xb3200000b34, - 0xb3500000b3a, - 0xb3c00000b45, - 0xb4700000b49, - 0xb4b00000b4e, - 0xb5600000b58, - 0xb5f00000b64, - 0xb6600000b70, - 0xb7100000b72, - 0xb8200000b84, - 0xb8500000b8b, - 0xb8e00000b91, - 0xb9200000b96, - 0xb9900000b9b, - 0xb9c00000b9d, - 0xb9e00000ba0, - 0xba300000ba5, - 0xba800000bab, - 0xbae00000bba, - 0xbbe00000bc3, - 0xbc600000bc9, - 0xbca00000bce, - 0xbd000000bd1, - 0xbd700000bd8, - 0xbe600000bf0, - 0xc0000000c0d, - 0xc0e00000c11, - 0xc1200000c29, - 0xc2a00000c3a, - 0xc3d00000c45, - 0xc4600000c49, - 0xc4a00000c4e, - 0xc5500000c57, - 0xc5800000c5b, - 0xc6000000c64, - 0xc6600000c70, - 0xc8000000c84, - 0xc8500000c8d, - 0xc8e00000c91, - 0xc9200000ca9, - 0xcaa00000cb4, - 0xcb500000cba, - 0xcbc00000cc5, - 0xcc600000cc9, - 0xcca00000cce, - 0xcd500000cd7, - 0xcde00000cdf, - 0xce000000ce4, - 0xce600000cf0, - 0xcf100000cf3, - 0xd0000000d04, - 0xd0500000d0d, - 0xd0e00000d11, - 0xd1200000d45, - 0xd4600000d49, - 0xd4a00000d4f, - 0xd5400000d58, - 0xd5f00000d64, - 0xd6600000d70, - 0xd7a00000d80, - 0xd8200000d84, - 0xd8500000d97, - 0xd9a00000db2, - 0xdb300000dbc, - 0xdbd00000dbe, - 0xdc000000dc7, - 0xdca00000dcb, - 0xdcf00000dd5, - 0xdd600000dd7, - 0xdd800000de0, - 0xde600000df0, - 0xdf200000df4, - 0xe0100000e33, - 0xe3400000e3b, - 0xe4000000e4f, - 0xe5000000e5a, - 0xe8100000e83, - 0xe8400000e85, - 0xe8700000e89, - 0xe8a00000e8b, - 0xe8d00000e8e, - 0xe9400000e98, - 0xe9900000ea0, - 0xea100000ea4, - 0xea500000ea6, - 0xea700000ea8, - 0xeaa00000eac, - 0xead00000eb3, - 0xeb400000eba, - 0xebb00000ebe, - 0xec000000ec5, - 0xec600000ec7, - 0xec800000ece, - 0xed000000eda, - 0xede00000ee0, - 0xf0000000f01, - 0xf0b00000f0c, - 0xf1800000f1a, - 0xf2000000f2a, - 0xf3500000f36, - 0xf3700000f38, - 0xf3900000f3a, - 0xf3e00000f43, - 0xf4400000f48, - 0xf4900000f4d, - 0xf4e00000f52, - 0xf5300000f57, - 0xf5800000f5c, - 0xf5d00000f69, - 0xf6a00000f6d, - 0xf7100000f73, - 0xf7400000f75, - 0xf7a00000f81, - 0xf8200000f85, - 0xf8600000f93, - 0xf9400000f98, - 0xf9900000f9d, - 0xf9e00000fa2, - 0xfa300000fa7, - 0xfa800000fac, - 0xfad00000fb9, - 0xfba00000fbd, - 0xfc600000fc7, - 0x10000000104a, - 0x10500000109e, - 0x10d0000010fb, - 0x10fd00001100, - 0x120000001249, - 0x124a0000124e, - 0x125000001257, - 0x125800001259, - 0x125a0000125e, - 0x126000001289, - 0x128a0000128e, - 0x1290000012b1, - 0x12b2000012b6, - 0x12b8000012bf, - 0x12c0000012c1, - 0x12c2000012c6, - 0x12c8000012d7, - 0x12d800001311, - 0x131200001316, - 0x13180000135b, - 0x135d00001360, - 0x138000001390, - 0x13a0000013f6, - 0x14010000166d, - 0x166f00001680, - 0x16810000169b, - 0x16a0000016eb, - 0x16f1000016f9, - 0x17000000170d, - 0x170e00001715, - 0x172000001735, - 0x174000001754, - 0x17600000176d, - 0x176e00001771, - 0x177200001774, - 0x1780000017b4, - 0x17b6000017d4, - 0x17d7000017d8, - 0x17dc000017de, - 0x17e0000017ea, - 0x18100000181a, - 0x182000001879, - 0x1880000018ab, - 0x18b0000018f6, - 0x19000000191f, - 0x19200000192c, - 0x19300000193c, - 0x19460000196e, - 0x197000001975, - 0x1980000019ac, - 0x19b0000019ca, - 0x19d0000019da, - 0x1a0000001a1c, - 0x1a2000001a5f, - 0x1a6000001a7d, - 0x1a7f00001a8a, - 0x1a9000001a9a, - 0x1aa700001aa8, - 0x1ab000001abe, - 0x1b0000001b4c, - 0x1b5000001b5a, - 0x1b6b00001b74, - 0x1b8000001bf4, - 0x1c0000001c38, - 0x1c4000001c4a, - 0x1c4d00001c7e, - 0x1cd000001cd3, - 0x1cd400001cfa, - 0x1d0000001d2c, - 0x1d2f00001d30, - 0x1d3b00001d3c, - 0x1d4e00001d4f, - 0x1d6b00001d78, - 0x1d7900001d9b, - 0x1dc000001dfa, - 0x1dfb00001e00, - 0x1e0100001e02, - 0x1e0300001e04, - 0x1e0500001e06, - 0x1e0700001e08, - 0x1e0900001e0a, - 0x1e0b00001e0c, - 0x1e0d00001e0e, - 0x1e0f00001e10, - 0x1e1100001e12, - 0x1e1300001e14, - 0x1e1500001e16, - 0x1e1700001e18, - 0x1e1900001e1a, - 0x1e1b00001e1c, - 0x1e1d00001e1e, - 0x1e1f00001e20, - 0x1e2100001e22, - 0x1e2300001e24, - 0x1e2500001e26, - 0x1e2700001e28, - 0x1e2900001e2a, - 0x1e2b00001e2c, - 0x1e2d00001e2e, - 0x1e2f00001e30, - 0x1e3100001e32, - 0x1e3300001e34, - 0x1e3500001e36, - 0x1e3700001e38, - 0x1e3900001e3a, - 0x1e3b00001e3c, - 0x1e3d00001e3e, - 0x1e3f00001e40, - 0x1e4100001e42, - 0x1e4300001e44, - 0x1e4500001e46, - 0x1e4700001e48, - 0x1e4900001e4a, - 0x1e4b00001e4c, - 0x1e4d00001e4e, - 0x1e4f00001e50, - 0x1e5100001e52, - 0x1e5300001e54, - 0x1e5500001e56, - 0x1e5700001e58, - 0x1e5900001e5a, - 0x1e5b00001e5c, - 0x1e5d00001e5e, - 0x1e5f00001e60, - 0x1e6100001e62, - 0x1e6300001e64, - 0x1e6500001e66, - 0x1e6700001e68, - 0x1e6900001e6a, - 0x1e6b00001e6c, - 0x1e6d00001e6e, - 0x1e6f00001e70, - 0x1e7100001e72, - 0x1e7300001e74, - 0x1e7500001e76, - 0x1e7700001e78, - 0x1e7900001e7a, - 0x1e7b00001e7c, - 0x1e7d00001e7e, - 0x1e7f00001e80, - 0x1e8100001e82, - 0x1e8300001e84, - 0x1e8500001e86, - 0x1e8700001e88, - 0x1e8900001e8a, - 0x1e8b00001e8c, - 0x1e8d00001e8e, - 0x1e8f00001e90, - 0x1e9100001e92, - 0x1e9300001e94, - 0x1e9500001e9a, - 0x1e9c00001e9e, - 0x1e9f00001ea0, - 0x1ea100001ea2, - 0x1ea300001ea4, - 0x1ea500001ea6, - 0x1ea700001ea8, - 0x1ea900001eaa, - 0x1eab00001eac, - 0x1ead00001eae, - 0x1eaf00001eb0, - 0x1eb100001eb2, - 0x1eb300001eb4, - 0x1eb500001eb6, - 0x1eb700001eb8, - 0x1eb900001eba, - 0x1ebb00001ebc, - 0x1ebd00001ebe, - 0x1ebf00001ec0, - 0x1ec100001ec2, - 0x1ec300001ec4, - 0x1ec500001ec6, - 0x1ec700001ec8, - 0x1ec900001eca, - 0x1ecb00001ecc, - 0x1ecd00001ece, - 0x1ecf00001ed0, - 0x1ed100001ed2, - 0x1ed300001ed4, - 0x1ed500001ed6, - 0x1ed700001ed8, - 0x1ed900001eda, - 0x1edb00001edc, - 0x1edd00001ede, - 0x1edf00001ee0, - 0x1ee100001ee2, - 0x1ee300001ee4, - 0x1ee500001ee6, - 0x1ee700001ee8, - 0x1ee900001eea, - 0x1eeb00001eec, - 0x1eed00001eee, - 0x1eef00001ef0, - 0x1ef100001ef2, - 0x1ef300001ef4, - 0x1ef500001ef6, - 0x1ef700001ef8, - 0x1ef900001efa, - 0x1efb00001efc, - 0x1efd00001efe, - 0x1eff00001f08, - 0x1f1000001f16, - 0x1f2000001f28, - 0x1f3000001f38, - 0x1f4000001f46, - 0x1f5000001f58, - 0x1f6000001f68, - 0x1f7000001f71, - 0x1f7200001f73, - 0x1f7400001f75, - 0x1f7600001f77, - 0x1f7800001f79, - 0x1f7a00001f7b, - 0x1f7c00001f7d, - 0x1fb000001fb2, - 0x1fb600001fb7, - 0x1fc600001fc7, - 0x1fd000001fd3, - 0x1fd600001fd8, - 0x1fe000001fe3, - 0x1fe400001fe8, - 0x1ff600001ff7, - 0x214e0000214f, - 0x218400002185, - 0x2c3000002c5f, - 0x2c6100002c62, - 0x2c6500002c67, - 0x2c6800002c69, - 0x2c6a00002c6b, - 0x2c6c00002c6d, - 0x2c7100002c72, - 0x2c7300002c75, - 0x2c7600002c7c, - 0x2c8100002c82, - 0x2c8300002c84, - 0x2c8500002c86, - 0x2c8700002c88, - 0x2c8900002c8a, - 0x2c8b00002c8c, - 0x2c8d00002c8e, - 0x2c8f00002c90, - 0x2c9100002c92, - 0x2c9300002c94, - 0x2c9500002c96, - 0x2c9700002c98, - 0x2c9900002c9a, - 0x2c9b00002c9c, - 0x2c9d00002c9e, - 0x2c9f00002ca0, - 0x2ca100002ca2, - 0x2ca300002ca4, - 0x2ca500002ca6, - 0x2ca700002ca8, - 0x2ca900002caa, - 0x2cab00002cac, - 0x2cad00002cae, - 0x2caf00002cb0, - 0x2cb100002cb2, - 0x2cb300002cb4, - 0x2cb500002cb6, - 0x2cb700002cb8, - 0x2cb900002cba, - 0x2cbb00002cbc, - 0x2cbd00002cbe, - 0x2cbf00002cc0, - 0x2cc100002cc2, - 0x2cc300002cc4, - 0x2cc500002cc6, - 0x2cc700002cc8, - 0x2cc900002cca, - 0x2ccb00002ccc, - 0x2ccd00002cce, - 0x2ccf00002cd0, - 0x2cd100002cd2, - 0x2cd300002cd4, - 0x2cd500002cd6, - 0x2cd700002cd8, - 0x2cd900002cda, - 0x2cdb00002cdc, - 0x2cdd00002cde, - 0x2cdf00002ce0, - 0x2ce100002ce2, - 0x2ce300002ce5, - 0x2cec00002ced, - 0x2cee00002cf2, - 0x2cf300002cf4, - 0x2d0000002d26, - 0x2d2700002d28, - 0x2d2d00002d2e, - 0x2d3000002d68, - 0x2d7f00002d97, - 0x2da000002da7, - 0x2da800002daf, - 0x2db000002db7, - 0x2db800002dbf, - 0x2dc000002dc7, - 0x2dc800002dcf, - 0x2dd000002dd7, - 0x2dd800002ddf, - 0x2de000002e00, - 0x2e2f00002e30, - 0x300500003008, - 0x302a0000302e, - 0x303c0000303d, - 0x304100003097, - 0x30990000309b, - 0x309d0000309f, - 0x30a1000030fb, - 0x30fc000030ff, - 0x310500003130, - 0x31a0000031bb, - 0x31f000003200, - 0x340000004db6, - 0x4e0000009ff0, - 0xa0000000a48d, - 0xa4d00000a4fe, - 0xa5000000a60d, - 0xa6100000a62c, - 0xa6410000a642, - 0xa6430000a644, - 0xa6450000a646, - 0xa6470000a648, - 0xa6490000a64a, - 0xa64b0000a64c, - 0xa64d0000a64e, - 0xa64f0000a650, - 0xa6510000a652, - 0xa6530000a654, - 0xa6550000a656, - 0xa6570000a658, - 0xa6590000a65a, - 0xa65b0000a65c, - 0xa65d0000a65e, - 0xa65f0000a660, - 0xa6610000a662, - 0xa6630000a664, - 0xa6650000a666, - 0xa6670000a668, - 0xa6690000a66a, - 0xa66b0000a66c, - 0xa66d0000a670, - 0xa6740000a67e, - 0xa67f0000a680, - 0xa6810000a682, - 0xa6830000a684, - 0xa6850000a686, - 0xa6870000a688, - 0xa6890000a68a, - 0xa68b0000a68c, - 0xa68d0000a68e, - 0xa68f0000a690, - 0xa6910000a692, - 0xa6930000a694, - 0xa6950000a696, - 0xa6970000a698, - 0xa6990000a69a, - 0xa69b0000a69c, - 0xa69e0000a6e6, - 0xa6f00000a6f2, - 0xa7170000a720, - 0xa7230000a724, - 0xa7250000a726, - 0xa7270000a728, - 0xa7290000a72a, - 0xa72b0000a72c, - 0xa72d0000a72e, - 0xa72f0000a732, - 0xa7330000a734, - 0xa7350000a736, - 0xa7370000a738, - 0xa7390000a73a, - 0xa73b0000a73c, - 0xa73d0000a73e, - 0xa73f0000a740, - 0xa7410000a742, - 0xa7430000a744, - 0xa7450000a746, - 0xa7470000a748, - 0xa7490000a74a, - 0xa74b0000a74c, - 0xa74d0000a74e, - 0xa74f0000a750, - 0xa7510000a752, - 0xa7530000a754, - 0xa7550000a756, - 0xa7570000a758, - 0xa7590000a75a, - 0xa75b0000a75c, - 0xa75d0000a75e, - 0xa75f0000a760, - 0xa7610000a762, - 0xa7630000a764, - 0xa7650000a766, - 0xa7670000a768, - 0xa7690000a76a, - 0xa76b0000a76c, - 0xa76d0000a76e, - 0xa76f0000a770, - 0xa7710000a779, - 0xa77a0000a77b, - 0xa77c0000a77d, - 0xa77f0000a780, - 0xa7810000a782, - 0xa7830000a784, - 0xa7850000a786, - 0xa7870000a789, - 0xa78c0000a78d, - 0xa78e0000a790, - 0xa7910000a792, - 0xa7930000a796, - 0xa7970000a798, - 0xa7990000a79a, - 0xa79b0000a79c, - 0xa79d0000a79e, - 0xa79f0000a7a0, - 0xa7a10000a7a2, - 0xa7a30000a7a4, - 0xa7a50000a7a6, - 0xa7a70000a7a8, - 0xa7a90000a7aa, - 0xa7af0000a7b0, - 0xa7b50000a7b6, - 0xa7b70000a7b8, - 0xa7b90000a7ba, - 0xa7f70000a7f8, - 0xa7fa0000a828, - 0xa8400000a874, - 0xa8800000a8c6, - 0xa8d00000a8da, - 0xa8e00000a8f8, - 0xa8fb0000a8fc, - 0xa8fd0000a92e, - 0xa9300000a954, - 0xa9800000a9c1, - 0xa9cf0000a9da, - 0xa9e00000a9ff, - 0xaa000000aa37, - 0xaa400000aa4e, - 0xaa500000aa5a, - 0xaa600000aa77, - 0xaa7a0000aac3, - 0xaadb0000aade, - 0xaae00000aaf0, - 0xaaf20000aaf7, - 0xab010000ab07, - 0xab090000ab0f, - 0xab110000ab17, - 0xab200000ab27, - 0xab280000ab2f, - 0xab300000ab5b, - 0xab600000ab66, - 0xabc00000abeb, - 0xabec0000abee, - 0xabf00000abfa, - 0xac000000d7a4, - 0xfa0e0000fa10, - 0xfa110000fa12, - 0xfa130000fa15, - 0xfa1f0000fa20, - 0xfa210000fa22, - 0xfa230000fa25, - 0xfa270000fa2a, - 0xfb1e0000fb1f, - 0xfe200000fe30, - 0xfe730000fe74, - 0x100000001000c, - 0x1000d00010027, - 0x100280001003b, - 0x1003c0001003e, - 0x1003f0001004e, - 0x100500001005e, - 0x10080000100fb, - 0x101fd000101fe, - 0x102800001029d, - 0x102a0000102d1, - 0x102e0000102e1, - 0x1030000010320, - 0x1032d00010341, - 0x103420001034a, - 0x103500001037b, - 0x103800001039e, - 0x103a0000103c4, - 0x103c8000103d0, - 0x104280001049e, - 0x104a0000104aa, - 0x104d8000104fc, - 0x1050000010528, - 0x1053000010564, - 0x1060000010737, - 0x1074000010756, - 0x1076000010768, - 0x1080000010806, - 0x1080800010809, - 0x1080a00010836, - 0x1083700010839, - 0x1083c0001083d, - 0x1083f00010856, - 0x1086000010877, - 0x108800001089f, - 0x108e0000108f3, - 0x108f4000108f6, - 0x1090000010916, - 0x109200001093a, - 0x10980000109b8, - 0x109be000109c0, - 0x10a0000010a04, - 0x10a0500010a07, - 0x10a0c00010a14, - 0x10a1500010a18, - 0x10a1900010a36, - 0x10a3800010a3b, - 0x10a3f00010a40, - 0x10a6000010a7d, - 0x10a8000010a9d, - 0x10ac000010ac8, - 0x10ac900010ae7, - 0x10b0000010b36, - 0x10b4000010b56, - 0x10b6000010b73, - 0x10b8000010b92, - 0x10c0000010c49, - 0x10cc000010cf3, - 0x10d0000010d28, - 0x10d3000010d3a, - 0x10f0000010f1d, - 0x10f2700010f28, - 0x10f3000010f51, - 0x1100000011047, - 0x1106600011070, - 0x1107f000110bb, - 0x110d0000110e9, - 0x110f0000110fa, - 0x1110000011135, - 0x1113600011140, - 0x1114400011147, - 0x1115000011174, - 0x1117600011177, - 0x11180000111c5, - 0x111c9000111cd, - 0x111d0000111db, - 0x111dc000111dd, - 0x1120000011212, - 0x1121300011238, - 0x1123e0001123f, - 0x1128000011287, - 0x1128800011289, - 0x1128a0001128e, - 0x1128f0001129e, - 0x1129f000112a9, - 0x112b0000112eb, - 0x112f0000112fa, - 0x1130000011304, - 0x113050001130d, - 0x1130f00011311, - 0x1131300011329, - 0x1132a00011331, - 0x1133200011334, - 0x113350001133a, - 0x1133b00011345, - 0x1134700011349, - 0x1134b0001134e, - 0x1135000011351, - 0x1135700011358, - 0x1135d00011364, - 0x113660001136d, - 0x1137000011375, - 0x114000001144b, - 0x114500001145a, - 0x1145e0001145f, - 0x11480000114c6, - 0x114c7000114c8, - 0x114d0000114da, - 0x11580000115b6, - 0x115b8000115c1, - 0x115d8000115de, - 0x1160000011641, - 0x1164400011645, - 0x116500001165a, - 0x11680000116b8, - 0x116c0000116ca, - 0x117000001171b, - 0x1171d0001172c, - 0x117300001173a, - 0x118000001183b, - 0x118c0000118ea, - 0x118ff00011900, - 0x11a0000011a3f, - 0x11a4700011a48, - 0x11a5000011a84, - 0x11a8600011a9a, - 0x11a9d00011a9e, - 0x11ac000011af9, - 0x11c0000011c09, - 0x11c0a00011c37, - 0x11c3800011c41, - 0x11c5000011c5a, - 0x11c7200011c90, - 0x11c9200011ca8, - 0x11ca900011cb7, - 0x11d0000011d07, - 0x11d0800011d0a, - 0x11d0b00011d37, - 0x11d3a00011d3b, - 0x11d3c00011d3e, - 0x11d3f00011d48, - 0x11d5000011d5a, - 0x11d6000011d66, - 0x11d6700011d69, - 0x11d6a00011d8f, - 0x11d9000011d92, - 0x11d9300011d99, - 0x11da000011daa, - 0x11ee000011ef7, - 0x120000001239a, - 0x1248000012544, - 0x130000001342f, - 0x1440000014647, - 0x1680000016a39, - 0x16a4000016a5f, - 0x16a6000016a6a, - 0x16ad000016aee, - 0x16af000016af5, - 0x16b0000016b37, - 0x16b4000016b44, - 0x16b5000016b5a, - 0x16b6300016b78, - 0x16b7d00016b90, - 0x16e6000016e80, - 0x16f0000016f45, - 0x16f5000016f7f, - 0x16f8f00016fa0, - 0x16fe000016fe2, - 0x17000000187f2, - 0x1880000018af3, - 0x1b0000001b11f, - 0x1b1700001b2fc, - 0x1bc000001bc6b, - 0x1bc700001bc7d, - 0x1bc800001bc89, - 0x1bc900001bc9a, - 0x1bc9d0001bc9f, - 0x1da000001da37, - 0x1da3b0001da6d, - 0x1da750001da76, - 0x1da840001da85, - 0x1da9b0001daa0, - 0x1daa10001dab0, - 0x1e0000001e007, - 0x1e0080001e019, - 0x1e01b0001e022, - 0x1e0230001e025, - 0x1e0260001e02b, - 0x1e8000001e8c5, - 0x1e8d00001e8d7, - 0x1e9220001e94b, - 0x1e9500001e95a, - 0x200000002a6d7, - 0x2a7000002b735, - 0x2b7400002b81e, - 0x2b8200002cea2, - 0x2ceb00002ebe1, - ), - 'CONTEXTJ': ( - 0x200c0000200e, - ), - 'CONTEXTO': ( - 0xb7000000b8, - 0x37500000376, - 0x5f3000005f5, - 0x6600000066a, - 0x6f0000006fa, - 0x30fb000030fc, - ), -} diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/idna/intranges.py b/venv2/lib/python2.7/site-packages/pip/_vendor/idna/intranges.py deleted file mode 100644 index fa8a735..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/idna/intranges.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Given a list of integers, made up of (hopefully) a small number of long runs -of consecutive integers, compute a representation of the form -((start1, end1), (start2, end2) ...). Then answer the question "was x present -in the original list?" in time O(log(# runs)). -""" - -import bisect - -def intranges_from_list(list_): - """Represent a list of integers as a sequence of ranges: - ((start_0, end_0), (start_1, end_1), ...), such that the original - integers are exactly those x such that start_i <= x < end_i for some i. - - Ranges are encoded as single integers (start << 32 | end), not as tuples. - """ - - sorted_list = sorted(list_) - ranges = [] - last_write = -1 - for i in range(len(sorted_list)): - if i+1 < len(sorted_list): - if sorted_list[i] == sorted_list[i+1]-1: - continue - current_range = sorted_list[last_write+1:i+1] - ranges.append(_encode_range(current_range[0], current_range[-1] + 1)) - last_write = i - - return tuple(ranges) - -def _encode_range(start, end): - return (start << 32) | end - -def _decode_range(r): - return (r >> 32), (r & ((1 << 32) - 1)) - - -def intranges_contain(int_, ranges): - """Determine if `int_` falls into one of the ranges in `ranges`.""" - tuple_ = _encode_range(int_, 0) - pos = bisect.bisect_left(ranges, tuple_) - # we could be immediately ahead of a tuple (start, end) - # with start < int_ <= end - if pos > 0: - left, right = _decode_range(ranges[pos-1]) - if left <= int_ < right: - return True - # or we could be immediately behind a tuple (int_, end) - if pos < len(ranges): - left, _ = _decode_range(ranges[pos]) - if left == int_: - return True - return False diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/idna/package_data.py b/venv2/lib/python2.7/site-packages/pip/_vendor/idna/package_data.py deleted file mode 100644 index 257e898..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/idna/package_data.py +++ /dev/null @@ -1,2 +0,0 @@ -__version__ = '2.8' - diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/idna/uts46data.py b/venv2/lib/python2.7/site-packages/pip/_vendor/idna/uts46data.py deleted file mode 100644 index a68ed4c..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/idna/uts46data.py +++ /dev/null @@ -1,8205 +0,0 @@ -# This file is automatically generated by tools/idna-data -# vim: set fileencoding=utf-8 : - -"""IDNA Mapping Table from UTS46.""" - - -__version__ = "11.0.0" -def _seg_0(): - return [ - (0x0, '3'), - (0x1, '3'), - (0x2, '3'), - (0x3, '3'), - (0x4, '3'), - (0x5, '3'), - (0x6, '3'), - (0x7, '3'), - (0x8, '3'), - (0x9, '3'), - (0xA, '3'), - (0xB, '3'), - (0xC, '3'), - (0xD, '3'), - (0xE, '3'), - (0xF, '3'), - (0x10, '3'), - (0x11, '3'), - (0x12, '3'), - (0x13, '3'), - (0x14, '3'), - (0x15, '3'), - (0x16, '3'), - (0x17, '3'), - (0x18, '3'), - (0x19, '3'), - (0x1A, '3'), - (0x1B, '3'), - (0x1C, '3'), - (0x1D, '3'), - (0x1E, '3'), - (0x1F, '3'), - (0x20, '3'), - (0x21, '3'), - (0x22, '3'), - (0x23, '3'), - (0x24, '3'), - (0x25, '3'), - (0x26, '3'), - (0x27, '3'), - (0x28, '3'), - (0x29, '3'), - (0x2A, '3'), - (0x2B, '3'), - (0x2C, '3'), - (0x2D, 'V'), - (0x2E, 'V'), - (0x2F, '3'), - (0x30, 'V'), - (0x31, 'V'), - (0x32, 'V'), - (0x33, 'V'), - (0x34, 'V'), - (0x35, 'V'), - (0x36, 'V'), - (0x37, 'V'), - (0x38, 'V'), - (0x39, 'V'), - (0x3A, '3'), - (0x3B, '3'), - (0x3C, '3'), - (0x3D, '3'), - (0x3E, '3'), - (0x3F, '3'), - (0x40, '3'), - (0x41, 'M', u'a'), - (0x42, 'M', u'b'), - (0x43, 'M', u'c'), - (0x44, 'M', u'd'), - (0x45, 'M', u'e'), - (0x46, 'M', u'f'), - (0x47, 'M', u'g'), - (0x48, 'M', u'h'), - (0x49, 'M', u'i'), - (0x4A, 'M', u'j'), - (0x4B, 'M', u'k'), - (0x4C, 'M', u'l'), - (0x4D, 'M', u'm'), - (0x4E, 'M', u'n'), - (0x4F, 'M', u'o'), - (0x50, 'M', u'p'), - (0x51, 'M', u'q'), - (0x52, 'M', u'r'), - (0x53, 'M', u's'), - (0x54, 'M', u't'), - (0x55, 'M', u'u'), - (0x56, 'M', u'v'), - (0x57, 'M', u'w'), - (0x58, 'M', u'x'), - (0x59, 'M', u'y'), - (0x5A, 'M', u'z'), - (0x5B, '3'), - (0x5C, '3'), - (0x5D, '3'), - (0x5E, '3'), - (0x5F, '3'), - (0x60, '3'), - (0x61, 'V'), - (0x62, 'V'), - (0x63, 'V'), - ] - -def _seg_1(): - return [ - (0x64, 'V'), - (0x65, 'V'), - (0x66, 'V'), - (0x67, 'V'), - (0x68, 'V'), - (0x69, 'V'), - (0x6A, 'V'), - (0x6B, 'V'), - (0x6C, 'V'), - (0x6D, 'V'), - (0x6E, 'V'), - (0x6F, 'V'), - (0x70, 'V'), - (0x71, 'V'), - (0x72, 'V'), - (0x73, 'V'), - (0x74, 'V'), - (0x75, 'V'), - (0x76, 'V'), - (0x77, 'V'), - (0x78, 'V'), - (0x79, 'V'), - (0x7A, 'V'), - (0x7B, '3'), - (0x7C, '3'), - (0x7D, '3'), - (0x7E, '3'), - (0x7F, '3'), - (0x80, 'X'), - (0x81, 'X'), - (0x82, 'X'), - (0x83, 'X'), - (0x84, 'X'), - (0x85, 'X'), - (0x86, 'X'), - (0x87, 'X'), - (0x88, 'X'), - (0x89, 'X'), - (0x8A, 'X'), - (0x8B, 'X'), - (0x8C, 'X'), - (0x8D, 'X'), - (0x8E, 'X'), - (0x8F, 'X'), - (0x90, 'X'), - (0x91, 'X'), - (0x92, 'X'), - (0x93, 'X'), - (0x94, 'X'), - (0x95, 'X'), - (0x96, 'X'), - (0x97, 'X'), - (0x98, 'X'), - (0x99, 'X'), - (0x9A, 'X'), - (0x9B, 'X'), - (0x9C, 'X'), - (0x9D, 'X'), - (0x9E, 'X'), - (0x9F, 'X'), - (0xA0, '3', u' '), - (0xA1, 'V'), - (0xA2, 'V'), - (0xA3, 'V'), - (0xA4, 'V'), - (0xA5, 'V'), - (0xA6, 'V'), - (0xA7, 'V'), - (0xA8, '3', u' ̈'), - (0xA9, 'V'), - (0xAA, 'M', u'a'), - (0xAB, 'V'), - (0xAC, 'V'), - (0xAD, 'I'), - (0xAE, 'V'), - (0xAF, '3', u' ̄'), - (0xB0, 'V'), - (0xB1, 'V'), - (0xB2, 'M', u'2'), - (0xB3, 'M', u'3'), - (0xB4, '3', u' ́'), - (0xB5, 'M', u'μ'), - (0xB6, 'V'), - (0xB7, 'V'), - (0xB8, '3', u' ̧'), - (0xB9, 'M', u'1'), - (0xBA, 'M', u'o'), - (0xBB, 'V'), - (0xBC, 'M', u'1⁄4'), - (0xBD, 'M', u'1⁄2'), - (0xBE, 'M', u'3⁄4'), - (0xBF, 'V'), - (0xC0, 'M', u'à'), - (0xC1, 'M', u'á'), - (0xC2, 'M', u'â'), - (0xC3, 'M', u'ã'), - (0xC4, 'M', u'ä'), - (0xC5, 'M', u'å'), - (0xC6, 'M', u'æ'), - (0xC7, 'M', u'ç'), - ] - -def _seg_2(): - return [ - (0xC8, 'M', u'è'), - (0xC9, 'M', u'é'), - (0xCA, 'M', u'ê'), - (0xCB, 'M', u'ë'), - (0xCC, 'M', u'ì'), - (0xCD, 'M', u'í'), - (0xCE, 'M', u'î'), - (0xCF, 'M', u'ï'), - (0xD0, 'M', u'ð'), - (0xD1, 'M', u'ñ'), - (0xD2, 'M', u'ò'), - (0xD3, 'M', u'ó'), - (0xD4, 'M', u'ô'), - (0xD5, 'M', u'õ'), - (0xD6, 'M', u'ö'), - (0xD7, 'V'), - (0xD8, 'M', u'ø'), - (0xD9, 'M', u'ù'), - (0xDA, 'M', u'ú'), - (0xDB, 'M', u'û'), - (0xDC, 'M', u'ü'), - (0xDD, 'M', u'ý'), - (0xDE, 'M', u'þ'), - (0xDF, 'D', u'ss'), - (0xE0, 'V'), - (0xE1, 'V'), - (0xE2, 'V'), - (0xE3, 'V'), - (0xE4, 'V'), - (0xE5, 'V'), - (0xE6, 'V'), - (0xE7, 'V'), - (0xE8, 'V'), - (0xE9, 'V'), - (0xEA, 'V'), - (0xEB, 'V'), - (0xEC, 'V'), - (0xED, 'V'), - (0xEE, 'V'), - (0xEF, 'V'), - (0xF0, 'V'), - (0xF1, 'V'), - (0xF2, 'V'), - (0xF3, 'V'), - (0xF4, 'V'), - (0xF5, 'V'), - (0xF6, 'V'), - (0xF7, 'V'), - (0xF8, 'V'), - (0xF9, 'V'), - (0xFA, 'V'), - (0xFB, 'V'), - (0xFC, 'V'), - (0xFD, 'V'), - (0xFE, 'V'), - (0xFF, 'V'), - (0x100, 'M', u'ā'), - (0x101, 'V'), - (0x102, 'M', u'ă'), - (0x103, 'V'), - (0x104, 'M', u'ą'), - (0x105, 'V'), - (0x106, 'M', u'ć'), - (0x107, 'V'), - (0x108, 'M', u'ĉ'), - (0x109, 'V'), - (0x10A, 'M', u'ċ'), - (0x10B, 'V'), - (0x10C, 'M', u'č'), - (0x10D, 'V'), - (0x10E, 'M', u'ď'), - (0x10F, 'V'), - (0x110, 'M', u'đ'), - (0x111, 'V'), - (0x112, 'M', u'ē'), - (0x113, 'V'), - (0x114, 'M', u'ĕ'), - (0x115, 'V'), - (0x116, 'M', u'ė'), - (0x117, 'V'), - (0x118, 'M', u'ę'), - (0x119, 'V'), - (0x11A, 'M', u'ě'), - (0x11B, 'V'), - (0x11C, 'M', u'ĝ'), - (0x11D, 'V'), - (0x11E, 'M', u'ğ'), - (0x11F, 'V'), - (0x120, 'M', u'ġ'), - (0x121, 'V'), - (0x122, 'M', u'ģ'), - (0x123, 'V'), - (0x124, 'M', u'ĥ'), - (0x125, 'V'), - (0x126, 'M', u'ħ'), - (0x127, 'V'), - (0x128, 'M', u'ĩ'), - (0x129, 'V'), - (0x12A, 'M', u'ī'), - (0x12B, 'V'), - ] - -def _seg_3(): - return [ - (0x12C, 'M', u'ĭ'), - (0x12D, 'V'), - (0x12E, 'M', u'į'), - (0x12F, 'V'), - (0x130, 'M', u'i̇'), - (0x131, 'V'), - (0x132, 'M', u'ij'), - (0x134, 'M', u'ĵ'), - (0x135, 'V'), - (0x136, 'M', u'ķ'), - (0x137, 'V'), - (0x139, 'M', u'ĺ'), - (0x13A, 'V'), - (0x13B, 'M', u'ļ'), - (0x13C, 'V'), - (0x13D, 'M', u'ľ'), - (0x13E, 'V'), - (0x13F, 'M', u'l·'), - (0x141, 'M', u'ł'), - (0x142, 'V'), - (0x143, 'M', u'ń'), - (0x144, 'V'), - (0x145, 'M', u'ņ'), - (0x146, 'V'), - (0x147, 'M', u'ň'), - (0x148, 'V'), - (0x149, 'M', u'ʼn'), - (0x14A, 'M', u'ŋ'), - (0x14B, 'V'), - (0x14C, 'M', u'ō'), - (0x14D, 'V'), - (0x14E, 'M', u'ŏ'), - (0x14F, 'V'), - (0x150, 'M', u'ő'), - (0x151, 'V'), - (0x152, 'M', u'œ'), - (0x153, 'V'), - (0x154, 'M', u'ŕ'), - (0x155, 'V'), - (0x156, 'M', u'ŗ'), - (0x157, 'V'), - (0x158, 'M', u'ř'), - (0x159, 'V'), - (0x15A, 'M', u'ś'), - (0x15B, 'V'), - (0x15C, 'M', u'ŝ'), - (0x15D, 'V'), - (0x15E, 'M', u'ş'), - (0x15F, 'V'), - (0x160, 'M', u'š'), - (0x161, 'V'), - (0x162, 'M', u'ţ'), - (0x163, 'V'), - (0x164, 'M', u'ť'), - (0x165, 'V'), - (0x166, 'M', u'ŧ'), - (0x167, 'V'), - (0x168, 'M', u'ũ'), - (0x169, 'V'), - (0x16A, 'M', u'ū'), - (0x16B, 'V'), - (0x16C, 'M', u'ŭ'), - (0x16D, 'V'), - (0x16E, 'M', u'ů'), - (0x16F, 'V'), - (0x170, 'M', u'ű'), - (0x171, 'V'), - (0x172, 'M', u'ų'), - (0x173, 'V'), - (0x174, 'M', u'ŵ'), - (0x175, 'V'), - (0x176, 'M', u'ŷ'), - (0x177, 'V'), - (0x178, 'M', u'ÿ'), - (0x179, 'M', u'ź'), - (0x17A, 'V'), - (0x17B, 'M', u'ż'), - (0x17C, 'V'), - (0x17D, 'M', u'ž'), - (0x17E, 'V'), - (0x17F, 'M', u's'), - (0x180, 'V'), - (0x181, 'M', u'ɓ'), - (0x182, 'M', u'ƃ'), - (0x183, 'V'), - (0x184, 'M', u'ƅ'), - (0x185, 'V'), - (0x186, 'M', u'ɔ'), - (0x187, 'M', u'ƈ'), - (0x188, 'V'), - (0x189, 'M', u'ɖ'), - (0x18A, 'M', u'ɗ'), - (0x18B, 'M', u'ƌ'), - (0x18C, 'V'), - (0x18E, 'M', u'ǝ'), - (0x18F, 'M', u'ə'), - (0x190, 'M', u'ɛ'), - (0x191, 'M', u'ƒ'), - (0x192, 'V'), - (0x193, 'M', u'ɠ'), - ] - -def _seg_4(): - return [ - (0x194, 'M', u'ɣ'), - (0x195, 'V'), - (0x196, 'M', u'ɩ'), - (0x197, 'M', u'ɨ'), - (0x198, 'M', u'ƙ'), - (0x199, 'V'), - (0x19C, 'M', u'ɯ'), - (0x19D, 'M', u'ɲ'), - (0x19E, 'V'), - (0x19F, 'M', u'ɵ'), - (0x1A0, 'M', u'ơ'), - (0x1A1, 'V'), - (0x1A2, 'M', u'ƣ'), - (0x1A3, 'V'), - (0x1A4, 'M', u'ƥ'), - (0x1A5, 'V'), - (0x1A6, 'M', u'ʀ'), - (0x1A7, 'M', u'ƨ'), - (0x1A8, 'V'), - (0x1A9, 'M', u'ʃ'), - (0x1AA, 'V'), - (0x1AC, 'M', u'ƭ'), - (0x1AD, 'V'), - (0x1AE, 'M', u'ʈ'), - (0x1AF, 'M', u'ư'), - (0x1B0, 'V'), - (0x1B1, 'M', u'ʊ'), - (0x1B2, 'M', u'ʋ'), - (0x1B3, 'M', u'ƴ'), - (0x1B4, 'V'), - (0x1B5, 'M', u'ƶ'), - (0x1B6, 'V'), - (0x1B7, 'M', u'ʒ'), - (0x1B8, 'M', u'ƹ'), - (0x1B9, 'V'), - (0x1BC, 'M', u'ƽ'), - (0x1BD, 'V'), - (0x1C4, 'M', u'dž'), - (0x1C7, 'M', u'lj'), - (0x1CA, 'M', u'nj'), - (0x1CD, 'M', u'ǎ'), - (0x1CE, 'V'), - (0x1CF, 'M', u'ǐ'), - (0x1D0, 'V'), - (0x1D1, 'M', u'ǒ'), - (0x1D2, 'V'), - (0x1D3, 'M', u'ǔ'), - (0x1D4, 'V'), - (0x1D5, 'M', u'ǖ'), - (0x1D6, 'V'), - (0x1D7, 'M', u'ǘ'), - (0x1D8, 'V'), - (0x1D9, 'M', u'ǚ'), - (0x1DA, 'V'), - (0x1DB, 'M', u'ǜ'), - (0x1DC, 'V'), - (0x1DE, 'M', u'ǟ'), - (0x1DF, 'V'), - (0x1E0, 'M', u'ǡ'), - (0x1E1, 'V'), - (0x1E2, 'M', u'ǣ'), - (0x1E3, 'V'), - (0x1E4, 'M', u'ǥ'), - (0x1E5, 'V'), - (0x1E6, 'M', u'ǧ'), - (0x1E7, 'V'), - (0x1E8, 'M', u'ǩ'), - (0x1E9, 'V'), - (0x1EA, 'M', u'ǫ'), - (0x1EB, 'V'), - (0x1EC, 'M', u'ǭ'), - (0x1ED, 'V'), - (0x1EE, 'M', u'ǯ'), - (0x1EF, 'V'), - (0x1F1, 'M', u'dz'), - (0x1F4, 'M', u'ǵ'), - (0x1F5, 'V'), - (0x1F6, 'M', u'ƕ'), - (0x1F7, 'M', u'ƿ'), - (0x1F8, 'M', u'ǹ'), - (0x1F9, 'V'), - (0x1FA, 'M', u'ǻ'), - (0x1FB, 'V'), - (0x1FC, 'M', u'ǽ'), - (0x1FD, 'V'), - (0x1FE, 'M', u'ǿ'), - (0x1FF, 'V'), - (0x200, 'M', u'ȁ'), - (0x201, 'V'), - (0x202, 'M', u'ȃ'), - (0x203, 'V'), - (0x204, 'M', u'ȅ'), - (0x205, 'V'), - (0x206, 'M', u'ȇ'), - (0x207, 'V'), - (0x208, 'M', u'ȉ'), - (0x209, 'V'), - (0x20A, 'M', u'ȋ'), - (0x20B, 'V'), - (0x20C, 'M', u'ȍ'), - ] - -def _seg_5(): - return [ - (0x20D, 'V'), - (0x20E, 'M', u'ȏ'), - (0x20F, 'V'), - (0x210, 'M', u'ȑ'), - (0x211, 'V'), - (0x212, 'M', u'ȓ'), - (0x213, 'V'), - (0x214, 'M', u'ȕ'), - (0x215, 'V'), - (0x216, 'M', u'ȗ'), - (0x217, 'V'), - (0x218, 'M', u'ș'), - (0x219, 'V'), - (0x21A, 'M', u'ț'), - (0x21B, 'V'), - (0x21C, 'M', u'ȝ'), - (0x21D, 'V'), - (0x21E, 'M', u'ȟ'), - (0x21F, 'V'), - (0x220, 'M', u'ƞ'), - (0x221, 'V'), - (0x222, 'M', u'ȣ'), - (0x223, 'V'), - (0x224, 'M', u'ȥ'), - (0x225, 'V'), - (0x226, 'M', u'ȧ'), - (0x227, 'V'), - (0x228, 'M', u'ȩ'), - (0x229, 'V'), - (0x22A, 'M', u'ȫ'), - (0x22B, 'V'), - (0x22C, 'M', u'ȭ'), - (0x22D, 'V'), - (0x22E, 'M', u'ȯ'), - (0x22F, 'V'), - (0x230, 'M', u'ȱ'), - (0x231, 'V'), - (0x232, 'M', u'ȳ'), - (0x233, 'V'), - (0x23A, 'M', u'ⱥ'), - (0x23B, 'M', u'ȼ'), - (0x23C, 'V'), - (0x23D, 'M', u'ƚ'), - (0x23E, 'M', u'ⱦ'), - (0x23F, 'V'), - (0x241, 'M', u'ɂ'), - (0x242, 'V'), - (0x243, 'M', u'ƀ'), - (0x244, 'M', u'ʉ'), - (0x245, 'M', u'ʌ'), - (0x246, 'M', u'ɇ'), - (0x247, 'V'), - (0x248, 'M', u'ɉ'), - (0x249, 'V'), - (0x24A, 'M', u'ɋ'), - (0x24B, 'V'), - (0x24C, 'M', u'ɍ'), - (0x24D, 'V'), - (0x24E, 'M', u'ɏ'), - (0x24F, 'V'), - (0x2B0, 'M', u'h'), - (0x2B1, 'M', u'ɦ'), - (0x2B2, 'M', u'j'), - (0x2B3, 'M', u'r'), - (0x2B4, 'M', u'ɹ'), - (0x2B5, 'M', u'ɻ'), - (0x2B6, 'M', u'ʁ'), - (0x2B7, 'M', u'w'), - (0x2B8, 'M', u'y'), - (0x2B9, 'V'), - (0x2D8, '3', u' ̆'), - (0x2D9, '3', u' ̇'), - (0x2DA, '3', u' ̊'), - (0x2DB, '3', u' ̨'), - (0x2DC, '3', u' ̃'), - (0x2DD, '3', u' ̋'), - (0x2DE, 'V'), - (0x2E0, 'M', u'ɣ'), - (0x2E1, 'M', u'l'), - (0x2E2, 'M', u's'), - (0x2E3, 'M', u'x'), - (0x2E4, 'M', u'ʕ'), - (0x2E5, 'V'), - (0x340, 'M', u'̀'), - (0x341, 'M', u'́'), - (0x342, 'V'), - (0x343, 'M', u'̓'), - (0x344, 'M', u'̈́'), - (0x345, 'M', u'ι'), - (0x346, 'V'), - (0x34F, 'I'), - (0x350, 'V'), - (0x370, 'M', u'ͱ'), - (0x371, 'V'), - (0x372, 'M', u'ͳ'), - (0x373, 'V'), - (0x374, 'M', u'ʹ'), - (0x375, 'V'), - (0x376, 'M', u'ͷ'), - (0x377, 'V'), - ] - -def _seg_6(): - return [ - (0x378, 'X'), - (0x37A, '3', u' ι'), - (0x37B, 'V'), - (0x37E, '3', u';'), - (0x37F, 'M', u'ϳ'), - (0x380, 'X'), - (0x384, '3', u' ́'), - (0x385, '3', u' ̈́'), - (0x386, 'M', u'ά'), - (0x387, 'M', u'·'), - (0x388, 'M', u'έ'), - (0x389, 'M', u'ή'), - (0x38A, 'M', u'ί'), - (0x38B, 'X'), - (0x38C, 'M', u'ό'), - (0x38D, 'X'), - (0x38E, 'M', u'ύ'), - (0x38F, 'M', u'ώ'), - (0x390, 'V'), - (0x391, 'M', u'α'), - (0x392, 'M', u'β'), - (0x393, 'M', u'γ'), - (0x394, 'M', u'δ'), - (0x395, 'M', u'ε'), - (0x396, 'M', u'ζ'), - (0x397, 'M', u'η'), - (0x398, 'M', u'θ'), - (0x399, 'M', u'ι'), - (0x39A, 'M', u'κ'), - (0x39B, 'M', u'λ'), - (0x39C, 'M', u'μ'), - (0x39D, 'M', u'ν'), - (0x39E, 'M', u'ξ'), - (0x39F, 'M', u'ο'), - (0x3A0, 'M', u'π'), - (0x3A1, 'M', u'ρ'), - (0x3A2, 'X'), - (0x3A3, 'M', u'σ'), - (0x3A4, 'M', u'τ'), - (0x3A5, 'M', u'υ'), - (0x3A6, 'M', u'φ'), - (0x3A7, 'M', u'χ'), - (0x3A8, 'M', u'ψ'), - (0x3A9, 'M', u'ω'), - (0x3AA, 'M', u'ϊ'), - (0x3AB, 'M', u'ϋ'), - (0x3AC, 'V'), - (0x3C2, 'D', u'σ'), - (0x3C3, 'V'), - (0x3CF, 'M', u'ϗ'), - (0x3D0, 'M', u'β'), - (0x3D1, 'M', u'θ'), - (0x3D2, 'M', u'υ'), - (0x3D3, 'M', u'ύ'), - (0x3D4, 'M', u'ϋ'), - (0x3D5, 'M', u'φ'), - (0x3D6, 'M', u'π'), - (0x3D7, 'V'), - (0x3D8, 'M', u'ϙ'), - (0x3D9, 'V'), - (0x3DA, 'M', u'ϛ'), - (0x3DB, 'V'), - (0x3DC, 'M', u'ϝ'), - (0x3DD, 'V'), - (0x3DE, 'M', u'ϟ'), - (0x3DF, 'V'), - (0x3E0, 'M', u'ϡ'), - (0x3E1, 'V'), - (0x3E2, 'M', u'ϣ'), - (0x3E3, 'V'), - (0x3E4, 'M', u'ϥ'), - (0x3E5, 'V'), - (0x3E6, 'M', u'ϧ'), - (0x3E7, 'V'), - (0x3E8, 'M', u'ϩ'), - (0x3E9, 'V'), - (0x3EA, 'M', u'ϫ'), - (0x3EB, 'V'), - (0x3EC, 'M', u'ϭ'), - (0x3ED, 'V'), - (0x3EE, 'M', u'ϯ'), - (0x3EF, 'V'), - (0x3F0, 'M', u'κ'), - (0x3F1, 'M', u'ρ'), - (0x3F2, 'M', u'σ'), - (0x3F3, 'V'), - (0x3F4, 'M', u'θ'), - (0x3F5, 'M', u'ε'), - (0x3F6, 'V'), - (0x3F7, 'M', u'ϸ'), - (0x3F8, 'V'), - (0x3F9, 'M', u'σ'), - (0x3FA, 'M', u'ϻ'), - (0x3FB, 'V'), - (0x3FD, 'M', u'ͻ'), - (0x3FE, 'M', u'ͼ'), - (0x3FF, 'M', u'ͽ'), - (0x400, 'M', u'ѐ'), - (0x401, 'M', u'ё'), - (0x402, 'M', u'ђ'), - ] - -def _seg_7(): - return [ - (0x403, 'M', u'ѓ'), - (0x404, 'M', u'є'), - (0x405, 'M', u'ѕ'), - (0x406, 'M', u'і'), - (0x407, 'M', u'ї'), - (0x408, 'M', u'ј'), - (0x409, 'M', u'љ'), - (0x40A, 'M', u'њ'), - (0x40B, 'M', u'ћ'), - (0x40C, 'M', u'ќ'), - (0x40D, 'M', u'ѝ'), - (0x40E, 'M', u'ў'), - (0x40F, 'M', u'џ'), - (0x410, 'M', u'а'), - (0x411, 'M', u'б'), - (0x412, 'M', u'в'), - (0x413, 'M', u'г'), - (0x414, 'M', u'д'), - (0x415, 'M', u'е'), - (0x416, 'M', u'ж'), - (0x417, 'M', u'з'), - (0x418, 'M', u'и'), - (0x419, 'M', u'й'), - (0x41A, 'M', u'к'), - (0x41B, 'M', u'л'), - (0x41C, 'M', u'м'), - (0x41D, 'M', u'н'), - (0x41E, 'M', u'о'), - (0x41F, 'M', u'п'), - (0x420, 'M', u'р'), - (0x421, 'M', u'с'), - (0x422, 'M', u'т'), - (0x423, 'M', u'у'), - (0x424, 'M', u'ф'), - (0x425, 'M', u'х'), - (0x426, 'M', u'ц'), - (0x427, 'M', u'ч'), - (0x428, 'M', u'ш'), - (0x429, 'M', u'щ'), - (0x42A, 'M', u'ъ'), - (0x42B, 'M', u'ы'), - (0x42C, 'M', u'ь'), - (0x42D, 'M', u'э'), - (0x42E, 'M', u'ю'), - (0x42F, 'M', u'я'), - (0x430, 'V'), - (0x460, 'M', u'ѡ'), - (0x461, 'V'), - (0x462, 'M', u'ѣ'), - (0x463, 'V'), - (0x464, 'M', u'ѥ'), - (0x465, 'V'), - (0x466, 'M', u'ѧ'), - (0x467, 'V'), - (0x468, 'M', u'ѩ'), - (0x469, 'V'), - (0x46A, 'M', u'ѫ'), - (0x46B, 'V'), - (0x46C, 'M', u'ѭ'), - (0x46D, 'V'), - (0x46E, 'M', u'ѯ'), - (0x46F, 'V'), - (0x470, 'M', u'ѱ'), - (0x471, 'V'), - (0x472, 'M', u'ѳ'), - (0x473, 'V'), - (0x474, 'M', u'ѵ'), - (0x475, 'V'), - (0x476, 'M', u'ѷ'), - (0x477, 'V'), - (0x478, 'M', u'ѹ'), - (0x479, 'V'), - (0x47A, 'M', u'ѻ'), - (0x47B, 'V'), - (0x47C, 'M', u'ѽ'), - (0x47D, 'V'), - (0x47E, 'M', u'ѿ'), - (0x47F, 'V'), - (0x480, 'M', u'ҁ'), - (0x481, 'V'), - (0x48A, 'M', u'ҋ'), - (0x48B, 'V'), - (0x48C, 'M', u'ҍ'), - (0x48D, 'V'), - (0x48E, 'M', u'ҏ'), - (0x48F, 'V'), - (0x490, 'M', u'ґ'), - (0x491, 'V'), - (0x492, 'M', u'ғ'), - (0x493, 'V'), - (0x494, 'M', u'ҕ'), - (0x495, 'V'), - (0x496, 'M', u'җ'), - (0x497, 'V'), - (0x498, 'M', u'ҙ'), - (0x499, 'V'), - (0x49A, 'M', u'қ'), - (0x49B, 'V'), - (0x49C, 'M', u'ҝ'), - (0x49D, 'V'), - ] - -def _seg_8(): - return [ - (0x49E, 'M', u'ҟ'), - (0x49F, 'V'), - (0x4A0, 'M', u'ҡ'), - (0x4A1, 'V'), - (0x4A2, 'M', u'ң'), - (0x4A3, 'V'), - (0x4A4, 'M', u'ҥ'), - (0x4A5, 'V'), - (0x4A6, 'M', u'ҧ'), - (0x4A7, 'V'), - (0x4A8, 'M', u'ҩ'), - (0x4A9, 'V'), - (0x4AA, 'M', u'ҫ'), - (0x4AB, 'V'), - (0x4AC, 'M', u'ҭ'), - (0x4AD, 'V'), - (0x4AE, 'M', u'ү'), - (0x4AF, 'V'), - (0x4B0, 'M', u'ұ'), - (0x4B1, 'V'), - (0x4B2, 'M', u'ҳ'), - (0x4B3, 'V'), - (0x4B4, 'M', u'ҵ'), - (0x4B5, 'V'), - (0x4B6, 'M', u'ҷ'), - (0x4B7, 'V'), - (0x4B8, 'M', u'ҹ'), - (0x4B9, 'V'), - (0x4BA, 'M', u'һ'), - (0x4BB, 'V'), - (0x4BC, 'M', u'ҽ'), - (0x4BD, 'V'), - (0x4BE, 'M', u'ҿ'), - (0x4BF, 'V'), - (0x4C0, 'X'), - (0x4C1, 'M', u'ӂ'), - (0x4C2, 'V'), - (0x4C3, 'M', u'ӄ'), - (0x4C4, 'V'), - (0x4C5, 'M', u'ӆ'), - (0x4C6, 'V'), - (0x4C7, 'M', u'ӈ'), - (0x4C8, 'V'), - (0x4C9, 'M', u'ӊ'), - (0x4CA, 'V'), - (0x4CB, 'M', u'ӌ'), - (0x4CC, 'V'), - (0x4CD, 'M', u'ӎ'), - (0x4CE, 'V'), - (0x4D0, 'M', u'ӑ'), - (0x4D1, 'V'), - (0x4D2, 'M', u'ӓ'), - (0x4D3, 'V'), - (0x4D4, 'M', u'ӕ'), - (0x4D5, 'V'), - (0x4D6, 'M', u'ӗ'), - (0x4D7, 'V'), - (0x4D8, 'M', u'ә'), - (0x4D9, 'V'), - (0x4DA, 'M', u'ӛ'), - (0x4DB, 'V'), - (0x4DC, 'M', u'ӝ'), - (0x4DD, 'V'), - (0x4DE, 'M', u'ӟ'), - (0x4DF, 'V'), - (0x4E0, 'M', u'ӡ'), - (0x4E1, 'V'), - (0x4E2, 'M', u'ӣ'), - (0x4E3, 'V'), - (0x4E4, 'M', u'ӥ'), - (0x4E5, 'V'), - (0x4E6, 'M', u'ӧ'), - (0x4E7, 'V'), - (0x4E8, 'M', u'ө'), - (0x4E9, 'V'), - (0x4EA, 'M', u'ӫ'), - (0x4EB, 'V'), - (0x4EC, 'M', u'ӭ'), - (0x4ED, 'V'), - (0x4EE, 'M', u'ӯ'), - (0x4EF, 'V'), - (0x4F0, 'M', u'ӱ'), - (0x4F1, 'V'), - (0x4F2, 'M', u'ӳ'), - (0x4F3, 'V'), - (0x4F4, 'M', u'ӵ'), - (0x4F5, 'V'), - (0x4F6, 'M', u'ӷ'), - (0x4F7, 'V'), - (0x4F8, 'M', u'ӹ'), - (0x4F9, 'V'), - (0x4FA, 'M', u'ӻ'), - (0x4FB, 'V'), - (0x4FC, 'M', u'ӽ'), - (0x4FD, 'V'), - (0x4FE, 'M', u'ӿ'), - (0x4FF, 'V'), - (0x500, 'M', u'ԁ'), - (0x501, 'V'), - (0x502, 'M', u'ԃ'), - ] - -def _seg_9(): - return [ - (0x503, 'V'), - (0x504, 'M', u'ԅ'), - (0x505, 'V'), - (0x506, 'M', u'ԇ'), - (0x507, 'V'), - (0x508, 'M', u'ԉ'), - (0x509, 'V'), - (0x50A, 'M', u'ԋ'), - (0x50B, 'V'), - (0x50C, 'M', u'ԍ'), - (0x50D, 'V'), - (0x50E, 'M', u'ԏ'), - (0x50F, 'V'), - (0x510, 'M', u'ԑ'), - (0x511, 'V'), - (0x512, 'M', u'ԓ'), - (0x513, 'V'), - (0x514, 'M', u'ԕ'), - (0x515, 'V'), - (0x516, 'M', u'ԗ'), - (0x517, 'V'), - (0x518, 'M', u'ԙ'), - (0x519, 'V'), - (0x51A, 'M', u'ԛ'), - (0x51B, 'V'), - (0x51C, 'M', u'ԝ'), - (0x51D, 'V'), - (0x51E, 'M', u'ԟ'), - (0x51F, 'V'), - (0x520, 'M', u'ԡ'), - (0x521, 'V'), - (0x522, 'M', u'ԣ'), - (0x523, 'V'), - (0x524, 'M', u'ԥ'), - (0x525, 'V'), - (0x526, 'M', u'ԧ'), - (0x527, 'V'), - (0x528, 'M', u'ԩ'), - (0x529, 'V'), - (0x52A, 'M', u'ԫ'), - (0x52B, 'V'), - (0x52C, 'M', u'ԭ'), - (0x52D, 'V'), - (0x52E, 'M', u'ԯ'), - (0x52F, 'V'), - (0x530, 'X'), - (0x531, 'M', u'ա'), - (0x532, 'M', u'բ'), - (0x533, 'M', u'գ'), - (0x534, 'M', u'դ'), - (0x535, 'M', u'ե'), - (0x536, 'M', u'զ'), - (0x537, 'M', u'է'), - (0x538, 'M', u'ը'), - (0x539, 'M', u'թ'), - (0x53A, 'M', u'ժ'), - (0x53B, 'M', u'ի'), - (0x53C, 'M', u'լ'), - (0x53D, 'M', u'խ'), - (0x53E, 'M', u'ծ'), - (0x53F, 'M', u'կ'), - (0x540, 'M', u'հ'), - (0x541, 'M', u'ձ'), - (0x542, 'M', u'ղ'), - (0x543, 'M', u'ճ'), - (0x544, 'M', u'մ'), - (0x545, 'M', u'յ'), - (0x546, 'M', u'ն'), - (0x547, 'M', u'շ'), - (0x548, 'M', u'ո'), - (0x549, 'M', u'չ'), - (0x54A, 'M', u'պ'), - (0x54B, 'M', u'ջ'), - (0x54C, 'M', u'ռ'), - (0x54D, 'M', u'ս'), - (0x54E, 'M', u'վ'), - (0x54F, 'M', u'տ'), - (0x550, 'M', u'ր'), - (0x551, 'M', u'ց'), - (0x552, 'M', u'ւ'), - (0x553, 'M', u'փ'), - (0x554, 'M', u'ք'), - (0x555, 'M', u'օ'), - (0x556, 'M', u'ֆ'), - (0x557, 'X'), - (0x559, 'V'), - (0x587, 'M', u'եւ'), - (0x588, 'V'), - (0x58B, 'X'), - (0x58D, 'V'), - (0x590, 'X'), - (0x591, 'V'), - (0x5C8, 'X'), - (0x5D0, 'V'), - (0x5EB, 'X'), - (0x5EF, 'V'), - (0x5F5, 'X'), - (0x606, 'V'), - (0x61C, 'X'), - (0x61E, 'V'), - ] - -def _seg_10(): - return [ - (0x675, 'M', u'اٴ'), - (0x676, 'M', u'وٴ'), - (0x677, 'M', u'ۇٴ'), - (0x678, 'M', u'يٴ'), - (0x679, 'V'), - (0x6DD, 'X'), - (0x6DE, 'V'), - (0x70E, 'X'), - (0x710, 'V'), - (0x74B, 'X'), - (0x74D, 'V'), - (0x7B2, 'X'), - (0x7C0, 'V'), - (0x7FB, 'X'), - (0x7FD, 'V'), - (0x82E, 'X'), - (0x830, 'V'), - (0x83F, 'X'), - (0x840, 'V'), - (0x85C, 'X'), - (0x85E, 'V'), - (0x85F, 'X'), - (0x860, 'V'), - (0x86B, 'X'), - (0x8A0, 'V'), - (0x8B5, 'X'), - (0x8B6, 'V'), - (0x8BE, 'X'), - (0x8D3, 'V'), - (0x8E2, 'X'), - (0x8E3, 'V'), - (0x958, 'M', u'क़'), - (0x959, 'M', u'ख़'), - (0x95A, 'M', u'ग़'), - (0x95B, 'M', u'ज़'), - (0x95C, 'M', u'ड़'), - (0x95D, 'M', u'ढ़'), - (0x95E, 'M', u'फ़'), - (0x95F, 'M', u'य़'), - (0x960, 'V'), - (0x984, 'X'), - (0x985, 'V'), - (0x98D, 'X'), - (0x98F, 'V'), - (0x991, 'X'), - (0x993, 'V'), - (0x9A9, 'X'), - (0x9AA, 'V'), - (0x9B1, 'X'), - (0x9B2, 'V'), - (0x9B3, 'X'), - (0x9B6, 'V'), - (0x9BA, 'X'), - (0x9BC, 'V'), - (0x9C5, 'X'), - (0x9C7, 'V'), - (0x9C9, 'X'), - (0x9CB, 'V'), - (0x9CF, 'X'), - (0x9D7, 'V'), - (0x9D8, 'X'), - (0x9DC, 'M', u'ড়'), - (0x9DD, 'M', u'ঢ়'), - (0x9DE, 'X'), - (0x9DF, 'M', u'য়'), - (0x9E0, 'V'), - (0x9E4, 'X'), - (0x9E6, 'V'), - (0x9FF, 'X'), - (0xA01, 'V'), - (0xA04, 'X'), - (0xA05, 'V'), - (0xA0B, 'X'), - (0xA0F, 'V'), - (0xA11, 'X'), - (0xA13, 'V'), - (0xA29, 'X'), - (0xA2A, 'V'), - (0xA31, 'X'), - (0xA32, 'V'), - (0xA33, 'M', u'ਲ਼'), - (0xA34, 'X'), - (0xA35, 'V'), - (0xA36, 'M', u'ਸ਼'), - (0xA37, 'X'), - (0xA38, 'V'), - (0xA3A, 'X'), - (0xA3C, 'V'), - (0xA3D, 'X'), - (0xA3E, 'V'), - (0xA43, 'X'), - (0xA47, 'V'), - (0xA49, 'X'), - (0xA4B, 'V'), - (0xA4E, 'X'), - (0xA51, 'V'), - (0xA52, 'X'), - (0xA59, 'M', u'ਖ਼'), - (0xA5A, 'M', u'ਗ਼'), - (0xA5B, 'M', u'ਜ਼'), - ] - -def _seg_11(): - return [ - (0xA5C, 'V'), - (0xA5D, 'X'), - (0xA5E, 'M', u'ਫ਼'), - (0xA5F, 'X'), - (0xA66, 'V'), - (0xA77, 'X'), - (0xA81, 'V'), - (0xA84, 'X'), - (0xA85, 'V'), - (0xA8E, 'X'), - (0xA8F, 'V'), - (0xA92, 'X'), - (0xA93, 'V'), - (0xAA9, 'X'), - (0xAAA, 'V'), - (0xAB1, 'X'), - (0xAB2, 'V'), - (0xAB4, 'X'), - (0xAB5, 'V'), - (0xABA, 'X'), - (0xABC, 'V'), - (0xAC6, 'X'), - (0xAC7, 'V'), - (0xACA, 'X'), - (0xACB, 'V'), - (0xACE, 'X'), - (0xAD0, 'V'), - (0xAD1, 'X'), - (0xAE0, 'V'), - (0xAE4, 'X'), - (0xAE6, 'V'), - (0xAF2, 'X'), - (0xAF9, 'V'), - (0xB00, 'X'), - (0xB01, 'V'), - (0xB04, 'X'), - (0xB05, 'V'), - (0xB0D, 'X'), - (0xB0F, 'V'), - (0xB11, 'X'), - (0xB13, 'V'), - (0xB29, 'X'), - (0xB2A, 'V'), - (0xB31, 'X'), - (0xB32, 'V'), - (0xB34, 'X'), - (0xB35, 'V'), - (0xB3A, 'X'), - (0xB3C, 'V'), - (0xB45, 'X'), - (0xB47, 'V'), - (0xB49, 'X'), - (0xB4B, 'V'), - (0xB4E, 'X'), - (0xB56, 'V'), - (0xB58, 'X'), - (0xB5C, 'M', u'ଡ଼'), - (0xB5D, 'M', u'ଢ଼'), - (0xB5E, 'X'), - (0xB5F, 'V'), - (0xB64, 'X'), - (0xB66, 'V'), - (0xB78, 'X'), - (0xB82, 'V'), - (0xB84, 'X'), - (0xB85, 'V'), - (0xB8B, 'X'), - (0xB8E, 'V'), - (0xB91, 'X'), - (0xB92, 'V'), - (0xB96, 'X'), - (0xB99, 'V'), - (0xB9B, 'X'), - (0xB9C, 'V'), - (0xB9D, 'X'), - (0xB9E, 'V'), - (0xBA0, 'X'), - (0xBA3, 'V'), - (0xBA5, 'X'), - (0xBA8, 'V'), - (0xBAB, 'X'), - (0xBAE, 'V'), - (0xBBA, 'X'), - (0xBBE, 'V'), - (0xBC3, 'X'), - (0xBC6, 'V'), - (0xBC9, 'X'), - (0xBCA, 'V'), - (0xBCE, 'X'), - (0xBD0, 'V'), - (0xBD1, 'X'), - (0xBD7, 'V'), - (0xBD8, 'X'), - (0xBE6, 'V'), - (0xBFB, 'X'), - (0xC00, 'V'), - (0xC0D, 'X'), - (0xC0E, 'V'), - (0xC11, 'X'), - (0xC12, 'V'), - ] - -def _seg_12(): - return [ - (0xC29, 'X'), - (0xC2A, 'V'), - (0xC3A, 'X'), - (0xC3D, 'V'), - (0xC45, 'X'), - (0xC46, 'V'), - (0xC49, 'X'), - (0xC4A, 'V'), - (0xC4E, 'X'), - (0xC55, 'V'), - (0xC57, 'X'), - (0xC58, 'V'), - (0xC5B, 'X'), - (0xC60, 'V'), - (0xC64, 'X'), - (0xC66, 'V'), - (0xC70, 'X'), - (0xC78, 'V'), - (0xC8D, 'X'), - (0xC8E, 'V'), - (0xC91, 'X'), - (0xC92, 'V'), - (0xCA9, 'X'), - (0xCAA, 'V'), - (0xCB4, 'X'), - (0xCB5, 'V'), - (0xCBA, 'X'), - (0xCBC, 'V'), - (0xCC5, 'X'), - (0xCC6, 'V'), - (0xCC9, 'X'), - (0xCCA, 'V'), - (0xCCE, 'X'), - (0xCD5, 'V'), - (0xCD7, 'X'), - (0xCDE, 'V'), - (0xCDF, 'X'), - (0xCE0, 'V'), - (0xCE4, 'X'), - (0xCE6, 'V'), - (0xCF0, 'X'), - (0xCF1, 'V'), - (0xCF3, 'X'), - (0xD00, 'V'), - (0xD04, 'X'), - (0xD05, 'V'), - (0xD0D, 'X'), - (0xD0E, 'V'), - (0xD11, 'X'), - (0xD12, 'V'), - (0xD45, 'X'), - (0xD46, 'V'), - (0xD49, 'X'), - (0xD4A, 'V'), - (0xD50, 'X'), - (0xD54, 'V'), - (0xD64, 'X'), - (0xD66, 'V'), - (0xD80, 'X'), - (0xD82, 'V'), - (0xD84, 'X'), - (0xD85, 'V'), - (0xD97, 'X'), - (0xD9A, 'V'), - (0xDB2, 'X'), - (0xDB3, 'V'), - (0xDBC, 'X'), - (0xDBD, 'V'), - (0xDBE, 'X'), - (0xDC0, 'V'), - (0xDC7, 'X'), - (0xDCA, 'V'), - (0xDCB, 'X'), - (0xDCF, 'V'), - (0xDD5, 'X'), - (0xDD6, 'V'), - (0xDD7, 'X'), - (0xDD8, 'V'), - (0xDE0, 'X'), - (0xDE6, 'V'), - (0xDF0, 'X'), - (0xDF2, 'V'), - (0xDF5, 'X'), - (0xE01, 'V'), - (0xE33, 'M', u'ํา'), - (0xE34, 'V'), - (0xE3B, 'X'), - (0xE3F, 'V'), - (0xE5C, 'X'), - (0xE81, 'V'), - (0xE83, 'X'), - (0xE84, 'V'), - (0xE85, 'X'), - (0xE87, 'V'), - (0xE89, 'X'), - (0xE8A, 'V'), - (0xE8B, 'X'), - (0xE8D, 'V'), - (0xE8E, 'X'), - (0xE94, 'V'), - ] - -def _seg_13(): - return [ - (0xE98, 'X'), - (0xE99, 'V'), - (0xEA0, 'X'), - (0xEA1, 'V'), - (0xEA4, 'X'), - (0xEA5, 'V'), - (0xEA6, 'X'), - (0xEA7, 'V'), - (0xEA8, 'X'), - (0xEAA, 'V'), - (0xEAC, 'X'), - (0xEAD, 'V'), - (0xEB3, 'M', u'ໍາ'), - (0xEB4, 'V'), - (0xEBA, 'X'), - (0xEBB, 'V'), - (0xEBE, 'X'), - (0xEC0, 'V'), - (0xEC5, 'X'), - (0xEC6, 'V'), - (0xEC7, 'X'), - (0xEC8, 'V'), - (0xECE, 'X'), - (0xED0, 'V'), - (0xEDA, 'X'), - (0xEDC, 'M', u'ຫນ'), - (0xEDD, 'M', u'ຫມ'), - (0xEDE, 'V'), - (0xEE0, 'X'), - (0xF00, 'V'), - (0xF0C, 'M', u'་'), - (0xF0D, 'V'), - (0xF43, 'M', u'གྷ'), - (0xF44, 'V'), - (0xF48, 'X'), - (0xF49, 'V'), - (0xF4D, 'M', u'ཌྷ'), - (0xF4E, 'V'), - (0xF52, 'M', u'དྷ'), - (0xF53, 'V'), - (0xF57, 'M', u'བྷ'), - (0xF58, 'V'), - (0xF5C, 'M', u'ཛྷ'), - (0xF5D, 'V'), - (0xF69, 'M', u'ཀྵ'), - (0xF6A, 'V'), - (0xF6D, 'X'), - (0xF71, 'V'), - (0xF73, 'M', u'ཱི'), - (0xF74, 'V'), - (0xF75, 'M', u'ཱུ'), - (0xF76, 'M', u'ྲྀ'), - (0xF77, 'M', u'ྲཱྀ'), - (0xF78, 'M', u'ླྀ'), - (0xF79, 'M', u'ླཱྀ'), - (0xF7A, 'V'), - (0xF81, 'M', u'ཱྀ'), - (0xF82, 'V'), - (0xF93, 'M', u'ྒྷ'), - (0xF94, 'V'), - (0xF98, 'X'), - (0xF99, 'V'), - (0xF9D, 'M', u'ྜྷ'), - (0xF9E, 'V'), - (0xFA2, 'M', u'ྡྷ'), - (0xFA3, 'V'), - (0xFA7, 'M', u'ྦྷ'), - (0xFA8, 'V'), - (0xFAC, 'M', u'ྫྷ'), - (0xFAD, 'V'), - (0xFB9, 'M', u'ྐྵ'), - (0xFBA, 'V'), - (0xFBD, 'X'), - (0xFBE, 'V'), - (0xFCD, 'X'), - (0xFCE, 'V'), - (0xFDB, 'X'), - (0x1000, 'V'), - (0x10A0, 'X'), - (0x10C7, 'M', u'ⴧ'), - (0x10C8, 'X'), - (0x10CD, 'M', u'ⴭ'), - (0x10CE, 'X'), - (0x10D0, 'V'), - (0x10FC, 'M', u'ნ'), - (0x10FD, 'V'), - (0x115F, 'X'), - (0x1161, 'V'), - (0x1249, 'X'), - (0x124A, 'V'), - (0x124E, 'X'), - (0x1250, 'V'), - (0x1257, 'X'), - (0x1258, 'V'), - (0x1259, 'X'), - (0x125A, 'V'), - (0x125E, 'X'), - (0x1260, 'V'), - (0x1289, 'X'), - (0x128A, 'V'), - ] - -def _seg_14(): - return [ - (0x128E, 'X'), - (0x1290, 'V'), - (0x12B1, 'X'), - (0x12B2, 'V'), - (0x12B6, 'X'), - (0x12B8, 'V'), - (0x12BF, 'X'), - (0x12C0, 'V'), - (0x12C1, 'X'), - (0x12C2, 'V'), - (0x12C6, 'X'), - (0x12C8, 'V'), - (0x12D7, 'X'), - (0x12D8, 'V'), - (0x1311, 'X'), - (0x1312, 'V'), - (0x1316, 'X'), - (0x1318, 'V'), - (0x135B, 'X'), - (0x135D, 'V'), - (0x137D, 'X'), - (0x1380, 'V'), - (0x139A, 'X'), - (0x13A0, 'V'), - (0x13F6, 'X'), - (0x13F8, 'M', u'Ᏸ'), - (0x13F9, 'M', u'Ᏹ'), - (0x13FA, 'M', u'Ᏺ'), - (0x13FB, 'M', u'Ᏻ'), - (0x13FC, 'M', u'Ᏼ'), - (0x13FD, 'M', u'Ᏽ'), - (0x13FE, 'X'), - (0x1400, 'V'), - (0x1680, 'X'), - (0x1681, 'V'), - (0x169D, 'X'), - (0x16A0, 'V'), - (0x16F9, 'X'), - (0x1700, 'V'), - (0x170D, 'X'), - (0x170E, 'V'), - (0x1715, 'X'), - (0x1720, 'V'), - (0x1737, 'X'), - (0x1740, 'V'), - (0x1754, 'X'), - (0x1760, 'V'), - (0x176D, 'X'), - (0x176E, 'V'), - (0x1771, 'X'), - (0x1772, 'V'), - (0x1774, 'X'), - (0x1780, 'V'), - (0x17B4, 'X'), - (0x17B6, 'V'), - (0x17DE, 'X'), - (0x17E0, 'V'), - (0x17EA, 'X'), - (0x17F0, 'V'), - (0x17FA, 'X'), - (0x1800, 'V'), - (0x1806, 'X'), - (0x1807, 'V'), - (0x180B, 'I'), - (0x180E, 'X'), - (0x1810, 'V'), - (0x181A, 'X'), - (0x1820, 'V'), - (0x1879, 'X'), - (0x1880, 'V'), - (0x18AB, 'X'), - (0x18B0, 'V'), - (0x18F6, 'X'), - (0x1900, 'V'), - (0x191F, 'X'), - (0x1920, 'V'), - (0x192C, 'X'), - (0x1930, 'V'), - (0x193C, 'X'), - (0x1940, 'V'), - (0x1941, 'X'), - (0x1944, 'V'), - (0x196E, 'X'), - (0x1970, 'V'), - (0x1975, 'X'), - (0x1980, 'V'), - (0x19AC, 'X'), - (0x19B0, 'V'), - (0x19CA, 'X'), - (0x19D0, 'V'), - (0x19DB, 'X'), - (0x19DE, 'V'), - (0x1A1C, 'X'), - (0x1A1E, 'V'), - (0x1A5F, 'X'), - (0x1A60, 'V'), - (0x1A7D, 'X'), - (0x1A7F, 'V'), - (0x1A8A, 'X'), - (0x1A90, 'V'), - ] - -def _seg_15(): - return [ - (0x1A9A, 'X'), - (0x1AA0, 'V'), - (0x1AAE, 'X'), - (0x1AB0, 'V'), - (0x1ABF, 'X'), - (0x1B00, 'V'), - (0x1B4C, 'X'), - (0x1B50, 'V'), - (0x1B7D, 'X'), - (0x1B80, 'V'), - (0x1BF4, 'X'), - (0x1BFC, 'V'), - (0x1C38, 'X'), - (0x1C3B, 'V'), - (0x1C4A, 'X'), - (0x1C4D, 'V'), - (0x1C80, 'M', u'в'), - (0x1C81, 'M', u'д'), - (0x1C82, 'M', u'о'), - (0x1C83, 'M', u'с'), - (0x1C84, 'M', u'т'), - (0x1C86, 'M', u'ъ'), - (0x1C87, 'M', u'ѣ'), - (0x1C88, 'M', u'ꙋ'), - (0x1C89, 'X'), - (0x1CC0, 'V'), - (0x1CC8, 'X'), - (0x1CD0, 'V'), - (0x1CFA, 'X'), - (0x1D00, 'V'), - (0x1D2C, 'M', u'a'), - (0x1D2D, 'M', u'æ'), - (0x1D2E, 'M', u'b'), - (0x1D2F, 'V'), - (0x1D30, 'M', u'd'), - (0x1D31, 'M', u'e'), - (0x1D32, 'M', u'ǝ'), - (0x1D33, 'M', u'g'), - (0x1D34, 'M', u'h'), - (0x1D35, 'M', u'i'), - (0x1D36, 'M', u'j'), - (0x1D37, 'M', u'k'), - (0x1D38, 'M', u'l'), - (0x1D39, 'M', u'm'), - (0x1D3A, 'M', u'n'), - (0x1D3B, 'V'), - (0x1D3C, 'M', u'o'), - (0x1D3D, 'M', u'ȣ'), - (0x1D3E, 'M', u'p'), - (0x1D3F, 'M', u'r'), - (0x1D40, 'M', u't'), - (0x1D41, 'M', u'u'), - (0x1D42, 'M', u'w'), - (0x1D43, 'M', u'a'), - (0x1D44, 'M', u'ɐ'), - (0x1D45, 'M', u'ɑ'), - (0x1D46, 'M', u'ᴂ'), - (0x1D47, 'M', u'b'), - (0x1D48, 'M', u'd'), - (0x1D49, 'M', u'e'), - (0x1D4A, 'M', u'ə'), - (0x1D4B, 'M', u'ɛ'), - (0x1D4C, 'M', u'ɜ'), - (0x1D4D, 'M', u'g'), - (0x1D4E, 'V'), - (0x1D4F, 'M', u'k'), - (0x1D50, 'M', u'm'), - (0x1D51, 'M', u'ŋ'), - (0x1D52, 'M', u'o'), - (0x1D53, 'M', u'ɔ'), - (0x1D54, 'M', u'ᴖ'), - (0x1D55, 'M', u'ᴗ'), - (0x1D56, 'M', u'p'), - (0x1D57, 'M', u't'), - (0x1D58, 'M', u'u'), - (0x1D59, 'M', u'ᴝ'), - (0x1D5A, 'M', u'ɯ'), - (0x1D5B, 'M', u'v'), - (0x1D5C, 'M', u'ᴥ'), - (0x1D5D, 'M', u'β'), - (0x1D5E, 'M', u'γ'), - (0x1D5F, 'M', u'δ'), - (0x1D60, 'M', u'φ'), - (0x1D61, 'M', u'χ'), - (0x1D62, 'M', u'i'), - (0x1D63, 'M', u'r'), - (0x1D64, 'M', u'u'), - (0x1D65, 'M', u'v'), - (0x1D66, 'M', u'β'), - (0x1D67, 'M', u'γ'), - (0x1D68, 'M', u'ρ'), - (0x1D69, 'M', u'φ'), - (0x1D6A, 'M', u'χ'), - (0x1D6B, 'V'), - (0x1D78, 'M', u'н'), - (0x1D79, 'V'), - (0x1D9B, 'M', u'ɒ'), - (0x1D9C, 'M', u'c'), - (0x1D9D, 'M', u'ɕ'), - (0x1D9E, 'M', u'ð'), - ] - -def _seg_16(): - return [ - (0x1D9F, 'M', u'ɜ'), - (0x1DA0, 'M', u'f'), - (0x1DA1, 'M', u'ɟ'), - (0x1DA2, 'M', u'ɡ'), - (0x1DA3, 'M', u'ɥ'), - (0x1DA4, 'M', u'ɨ'), - (0x1DA5, 'M', u'ɩ'), - (0x1DA6, 'M', u'ɪ'), - (0x1DA7, 'M', u'ᵻ'), - (0x1DA8, 'M', u'ʝ'), - (0x1DA9, 'M', u'ɭ'), - (0x1DAA, 'M', u'ᶅ'), - (0x1DAB, 'M', u'ʟ'), - (0x1DAC, 'M', u'ɱ'), - (0x1DAD, 'M', u'ɰ'), - (0x1DAE, 'M', u'ɲ'), - (0x1DAF, 'M', u'ɳ'), - (0x1DB0, 'M', u'ɴ'), - (0x1DB1, 'M', u'ɵ'), - (0x1DB2, 'M', u'ɸ'), - (0x1DB3, 'M', u'ʂ'), - (0x1DB4, 'M', u'ʃ'), - (0x1DB5, 'M', u'ƫ'), - (0x1DB6, 'M', u'ʉ'), - (0x1DB7, 'M', u'ʊ'), - (0x1DB8, 'M', u'ᴜ'), - (0x1DB9, 'M', u'ʋ'), - (0x1DBA, 'M', u'ʌ'), - (0x1DBB, 'M', u'z'), - (0x1DBC, 'M', u'ʐ'), - (0x1DBD, 'M', u'ʑ'), - (0x1DBE, 'M', u'ʒ'), - (0x1DBF, 'M', u'θ'), - (0x1DC0, 'V'), - (0x1DFA, 'X'), - (0x1DFB, 'V'), - (0x1E00, 'M', u'ḁ'), - (0x1E01, 'V'), - (0x1E02, 'M', u'ḃ'), - (0x1E03, 'V'), - (0x1E04, 'M', u'ḅ'), - (0x1E05, 'V'), - (0x1E06, 'M', u'ḇ'), - (0x1E07, 'V'), - (0x1E08, 'M', u'ḉ'), - (0x1E09, 'V'), - (0x1E0A, 'M', u'ḋ'), - (0x1E0B, 'V'), - (0x1E0C, 'M', u'ḍ'), - (0x1E0D, 'V'), - (0x1E0E, 'M', u'ḏ'), - (0x1E0F, 'V'), - (0x1E10, 'M', u'ḑ'), - (0x1E11, 'V'), - (0x1E12, 'M', u'ḓ'), - (0x1E13, 'V'), - (0x1E14, 'M', u'ḕ'), - (0x1E15, 'V'), - (0x1E16, 'M', u'ḗ'), - (0x1E17, 'V'), - (0x1E18, 'M', u'ḙ'), - (0x1E19, 'V'), - (0x1E1A, 'M', u'ḛ'), - (0x1E1B, 'V'), - (0x1E1C, 'M', u'ḝ'), - (0x1E1D, 'V'), - (0x1E1E, 'M', u'ḟ'), - (0x1E1F, 'V'), - (0x1E20, 'M', u'ḡ'), - (0x1E21, 'V'), - (0x1E22, 'M', u'ḣ'), - (0x1E23, 'V'), - (0x1E24, 'M', u'ḥ'), - (0x1E25, 'V'), - (0x1E26, 'M', u'ḧ'), - (0x1E27, 'V'), - (0x1E28, 'M', u'ḩ'), - (0x1E29, 'V'), - (0x1E2A, 'M', u'ḫ'), - (0x1E2B, 'V'), - (0x1E2C, 'M', u'ḭ'), - (0x1E2D, 'V'), - (0x1E2E, 'M', u'ḯ'), - (0x1E2F, 'V'), - (0x1E30, 'M', u'ḱ'), - (0x1E31, 'V'), - (0x1E32, 'M', u'ḳ'), - (0x1E33, 'V'), - (0x1E34, 'M', u'ḵ'), - (0x1E35, 'V'), - (0x1E36, 'M', u'ḷ'), - (0x1E37, 'V'), - (0x1E38, 'M', u'ḹ'), - (0x1E39, 'V'), - (0x1E3A, 'M', u'ḻ'), - (0x1E3B, 'V'), - (0x1E3C, 'M', u'ḽ'), - (0x1E3D, 'V'), - (0x1E3E, 'M', u'ḿ'), - (0x1E3F, 'V'), - ] - -def _seg_17(): - return [ - (0x1E40, 'M', u'ṁ'), - (0x1E41, 'V'), - (0x1E42, 'M', u'ṃ'), - (0x1E43, 'V'), - (0x1E44, 'M', u'ṅ'), - (0x1E45, 'V'), - (0x1E46, 'M', u'ṇ'), - (0x1E47, 'V'), - (0x1E48, 'M', u'ṉ'), - (0x1E49, 'V'), - (0x1E4A, 'M', u'ṋ'), - (0x1E4B, 'V'), - (0x1E4C, 'M', u'ṍ'), - (0x1E4D, 'V'), - (0x1E4E, 'M', u'ṏ'), - (0x1E4F, 'V'), - (0x1E50, 'M', u'ṑ'), - (0x1E51, 'V'), - (0x1E52, 'M', u'ṓ'), - (0x1E53, 'V'), - (0x1E54, 'M', u'ṕ'), - (0x1E55, 'V'), - (0x1E56, 'M', u'ṗ'), - (0x1E57, 'V'), - (0x1E58, 'M', u'ṙ'), - (0x1E59, 'V'), - (0x1E5A, 'M', u'ṛ'), - (0x1E5B, 'V'), - (0x1E5C, 'M', u'ṝ'), - (0x1E5D, 'V'), - (0x1E5E, 'M', u'ṟ'), - (0x1E5F, 'V'), - (0x1E60, 'M', u'ṡ'), - (0x1E61, 'V'), - (0x1E62, 'M', u'ṣ'), - (0x1E63, 'V'), - (0x1E64, 'M', u'ṥ'), - (0x1E65, 'V'), - (0x1E66, 'M', u'ṧ'), - (0x1E67, 'V'), - (0x1E68, 'M', u'ṩ'), - (0x1E69, 'V'), - (0x1E6A, 'M', u'ṫ'), - (0x1E6B, 'V'), - (0x1E6C, 'M', u'ṭ'), - (0x1E6D, 'V'), - (0x1E6E, 'M', u'ṯ'), - (0x1E6F, 'V'), - (0x1E70, 'M', u'ṱ'), - (0x1E71, 'V'), - (0x1E72, 'M', u'ṳ'), - (0x1E73, 'V'), - (0x1E74, 'M', u'ṵ'), - (0x1E75, 'V'), - (0x1E76, 'M', u'ṷ'), - (0x1E77, 'V'), - (0x1E78, 'M', u'ṹ'), - (0x1E79, 'V'), - (0x1E7A, 'M', u'ṻ'), - (0x1E7B, 'V'), - (0x1E7C, 'M', u'ṽ'), - (0x1E7D, 'V'), - (0x1E7E, 'M', u'ṿ'), - (0x1E7F, 'V'), - (0x1E80, 'M', u'ẁ'), - (0x1E81, 'V'), - (0x1E82, 'M', u'ẃ'), - (0x1E83, 'V'), - (0x1E84, 'M', u'ẅ'), - (0x1E85, 'V'), - (0x1E86, 'M', u'ẇ'), - (0x1E87, 'V'), - (0x1E88, 'M', u'ẉ'), - (0x1E89, 'V'), - (0x1E8A, 'M', u'ẋ'), - (0x1E8B, 'V'), - (0x1E8C, 'M', u'ẍ'), - (0x1E8D, 'V'), - (0x1E8E, 'M', u'ẏ'), - (0x1E8F, 'V'), - (0x1E90, 'M', u'ẑ'), - (0x1E91, 'V'), - (0x1E92, 'M', u'ẓ'), - (0x1E93, 'V'), - (0x1E94, 'M', u'ẕ'), - (0x1E95, 'V'), - (0x1E9A, 'M', u'aʾ'), - (0x1E9B, 'M', u'ṡ'), - (0x1E9C, 'V'), - (0x1E9E, 'M', u'ss'), - (0x1E9F, 'V'), - (0x1EA0, 'M', u'ạ'), - (0x1EA1, 'V'), - (0x1EA2, 'M', u'ả'), - (0x1EA3, 'V'), - (0x1EA4, 'M', u'ấ'), - (0x1EA5, 'V'), - (0x1EA6, 'M', u'ầ'), - (0x1EA7, 'V'), - (0x1EA8, 'M', u'ẩ'), - ] - -def _seg_18(): - return [ - (0x1EA9, 'V'), - (0x1EAA, 'M', u'ẫ'), - (0x1EAB, 'V'), - (0x1EAC, 'M', u'ậ'), - (0x1EAD, 'V'), - (0x1EAE, 'M', u'ắ'), - (0x1EAF, 'V'), - (0x1EB0, 'M', u'ằ'), - (0x1EB1, 'V'), - (0x1EB2, 'M', u'ẳ'), - (0x1EB3, 'V'), - (0x1EB4, 'M', u'ẵ'), - (0x1EB5, 'V'), - (0x1EB6, 'M', u'ặ'), - (0x1EB7, 'V'), - (0x1EB8, 'M', u'ẹ'), - (0x1EB9, 'V'), - (0x1EBA, 'M', u'ẻ'), - (0x1EBB, 'V'), - (0x1EBC, 'M', u'ẽ'), - (0x1EBD, 'V'), - (0x1EBE, 'M', u'ế'), - (0x1EBF, 'V'), - (0x1EC0, 'M', u'ề'), - (0x1EC1, 'V'), - (0x1EC2, 'M', u'ể'), - (0x1EC3, 'V'), - (0x1EC4, 'M', u'ễ'), - (0x1EC5, 'V'), - (0x1EC6, 'M', u'ệ'), - (0x1EC7, 'V'), - (0x1EC8, 'M', u'ỉ'), - (0x1EC9, 'V'), - (0x1ECA, 'M', u'ị'), - (0x1ECB, 'V'), - (0x1ECC, 'M', u'ọ'), - (0x1ECD, 'V'), - (0x1ECE, 'M', u'ỏ'), - (0x1ECF, 'V'), - (0x1ED0, 'M', u'ố'), - (0x1ED1, 'V'), - (0x1ED2, 'M', u'ồ'), - (0x1ED3, 'V'), - (0x1ED4, 'M', u'ổ'), - (0x1ED5, 'V'), - (0x1ED6, 'M', u'ỗ'), - (0x1ED7, 'V'), - (0x1ED8, 'M', u'ộ'), - (0x1ED9, 'V'), - (0x1EDA, 'M', u'ớ'), - (0x1EDB, 'V'), - (0x1EDC, 'M', u'ờ'), - (0x1EDD, 'V'), - (0x1EDE, 'M', u'ở'), - (0x1EDF, 'V'), - (0x1EE0, 'M', u'ỡ'), - (0x1EE1, 'V'), - (0x1EE2, 'M', u'ợ'), - (0x1EE3, 'V'), - (0x1EE4, 'M', u'ụ'), - (0x1EE5, 'V'), - (0x1EE6, 'M', u'ủ'), - (0x1EE7, 'V'), - (0x1EE8, 'M', u'ứ'), - (0x1EE9, 'V'), - (0x1EEA, 'M', u'ừ'), - (0x1EEB, 'V'), - (0x1EEC, 'M', u'ử'), - (0x1EED, 'V'), - (0x1EEE, 'M', u'ữ'), - (0x1EEF, 'V'), - (0x1EF0, 'M', u'ự'), - (0x1EF1, 'V'), - (0x1EF2, 'M', u'ỳ'), - (0x1EF3, 'V'), - (0x1EF4, 'M', u'ỵ'), - (0x1EF5, 'V'), - (0x1EF6, 'M', u'ỷ'), - (0x1EF7, 'V'), - (0x1EF8, 'M', u'ỹ'), - (0x1EF9, 'V'), - (0x1EFA, 'M', u'ỻ'), - (0x1EFB, 'V'), - (0x1EFC, 'M', u'ỽ'), - (0x1EFD, 'V'), - (0x1EFE, 'M', u'ỿ'), - (0x1EFF, 'V'), - (0x1F08, 'M', u'ἀ'), - (0x1F09, 'M', u'ἁ'), - (0x1F0A, 'M', u'ἂ'), - (0x1F0B, 'M', u'ἃ'), - (0x1F0C, 'M', u'ἄ'), - (0x1F0D, 'M', u'ἅ'), - (0x1F0E, 'M', u'ἆ'), - (0x1F0F, 'M', u'ἇ'), - (0x1F10, 'V'), - (0x1F16, 'X'), - (0x1F18, 'M', u'ἐ'), - (0x1F19, 'M', u'ἑ'), - (0x1F1A, 'M', u'ἒ'), - ] - -def _seg_19(): - return [ - (0x1F1B, 'M', u'ἓ'), - (0x1F1C, 'M', u'ἔ'), - (0x1F1D, 'M', u'ἕ'), - (0x1F1E, 'X'), - (0x1F20, 'V'), - (0x1F28, 'M', u'ἠ'), - (0x1F29, 'M', u'ἡ'), - (0x1F2A, 'M', u'ἢ'), - (0x1F2B, 'M', u'ἣ'), - (0x1F2C, 'M', u'ἤ'), - (0x1F2D, 'M', u'ἥ'), - (0x1F2E, 'M', u'ἦ'), - (0x1F2F, 'M', u'ἧ'), - (0x1F30, 'V'), - (0x1F38, 'M', u'ἰ'), - (0x1F39, 'M', u'ἱ'), - (0x1F3A, 'M', u'ἲ'), - (0x1F3B, 'M', u'ἳ'), - (0x1F3C, 'M', u'ἴ'), - (0x1F3D, 'M', u'ἵ'), - (0x1F3E, 'M', u'ἶ'), - (0x1F3F, 'M', u'ἷ'), - (0x1F40, 'V'), - (0x1F46, 'X'), - (0x1F48, 'M', u'ὀ'), - (0x1F49, 'M', u'ὁ'), - (0x1F4A, 'M', u'ὂ'), - (0x1F4B, 'M', u'ὃ'), - (0x1F4C, 'M', u'ὄ'), - (0x1F4D, 'M', u'ὅ'), - (0x1F4E, 'X'), - (0x1F50, 'V'), - (0x1F58, 'X'), - (0x1F59, 'M', u'ὑ'), - (0x1F5A, 'X'), - (0x1F5B, 'M', u'ὓ'), - (0x1F5C, 'X'), - (0x1F5D, 'M', u'ὕ'), - (0x1F5E, 'X'), - (0x1F5F, 'M', u'ὗ'), - (0x1F60, 'V'), - (0x1F68, 'M', u'ὠ'), - (0x1F69, 'M', u'ὡ'), - (0x1F6A, 'M', u'ὢ'), - (0x1F6B, 'M', u'ὣ'), - (0x1F6C, 'M', u'ὤ'), - (0x1F6D, 'M', u'ὥ'), - (0x1F6E, 'M', u'ὦ'), - (0x1F6F, 'M', u'ὧ'), - (0x1F70, 'V'), - (0x1F71, 'M', u'ά'), - (0x1F72, 'V'), - (0x1F73, 'M', u'έ'), - (0x1F74, 'V'), - (0x1F75, 'M', u'ή'), - (0x1F76, 'V'), - (0x1F77, 'M', u'ί'), - (0x1F78, 'V'), - (0x1F79, 'M', u'ό'), - (0x1F7A, 'V'), - (0x1F7B, 'M', u'ύ'), - (0x1F7C, 'V'), - (0x1F7D, 'M', u'ώ'), - (0x1F7E, 'X'), - (0x1F80, 'M', u'ἀι'), - (0x1F81, 'M', u'ἁι'), - (0x1F82, 'M', u'ἂι'), - (0x1F83, 'M', u'ἃι'), - (0x1F84, 'M', u'ἄι'), - (0x1F85, 'M', u'ἅι'), - (0x1F86, 'M', u'ἆι'), - (0x1F87, 'M', u'ἇι'), - (0x1F88, 'M', u'ἀι'), - (0x1F89, 'M', u'ἁι'), - (0x1F8A, 'M', u'ἂι'), - (0x1F8B, 'M', u'ἃι'), - (0x1F8C, 'M', u'ἄι'), - (0x1F8D, 'M', u'ἅι'), - (0x1F8E, 'M', u'ἆι'), - (0x1F8F, 'M', u'ἇι'), - (0x1F90, 'M', u'ἠι'), - (0x1F91, 'M', u'ἡι'), - (0x1F92, 'M', u'ἢι'), - (0x1F93, 'M', u'ἣι'), - (0x1F94, 'M', u'ἤι'), - (0x1F95, 'M', u'ἥι'), - (0x1F96, 'M', u'ἦι'), - (0x1F97, 'M', u'ἧι'), - (0x1F98, 'M', u'ἠι'), - (0x1F99, 'M', u'ἡι'), - (0x1F9A, 'M', u'ἢι'), - (0x1F9B, 'M', u'ἣι'), - (0x1F9C, 'M', u'ἤι'), - (0x1F9D, 'M', u'ἥι'), - (0x1F9E, 'M', u'ἦι'), - (0x1F9F, 'M', u'ἧι'), - (0x1FA0, 'M', u'ὠι'), - (0x1FA1, 'M', u'ὡι'), - (0x1FA2, 'M', u'ὢι'), - (0x1FA3, 'M', u'ὣι'), - ] - -def _seg_20(): - return [ - (0x1FA4, 'M', u'ὤι'), - (0x1FA5, 'M', u'ὥι'), - (0x1FA6, 'M', u'ὦι'), - (0x1FA7, 'M', u'ὧι'), - (0x1FA8, 'M', u'ὠι'), - (0x1FA9, 'M', u'ὡι'), - (0x1FAA, 'M', u'ὢι'), - (0x1FAB, 'M', u'ὣι'), - (0x1FAC, 'M', u'ὤι'), - (0x1FAD, 'M', u'ὥι'), - (0x1FAE, 'M', u'ὦι'), - (0x1FAF, 'M', u'ὧι'), - (0x1FB0, 'V'), - (0x1FB2, 'M', u'ὰι'), - (0x1FB3, 'M', u'αι'), - (0x1FB4, 'M', u'άι'), - (0x1FB5, 'X'), - (0x1FB6, 'V'), - (0x1FB7, 'M', u'ᾶι'), - (0x1FB8, 'M', u'ᾰ'), - (0x1FB9, 'M', u'ᾱ'), - (0x1FBA, 'M', u'ὰ'), - (0x1FBB, 'M', u'ά'), - (0x1FBC, 'M', u'αι'), - (0x1FBD, '3', u' ̓'), - (0x1FBE, 'M', u'ι'), - (0x1FBF, '3', u' ̓'), - (0x1FC0, '3', u' ͂'), - (0x1FC1, '3', u' ̈͂'), - (0x1FC2, 'M', u'ὴι'), - (0x1FC3, 'M', u'ηι'), - (0x1FC4, 'M', u'ήι'), - (0x1FC5, 'X'), - (0x1FC6, 'V'), - (0x1FC7, 'M', u'ῆι'), - (0x1FC8, 'M', u'ὲ'), - (0x1FC9, 'M', u'έ'), - (0x1FCA, 'M', u'ὴ'), - (0x1FCB, 'M', u'ή'), - (0x1FCC, 'M', u'ηι'), - (0x1FCD, '3', u' ̓̀'), - (0x1FCE, '3', u' ̓́'), - (0x1FCF, '3', u' ̓͂'), - (0x1FD0, 'V'), - (0x1FD3, 'M', u'ΐ'), - (0x1FD4, 'X'), - (0x1FD6, 'V'), - (0x1FD8, 'M', u'ῐ'), - (0x1FD9, 'M', u'ῑ'), - (0x1FDA, 'M', u'ὶ'), - (0x1FDB, 'M', u'ί'), - (0x1FDC, 'X'), - (0x1FDD, '3', u' ̔̀'), - (0x1FDE, '3', u' ̔́'), - (0x1FDF, '3', u' ̔͂'), - (0x1FE0, 'V'), - (0x1FE3, 'M', u'ΰ'), - (0x1FE4, 'V'), - (0x1FE8, 'M', u'ῠ'), - (0x1FE9, 'M', u'ῡ'), - (0x1FEA, 'M', u'ὺ'), - (0x1FEB, 'M', u'ύ'), - (0x1FEC, 'M', u'ῥ'), - (0x1FED, '3', u' ̈̀'), - (0x1FEE, '3', u' ̈́'), - (0x1FEF, '3', u'`'), - (0x1FF0, 'X'), - (0x1FF2, 'M', u'ὼι'), - (0x1FF3, 'M', u'ωι'), - (0x1FF4, 'M', u'ώι'), - (0x1FF5, 'X'), - (0x1FF6, 'V'), - (0x1FF7, 'M', u'ῶι'), - (0x1FF8, 'M', u'ὸ'), - (0x1FF9, 'M', u'ό'), - (0x1FFA, 'M', u'ὼ'), - (0x1FFB, 'M', u'ώ'), - (0x1FFC, 'M', u'ωι'), - (0x1FFD, '3', u' ́'), - (0x1FFE, '3', u' ̔'), - (0x1FFF, 'X'), - (0x2000, '3', u' '), - (0x200B, 'I'), - (0x200C, 'D', u''), - (0x200E, 'X'), - (0x2010, 'V'), - (0x2011, 'M', u'‐'), - (0x2012, 'V'), - (0x2017, '3', u' ̳'), - (0x2018, 'V'), - (0x2024, 'X'), - (0x2027, 'V'), - (0x2028, 'X'), - (0x202F, '3', u' '), - (0x2030, 'V'), - (0x2033, 'M', u'′′'), - (0x2034, 'M', u'′′′'), - (0x2035, 'V'), - (0x2036, 'M', u'‵‵'), - (0x2037, 'M', u'‵‵‵'), - ] - -def _seg_21(): - return [ - (0x2038, 'V'), - (0x203C, '3', u'!!'), - (0x203D, 'V'), - (0x203E, '3', u' ̅'), - (0x203F, 'V'), - (0x2047, '3', u'??'), - (0x2048, '3', u'?!'), - (0x2049, '3', u'!?'), - (0x204A, 'V'), - (0x2057, 'M', u'′′′′'), - (0x2058, 'V'), - (0x205F, '3', u' '), - (0x2060, 'I'), - (0x2061, 'X'), - (0x2064, 'I'), - (0x2065, 'X'), - (0x2070, 'M', u'0'), - (0x2071, 'M', u'i'), - (0x2072, 'X'), - (0x2074, 'M', u'4'), - (0x2075, 'M', u'5'), - (0x2076, 'M', u'6'), - (0x2077, 'M', u'7'), - (0x2078, 'M', u'8'), - (0x2079, 'M', u'9'), - (0x207A, '3', u'+'), - (0x207B, 'M', u'−'), - (0x207C, '3', u'='), - (0x207D, '3', u'('), - (0x207E, '3', u')'), - (0x207F, 'M', u'n'), - (0x2080, 'M', u'0'), - (0x2081, 'M', u'1'), - (0x2082, 'M', u'2'), - (0x2083, 'M', u'3'), - (0x2084, 'M', u'4'), - (0x2085, 'M', u'5'), - (0x2086, 'M', u'6'), - (0x2087, 'M', u'7'), - (0x2088, 'M', u'8'), - (0x2089, 'M', u'9'), - (0x208A, '3', u'+'), - (0x208B, 'M', u'−'), - (0x208C, '3', u'='), - (0x208D, '3', u'('), - (0x208E, '3', u')'), - (0x208F, 'X'), - (0x2090, 'M', u'a'), - (0x2091, 'M', u'e'), - (0x2092, 'M', u'o'), - (0x2093, 'M', u'x'), - (0x2094, 'M', u'ə'), - (0x2095, 'M', u'h'), - (0x2096, 'M', u'k'), - (0x2097, 'M', u'l'), - (0x2098, 'M', u'm'), - (0x2099, 'M', u'n'), - (0x209A, 'M', u'p'), - (0x209B, 'M', u's'), - (0x209C, 'M', u't'), - (0x209D, 'X'), - (0x20A0, 'V'), - (0x20A8, 'M', u'rs'), - (0x20A9, 'V'), - (0x20C0, 'X'), - (0x20D0, 'V'), - (0x20F1, 'X'), - (0x2100, '3', u'a/c'), - (0x2101, '3', u'a/s'), - (0x2102, 'M', u'c'), - (0x2103, 'M', u'°c'), - (0x2104, 'V'), - (0x2105, '3', u'c/o'), - (0x2106, '3', u'c/u'), - (0x2107, 'M', u'ɛ'), - (0x2108, 'V'), - (0x2109, 'M', u'°f'), - (0x210A, 'M', u'g'), - (0x210B, 'M', u'h'), - (0x210F, 'M', u'ħ'), - (0x2110, 'M', u'i'), - (0x2112, 'M', u'l'), - (0x2114, 'V'), - (0x2115, 'M', u'n'), - (0x2116, 'M', u'no'), - (0x2117, 'V'), - (0x2119, 'M', u'p'), - (0x211A, 'M', u'q'), - (0x211B, 'M', u'r'), - (0x211E, 'V'), - (0x2120, 'M', u'sm'), - (0x2121, 'M', u'tel'), - (0x2122, 'M', u'tm'), - (0x2123, 'V'), - (0x2124, 'M', u'z'), - (0x2125, 'V'), - (0x2126, 'M', u'ω'), - (0x2127, 'V'), - (0x2128, 'M', u'z'), - (0x2129, 'V'), - ] - -def _seg_22(): - return [ - (0x212A, 'M', u'k'), - (0x212B, 'M', u'å'), - (0x212C, 'M', u'b'), - (0x212D, 'M', u'c'), - (0x212E, 'V'), - (0x212F, 'M', u'e'), - (0x2131, 'M', u'f'), - (0x2132, 'X'), - (0x2133, 'M', u'm'), - (0x2134, 'M', u'o'), - (0x2135, 'M', u'א'), - (0x2136, 'M', u'ב'), - (0x2137, 'M', u'ג'), - (0x2138, 'M', u'ד'), - (0x2139, 'M', u'i'), - (0x213A, 'V'), - (0x213B, 'M', u'fax'), - (0x213C, 'M', u'π'), - (0x213D, 'M', u'γ'), - (0x213F, 'M', u'π'), - (0x2140, 'M', u'∑'), - (0x2141, 'V'), - (0x2145, 'M', u'd'), - (0x2147, 'M', u'e'), - (0x2148, 'M', u'i'), - (0x2149, 'M', u'j'), - (0x214A, 'V'), - (0x2150, 'M', u'1⁄7'), - (0x2151, 'M', u'1⁄9'), - (0x2152, 'M', u'1⁄10'), - (0x2153, 'M', u'1⁄3'), - (0x2154, 'M', u'2⁄3'), - (0x2155, 'M', u'1⁄5'), - (0x2156, 'M', u'2⁄5'), - (0x2157, 'M', u'3⁄5'), - (0x2158, 'M', u'4⁄5'), - (0x2159, 'M', u'1⁄6'), - (0x215A, 'M', u'5⁄6'), - (0x215B, 'M', u'1⁄8'), - (0x215C, 'M', u'3⁄8'), - (0x215D, 'M', u'5⁄8'), - (0x215E, 'M', u'7⁄8'), - (0x215F, 'M', u'1⁄'), - (0x2160, 'M', u'i'), - (0x2161, 'M', u'ii'), - (0x2162, 'M', u'iii'), - (0x2163, 'M', u'iv'), - (0x2164, 'M', u'v'), - (0x2165, 'M', u'vi'), - (0x2166, 'M', u'vii'), - (0x2167, 'M', u'viii'), - (0x2168, 'M', u'ix'), - (0x2169, 'M', u'x'), - (0x216A, 'M', u'xi'), - (0x216B, 'M', u'xii'), - (0x216C, 'M', u'l'), - (0x216D, 'M', u'c'), - (0x216E, 'M', u'd'), - (0x216F, 'M', u'm'), - (0x2170, 'M', u'i'), - (0x2171, 'M', u'ii'), - (0x2172, 'M', u'iii'), - (0x2173, 'M', u'iv'), - (0x2174, 'M', u'v'), - (0x2175, 'M', u'vi'), - (0x2176, 'M', u'vii'), - (0x2177, 'M', u'viii'), - (0x2178, 'M', u'ix'), - (0x2179, 'M', u'x'), - (0x217A, 'M', u'xi'), - (0x217B, 'M', u'xii'), - (0x217C, 'M', u'l'), - (0x217D, 'M', u'c'), - (0x217E, 'M', u'd'), - (0x217F, 'M', u'm'), - (0x2180, 'V'), - (0x2183, 'X'), - (0x2184, 'V'), - (0x2189, 'M', u'0⁄3'), - (0x218A, 'V'), - (0x218C, 'X'), - (0x2190, 'V'), - (0x222C, 'M', u'∫∫'), - (0x222D, 'M', u'∫∫∫'), - (0x222E, 'V'), - (0x222F, 'M', u'∮∮'), - (0x2230, 'M', u'∮∮∮'), - (0x2231, 'V'), - (0x2260, '3'), - (0x2261, 'V'), - (0x226E, '3'), - (0x2270, 'V'), - (0x2329, 'M', u'〈'), - (0x232A, 'M', u'〉'), - (0x232B, 'V'), - (0x2427, 'X'), - (0x2440, 'V'), - (0x244B, 'X'), - (0x2460, 'M', u'1'), - (0x2461, 'M', u'2'), - ] - -def _seg_23(): - return [ - (0x2462, 'M', u'3'), - (0x2463, 'M', u'4'), - (0x2464, 'M', u'5'), - (0x2465, 'M', u'6'), - (0x2466, 'M', u'7'), - (0x2467, 'M', u'8'), - (0x2468, 'M', u'9'), - (0x2469, 'M', u'10'), - (0x246A, 'M', u'11'), - (0x246B, 'M', u'12'), - (0x246C, 'M', u'13'), - (0x246D, 'M', u'14'), - (0x246E, 'M', u'15'), - (0x246F, 'M', u'16'), - (0x2470, 'M', u'17'), - (0x2471, 'M', u'18'), - (0x2472, 'M', u'19'), - (0x2473, 'M', u'20'), - (0x2474, '3', u'(1)'), - (0x2475, '3', u'(2)'), - (0x2476, '3', u'(3)'), - (0x2477, '3', u'(4)'), - (0x2478, '3', u'(5)'), - (0x2479, '3', u'(6)'), - (0x247A, '3', u'(7)'), - (0x247B, '3', u'(8)'), - (0x247C, '3', u'(9)'), - (0x247D, '3', u'(10)'), - (0x247E, '3', u'(11)'), - (0x247F, '3', u'(12)'), - (0x2480, '3', u'(13)'), - (0x2481, '3', u'(14)'), - (0x2482, '3', u'(15)'), - (0x2483, '3', u'(16)'), - (0x2484, '3', u'(17)'), - (0x2485, '3', u'(18)'), - (0x2486, '3', u'(19)'), - (0x2487, '3', u'(20)'), - (0x2488, 'X'), - (0x249C, '3', u'(a)'), - (0x249D, '3', u'(b)'), - (0x249E, '3', u'(c)'), - (0x249F, '3', u'(d)'), - (0x24A0, '3', u'(e)'), - (0x24A1, '3', u'(f)'), - (0x24A2, '3', u'(g)'), - (0x24A3, '3', u'(h)'), - (0x24A4, '3', u'(i)'), - (0x24A5, '3', u'(j)'), - (0x24A6, '3', u'(k)'), - (0x24A7, '3', u'(l)'), - (0x24A8, '3', u'(m)'), - (0x24A9, '3', u'(n)'), - (0x24AA, '3', u'(o)'), - (0x24AB, '3', u'(p)'), - (0x24AC, '3', u'(q)'), - (0x24AD, '3', u'(r)'), - (0x24AE, '3', u'(s)'), - (0x24AF, '3', u'(t)'), - (0x24B0, '3', u'(u)'), - (0x24B1, '3', u'(v)'), - (0x24B2, '3', u'(w)'), - (0x24B3, '3', u'(x)'), - (0x24B4, '3', u'(y)'), - (0x24B5, '3', u'(z)'), - (0x24B6, 'M', u'a'), - (0x24B7, 'M', u'b'), - (0x24B8, 'M', u'c'), - (0x24B9, 'M', u'd'), - (0x24BA, 'M', u'e'), - (0x24BB, 'M', u'f'), - (0x24BC, 'M', u'g'), - (0x24BD, 'M', u'h'), - (0x24BE, 'M', u'i'), - (0x24BF, 'M', u'j'), - (0x24C0, 'M', u'k'), - (0x24C1, 'M', u'l'), - (0x24C2, 'M', u'm'), - (0x24C3, 'M', u'n'), - (0x24C4, 'M', u'o'), - (0x24C5, 'M', u'p'), - (0x24C6, 'M', u'q'), - (0x24C7, 'M', u'r'), - (0x24C8, 'M', u's'), - (0x24C9, 'M', u't'), - (0x24CA, 'M', u'u'), - (0x24CB, 'M', u'v'), - (0x24CC, 'M', u'w'), - (0x24CD, 'M', u'x'), - (0x24CE, 'M', u'y'), - (0x24CF, 'M', u'z'), - (0x24D0, 'M', u'a'), - (0x24D1, 'M', u'b'), - (0x24D2, 'M', u'c'), - (0x24D3, 'M', u'd'), - (0x24D4, 'M', u'e'), - (0x24D5, 'M', u'f'), - (0x24D6, 'M', u'g'), - (0x24D7, 'M', u'h'), - (0x24D8, 'M', u'i'), - ] - -def _seg_24(): - return [ - (0x24D9, 'M', u'j'), - (0x24DA, 'M', u'k'), - (0x24DB, 'M', u'l'), - (0x24DC, 'M', u'm'), - (0x24DD, 'M', u'n'), - (0x24DE, 'M', u'o'), - (0x24DF, 'M', u'p'), - (0x24E0, 'M', u'q'), - (0x24E1, 'M', u'r'), - (0x24E2, 'M', u's'), - (0x24E3, 'M', u't'), - (0x24E4, 'M', u'u'), - (0x24E5, 'M', u'v'), - (0x24E6, 'M', u'w'), - (0x24E7, 'M', u'x'), - (0x24E8, 'M', u'y'), - (0x24E9, 'M', u'z'), - (0x24EA, 'M', u'0'), - (0x24EB, 'V'), - (0x2A0C, 'M', u'∫∫∫∫'), - (0x2A0D, 'V'), - (0x2A74, '3', u'::='), - (0x2A75, '3', u'=='), - (0x2A76, '3', u'==='), - (0x2A77, 'V'), - (0x2ADC, 'M', u'⫝̸'), - (0x2ADD, 'V'), - (0x2B74, 'X'), - (0x2B76, 'V'), - (0x2B96, 'X'), - (0x2B98, 'V'), - (0x2BC9, 'X'), - (0x2BCA, 'V'), - (0x2BFF, 'X'), - (0x2C00, 'M', u'ⰰ'), - (0x2C01, 'M', u'ⰱ'), - (0x2C02, 'M', u'ⰲ'), - (0x2C03, 'M', u'ⰳ'), - (0x2C04, 'M', u'ⰴ'), - (0x2C05, 'M', u'ⰵ'), - (0x2C06, 'M', u'ⰶ'), - (0x2C07, 'M', u'ⰷ'), - (0x2C08, 'M', u'ⰸ'), - (0x2C09, 'M', u'ⰹ'), - (0x2C0A, 'M', u'ⰺ'), - (0x2C0B, 'M', u'ⰻ'), - (0x2C0C, 'M', u'ⰼ'), - (0x2C0D, 'M', u'ⰽ'), - (0x2C0E, 'M', u'ⰾ'), - (0x2C0F, 'M', u'ⰿ'), - (0x2C10, 'M', u'ⱀ'), - (0x2C11, 'M', u'ⱁ'), - (0x2C12, 'M', u'ⱂ'), - (0x2C13, 'M', u'ⱃ'), - (0x2C14, 'M', u'ⱄ'), - (0x2C15, 'M', u'ⱅ'), - (0x2C16, 'M', u'ⱆ'), - (0x2C17, 'M', u'ⱇ'), - (0x2C18, 'M', u'ⱈ'), - (0x2C19, 'M', u'ⱉ'), - (0x2C1A, 'M', u'ⱊ'), - (0x2C1B, 'M', u'ⱋ'), - (0x2C1C, 'M', u'ⱌ'), - (0x2C1D, 'M', u'ⱍ'), - (0x2C1E, 'M', u'ⱎ'), - (0x2C1F, 'M', u'ⱏ'), - (0x2C20, 'M', u'ⱐ'), - (0x2C21, 'M', u'ⱑ'), - (0x2C22, 'M', u'ⱒ'), - (0x2C23, 'M', u'ⱓ'), - (0x2C24, 'M', u'ⱔ'), - (0x2C25, 'M', u'ⱕ'), - (0x2C26, 'M', u'ⱖ'), - (0x2C27, 'M', u'ⱗ'), - (0x2C28, 'M', u'ⱘ'), - (0x2C29, 'M', u'ⱙ'), - (0x2C2A, 'M', u'ⱚ'), - (0x2C2B, 'M', u'ⱛ'), - (0x2C2C, 'M', u'ⱜ'), - (0x2C2D, 'M', u'ⱝ'), - (0x2C2E, 'M', u'ⱞ'), - (0x2C2F, 'X'), - (0x2C30, 'V'), - (0x2C5F, 'X'), - (0x2C60, 'M', u'ⱡ'), - (0x2C61, 'V'), - (0x2C62, 'M', u'ɫ'), - (0x2C63, 'M', u'ᵽ'), - (0x2C64, 'M', u'ɽ'), - (0x2C65, 'V'), - (0x2C67, 'M', u'ⱨ'), - (0x2C68, 'V'), - (0x2C69, 'M', u'ⱪ'), - (0x2C6A, 'V'), - (0x2C6B, 'M', u'ⱬ'), - (0x2C6C, 'V'), - (0x2C6D, 'M', u'ɑ'), - (0x2C6E, 'M', u'ɱ'), - (0x2C6F, 'M', u'ɐ'), - (0x2C70, 'M', u'ɒ'), - ] - -def _seg_25(): - return [ - (0x2C71, 'V'), - (0x2C72, 'M', u'ⱳ'), - (0x2C73, 'V'), - (0x2C75, 'M', u'ⱶ'), - (0x2C76, 'V'), - (0x2C7C, 'M', u'j'), - (0x2C7D, 'M', u'v'), - (0x2C7E, 'M', u'ȿ'), - (0x2C7F, 'M', u'ɀ'), - (0x2C80, 'M', u'ⲁ'), - (0x2C81, 'V'), - (0x2C82, 'M', u'ⲃ'), - (0x2C83, 'V'), - (0x2C84, 'M', u'ⲅ'), - (0x2C85, 'V'), - (0x2C86, 'M', u'ⲇ'), - (0x2C87, 'V'), - (0x2C88, 'M', u'ⲉ'), - (0x2C89, 'V'), - (0x2C8A, 'M', u'ⲋ'), - (0x2C8B, 'V'), - (0x2C8C, 'M', u'ⲍ'), - (0x2C8D, 'V'), - (0x2C8E, 'M', u'ⲏ'), - (0x2C8F, 'V'), - (0x2C90, 'M', u'ⲑ'), - (0x2C91, 'V'), - (0x2C92, 'M', u'ⲓ'), - (0x2C93, 'V'), - (0x2C94, 'M', u'ⲕ'), - (0x2C95, 'V'), - (0x2C96, 'M', u'ⲗ'), - (0x2C97, 'V'), - (0x2C98, 'M', u'ⲙ'), - (0x2C99, 'V'), - (0x2C9A, 'M', u'ⲛ'), - (0x2C9B, 'V'), - (0x2C9C, 'M', u'ⲝ'), - (0x2C9D, 'V'), - (0x2C9E, 'M', u'ⲟ'), - (0x2C9F, 'V'), - (0x2CA0, 'M', u'ⲡ'), - (0x2CA1, 'V'), - (0x2CA2, 'M', u'ⲣ'), - (0x2CA3, 'V'), - (0x2CA4, 'M', u'ⲥ'), - (0x2CA5, 'V'), - (0x2CA6, 'M', u'ⲧ'), - (0x2CA7, 'V'), - (0x2CA8, 'M', u'ⲩ'), - (0x2CA9, 'V'), - (0x2CAA, 'M', u'ⲫ'), - (0x2CAB, 'V'), - (0x2CAC, 'M', u'ⲭ'), - (0x2CAD, 'V'), - (0x2CAE, 'M', u'ⲯ'), - (0x2CAF, 'V'), - (0x2CB0, 'M', u'ⲱ'), - (0x2CB1, 'V'), - (0x2CB2, 'M', u'ⲳ'), - (0x2CB3, 'V'), - (0x2CB4, 'M', u'ⲵ'), - (0x2CB5, 'V'), - (0x2CB6, 'M', u'ⲷ'), - (0x2CB7, 'V'), - (0x2CB8, 'M', u'ⲹ'), - (0x2CB9, 'V'), - (0x2CBA, 'M', u'ⲻ'), - (0x2CBB, 'V'), - (0x2CBC, 'M', u'ⲽ'), - (0x2CBD, 'V'), - (0x2CBE, 'M', u'ⲿ'), - (0x2CBF, 'V'), - (0x2CC0, 'M', u'ⳁ'), - (0x2CC1, 'V'), - (0x2CC2, 'M', u'ⳃ'), - (0x2CC3, 'V'), - (0x2CC4, 'M', u'ⳅ'), - (0x2CC5, 'V'), - (0x2CC6, 'M', u'ⳇ'), - (0x2CC7, 'V'), - (0x2CC8, 'M', u'ⳉ'), - (0x2CC9, 'V'), - (0x2CCA, 'M', u'ⳋ'), - (0x2CCB, 'V'), - (0x2CCC, 'M', u'ⳍ'), - (0x2CCD, 'V'), - (0x2CCE, 'M', u'ⳏ'), - (0x2CCF, 'V'), - (0x2CD0, 'M', u'ⳑ'), - (0x2CD1, 'V'), - (0x2CD2, 'M', u'ⳓ'), - (0x2CD3, 'V'), - (0x2CD4, 'M', u'ⳕ'), - (0x2CD5, 'V'), - (0x2CD6, 'M', u'ⳗ'), - (0x2CD7, 'V'), - (0x2CD8, 'M', u'ⳙ'), - (0x2CD9, 'V'), - (0x2CDA, 'M', u'ⳛ'), - ] - -def _seg_26(): - return [ - (0x2CDB, 'V'), - (0x2CDC, 'M', u'ⳝ'), - (0x2CDD, 'V'), - (0x2CDE, 'M', u'ⳟ'), - (0x2CDF, 'V'), - (0x2CE0, 'M', u'ⳡ'), - (0x2CE1, 'V'), - (0x2CE2, 'M', u'ⳣ'), - (0x2CE3, 'V'), - (0x2CEB, 'M', u'ⳬ'), - (0x2CEC, 'V'), - (0x2CED, 'M', u'ⳮ'), - (0x2CEE, 'V'), - (0x2CF2, 'M', u'ⳳ'), - (0x2CF3, 'V'), - (0x2CF4, 'X'), - (0x2CF9, 'V'), - (0x2D26, 'X'), - (0x2D27, 'V'), - (0x2D28, 'X'), - (0x2D2D, 'V'), - (0x2D2E, 'X'), - (0x2D30, 'V'), - (0x2D68, 'X'), - (0x2D6F, 'M', u'ⵡ'), - (0x2D70, 'V'), - (0x2D71, 'X'), - (0x2D7F, 'V'), - (0x2D97, 'X'), - (0x2DA0, 'V'), - (0x2DA7, 'X'), - (0x2DA8, 'V'), - (0x2DAF, 'X'), - (0x2DB0, 'V'), - (0x2DB7, 'X'), - (0x2DB8, 'V'), - (0x2DBF, 'X'), - (0x2DC0, 'V'), - (0x2DC7, 'X'), - (0x2DC8, 'V'), - (0x2DCF, 'X'), - (0x2DD0, 'V'), - (0x2DD7, 'X'), - (0x2DD8, 'V'), - (0x2DDF, 'X'), - (0x2DE0, 'V'), - (0x2E4F, 'X'), - (0x2E80, 'V'), - (0x2E9A, 'X'), - (0x2E9B, 'V'), - (0x2E9F, 'M', u'母'), - (0x2EA0, 'V'), - (0x2EF3, 'M', u'龟'), - (0x2EF4, 'X'), - (0x2F00, 'M', u'一'), - (0x2F01, 'M', u'丨'), - (0x2F02, 'M', u'丶'), - (0x2F03, 'M', u'丿'), - (0x2F04, 'M', u'乙'), - (0x2F05, 'M', u'亅'), - (0x2F06, 'M', u'二'), - (0x2F07, 'M', u'亠'), - (0x2F08, 'M', u'人'), - (0x2F09, 'M', u'儿'), - (0x2F0A, 'M', u'入'), - (0x2F0B, 'M', u'八'), - (0x2F0C, 'M', u'冂'), - (0x2F0D, 'M', u'冖'), - (0x2F0E, 'M', u'冫'), - (0x2F0F, 'M', u'几'), - (0x2F10, 'M', u'凵'), - (0x2F11, 'M', u'刀'), - (0x2F12, 'M', u'力'), - (0x2F13, 'M', u'勹'), - (0x2F14, 'M', u'匕'), - (0x2F15, 'M', u'匚'), - (0x2F16, 'M', u'匸'), - (0x2F17, 'M', u'十'), - (0x2F18, 'M', u'卜'), - (0x2F19, 'M', u'卩'), - (0x2F1A, 'M', u'厂'), - (0x2F1B, 'M', u'厶'), - (0x2F1C, 'M', u'又'), - (0x2F1D, 'M', u'口'), - (0x2F1E, 'M', u'囗'), - (0x2F1F, 'M', u'土'), - (0x2F20, 'M', u'士'), - (0x2F21, 'M', u'夂'), - (0x2F22, 'M', u'夊'), - (0x2F23, 'M', u'夕'), - (0x2F24, 'M', u'大'), - (0x2F25, 'M', u'女'), - (0x2F26, 'M', u'子'), - (0x2F27, 'M', u'宀'), - (0x2F28, 'M', u'寸'), - (0x2F29, 'M', u'小'), - (0x2F2A, 'M', u'尢'), - (0x2F2B, 'M', u'尸'), - (0x2F2C, 'M', u'屮'), - (0x2F2D, 'M', u'山'), - ] - -def _seg_27(): - return [ - (0x2F2E, 'M', u'巛'), - (0x2F2F, 'M', u'工'), - (0x2F30, 'M', u'己'), - (0x2F31, 'M', u'巾'), - (0x2F32, 'M', u'干'), - (0x2F33, 'M', u'幺'), - (0x2F34, 'M', u'广'), - (0x2F35, 'M', u'廴'), - (0x2F36, 'M', u'廾'), - (0x2F37, 'M', u'弋'), - (0x2F38, 'M', u'弓'), - (0x2F39, 'M', u'彐'), - (0x2F3A, 'M', u'彡'), - (0x2F3B, 'M', u'彳'), - (0x2F3C, 'M', u'心'), - (0x2F3D, 'M', u'戈'), - (0x2F3E, 'M', u'戶'), - (0x2F3F, 'M', u'手'), - (0x2F40, 'M', u'支'), - (0x2F41, 'M', u'攴'), - (0x2F42, 'M', u'文'), - (0x2F43, 'M', u'斗'), - (0x2F44, 'M', u'斤'), - (0x2F45, 'M', u'方'), - (0x2F46, 'M', u'无'), - (0x2F47, 'M', u'日'), - (0x2F48, 'M', u'曰'), - (0x2F49, 'M', u'月'), - (0x2F4A, 'M', u'木'), - (0x2F4B, 'M', u'欠'), - (0x2F4C, 'M', u'止'), - (0x2F4D, 'M', u'歹'), - (0x2F4E, 'M', u'殳'), - (0x2F4F, 'M', u'毋'), - (0x2F50, 'M', u'比'), - (0x2F51, 'M', u'毛'), - (0x2F52, 'M', u'氏'), - (0x2F53, 'M', u'气'), - (0x2F54, 'M', u'水'), - (0x2F55, 'M', u'火'), - (0x2F56, 'M', u'爪'), - (0x2F57, 'M', u'父'), - (0x2F58, 'M', u'爻'), - (0x2F59, 'M', u'爿'), - (0x2F5A, 'M', u'片'), - (0x2F5B, 'M', u'牙'), - (0x2F5C, 'M', u'牛'), - (0x2F5D, 'M', u'犬'), - (0x2F5E, 'M', u'玄'), - (0x2F5F, 'M', u'玉'), - (0x2F60, 'M', u'瓜'), - (0x2F61, 'M', u'瓦'), - (0x2F62, 'M', u'甘'), - (0x2F63, 'M', u'生'), - (0x2F64, 'M', u'用'), - (0x2F65, 'M', u'田'), - (0x2F66, 'M', u'疋'), - (0x2F67, 'M', u'疒'), - (0x2F68, 'M', u'癶'), - (0x2F69, 'M', u'白'), - (0x2F6A, 'M', u'皮'), - (0x2F6B, 'M', u'皿'), - (0x2F6C, 'M', u'目'), - (0x2F6D, 'M', u'矛'), - (0x2F6E, 'M', u'矢'), - (0x2F6F, 'M', u'石'), - (0x2F70, 'M', u'示'), - (0x2F71, 'M', u'禸'), - (0x2F72, 'M', u'禾'), - (0x2F73, 'M', u'穴'), - (0x2F74, 'M', u'立'), - (0x2F75, 'M', u'竹'), - (0x2F76, 'M', u'米'), - (0x2F77, 'M', u'糸'), - (0x2F78, 'M', u'缶'), - (0x2F79, 'M', u'网'), - (0x2F7A, 'M', u'羊'), - (0x2F7B, 'M', u'羽'), - (0x2F7C, 'M', u'老'), - (0x2F7D, 'M', u'而'), - (0x2F7E, 'M', u'耒'), - (0x2F7F, 'M', u'耳'), - (0x2F80, 'M', u'聿'), - (0x2F81, 'M', u'肉'), - (0x2F82, 'M', u'臣'), - (0x2F83, 'M', u'自'), - (0x2F84, 'M', u'至'), - (0x2F85, 'M', u'臼'), - (0x2F86, 'M', u'舌'), - (0x2F87, 'M', u'舛'), - (0x2F88, 'M', u'舟'), - (0x2F89, 'M', u'艮'), - (0x2F8A, 'M', u'色'), - (0x2F8B, 'M', u'艸'), - (0x2F8C, 'M', u'虍'), - (0x2F8D, 'M', u'虫'), - (0x2F8E, 'M', u'血'), - (0x2F8F, 'M', u'行'), - (0x2F90, 'M', u'衣'), - (0x2F91, 'M', u'襾'), - ] - -def _seg_28(): - return [ - (0x2F92, 'M', u'見'), - (0x2F93, 'M', u'角'), - (0x2F94, 'M', u'言'), - (0x2F95, 'M', u'谷'), - (0x2F96, 'M', u'豆'), - (0x2F97, 'M', u'豕'), - (0x2F98, 'M', u'豸'), - (0x2F99, 'M', u'貝'), - (0x2F9A, 'M', u'赤'), - (0x2F9B, 'M', u'走'), - (0x2F9C, 'M', u'足'), - (0x2F9D, 'M', u'身'), - (0x2F9E, 'M', u'車'), - (0x2F9F, 'M', u'辛'), - (0x2FA0, 'M', u'辰'), - (0x2FA1, 'M', u'辵'), - (0x2FA2, 'M', u'邑'), - (0x2FA3, 'M', u'酉'), - (0x2FA4, 'M', u'釆'), - (0x2FA5, 'M', u'里'), - (0x2FA6, 'M', u'金'), - (0x2FA7, 'M', u'長'), - (0x2FA8, 'M', u'門'), - (0x2FA9, 'M', u'阜'), - (0x2FAA, 'M', u'隶'), - (0x2FAB, 'M', u'隹'), - (0x2FAC, 'M', u'雨'), - (0x2FAD, 'M', u'靑'), - (0x2FAE, 'M', u'非'), - (0x2FAF, 'M', u'面'), - (0x2FB0, 'M', u'革'), - (0x2FB1, 'M', u'韋'), - (0x2FB2, 'M', u'韭'), - (0x2FB3, 'M', u'音'), - (0x2FB4, 'M', u'頁'), - (0x2FB5, 'M', u'風'), - (0x2FB6, 'M', u'飛'), - (0x2FB7, 'M', u'食'), - (0x2FB8, 'M', u'首'), - (0x2FB9, 'M', u'香'), - (0x2FBA, 'M', u'馬'), - (0x2FBB, 'M', u'骨'), - (0x2FBC, 'M', u'高'), - (0x2FBD, 'M', u'髟'), - (0x2FBE, 'M', u'鬥'), - (0x2FBF, 'M', u'鬯'), - (0x2FC0, 'M', u'鬲'), - (0x2FC1, 'M', u'鬼'), - (0x2FC2, 'M', u'魚'), - (0x2FC3, 'M', u'鳥'), - (0x2FC4, 'M', u'鹵'), - (0x2FC5, 'M', u'鹿'), - (0x2FC6, 'M', u'麥'), - (0x2FC7, 'M', u'麻'), - (0x2FC8, 'M', u'黃'), - (0x2FC9, 'M', u'黍'), - (0x2FCA, 'M', u'黑'), - (0x2FCB, 'M', u'黹'), - (0x2FCC, 'M', u'黽'), - (0x2FCD, 'M', u'鼎'), - (0x2FCE, 'M', u'鼓'), - (0x2FCF, 'M', u'鼠'), - (0x2FD0, 'M', u'鼻'), - (0x2FD1, 'M', u'齊'), - (0x2FD2, 'M', u'齒'), - (0x2FD3, 'M', u'龍'), - (0x2FD4, 'M', u'龜'), - (0x2FD5, 'M', u'龠'), - (0x2FD6, 'X'), - (0x3000, '3', u' '), - (0x3001, 'V'), - (0x3002, 'M', u'.'), - (0x3003, 'V'), - (0x3036, 'M', u'〒'), - (0x3037, 'V'), - (0x3038, 'M', u'十'), - (0x3039, 'M', u'卄'), - (0x303A, 'M', u'卅'), - (0x303B, 'V'), - (0x3040, 'X'), - (0x3041, 'V'), - (0x3097, 'X'), - (0x3099, 'V'), - (0x309B, '3', u' ゙'), - (0x309C, '3', u' ゚'), - (0x309D, 'V'), - (0x309F, 'M', u'より'), - (0x30A0, 'V'), - (0x30FF, 'M', u'コト'), - (0x3100, 'X'), - (0x3105, 'V'), - (0x3130, 'X'), - (0x3131, 'M', u'ᄀ'), - (0x3132, 'M', u'ᄁ'), - (0x3133, 'M', u'ᆪ'), - (0x3134, 'M', u'ᄂ'), - (0x3135, 'M', u'ᆬ'), - (0x3136, 'M', u'ᆭ'), - (0x3137, 'M', u'ᄃ'), - (0x3138, 'M', u'ᄄ'), - ] - -def _seg_29(): - return [ - (0x3139, 'M', u'ᄅ'), - (0x313A, 'M', u'ᆰ'), - (0x313B, 'M', u'ᆱ'), - (0x313C, 'M', u'ᆲ'), - (0x313D, 'M', u'ᆳ'), - (0x313E, 'M', u'ᆴ'), - (0x313F, 'M', u'ᆵ'), - (0x3140, 'M', u'ᄚ'), - (0x3141, 'M', u'ᄆ'), - (0x3142, 'M', u'ᄇ'), - (0x3143, 'M', u'ᄈ'), - (0x3144, 'M', u'ᄡ'), - (0x3145, 'M', u'ᄉ'), - (0x3146, 'M', u'ᄊ'), - (0x3147, 'M', u'ᄋ'), - (0x3148, 'M', u'ᄌ'), - (0x3149, 'M', u'ᄍ'), - (0x314A, 'M', u'ᄎ'), - (0x314B, 'M', u'ᄏ'), - (0x314C, 'M', u'ᄐ'), - (0x314D, 'M', u'ᄑ'), - (0x314E, 'M', u'ᄒ'), - (0x314F, 'M', u'ᅡ'), - (0x3150, 'M', u'ᅢ'), - (0x3151, 'M', u'ᅣ'), - (0x3152, 'M', u'ᅤ'), - (0x3153, 'M', u'ᅥ'), - (0x3154, 'M', u'ᅦ'), - (0x3155, 'M', u'ᅧ'), - (0x3156, 'M', u'ᅨ'), - (0x3157, 'M', u'ᅩ'), - (0x3158, 'M', u'ᅪ'), - (0x3159, 'M', u'ᅫ'), - (0x315A, 'M', u'ᅬ'), - (0x315B, 'M', u'ᅭ'), - (0x315C, 'M', u'ᅮ'), - (0x315D, 'M', u'ᅯ'), - (0x315E, 'M', u'ᅰ'), - (0x315F, 'M', u'ᅱ'), - (0x3160, 'M', u'ᅲ'), - (0x3161, 'M', u'ᅳ'), - (0x3162, 'M', u'ᅴ'), - (0x3163, 'M', u'ᅵ'), - (0x3164, 'X'), - (0x3165, 'M', u'ᄔ'), - (0x3166, 'M', u'ᄕ'), - (0x3167, 'M', u'ᇇ'), - (0x3168, 'M', u'ᇈ'), - (0x3169, 'M', u'ᇌ'), - (0x316A, 'M', u'ᇎ'), - (0x316B, 'M', u'ᇓ'), - (0x316C, 'M', u'ᇗ'), - (0x316D, 'M', u'ᇙ'), - (0x316E, 'M', u'ᄜ'), - (0x316F, 'M', u'ᇝ'), - (0x3170, 'M', u'ᇟ'), - (0x3171, 'M', u'ᄝ'), - (0x3172, 'M', u'ᄞ'), - (0x3173, 'M', u'ᄠ'), - (0x3174, 'M', u'ᄢ'), - (0x3175, 'M', u'ᄣ'), - (0x3176, 'M', u'ᄧ'), - (0x3177, 'M', u'ᄩ'), - (0x3178, 'M', u'ᄫ'), - (0x3179, 'M', u'ᄬ'), - (0x317A, 'M', u'ᄭ'), - (0x317B, 'M', u'ᄮ'), - (0x317C, 'M', u'ᄯ'), - (0x317D, 'M', u'ᄲ'), - (0x317E, 'M', u'ᄶ'), - (0x317F, 'M', u'ᅀ'), - (0x3180, 'M', u'ᅇ'), - (0x3181, 'M', u'ᅌ'), - (0x3182, 'M', u'ᇱ'), - (0x3183, 'M', u'ᇲ'), - (0x3184, 'M', u'ᅗ'), - (0x3185, 'M', u'ᅘ'), - (0x3186, 'M', u'ᅙ'), - (0x3187, 'M', u'ᆄ'), - (0x3188, 'M', u'ᆅ'), - (0x3189, 'M', u'ᆈ'), - (0x318A, 'M', u'ᆑ'), - (0x318B, 'M', u'ᆒ'), - (0x318C, 'M', u'ᆔ'), - (0x318D, 'M', u'ᆞ'), - (0x318E, 'M', u'ᆡ'), - (0x318F, 'X'), - (0x3190, 'V'), - (0x3192, 'M', u'一'), - (0x3193, 'M', u'二'), - (0x3194, 'M', u'三'), - (0x3195, 'M', u'四'), - (0x3196, 'M', u'上'), - (0x3197, 'M', u'中'), - (0x3198, 'M', u'下'), - (0x3199, 'M', u'甲'), - (0x319A, 'M', u'乙'), - (0x319B, 'M', u'丙'), - (0x319C, 'M', u'丁'), - (0x319D, 'M', u'天'), - ] - -def _seg_30(): - return [ - (0x319E, 'M', u'地'), - (0x319F, 'M', u'人'), - (0x31A0, 'V'), - (0x31BB, 'X'), - (0x31C0, 'V'), - (0x31E4, 'X'), - (0x31F0, 'V'), - (0x3200, '3', u'(ᄀ)'), - (0x3201, '3', u'(ᄂ)'), - (0x3202, '3', u'(ᄃ)'), - (0x3203, '3', u'(ᄅ)'), - (0x3204, '3', u'(ᄆ)'), - (0x3205, '3', u'(ᄇ)'), - (0x3206, '3', u'(ᄉ)'), - (0x3207, '3', u'(ᄋ)'), - (0x3208, '3', u'(ᄌ)'), - (0x3209, '3', u'(ᄎ)'), - (0x320A, '3', u'(ᄏ)'), - (0x320B, '3', u'(ᄐ)'), - (0x320C, '3', u'(ᄑ)'), - (0x320D, '3', u'(ᄒ)'), - (0x320E, '3', u'(가)'), - (0x320F, '3', u'(나)'), - (0x3210, '3', u'(다)'), - (0x3211, '3', u'(라)'), - (0x3212, '3', u'(마)'), - (0x3213, '3', u'(바)'), - (0x3214, '3', u'(사)'), - (0x3215, '3', u'(아)'), - (0x3216, '3', u'(자)'), - (0x3217, '3', u'(차)'), - (0x3218, '3', u'(카)'), - (0x3219, '3', u'(타)'), - (0x321A, '3', u'(파)'), - (0x321B, '3', u'(하)'), - (0x321C, '3', u'(주)'), - (0x321D, '3', u'(오전)'), - (0x321E, '3', u'(오후)'), - (0x321F, 'X'), - (0x3220, '3', u'(一)'), - (0x3221, '3', u'(二)'), - (0x3222, '3', u'(三)'), - (0x3223, '3', u'(四)'), - (0x3224, '3', u'(五)'), - (0x3225, '3', u'(六)'), - (0x3226, '3', u'(七)'), - (0x3227, '3', u'(八)'), - (0x3228, '3', u'(九)'), - (0x3229, '3', u'(十)'), - (0x322A, '3', u'(月)'), - (0x322B, '3', u'(火)'), - (0x322C, '3', u'(水)'), - (0x322D, '3', u'(木)'), - (0x322E, '3', u'(金)'), - (0x322F, '3', u'(土)'), - (0x3230, '3', u'(日)'), - (0x3231, '3', u'(株)'), - (0x3232, '3', u'(有)'), - (0x3233, '3', u'(社)'), - (0x3234, '3', u'(名)'), - (0x3235, '3', u'(特)'), - (0x3236, '3', u'(財)'), - (0x3237, '3', u'(祝)'), - (0x3238, '3', u'(労)'), - (0x3239, '3', u'(代)'), - (0x323A, '3', u'(呼)'), - (0x323B, '3', u'(学)'), - (0x323C, '3', u'(監)'), - (0x323D, '3', u'(企)'), - (0x323E, '3', u'(資)'), - (0x323F, '3', u'(協)'), - (0x3240, '3', u'(祭)'), - (0x3241, '3', u'(休)'), - (0x3242, '3', u'(自)'), - (0x3243, '3', u'(至)'), - (0x3244, 'M', u'問'), - (0x3245, 'M', u'幼'), - (0x3246, 'M', u'文'), - (0x3247, 'M', u'箏'), - (0x3248, 'V'), - (0x3250, 'M', u'pte'), - (0x3251, 'M', u'21'), - (0x3252, 'M', u'22'), - (0x3253, 'M', u'23'), - (0x3254, 'M', u'24'), - (0x3255, 'M', u'25'), - (0x3256, 'M', u'26'), - (0x3257, 'M', u'27'), - (0x3258, 'M', u'28'), - (0x3259, 'M', u'29'), - (0x325A, 'M', u'30'), - (0x325B, 'M', u'31'), - (0x325C, 'M', u'32'), - (0x325D, 'M', u'33'), - (0x325E, 'M', u'34'), - (0x325F, 'M', u'35'), - (0x3260, 'M', u'ᄀ'), - (0x3261, 'M', u'ᄂ'), - (0x3262, 'M', u'ᄃ'), - (0x3263, 'M', u'ᄅ'), - ] - -def _seg_31(): - return [ - (0x3264, 'M', u'ᄆ'), - (0x3265, 'M', u'ᄇ'), - (0x3266, 'M', u'ᄉ'), - (0x3267, 'M', u'ᄋ'), - (0x3268, 'M', u'ᄌ'), - (0x3269, 'M', u'ᄎ'), - (0x326A, 'M', u'ᄏ'), - (0x326B, 'M', u'ᄐ'), - (0x326C, 'M', u'ᄑ'), - (0x326D, 'M', u'ᄒ'), - (0x326E, 'M', u'가'), - (0x326F, 'M', u'나'), - (0x3270, 'M', u'다'), - (0x3271, 'M', u'라'), - (0x3272, 'M', u'마'), - (0x3273, 'M', u'바'), - (0x3274, 'M', u'사'), - (0x3275, 'M', u'아'), - (0x3276, 'M', u'자'), - (0x3277, 'M', u'차'), - (0x3278, 'M', u'카'), - (0x3279, 'M', u'타'), - (0x327A, 'M', u'파'), - (0x327B, 'M', u'하'), - (0x327C, 'M', u'참고'), - (0x327D, 'M', u'주의'), - (0x327E, 'M', u'우'), - (0x327F, 'V'), - (0x3280, 'M', u'一'), - (0x3281, 'M', u'二'), - (0x3282, 'M', u'三'), - (0x3283, 'M', u'四'), - (0x3284, 'M', u'五'), - (0x3285, 'M', u'六'), - (0x3286, 'M', u'七'), - (0x3287, 'M', u'八'), - (0x3288, 'M', u'九'), - (0x3289, 'M', u'十'), - (0x328A, 'M', u'月'), - (0x328B, 'M', u'火'), - (0x328C, 'M', u'水'), - (0x328D, 'M', u'木'), - (0x328E, 'M', u'金'), - (0x328F, 'M', u'土'), - (0x3290, 'M', u'日'), - (0x3291, 'M', u'株'), - (0x3292, 'M', u'有'), - (0x3293, 'M', u'社'), - (0x3294, 'M', u'名'), - (0x3295, 'M', u'特'), - (0x3296, 'M', u'財'), - (0x3297, 'M', u'祝'), - (0x3298, 'M', u'労'), - (0x3299, 'M', u'秘'), - (0x329A, 'M', u'男'), - (0x329B, 'M', u'女'), - (0x329C, 'M', u'適'), - (0x329D, 'M', u'優'), - (0x329E, 'M', u'印'), - (0x329F, 'M', u'注'), - (0x32A0, 'M', u'項'), - (0x32A1, 'M', u'休'), - (0x32A2, 'M', u'写'), - (0x32A3, 'M', u'正'), - (0x32A4, 'M', u'上'), - (0x32A5, 'M', u'中'), - (0x32A6, 'M', u'下'), - (0x32A7, 'M', u'左'), - (0x32A8, 'M', u'右'), - (0x32A9, 'M', u'医'), - (0x32AA, 'M', u'宗'), - (0x32AB, 'M', u'学'), - (0x32AC, 'M', u'監'), - (0x32AD, 'M', u'企'), - (0x32AE, 'M', u'資'), - (0x32AF, 'M', u'協'), - (0x32B0, 'M', u'夜'), - (0x32B1, 'M', u'36'), - (0x32B2, 'M', u'37'), - (0x32B3, 'M', u'38'), - (0x32B4, 'M', u'39'), - (0x32B5, 'M', u'40'), - (0x32B6, 'M', u'41'), - (0x32B7, 'M', u'42'), - (0x32B8, 'M', u'43'), - (0x32B9, 'M', u'44'), - (0x32BA, 'M', u'45'), - (0x32BB, 'M', u'46'), - (0x32BC, 'M', u'47'), - (0x32BD, 'M', u'48'), - (0x32BE, 'M', u'49'), - (0x32BF, 'M', u'50'), - (0x32C0, 'M', u'1月'), - (0x32C1, 'M', u'2月'), - (0x32C2, 'M', u'3月'), - (0x32C3, 'M', u'4月'), - (0x32C4, 'M', u'5月'), - (0x32C5, 'M', u'6月'), - (0x32C6, 'M', u'7月'), - (0x32C7, 'M', u'8月'), - ] - -def _seg_32(): - return [ - (0x32C8, 'M', u'9月'), - (0x32C9, 'M', u'10月'), - (0x32CA, 'M', u'11月'), - (0x32CB, 'M', u'12月'), - (0x32CC, 'M', u'hg'), - (0x32CD, 'M', u'erg'), - (0x32CE, 'M', u'ev'), - (0x32CF, 'M', u'ltd'), - (0x32D0, 'M', u'ア'), - (0x32D1, 'M', u'イ'), - (0x32D2, 'M', u'ウ'), - (0x32D3, 'M', u'エ'), - (0x32D4, 'M', u'オ'), - (0x32D5, 'M', u'カ'), - (0x32D6, 'M', u'キ'), - (0x32D7, 'M', u'ク'), - (0x32D8, 'M', u'ケ'), - (0x32D9, 'M', u'コ'), - (0x32DA, 'M', u'サ'), - (0x32DB, 'M', u'シ'), - (0x32DC, 'M', u'ス'), - (0x32DD, 'M', u'セ'), - (0x32DE, 'M', u'ソ'), - (0x32DF, 'M', u'タ'), - (0x32E0, 'M', u'チ'), - (0x32E1, 'M', u'ツ'), - (0x32E2, 'M', u'テ'), - (0x32E3, 'M', u'ト'), - (0x32E4, 'M', u'ナ'), - (0x32E5, 'M', u'ニ'), - (0x32E6, 'M', u'ヌ'), - (0x32E7, 'M', u'ネ'), - (0x32E8, 'M', u'ノ'), - (0x32E9, 'M', u'ハ'), - (0x32EA, 'M', u'ヒ'), - (0x32EB, 'M', u'フ'), - (0x32EC, 'M', u'ヘ'), - (0x32ED, 'M', u'ホ'), - (0x32EE, 'M', u'マ'), - (0x32EF, 'M', u'ミ'), - (0x32F0, 'M', u'ム'), - (0x32F1, 'M', u'メ'), - (0x32F2, 'M', u'モ'), - (0x32F3, 'M', u'ヤ'), - (0x32F4, 'M', u'ユ'), - (0x32F5, 'M', u'ヨ'), - (0x32F6, 'M', u'ラ'), - (0x32F7, 'M', u'リ'), - (0x32F8, 'M', u'ル'), - (0x32F9, 'M', u'レ'), - (0x32FA, 'M', u'ロ'), - (0x32FB, 'M', u'ワ'), - (0x32FC, 'M', u'ヰ'), - (0x32FD, 'M', u'ヱ'), - (0x32FE, 'M', u'ヲ'), - (0x32FF, 'X'), - (0x3300, 'M', u'アパート'), - (0x3301, 'M', u'アルファ'), - (0x3302, 'M', u'アンペア'), - (0x3303, 'M', u'アール'), - (0x3304, 'M', u'イニング'), - (0x3305, 'M', u'インチ'), - (0x3306, 'M', u'ウォン'), - (0x3307, 'M', u'エスクード'), - (0x3308, 'M', u'エーカー'), - (0x3309, 'M', u'オンス'), - (0x330A, 'M', u'オーム'), - (0x330B, 'M', u'カイリ'), - (0x330C, 'M', u'カラット'), - (0x330D, 'M', u'カロリー'), - (0x330E, 'M', u'ガロン'), - (0x330F, 'M', u'ガンマ'), - (0x3310, 'M', u'ギガ'), - (0x3311, 'M', u'ギニー'), - (0x3312, 'M', u'キュリー'), - (0x3313, 'M', u'ギルダー'), - (0x3314, 'M', u'キロ'), - (0x3315, 'M', u'キログラム'), - (0x3316, 'M', u'キロメートル'), - (0x3317, 'M', u'キロワット'), - (0x3318, 'M', u'グラム'), - (0x3319, 'M', u'グラムトン'), - (0x331A, 'M', u'クルゼイロ'), - (0x331B, 'M', u'クローネ'), - (0x331C, 'M', u'ケース'), - (0x331D, 'M', u'コルナ'), - (0x331E, 'M', u'コーポ'), - (0x331F, 'M', u'サイクル'), - (0x3320, 'M', u'サンチーム'), - (0x3321, 'M', u'シリング'), - (0x3322, 'M', u'センチ'), - (0x3323, 'M', u'セント'), - (0x3324, 'M', u'ダース'), - (0x3325, 'M', u'デシ'), - (0x3326, 'M', u'ドル'), - (0x3327, 'M', u'トン'), - (0x3328, 'M', u'ナノ'), - (0x3329, 'M', u'ノット'), - (0x332A, 'M', u'ハイツ'), - (0x332B, 'M', u'パーセント'), - ] - -def _seg_33(): - return [ - (0x332C, 'M', u'パーツ'), - (0x332D, 'M', u'バーレル'), - (0x332E, 'M', u'ピアストル'), - (0x332F, 'M', u'ピクル'), - (0x3330, 'M', u'ピコ'), - (0x3331, 'M', u'ビル'), - (0x3332, 'M', u'ファラッド'), - (0x3333, 'M', u'フィート'), - (0x3334, 'M', u'ブッシェル'), - (0x3335, 'M', u'フラン'), - (0x3336, 'M', u'ヘクタール'), - (0x3337, 'M', u'ペソ'), - (0x3338, 'M', u'ペニヒ'), - (0x3339, 'M', u'ヘルツ'), - (0x333A, 'M', u'ペンス'), - (0x333B, 'M', u'ページ'), - (0x333C, 'M', u'ベータ'), - (0x333D, 'M', u'ポイント'), - (0x333E, 'M', u'ボルト'), - (0x333F, 'M', u'ホン'), - (0x3340, 'M', u'ポンド'), - (0x3341, 'M', u'ホール'), - (0x3342, 'M', u'ホーン'), - (0x3343, 'M', u'マイクロ'), - (0x3344, 'M', u'マイル'), - (0x3345, 'M', u'マッハ'), - (0x3346, 'M', u'マルク'), - (0x3347, 'M', u'マンション'), - (0x3348, 'M', u'ミクロン'), - (0x3349, 'M', u'ミリ'), - (0x334A, 'M', u'ミリバール'), - (0x334B, 'M', u'メガ'), - (0x334C, 'M', u'メガトン'), - (0x334D, 'M', u'メートル'), - (0x334E, 'M', u'ヤード'), - (0x334F, 'M', u'ヤール'), - (0x3350, 'M', u'ユアン'), - (0x3351, 'M', u'リットル'), - (0x3352, 'M', u'リラ'), - (0x3353, 'M', u'ルピー'), - (0x3354, 'M', u'ルーブル'), - (0x3355, 'M', u'レム'), - (0x3356, 'M', u'レントゲン'), - (0x3357, 'M', u'ワット'), - (0x3358, 'M', u'0点'), - (0x3359, 'M', u'1点'), - (0x335A, 'M', u'2点'), - (0x335B, 'M', u'3点'), - (0x335C, 'M', u'4点'), - (0x335D, 'M', u'5点'), - (0x335E, 'M', u'6点'), - (0x335F, 'M', u'7点'), - (0x3360, 'M', u'8点'), - (0x3361, 'M', u'9点'), - (0x3362, 'M', u'10点'), - (0x3363, 'M', u'11点'), - (0x3364, 'M', u'12点'), - (0x3365, 'M', u'13点'), - (0x3366, 'M', u'14点'), - (0x3367, 'M', u'15点'), - (0x3368, 'M', u'16点'), - (0x3369, 'M', u'17点'), - (0x336A, 'M', u'18点'), - (0x336B, 'M', u'19点'), - (0x336C, 'M', u'20点'), - (0x336D, 'M', u'21点'), - (0x336E, 'M', u'22点'), - (0x336F, 'M', u'23点'), - (0x3370, 'M', u'24点'), - (0x3371, 'M', u'hpa'), - (0x3372, 'M', u'da'), - (0x3373, 'M', u'au'), - (0x3374, 'M', u'bar'), - (0x3375, 'M', u'ov'), - (0x3376, 'M', u'pc'), - (0x3377, 'M', u'dm'), - (0x3378, 'M', u'dm2'), - (0x3379, 'M', u'dm3'), - (0x337A, 'M', u'iu'), - (0x337B, 'M', u'平成'), - (0x337C, 'M', u'昭和'), - (0x337D, 'M', u'大正'), - (0x337E, 'M', u'明治'), - (0x337F, 'M', u'株式会社'), - (0x3380, 'M', u'pa'), - (0x3381, 'M', u'na'), - (0x3382, 'M', u'μa'), - (0x3383, 'M', u'ma'), - (0x3384, 'M', u'ka'), - (0x3385, 'M', u'kb'), - (0x3386, 'M', u'mb'), - (0x3387, 'M', u'gb'), - (0x3388, 'M', u'cal'), - (0x3389, 'M', u'kcal'), - (0x338A, 'M', u'pf'), - (0x338B, 'M', u'nf'), - (0x338C, 'M', u'μf'), - (0x338D, 'M', u'μg'), - (0x338E, 'M', u'mg'), - (0x338F, 'M', u'kg'), - ] - -def _seg_34(): - return [ - (0x3390, 'M', u'hz'), - (0x3391, 'M', u'khz'), - (0x3392, 'M', u'mhz'), - (0x3393, 'M', u'ghz'), - (0x3394, 'M', u'thz'), - (0x3395, 'M', u'μl'), - (0x3396, 'M', u'ml'), - (0x3397, 'M', u'dl'), - (0x3398, 'M', u'kl'), - (0x3399, 'M', u'fm'), - (0x339A, 'M', u'nm'), - (0x339B, 'M', u'μm'), - (0x339C, 'M', u'mm'), - (0x339D, 'M', u'cm'), - (0x339E, 'M', u'km'), - (0x339F, 'M', u'mm2'), - (0x33A0, 'M', u'cm2'), - (0x33A1, 'M', u'm2'), - (0x33A2, 'M', u'km2'), - (0x33A3, 'M', u'mm3'), - (0x33A4, 'M', u'cm3'), - (0x33A5, 'M', u'm3'), - (0x33A6, 'M', u'km3'), - (0x33A7, 'M', u'm∕s'), - (0x33A8, 'M', u'm∕s2'), - (0x33A9, 'M', u'pa'), - (0x33AA, 'M', u'kpa'), - (0x33AB, 'M', u'mpa'), - (0x33AC, 'M', u'gpa'), - (0x33AD, 'M', u'rad'), - (0x33AE, 'M', u'rad∕s'), - (0x33AF, 'M', u'rad∕s2'), - (0x33B0, 'M', u'ps'), - (0x33B1, 'M', u'ns'), - (0x33B2, 'M', u'μs'), - (0x33B3, 'M', u'ms'), - (0x33B4, 'M', u'pv'), - (0x33B5, 'M', u'nv'), - (0x33B6, 'M', u'μv'), - (0x33B7, 'M', u'mv'), - (0x33B8, 'M', u'kv'), - (0x33B9, 'M', u'mv'), - (0x33BA, 'M', u'pw'), - (0x33BB, 'M', u'nw'), - (0x33BC, 'M', u'μw'), - (0x33BD, 'M', u'mw'), - (0x33BE, 'M', u'kw'), - (0x33BF, 'M', u'mw'), - (0x33C0, 'M', u'kω'), - (0x33C1, 'M', u'mω'), - (0x33C2, 'X'), - (0x33C3, 'M', u'bq'), - (0x33C4, 'M', u'cc'), - (0x33C5, 'M', u'cd'), - (0x33C6, 'M', u'c∕kg'), - (0x33C7, 'X'), - (0x33C8, 'M', u'db'), - (0x33C9, 'M', u'gy'), - (0x33CA, 'M', u'ha'), - (0x33CB, 'M', u'hp'), - (0x33CC, 'M', u'in'), - (0x33CD, 'M', u'kk'), - (0x33CE, 'M', u'km'), - (0x33CF, 'M', u'kt'), - (0x33D0, 'M', u'lm'), - (0x33D1, 'M', u'ln'), - (0x33D2, 'M', u'log'), - (0x33D3, 'M', u'lx'), - (0x33D4, 'M', u'mb'), - (0x33D5, 'M', u'mil'), - (0x33D6, 'M', u'mol'), - (0x33D7, 'M', u'ph'), - (0x33D8, 'X'), - (0x33D9, 'M', u'ppm'), - (0x33DA, 'M', u'pr'), - (0x33DB, 'M', u'sr'), - (0x33DC, 'M', u'sv'), - (0x33DD, 'M', u'wb'), - (0x33DE, 'M', u'v∕m'), - (0x33DF, 'M', u'a∕m'), - (0x33E0, 'M', u'1日'), - (0x33E1, 'M', u'2日'), - (0x33E2, 'M', u'3日'), - (0x33E3, 'M', u'4日'), - (0x33E4, 'M', u'5日'), - (0x33E5, 'M', u'6日'), - (0x33E6, 'M', u'7日'), - (0x33E7, 'M', u'8日'), - (0x33E8, 'M', u'9日'), - (0x33E9, 'M', u'10日'), - (0x33EA, 'M', u'11日'), - (0x33EB, 'M', u'12日'), - (0x33EC, 'M', u'13日'), - (0x33ED, 'M', u'14日'), - (0x33EE, 'M', u'15日'), - (0x33EF, 'M', u'16日'), - (0x33F0, 'M', u'17日'), - (0x33F1, 'M', u'18日'), - (0x33F2, 'M', u'19日'), - (0x33F3, 'M', u'20日'), - ] - -def _seg_35(): - return [ - (0x33F4, 'M', u'21日'), - (0x33F5, 'M', u'22日'), - (0x33F6, 'M', u'23日'), - (0x33F7, 'M', u'24日'), - (0x33F8, 'M', u'25日'), - (0x33F9, 'M', u'26日'), - (0x33FA, 'M', u'27日'), - (0x33FB, 'M', u'28日'), - (0x33FC, 'M', u'29日'), - (0x33FD, 'M', u'30日'), - (0x33FE, 'M', u'31日'), - (0x33FF, 'M', u'gal'), - (0x3400, 'V'), - (0x4DB6, 'X'), - (0x4DC0, 'V'), - (0x9FF0, 'X'), - (0xA000, 'V'), - (0xA48D, 'X'), - (0xA490, 'V'), - (0xA4C7, 'X'), - (0xA4D0, 'V'), - (0xA62C, 'X'), - (0xA640, 'M', u'ꙁ'), - (0xA641, 'V'), - (0xA642, 'M', u'ꙃ'), - (0xA643, 'V'), - (0xA644, 'M', u'ꙅ'), - (0xA645, 'V'), - (0xA646, 'M', u'ꙇ'), - (0xA647, 'V'), - (0xA648, 'M', u'ꙉ'), - (0xA649, 'V'), - (0xA64A, 'M', u'ꙋ'), - (0xA64B, 'V'), - (0xA64C, 'M', u'ꙍ'), - (0xA64D, 'V'), - (0xA64E, 'M', u'ꙏ'), - (0xA64F, 'V'), - (0xA650, 'M', u'ꙑ'), - (0xA651, 'V'), - (0xA652, 'M', u'ꙓ'), - (0xA653, 'V'), - (0xA654, 'M', u'ꙕ'), - (0xA655, 'V'), - (0xA656, 'M', u'ꙗ'), - (0xA657, 'V'), - (0xA658, 'M', u'ꙙ'), - (0xA659, 'V'), - (0xA65A, 'M', u'ꙛ'), - (0xA65B, 'V'), - (0xA65C, 'M', u'ꙝ'), - (0xA65D, 'V'), - (0xA65E, 'M', u'ꙟ'), - (0xA65F, 'V'), - (0xA660, 'M', u'ꙡ'), - (0xA661, 'V'), - (0xA662, 'M', u'ꙣ'), - (0xA663, 'V'), - (0xA664, 'M', u'ꙥ'), - (0xA665, 'V'), - (0xA666, 'M', u'ꙧ'), - (0xA667, 'V'), - (0xA668, 'M', u'ꙩ'), - (0xA669, 'V'), - (0xA66A, 'M', u'ꙫ'), - (0xA66B, 'V'), - (0xA66C, 'M', u'ꙭ'), - (0xA66D, 'V'), - (0xA680, 'M', u'ꚁ'), - (0xA681, 'V'), - (0xA682, 'M', u'ꚃ'), - (0xA683, 'V'), - (0xA684, 'M', u'ꚅ'), - (0xA685, 'V'), - (0xA686, 'M', u'ꚇ'), - (0xA687, 'V'), - (0xA688, 'M', u'ꚉ'), - (0xA689, 'V'), - (0xA68A, 'M', u'ꚋ'), - (0xA68B, 'V'), - (0xA68C, 'M', u'ꚍ'), - (0xA68D, 'V'), - (0xA68E, 'M', u'ꚏ'), - (0xA68F, 'V'), - (0xA690, 'M', u'ꚑ'), - (0xA691, 'V'), - (0xA692, 'M', u'ꚓ'), - (0xA693, 'V'), - (0xA694, 'M', u'ꚕ'), - (0xA695, 'V'), - (0xA696, 'M', u'ꚗ'), - (0xA697, 'V'), - (0xA698, 'M', u'ꚙ'), - (0xA699, 'V'), - (0xA69A, 'M', u'ꚛ'), - (0xA69B, 'V'), - (0xA69C, 'M', u'ъ'), - (0xA69D, 'M', u'ь'), - (0xA69E, 'V'), - (0xA6F8, 'X'), - ] - -def _seg_36(): - return [ - (0xA700, 'V'), - (0xA722, 'M', u'ꜣ'), - (0xA723, 'V'), - (0xA724, 'M', u'ꜥ'), - (0xA725, 'V'), - (0xA726, 'M', u'ꜧ'), - (0xA727, 'V'), - (0xA728, 'M', u'ꜩ'), - (0xA729, 'V'), - (0xA72A, 'M', u'ꜫ'), - (0xA72B, 'V'), - (0xA72C, 'M', u'ꜭ'), - (0xA72D, 'V'), - (0xA72E, 'M', u'ꜯ'), - (0xA72F, 'V'), - (0xA732, 'M', u'ꜳ'), - (0xA733, 'V'), - (0xA734, 'M', u'ꜵ'), - (0xA735, 'V'), - (0xA736, 'M', u'ꜷ'), - (0xA737, 'V'), - (0xA738, 'M', u'ꜹ'), - (0xA739, 'V'), - (0xA73A, 'M', u'ꜻ'), - (0xA73B, 'V'), - (0xA73C, 'M', u'ꜽ'), - (0xA73D, 'V'), - (0xA73E, 'M', u'ꜿ'), - (0xA73F, 'V'), - (0xA740, 'M', u'ꝁ'), - (0xA741, 'V'), - (0xA742, 'M', u'ꝃ'), - (0xA743, 'V'), - (0xA744, 'M', u'ꝅ'), - (0xA745, 'V'), - (0xA746, 'M', u'ꝇ'), - (0xA747, 'V'), - (0xA748, 'M', u'ꝉ'), - (0xA749, 'V'), - (0xA74A, 'M', u'ꝋ'), - (0xA74B, 'V'), - (0xA74C, 'M', u'ꝍ'), - (0xA74D, 'V'), - (0xA74E, 'M', u'ꝏ'), - (0xA74F, 'V'), - (0xA750, 'M', u'ꝑ'), - (0xA751, 'V'), - (0xA752, 'M', u'ꝓ'), - (0xA753, 'V'), - (0xA754, 'M', u'ꝕ'), - (0xA755, 'V'), - (0xA756, 'M', u'ꝗ'), - (0xA757, 'V'), - (0xA758, 'M', u'ꝙ'), - (0xA759, 'V'), - (0xA75A, 'M', u'ꝛ'), - (0xA75B, 'V'), - (0xA75C, 'M', u'ꝝ'), - (0xA75D, 'V'), - (0xA75E, 'M', u'ꝟ'), - (0xA75F, 'V'), - (0xA760, 'M', u'ꝡ'), - (0xA761, 'V'), - (0xA762, 'M', u'ꝣ'), - (0xA763, 'V'), - (0xA764, 'M', u'ꝥ'), - (0xA765, 'V'), - (0xA766, 'M', u'ꝧ'), - (0xA767, 'V'), - (0xA768, 'M', u'ꝩ'), - (0xA769, 'V'), - (0xA76A, 'M', u'ꝫ'), - (0xA76B, 'V'), - (0xA76C, 'M', u'ꝭ'), - (0xA76D, 'V'), - (0xA76E, 'M', u'ꝯ'), - (0xA76F, 'V'), - (0xA770, 'M', u'ꝯ'), - (0xA771, 'V'), - (0xA779, 'M', u'ꝺ'), - (0xA77A, 'V'), - (0xA77B, 'M', u'ꝼ'), - (0xA77C, 'V'), - (0xA77D, 'M', u'ᵹ'), - (0xA77E, 'M', u'ꝿ'), - (0xA77F, 'V'), - (0xA780, 'M', u'ꞁ'), - (0xA781, 'V'), - (0xA782, 'M', u'ꞃ'), - (0xA783, 'V'), - (0xA784, 'M', u'ꞅ'), - (0xA785, 'V'), - (0xA786, 'M', u'ꞇ'), - (0xA787, 'V'), - (0xA78B, 'M', u'ꞌ'), - (0xA78C, 'V'), - (0xA78D, 'M', u'ɥ'), - (0xA78E, 'V'), - (0xA790, 'M', u'ꞑ'), - (0xA791, 'V'), - ] - -def _seg_37(): - return [ - (0xA792, 'M', u'ꞓ'), - (0xA793, 'V'), - (0xA796, 'M', u'ꞗ'), - (0xA797, 'V'), - (0xA798, 'M', u'ꞙ'), - (0xA799, 'V'), - (0xA79A, 'M', u'ꞛ'), - (0xA79B, 'V'), - (0xA79C, 'M', u'ꞝ'), - (0xA79D, 'V'), - (0xA79E, 'M', u'ꞟ'), - (0xA79F, 'V'), - (0xA7A0, 'M', u'ꞡ'), - (0xA7A1, 'V'), - (0xA7A2, 'M', u'ꞣ'), - (0xA7A3, 'V'), - (0xA7A4, 'M', u'ꞥ'), - (0xA7A5, 'V'), - (0xA7A6, 'M', u'ꞧ'), - (0xA7A7, 'V'), - (0xA7A8, 'M', u'ꞩ'), - (0xA7A9, 'V'), - (0xA7AA, 'M', u'ɦ'), - (0xA7AB, 'M', u'ɜ'), - (0xA7AC, 'M', u'ɡ'), - (0xA7AD, 'M', u'ɬ'), - (0xA7AE, 'M', u'ɪ'), - (0xA7AF, 'V'), - (0xA7B0, 'M', u'ʞ'), - (0xA7B1, 'M', u'ʇ'), - (0xA7B2, 'M', u'ʝ'), - (0xA7B3, 'M', u'ꭓ'), - (0xA7B4, 'M', u'ꞵ'), - (0xA7B5, 'V'), - (0xA7B6, 'M', u'ꞷ'), - (0xA7B7, 'V'), - (0xA7B8, 'X'), - (0xA7B9, 'V'), - (0xA7BA, 'X'), - (0xA7F7, 'V'), - (0xA7F8, 'M', u'ħ'), - (0xA7F9, 'M', u'œ'), - (0xA7FA, 'V'), - (0xA82C, 'X'), - (0xA830, 'V'), - (0xA83A, 'X'), - (0xA840, 'V'), - (0xA878, 'X'), - (0xA880, 'V'), - (0xA8C6, 'X'), - (0xA8CE, 'V'), - (0xA8DA, 'X'), - (0xA8E0, 'V'), - (0xA954, 'X'), - (0xA95F, 'V'), - (0xA97D, 'X'), - (0xA980, 'V'), - (0xA9CE, 'X'), - (0xA9CF, 'V'), - (0xA9DA, 'X'), - (0xA9DE, 'V'), - (0xA9FF, 'X'), - (0xAA00, 'V'), - (0xAA37, 'X'), - (0xAA40, 'V'), - (0xAA4E, 'X'), - (0xAA50, 'V'), - (0xAA5A, 'X'), - (0xAA5C, 'V'), - (0xAAC3, 'X'), - (0xAADB, 'V'), - (0xAAF7, 'X'), - (0xAB01, 'V'), - (0xAB07, 'X'), - (0xAB09, 'V'), - (0xAB0F, 'X'), - (0xAB11, 'V'), - (0xAB17, 'X'), - (0xAB20, 'V'), - (0xAB27, 'X'), - (0xAB28, 'V'), - (0xAB2F, 'X'), - (0xAB30, 'V'), - (0xAB5C, 'M', u'ꜧ'), - (0xAB5D, 'M', u'ꬷ'), - (0xAB5E, 'M', u'ɫ'), - (0xAB5F, 'M', u'ꭒ'), - (0xAB60, 'V'), - (0xAB66, 'X'), - (0xAB70, 'M', u'Ꭰ'), - (0xAB71, 'M', u'Ꭱ'), - (0xAB72, 'M', u'Ꭲ'), - (0xAB73, 'M', u'Ꭳ'), - (0xAB74, 'M', u'Ꭴ'), - (0xAB75, 'M', u'Ꭵ'), - (0xAB76, 'M', u'Ꭶ'), - (0xAB77, 'M', u'Ꭷ'), - (0xAB78, 'M', u'Ꭸ'), - (0xAB79, 'M', u'Ꭹ'), - (0xAB7A, 'M', u'Ꭺ'), - ] - -def _seg_38(): - return [ - (0xAB7B, 'M', u'Ꭻ'), - (0xAB7C, 'M', u'Ꭼ'), - (0xAB7D, 'M', u'Ꭽ'), - (0xAB7E, 'M', u'Ꭾ'), - (0xAB7F, 'M', u'Ꭿ'), - (0xAB80, 'M', u'Ꮀ'), - (0xAB81, 'M', u'Ꮁ'), - (0xAB82, 'M', u'Ꮂ'), - (0xAB83, 'M', u'Ꮃ'), - (0xAB84, 'M', u'Ꮄ'), - (0xAB85, 'M', u'Ꮅ'), - (0xAB86, 'M', u'Ꮆ'), - (0xAB87, 'M', u'Ꮇ'), - (0xAB88, 'M', u'Ꮈ'), - (0xAB89, 'M', u'Ꮉ'), - (0xAB8A, 'M', u'Ꮊ'), - (0xAB8B, 'M', u'Ꮋ'), - (0xAB8C, 'M', u'Ꮌ'), - (0xAB8D, 'M', u'Ꮍ'), - (0xAB8E, 'M', u'Ꮎ'), - (0xAB8F, 'M', u'Ꮏ'), - (0xAB90, 'M', u'Ꮐ'), - (0xAB91, 'M', u'Ꮑ'), - (0xAB92, 'M', u'Ꮒ'), - (0xAB93, 'M', u'Ꮓ'), - (0xAB94, 'M', u'Ꮔ'), - (0xAB95, 'M', u'Ꮕ'), - (0xAB96, 'M', u'Ꮖ'), - (0xAB97, 'M', u'Ꮗ'), - (0xAB98, 'M', u'Ꮘ'), - (0xAB99, 'M', u'Ꮙ'), - (0xAB9A, 'M', u'Ꮚ'), - (0xAB9B, 'M', u'Ꮛ'), - (0xAB9C, 'M', u'Ꮜ'), - (0xAB9D, 'M', u'Ꮝ'), - (0xAB9E, 'M', u'Ꮞ'), - (0xAB9F, 'M', u'Ꮟ'), - (0xABA0, 'M', u'Ꮠ'), - (0xABA1, 'M', u'Ꮡ'), - (0xABA2, 'M', u'Ꮢ'), - (0xABA3, 'M', u'Ꮣ'), - (0xABA4, 'M', u'Ꮤ'), - (0xABA5, 'M', u'Ꮥ'), - (0xABA6, 'M', u'Ꮦ'), - (0xABA7, 'M', u'Ꮧ'), - (0xABA8, 'M', u'Ꮨ'), - (0xABA9, 'M', u'Ꮩ'), - (0xABAA, 'M', u'Ꮪ'), - (0xABAB, 'M', u'Ꮫ'), - (0xABAC, 'M', u'Ꮬ'), - (0xABAD, 'M', u'Ꮭ'), - (0xABAE, 'M', u'Ꮮ'), - (0xABAF, 'M', u'Ꮯ'), - (0xABB0, 'M', u'Ꮰ'), - (0xABB1, 'M', u'Ꮱ'), - (0xABB2, 'M', u'Ꮲ'), - (0xABB3, 'M', u'Ꮳ'), - (0xABB4, 'M', u'Ꮴ'), - (0xABB5, 'M', u'Ꮵ'), - (0xABB6, 'M', u'Ꮶ'), - (0xABB7, 'M', u'Ꮷ'), - (0xABB8, 'M', u'Ꮸ'), - (0xABB9, 'M', u'Ꮹ'), - (0xABBA, 'M', u'Ꮺ'), - (0xABBB, 'M', u'Ꮻ'), - (0xABBC, 'M', u'Ꮼ'), - (0xABBD, 'M', u'Ꮽ'), - (0xABBE, 'M', u'Ꮾ'), - (0xABBF, 'M', u'Ꮿ'), - (0xABC0, 'V'), - (0xABEE, 'X'), - (0xABF0, 'V'), - (0xABFA, 'X'), - (0xAC00, 'V'), - (0xD7A4, 'X'), - (0xD7B0, 'V'), - (0xD7C7, 'X'), - (0xD7CB, 'V'), - (0xD7FC, 'X'), - (0xF900, 'M', u'豈'), - (0xF901, 'M', u'更'), - (0xF902, 'M', u'車'), - (0xF903, 'M', u'賈'), - (0xF904, 'M', u'滑'), - (0xF905, 'M', u'串'), - (0xF906, 'M', u'句'), - (0xF907, 'M', u'龜'), - (0xF909, 'M', u'契'), - (0xF90A, 'M', u'金'), - (0xF90B, 'M', u'喇'), - (0xF90C, 'M', u'奈'), - (0xF90D, 'M', u'懶'), - (0xF90E, 'M', u'癩'), - (0xF90F, 'M', u'羅'), - (0xF910, 'M', u'蘿'), - (0xF911, 'M', u'螺'), - (0xF912, 'M', u'裸'), - (0xF913, 'M', u'邏'), - (0xF914, 'M', u'樂'), - (0xF915, 'M', u'洛'), - ] - -def _seg_39(): - return [ - (0xF916, 'M', u'烙'), - (0xF917, 'M', u'珞'), - (0xF918, 'M', u'落'), - (0xF919, 'M', u'酪'), - (0xF91A, 'M', u'駱'), - (0xF91B, 'M', u'亂'), - (0xF91C, 'M', u'卵'), - (0xF91D, 'M', u'欄'), - (0xF91E, 'M', u'爛'), - (0xF91F, 'M', u'蘭'), - (0xF920, 'M', u'鸞'), - (0xF921, 'M', u'嵐'), - (0xF922, 'M', u'濫'), - (0xF923, 'M', u'藍'), - (0xF924, 'M', u'襤'), - (0xF925, 'M', u'拉'), - (0xF926, 'M', u'臘'), - (0xF927, 'M', u'蠟'), - (0xF928, 'M', u'廊'), - (0xF929, 'M', u'朗'), - (0xF92A, 'M', u'浪'), - (0xF92B, 'M', u'狼'), - (0xF92C, 'M', u'郎'), - (0xF92D, 'M', u'來'), - (0xF92E, 'M', u'冷'), - (0xF92F, 'M', u'勞'), - (0xF930, 'M', u'擄'), - (0xF931, 'M', u'櫓'), - (0xF932, 'M', u'爐'), - (0xF933, 'M', u'盧'), - (0xF934, 'M', u'老'), - (0xF935, 'M', u'蘆'), - (0xF936, 'M', u'虜'), - (0xF937, 'M', u'路'), - (0xF938, 'M', u'露'), - (0xF939, 'M', u'魯'), - (0xF93A, 'M', u'鷺'), - (0xF93B, 'M', u'碌'), - (0xF93C, 'M', u'祿'), - (0xF93D, 'M', u'綠'), - (0xF93E, 'M', u'菉'), - (0xF93F, 'M', u'錄'), - (0xF940, 'M', u'鹿'), - (0xF941, 'M', u'論'), - (0xF942, 'M', u'壟'), - (0xF943, 'M', u'弄'), - (0xF944, 'M', u'籠'), - (0xF945, 'M', u'聾'), - (0xF946, 'M', u'牢'), - (0xF947, 'M', u'磊'), - (0xF948, 'M', u'賂'), - (0xF949, 'M', u'雷'), - (0xF94A, 'M', u'壘'), - (0xF94B, 'M', u'屢'), - (0xF94C, 'M', u'樓'), - (0xF94D, 'M', u'淚'), - (0xF94E, 'M', u'漏'), - (0xF94F, 'M', u'累'), - (0xF950, 'M', u'縷'), - (0xF951, 'M', u'陋'), - (0xF952, 'M', u'勒'), - (0xF953, 'M', u'肋'), - (0xF954, 'M', u'凜'), - (0xF955, 'M', u'凌'), - (0xF956, 'M', u'稜'), - (0xF957, 'M', u'綾'), - (0xF958, 'M', u'菱'), - (0xF959, 'M', u'陵'), - (0xF95A, 'M', u'讀'), - (0xF95B, 'M', u'拏'), - (0xF95C, 'M', u'樂'), - (0xF95D, 'M', u'諾'), - (0xF95E, 'M', u'丹'), - (0xF95F, 'M', u'寧'), - (0xF960, 'M', u'怒'), - (0xF961, 'M', u'率'), - (0xF962, 'M', u'異'), - (0xF963, 'M', u'北'), - (0xF964, 'M', u'磻'), - (0xF965, 'M', u'便'), - (0xF966, 'M', u'復'), - (0xF967, 'M', u'不'), - (0xF968, 'M', u'泌'), - (0xF969, 'M', u'數'), - (0xF96A, 'M', u'索'), - (0xF96B, 'M', u'參'), - (0xF96C, 'M', u'塞'), - (0xF96D, 'M', u'省'), - (0xF96E, 'M', u'葉'), - (0xF96F, 'M', u'說'), - (0xF970, 'M', u'殺'), - (0xF971, 'M', u'辰'), - (0xF972, 'M', u'沈'), - (0xF973, 'M', u'拾'), - (0xF974, 'M', u'若'), - (0xF975, 'M', u'掠'), - (0xF976, 'M', u'略'), - (0xF977, 'M', u'亮'), - (0xF978, 'M', u'兩'), - (0xF979, 'M', u'凉'), - ] - -def _seg_40(): - return [ - (0xF97A, 'M', u'梁'), - (0xF97B, 'M', u'糧'), - (0xF97C, 'M', u'良'), - (0xF97D, 'M', u'諒'), - (0xF97E, 'M', u'量'), - (0xF97F, 'M', u'勵'), - (0xF980, 'M', u'呂'), - (0xF981, 'M', u'女'), - (0xF982, 'M', u'廬'), - (0xF983, 'M', u'旅'), - (0xF984, 'M', u'濾'), - (0xF985, 'M', u'礪'), - (0xF986, 'M', u'閭'), - (0xF987, 'M', u'驪'), - (0xF988, 'M', u'麗'), - (0xF989, 'M', u'黎'), - (0xF98A, 'M', u'力'), - (0xF98B, 'M', u'曆'), - (0xF98C, 'M', u'歷'), - (0xF98D, 'M', u'轢'), - (0xF98E, 'M', u'年'), - (0xF98F, 'M', u'憐'), - (0xF990, 'M', u'戀'), - (0xF991, 'M', u'撚'), - (0xF992, 'M', u'漣'), - (0xF993, 'M', u'煉'), - (0xF994, 'M', u'璉'), - (0xF995, 'M', u'秊'), - (0xF996, 'M', u'練'), - (0xF997, 'M', u'聯'), - (0xF998, 'M', u'輦'), - (0xF999, 'M', u'蓮'), - (0xF99A, 'M', u'連'), - (0xF99B, 'M', u'鍊'), - (0xF99C, 'M', u'列'), - (0xF99D, 'M', u'劣'), - (0xF99E, 'M', u'咽'), - (0xF99F, 'M', u'烈'), - (0xF9A0, 'M', u'裂'), - (0xF9A1, 'M', u'說'), - (0xF9A2, 'M', u'廉'), - (0xF9A3, 'M', u'念'), - (0xF9A4, 'M', u'捻'), - (0xF9A5, 'M', u'殮'), - (0xF9A6, 'M', u'簾'), - (0xF9A7, 'M', u'獵'), - (0xF9A8, 'M', u'令'), - (0xF9A9, 'M', u'囹'), - (0xF9AA, 'M', u'寧'), - (0xF9AB, 'M', u'嶺'), - (0xF9AC, 'M', u'怜'), - (0xF9AD, 'M', u'玲'), - (0xF9AE, 'M', u'瑩'), - (0xF9AF, 'M', u'羚'), - (0xF9B0, 'M', u'聆'), - (0xF9B1, 'M', u'鈴'), - (0xF9B2, 'M', u'零'), - (0xF9B3, 'M', u'靈'), - (0xF9B4, 'M', u'領'), - (0xF9B5, 'M', u'例'), - (0xF9B6, 'M', u'禮'), - (0xF9B7, 'M', u'醴'), - (0xF9B8, 'M', u'隸'), - (0xF9B9, 'M', u'惡'), - (0xF9BA, 'M', u'了'), - (0xF9BB, 'M', u'僚'), - (0xF9BC, 'M', u'寮'), - (0xF9BD, 'M', u'尿'), - (0xF9BE, 'M', u'料'), - (0xF9BF, 'M', u'樂'), - (0xF9C0, 'M', u'燎'), - (0xF9C1, 'M', u'療'), - (0xF9C2, 'M', u'蓼'), - (0xF9C3, 'M', u'遼'), - (0xF9C4, 'M', u'龍'), - (0xF9C5, 'M', u'暈'), - (0xF9C6, 'M', u'阮'), - (0xF9C7, 'M', u'劉'), - (0xF9C8, 'M', u'杻'), - (0xF9C9, 'M', u'柳'), - (0xF9CA, 'M', u'流'), - (0xF9CB, 'M', u'溜'), - (0xF9CC, 'M', u'琉'), - (0xF9CD, 'M', u'留'), - (0xF9CE, 'M', u'硫'), - (0xF9CF, 'M', u'紐'), - (0xF9D0, 'M', u'類'), - (0xF9D1, 'M', u'六'), - (0xF9D2, 'M', u'戮'), - (0xF9D3, 'M', u'陸'), - (0xF9D4, 'M', u'倫'), - (0xF9D5, 'M', u'崙'), - (0xF9D6, 'M', u'淪'), - (0xF9D7, 'M', u'輪'), - (0xF9D8, 'M', u'律'), - (0xF9D9, 'M', u'慄'), - (0xF9DA, 'M', u'栗'), - (0xF9DB, 'M', u'率'), - (0xF9DC, 'M', u'隆'), - (0xF9DD, 'M', u'利'), - ] - -def _seg_41(): - return [ - (0xF9DE, 'M', u'吏'), - (0xF9DF, 'M', u'履'), - (0xF9E0, 'M', u'易'), - (0xF9E1, 'M', u'李'), - (0xF9E2, 'M', u'梨'), - (0xF9E3, 'M', u'泥'), - (0xF9E4, 'M', u'理'), - (0xF9E5, 'M', u'痢'), - (0xF9E6, 'M', u'罹'), - (0xF9E7, 'M', u'裏'), - (0xF9E8, 'M', u'裡'), - (0xF9E9, 'M', u'里'), - (0xF9EA, 'M', u'離'), - (0xF9EB, 'M', u'匿'), - (0xF9EC, 'M', u'溺'), - (0xF9ED, 'M', u'吝'), - (0xF9EE, 'M', u'燐'), - (0xF9EF, 'M', u'璘'), - (0xF9F0, 'M', u'藺'), - (0xF9F1, 'M', u'隣'), - (0xF9F2, 'M', u'鱗'), - (0xF9F3, 'M', u'麟'), - (0xF9F4, 'M', u'林'), - (0xF9F5, 'M', u'淋'), - (0xF9F6, 'M', u'臨'), - (0xF9F7, 'M', u'立'), - (0xF9F8, 'M', u'笠'), - (0xF9F9, 'M', u'粒'), - (0xF9FA, 'M', u'狀'), - (0xF9FB, 'M', u'炙'), - (0xF9FC, 'M', u'識'), - (0xF9FD, 'M', u'什'), - (0xF9FE, 'M', u'茶'), - (0xF9FF, 'M', u'刺'), - (0xFA00, 'M', u'切'), - (0xFA01, 'M', u'度'), - (0xFA02, 'M', u'拓'), - (0xFA03, 'M', u'糖'), - (0xFA04, 'M', u'宅'), - (0xFA05, 'M', u'洞'), - (0xFA06, 'M', u'暴'), - (0xFA07, 'M', u'輻'), - (0xFA08, 'M', u'行'), - (0xFA09, 'M', u'降'), - (0xFA0A, 'M', u'見'), - (0xFA0B, 'M', u'廓'), - (0xFA0C, 'M', u'兀'), - (0xFA0D, 'M', u'嗀'), - (0xFA0E, 'V'), - (0xFA10, 'M', u'塚'), - (0xFA11, 'V'), - (0xFA12, 'M', u'晴'), - (0xFA13, 'V'), - (0xFA15, 'M', u'凞'), - (0xFA16, 'M', u'猪'), - (0xFA17, 'M', u'益'), - (0xFA18, 'M', u'礼'), - (0xFA19, 'M', u'神'), - (0xFA1A, 'M', u'祥'), - (0xFA1B, 'M', u'福'), - (0xFA1C, 'M', u'靖'), - (0xFA1D, 'M', u'精'), - (0xFA1E, 'M', u'羽'), - (0xFA1F, 'V'), - (0xFA20, 'M', u'蘒'), - (0xFA21, 'V'), - (0xFA22, 'M', u'諸'), - (0xFA23, 'V'), - (0xFA25, 'M', u'逸'), - (0xFA26, 'M', u'都'), - (0xFA27, 'V'), - (0xFA2A, 'M', u'飯'), - (0xFA2B, 'M', u'飼'), - (0xFA2C, 'M', u'館'), - (0xFA2D, 'M', u'鶴'), - (0xFA2E, 'M', u'郞'), - (0xFA2F, 'M', u'隷'), - (0xFA30, 'M', u'侮'), - (0xFA31, 'M', u'僧'), - (0xFA32, 'M', u'免'), - (0xFA33, 'M', u'勉'), - (0xFA34, 'M', u'勤'), - (0xFA35, 'M', u'卑'), - (0xFA36, 'M', u'喝'), - (0xFA37, 'M', u'嘆'), - (0xFA38, 'M', u'器'), - (0xFA39, 'M', u'塀'), - (0xFA3A, 'M', u'墨'), - (0xFA3B, 'M', u'層'), - (0xFA3C, 'M', u'屮'), - (0xFA3D, 'M', u'悔'), - (0xFA3E, 'M', u'慨'), - (0xFA3F, 'M', u'憎'), - (0xFA40, 'M', u'懲'), - (0xFA41, 'M', u'敏'), - (0xFA42, 'M', u'既'), - (0xFA43, 'M', u'暑'), - (0xFA44, 'M', u'梅'), - (0xFA45, 'M', u'海'), - (0xFA46, 'M', u'渚'), - ] - -def _seg_42(): - return [ - (0xFA47, 'M', u'漢'), - (0xFA48, 'M', u'煮'), - (0xFA49, 'M', u'爫'), - (0xFA4A, 'M', u'琢'), - (0xFA4B, 'M', u'碑'), - (0xFA4C, 'M', u'社'), - (0xFA4D, 'M', u'祉'), - (0xFA4E, 'M', u'祈'), - (0xFA4F, 'M', u'祐'), - (0xFA50, 'M', u'祖'), - (0xFA51, 'M', u'祝'), - (0xFA52, 'M', u'禍'), - (0xFA53, 'M', u'禎'), - (0xFA54, 'M', u'穀'), - (0xFA55, 'M', u'突'), - (0xFA56, 'M', u'節'), - (0xFA57, 'M', u'練'), - (0xFA58, 'M', u'縉'), - (0xFA59, 'M', u'繁'), - (0xFA5A, 'M', u'署'), - (0xFA5B, 'M', u'者'), - (0xFA5C, 'M', u'臭'), - (0xFA5D, 'M', u'艹'), - (0xFA5F, 'M', u'著'), - (0xFA60, 'M', u'褐'), - (0xFA61, 'M', u'視'), - (0xFA62, 'M', u'謁'), - (0xFA63, 'M', u'謹'), - (0xFA64, 'M', u'賓'), - (0xFA65, 'M', u'贈'), - (0xFA66, 'M', u'辶'), - (0xFA67, 'M', u'逸'), - (0xFA68, 'M', u'難'), - (0xFA69, 'M', u'響'), - (0xFA6A, 'M', u'頻'), - (0xFA6B, 'M', u'恵'), - (0xFA6C, 'M', u'𤋮'), - (0xFA6D, 'M', u'舘'), - (0xFA6E, 'X'), - (0xFA70, 'M', u'並'), - (0xFA71, 'M', u'况'), - (0xFA72, 'M', u'全'), - (0xFA73, 'M', u'侀'), - (0xFA74, 'M', u'充'), - (0xFA75, 'M', u'冀'), - (0xFA76, 'M', u'勇'), - (0xFA77, 'M', u'勺'), - (0xFA78, 'M', u'喝'), - (0xFA79, 'M', u'啕'), - (0xFA7A, 'M', u'喙'), - (0xFA7B, 'M', u'嗢'), - (0xFA7C, 'M', u'塚'), - (0xFA7D, 'M', u'墳'), - (0xFA7E, 'M', u'奄'), - (0xFA7F, 'M', u'奔'), - (0xFA80, 'M', u'婢'), - (0xFA81, 'M', u'嬨'), - (0xFA82, 'M', u'廒'), - (0xFA83, 'M', u'廙'), - (0xFA84, 'M', u'彩'), - (0xFA85, 'M', u'徭'), - (0xFA86, 'M', u'惘'), - (0xFA87, 'M', u'慎'), - (0xFA88, 'M', u'愈'), - (0xFA89, 'M', u'憎'), - (0xFA8A, 'M', u'慠'), - (0xFA8B, 'M', u'懲'), - (0xFA8C, 'M', u'戴'), - (0xFA8D, 'M', u'揄'), - (0xFA8E, 'M', u'搜'), - (0xFA8F, 'M', u'摒'), - (0xFA90, 'M', u'敖'), - (0xFA91, 'M', u'晴'), - (0xFA92, 'M', u'朗'), - (0xFA93, 'M', u'望'), - (0xFA94, 'M', u'杖'), - (0xFA95, 'M', u'歹'), - (0xFA96, 'M', u'殺'), - (0xFA97, 'M', u'流'), - (0xFA98, 'M', u'滛'), - (0xFA99, 'M', u'滋'), - (0xFA9A, 'M', u'漢'), - (0xFA9B, 'M', u'瀞'), - (0xFA9C, 'M', u'煮'), - (0xFA9D, 'M', u'瞧'), - (0xFA9E, 'M', u'爵'), - (0xFA9F, 'M', u'犯'), - (0xFAA0, 'M', u'猪'), - (0xFAA1, 'M', u'瑱'), - (0xFAA2, 'M', u'甆'), - (0xFAA3, 'M', u'画'), - (0xFAA4, 'M', u'瘝'), - (0xFAA5, 'M', u'瘟'), - (0xFAA6, 'M', u'益'), - (0xFAA7, 'M', u'盛'), - (0xFAA8, 'M', u'直'), - (0xFAA9, 'M', u'睊'), - (0xFAAA, 'M', u'着'), - (0xFAAB, 'M', u'磌'), - (0xFAAC, 'M', u'窱'), - ] - -def _seg_43(): - return [ - (0xFAAD, 'M', u'節'), - (0xFAAE, 'M', u'类'), - (0xFAAF, 'M', u'絛'), - (0xFAB0, 'M', u'練'), - (0xFAB1, 'M', u'缾'), - (0xFAB2, 'M', u'者'), - (0xFAB3, 'M', u'荒'), - (0xFAB4, 'M', u'華'), - (0xFAB5, 'M', u'蝹'), - (0xFAB6, 'M', u'襁'), - (0xFAB7, 'M', u'覆'), - (0xFAB8, 'M', u'視'), - (0xFAB9, 'M', u'調'), - (0xFABA, 'M', u'諸'), - (0xFABB, 'M', u'請'), - (0xFABC, 'M', u'謁'), - (0xFABD, 'M', u'諾'), - (0xFABE, 'M', u'諭'), - (0xFABF, 'M', u'謹'), - (0xFAC0, 'M', u'變'), - (0xFAC1, 'M', u'贈'), - (0xFAC2, 'M', u'輸'), - (0xFAC3, 'M', u'遲'), - (0xFAC4, 'M', u'醙'), - (0xFAC5, 'M', u'鉶'), - (0xFAC6, 'M', u'陼'), - (0xFAC7, 'M', u'難'), - (0xFAC8, 'M', u'靖'), - (0xFAC9, 'M', u'韛'), - (0xFACA, 'M', u'響'), - (0xFACB, 'M', u'頋'), - (0xFACC, 'M', u'頻'), - (0xFACD, 'M', u'鬒'), - (0xFACE, 'M', u'龜'), - (0xFACF, 'M', u'𢡊'), - (0xFAD0, 'M', u'𢡄'), - (0xFAD1, 'M', u'𣏕'), - (0xFAD2, 'M', u'㮝'), - (0xFAD3, 'M', u'䀘'), - (0xFAD4, 'M', u'䀹'), - (0xFAD5, 'M', u'𥉉'), - (0xFAD6, 'M', u'𥳐'), - (0xFAD7, 'M', u'𧻓'), - (0xFAD8, 'M', u'齃'), - (0xFAD9, 'M', u'龎'), - (0xFADA, 'X'), - (0xFB00, 'M', u'ff'), - (0xFB01, 'M', u'fi'), - (0xFB02, 'M', u'fl'), - (0xFB03, 'M', u'ffi'), - (0xFB04, 'M', u'ffl'), - (0xFB05, 'M', u'st'), - (0xFB07, 'X'), - (0xFB13, 'M', u'մն'), - (0xFB14, 'M', u'մե'), - (0xFB15, 'M', u'մի'), - (0xFB16, 'M', u'վն'), - (0xFB17, 'M', u'մխ'), - (0xFB18, 'X'), - (0xFB1D, 'M', u'יִ'), - (0xFB1E, 'V'), - (0xFB1F, 'M', u'ײַ'), - (0xFB20, 'M', u'ע'), - (0xFB21, 'M', u'א'), - (0xFB22, 'M', u'ד'), - (0xFB23, 'M', u'ה'), - (0xFB24, 'M', u'כ'), - (0xFB25, 'M', u'ל'), - (0xFB26, 'M', u'ם'), - (0xFB27, 'M', u'ר'), - (0xFB28, 'M', u'ת'), - (0xFB29, '3', u'+'), - (0xFB2A, 'M', u'שׁ'), - (0xFB2B, 'M', u'שׂ'), - (0xFB2C, 'M', u'שּׁ'), - (0xFB2D, 'M', u'שּׂ'), - (0xFB2E, 'M', u'אַ'), - (0xFB2F, 'M', u'אָ'), - (0xFB30, 'M', u'אּ'), - (0xFB31, 'M', u'בּ'), - (0xFB32, 'M', u'גּ'), - (0xFB33, 'M', u'דּ'), - (0xFB34, 'M', u'הּ'), - (0xFB35, 'M', u'וּ'), - (0xFB36, 'M', u'זּ'), - (0xFB37, 'X'), - (0xFB38, 'M', u'טּ'), - (0xFB39, 'M', u'יּ'), - (0xFB3A, 'M', u'ךּ'), - (0xFB3B, 'M', u'כּ'), - (0xFB3C, 'M', u'לּ'), - (0xFB3D, 'X'), - (0xFB3E, 'M', u'מּ'), - (0xFB3F, 'X'), - (0xFB40, 'M', u'נּ'), - (0xFB41, 'M', u'סּ'), - (0xFB42, 'X'), - (0xFB43, 'M', u'ףּ'), - (0xFB44, 'M', u'פּ'), - (0xFB45, 'X'), - ] - -def _seg_44(): - return [ - (0xFB46, 'M', u'צּ'), - (0xFB47, 'M', u'קּ'), - (0xFB48, 'M', u'רּ'), - (0xFB49, 'M', u'שּ'), - (0xFB4A, 'M', u'תּ'), - (0xFB4B, 'M', u'וֹ'), - (0xFB4C, 'M', u'בֿ'), - (0xFB4D, 'M', u'כֿ'), - (0xFB4E, 'M', u'פֿ'), - (0xFB4F, 'M', u'אל'), - (0xFB50, 'M', u'ٱ'), - (0xFB52, 'M', u'ٻ'), - (0xFB56, 'M', u'پ'), - (0xFB5A, 'M', u'ڀ'), - (0xFB5E, 'M', u'ٺ'), - (0xFB62, 'M', u'ٿ'), - (0xFB66, 'M', u'ٹ'), - (0xFB6A, 'M', u'ڤ'), - (0xFB6E, 'M', u'ڦ'), - (0xFB72, 'M', u'ڄ'), - (0xFB76, 'M', u'ڃ'), - (0xFB7A, 'M', u'چ'), - (0xFB7E, 'M', u'ڇ'), - (0xFB82, 'M', u'ڍ'), - (0xFB84, 'M', u'ڌ'), - (0xFB86, 'M', u'ڎ'), - (0xFB88, 'M', u'ڈ'), - (0xFB8A, 'M', u'ژ'), - (0xFB8C, 'M', u'ڑ'), - (0xFB8E, 'M', u'ک'), - (0xFB92, 'M', u'گ'), - (0xFB96, 'M', u'ڳ'), - (0xFB9A, 'M', u'ڱ'), - (0xFB9E, 'M', u'ں'), - (0xFBA0, 'M', u'ڻ'), - (0xFBA4, 'M', u'ۀ'), - (0xFBA6, 'M', u'ہ'), - (0xFBAA, 'M', u'ھ'), - (0xFBAE, 'M', u'ے'), - (0xFBB0, 'M', u'ۓ'), - (0xFBB2, 'V'), - (0xFBC2, 'X'), - (0xFBD3, 'M', u'ڭ'), - (0xFBD7, 'M', u'ۇ'), - (0xFBD9, 'M', u'ۆ'), - (0xFBDB, 'M', u'ۈ'), - (0xFBDD, 'M', u'ۇٴ'), - (0xFBDE, 'M', u'ۋ'), - (0xFBE0, 'M', u'ۅ'), - (0xFBE2, 'M', u'ۉ'), - (0xFBE4, 'M', u'ې'), - (0xFBE8, 'M', u'ى'), - (0xFBEA, 'M', u'ئا'), - (0xFBEC, 'M', u'ئە'), - (0xFBEE, 'M', u'ئو'), - (0xFBF0, 'M', u'ئۇ'), - (0xFBF2, 'M', u'ئۆ'), - (0xFBF4, 'M', u'ئۈ'), - (0xFBF6, 'M', u'ئې'), - (0xFBF9, 'M', u'ئى'), - (0xFBFC, 'M', u'ی'), - (0xFC00, 'M', u'ئج'), - (0xFC01, 'M', u'ئح'), - (0xFC02, 'M', u'ئم'), - (0xFC03, 'M', u'ئى'), - (0xFC04, 'M', u'ئي'), - (0xFC05, 'M', u'بج'), - (0xFC06, 'M', u'بح'), - (0xFC07, 'M', u'بخ'), - (0xFC08, 'M', u'بم'), - (0xFC09, 'M', u'بى'), - (0xFC0A, 'M', u'بي'), - (0xFC0B, 'M', u'تج'), - (0xFC0C, 'M', u'تح'), - (0xFC0D, 'M', u'تخ'), - (0xFC0E, 'M', u'تم'), - (0xFC0F, 'M', u'تى'), - (0xFC10, 'M', u'تي'), - (0xFC11, 'M', u'ثج'), - (0xFC12, 'M', u'ثم'), - (0xFC13, 'M', u'ثى'), - (0xFC14, 'M', u'ثي'), - (0xFC15, 'M', u'جح'), - (0xFC16, 'M', u'جم'), - (0xFC17, 'M', u'حج'), - (0xFC18, 'M', u'حم'), - (0xFC19, 'M', u'خج'), - (0xFC1A, 'M', u'خح'), - (0xFC1B, 'M', u'خم'), - (0xFC1C, 'M', u'سج'), - (0xFC1D, 'M', u'سح'), - (0xFC1E, 'M', u'سخ'), - (0xFC1F, 'M', u'سم'), - (0xFC20, 'M', u'صح'), - (0xFC21, 'M', u'صم'), - (0xFC22, 'M', u'ضج'), - (0xFC23, 'M', u'ضح'), - (0xFC24, 'M', u'ضخ'), - (0xFC25, 'M', u'ضم'), - (0xFC26, 'M', u'طح'), - ] - -def _seg_45(): - return [ - (0xFC27, 'M', u'طم'), - (0xFC28, 'M', u'ظم'), - (0xFC29, 'M', u'عج'), - (0xFC2A, 'M', u'عم'), - (0xFC2B, 'M', u'غج'), - (0xFC2C, 'M', u'غم'), - (0xFC2D, 'M', u'فج'), - (0xFC2E, 'M', u'فح'), - (0xFC2F, 'M', u'فخ'), - (0xFC30, 'M', u'فم'), - (0xFC31, 'M', u'فى'), - (0xFC32, 'M', u'في'), - (0xFC33, 'M', u'قح'), - (0xFC34, 'M', u'قم'), - (0xFC35, 'M', u'قى'), - (0xFC36, 'M', u'قي'), - (0xFC37, 'M', u'كا'), - (0xFC38, 'M', u'كج'), - (0xFC39, 'M', u'كح'), - (0xFC3A, 'M', u'كخ'), - (0xFC3B, 'M', u'كل'), - (0xFC3C, 'M', u'كم'), - (0xFC3D, 'M', u'كى'), - (0xFC3E, 'M', u'كي'), - (0xFC3F, 'M', u'لج'), - (0xFC40, 'M', u'لح'), - (0xFC41, 'M', u'لخ'), - (0xFC42, 'M', u'لم'), - (0xFC43, 'M', u'لى'), - (0xFC44, 'M', u'لي'), - (0xFC45, 'M', u'مج'), - (0xFC46, 'M', u'مح'), - (0xFC47, 'M', u'مخ'), - (0xFC48, 'M', u'مم'), - (0xFC49, 'M', u'مى'), - (0xFC4A, 'M', u'مي'), - (0xFC4B, 'M', u'نج'), - (0xFC4C, 'M', u'نح'), - (0xFC4D, 'M', u'نخ'), - (0xFC4E, 'M', u'نم'), - (0xFC4F, 'M', u'نى'), - (0xFC50, 'M', u'ني'), - (0xFC51, 'M', u'هج'), - (0xFC52, 'M', u'هم'), - (0xFC53, 'M', u'هى'), - (0xFC54, 'M', u'هي'), - (0xFC55, 'M', u'يج'), - (0xFC56, 'M', u'يح'), - (0xFC57, 'M', u'يخ'), - (0xFC58, 'M', u'يم'), - (0xFC59, 'M', u'يى'), - (0xFC5A, 'M', u'يي'), - (0xFC5B, 'M', u'ذٰ'), - (0xFC5C, 'M', u'رٰ'), - (0xFC5D, 'M', u'ىٰ'), - (0xFC5E, '3', u' ٌّ'), - (0xFC5F, '3', u' ٍّ'), - (0xFC60, '3', u' َّ'), - (0xFC61, '3', u' ُّ'), - (0xFC62, '3', u' ِّ'), - (0xFC63, '3', u' ّٰ'), - (0xFC64, 'M', u'ئر'), - (0xFC65, 'M', u'ئز'), - (0xFC66, 'M', u'ئم'), - (0xFC67, 'M', u'ئن'), - (0xFC68, 'M', u'ئى'), - (0xFC69, 'M', u'ئي'), - (0xFC6A, 'M', u'بر'), - (0xFC6B, 'M', u'بز'), - (0xFC6C, 'M', u'بم'), - (0xFC6D, 'M', u'بن'), - (0xFC6E, 'M', u'بى'), - (0xFC6F, 'M', u'بي'), - (0xFC70, 'M', u'تر'), - (0xFC71, 'M', u'تز'), - (0xFC72, 'M', u'تم'), - (0xFC73, 'M', u'تن'), - (0xFC74, 'M', u'تى'), - (0xFC75, 'M', u'تي'), - (0xFC76, 'M', u'ثر'), - (0xFC77, 'M', u'ثز'), - (0xFC78, 'M', u'ثم'), - (0xFC79, 'M', u'ثن'), - (0xFC7A, 'M', u'ثى'), - (0xFC7B, 'M', u'ثي'), - (0xFC7C, 'M', u'فى'), - (0xFC7D, 'M', u'في'), - (0xFC7E, 'M', u'قى'), - (0xFC7F, 'M', u'قي'), - (0xFC80, 'M', u'كا'), - (0xFC81, 'M', u'كل'), - (0xFC82, 'M', u'كم'), - (0xFC83, 'M', u'كى'), - (0xFC84, 'M', u'كي'), - (0xFC85, 'M', u'لم'), - (0xFC86, 'M', u'لى'), - (0xFC87, 'M', u'لي'), - (0xFC88, 'M', u'ما'), - (0xFC89, 'M', u'مم'), - (0xFC8A, 'M', u'نر'), - ] - -def _seg_46(): - return [ - (0xFC8B, 'M', u'نز'), - (0xFC8C, 'M', u'نم'), - (0xFC8D, 'M', u'نن'), - (0xFC8E, 'M', u'نى'), - (0xFC8F, 'M', u'ني'), - (0xFC90, 'M', u'ىٰ'), - (0xFC91, 'M', u'ير'), - (0xFC92, 'M', u'يز'), - (0xFC93, 'M', u'يم'), - (0xFC94, 'M', u'ين'), - (0xFC95, 'M', u'يى'), - (0xFC96, 'M', u'يي'), - (0xFC97, 'M', u'ئج'), - (0xFC98, 'M', u'ئح'), - (0xFC99, 'M', u'ئخ'), - (0xFC9A, 'M', u'ئم'), - (0xFC9B, 'M', u'ئه'), - (0xFC9C, 'M', u'بج'), - (0xFC9D, 'M', u'بح'), - (0xFC9E, 'M', u'بخ'), - (0xFC9F, 'M', u'بم'), - (0xFCA0, 'M', u'به'), - (0xFCA1, 'M', u'تج'), - (0xFCA2, 'M', u'تح'), - (0xFCA3, 'M', u'تخ'), - (0xFCA4, 'M', u'تم'), - (0xFCA5, 'M', u'ته'), - (0xFCA6, 'M', u'ثم'), - (0xFCA7, 'M', u'جح'), - (0xFCA8, 'M', u'جم'), - (0xFCA9, 'M', u'حج'), - (0xFCAA, 'M', u'حم'), - (0xFCAB, 'M', u'خج'), - (0xFCAC, 'M', u'خم'), - (0xFCAD, 'M', u'سج'), - (0xFCAE, 'M', u'سح'), - (0xFCAF, 'M', u'سخ'), - (0xFCB0, 'M', u'سم'), - (0xFCB1, 'M', u'صح'), - (0xFCB2, 'M', u'صخ'), - (0xFCB3, 'M', u'صم'), - (0xFCB4, 'M', u'ضج'), - (0xFCB5, 'M', u'ضح'), - (0xFCB6, 'M', u'ضخ'), - (0xFCB7, 'M', u'ضم'), - (0xFCB8, 'M', u'طح'), - (0xFCB9, 'M', u'ظم'), - (0xFCBA, 'M', u'عج'), - (0xFCBB, 'M', u'عم'), - (0xFCBC, 'M', u'غج'), - (0xFCBD, 'M', u'غم'), - (0xFCBE, 'M', u'فج'), - (0xFCBF, 'M', u'فح'), - (0xFCC0, 'M', u'فخ'), - (0xFCC1, 'M', u'فم'), - (0xFCC2, 'M', u'قح'), - (0xFCC3, 'M', u'قم'), - (0xFCC4, 'M', u'كج'), - (0xFCC5, 'M', u'كح'), - (0xFCC6, 'M', u'كخ'), - (0xFCC7, 'M', u'كل'), - (0xFCC8, 'M', u'كم'), - (0xFCC9, 'M', u'لج'), - (0xFCCA, 'M', u'لح'), - (0xFCCB, 'M', u'لخ'), - (0xFCCC, 'M', u'لم'), - (0xFCCD, 'M', u'له'), - (0xFCCE, 'M', u'مج'), - (0xFCCF, 'M', u'مح'), - (0xFCD0, 'M', u'مخ'), - (0xFCD1, 'M', u'مم'), - (0xFCD2, 'M', u'نج'), - (0xFCD3, 'M', u'نح'), - (0xFCD4, 'M', u'نخ'), - (0xFCD5, 'M', u'نم'), - (0xFCD6, 'M', u'نه'), - (0xFCD7, 'M', u'هج'), - (0xFCD8, 'M', u'هم'), - (0xFCD9, 'M', u'هٰ'), - (0xFCDA, 'M', u'يج'), - (0xFCDB, 'M', u'يح'), - (0xFCDC, 'M', u'يخ'), - (0xFCDD, 'M', u'يم'), - (0xFCDE, 'M', u'يه'), - (0xFCDF, 'M', u'ئم'), - (0xFCE0, 'M', u'ئه'), - (0xFCE1, 'M', u'بم'), - (0xFCE2, 'M', u'به'), - (0xFCE3, 'M', u'تم'), - (0xFCE4, 'M', u'ته'), - (0xFCE5, 'M', u'ثم'), - (0xFCE6, 'M', u'ثه'), - (0xFCE7, 'M', u'سم'), - (0xFCE8, 'M', u'سه'), - (0xFCE9, 'M', u'شم'), - (0xFCEA, 'M', u'شه'), - (0xFCEB, 'M', u'كل'), - (0xFCEC, 'M', u'كم'), - (0xFCED, 'M', u'لم'), - (0xFCEE, 'M', u'نم'), - ] - -def _seg_47(): - return [ - (0xFCEF, 'M', u'نه'), - (0xFCF0, 'M', u'يم'), - (0xFCF1, 'M', u'يه'), - (0xFCF2, 'M', u'ـَّ'), - (0xFCF3, 'M', u'ـُّ'), - (0xFCF4, 'M', u'ـِّ'), - (0xFCF5, 'M', u'طى'), - (0xFCF6, 'M', u'طي'), - (0xFCF7, 'M', u'عى'), - (0xFCF8, 'M', u'عي'), - (0xFCF9, 'M', u'غى'), - (0xFCFA, 'M', u'غي'), - (0xFCFB, 'M', u'سى'), - (0xFCFC, 'M', u'سي'), - (0xFCFD, 'M', u'شى'), - (0xFCFE, 'M', u'شي'), - (0xFCFF, 'M', u'حى'), - (0xFD00, 'M', u'حي'), - (0xFD01, 'M', u'جى'), - (0xFD02, 'M', u'جي'), - (0xFD03, 'M', u'خى'), - (0xFD04, 'M', u'خي'), - (0xFD05, 'M', u'صى'), - (0xFD06, 'M', u'صي'), - (0xFD07, 'M', u'ضى'), - (0xFD08, 'M', u'ضي'), - (0xFD09, 'M', u'شج'), - (0xFD0A, 'M', u'شح'), - (0xFD0B, 'M', u'شخ'), - (0xFD0C, 'M', u'شم'), - (0xFD0D, 'M', u'شر'), - (0xFD0E, 'M', u'سر'), - (0xFD0F, 'M', u'صر'), - (0xFD10, 'M', u'ضر'), - (0xFD11, 'M', u'طى'), - (0xFD12, 'M', u'طي'), - (0xFD13, 'M', u'عى'), - (0xFD14, 'M', u'عي'), - (0xFD15, 'M', u'غى'), - (0xFD16, 'M', u'غي'), - (0xFD17, 'M', u'سى'), - (0xFD18, 'M', u'سي'), - (0xFD19, 'M', u'شى'), - (0xFD1A, 'M', u'شي'), - (0xFD1B, 'M', u'حى'), - (0xFD1C, 'M', u'حي'), - (0xFD1D, 'M', u'جى'), - (0xFD1E, 'M', u'جي'), - (0xFD1F, 'M', u'خى'), - (0xFD20, 'M', u'خي'), - (0xFD21, 'M', u'صى'), - (0xFD22, 'M', u'صي'), - (0xFD23, 'M', u'ضى'), - (0xFD24, 'M', u'ضي'), - (0xFD25, 'M', u'شج'), - (0xFD26, 'M', u'شح'), - (0xFD27, 'M', u'شخ'), - (0xFD28, 'M', u'شم'), - (0xFD29, 'M', u'شر'), - (0xFD2A, 'M', u'سر'), - (0xFD2B, 'M', u'صر'), - (0xFD2C, 'M', u'ضر'), - (0xFD2D, 'M', u'شج'), - (0xFD2E, 'M', u'شح'), - (0xFD2F, 'M', u'شخ'), - (0xFD30, 'M', u'شم'), - (0xFD31, 'M', u'سه'), - (0xFD32, 'M', u'شه'), - (0xFD33, 'M', u'طم'), - (0xFD34, 'M', u'سج'), - (0xFD35, 'M', u'سح'), - (0xFD36, 'M', u'سخ'), - (0xFD37, 'M', u'شج'), - (0xFD38, 'M', u'شح'), - (0xFD39, 'M', u'شخ'), - (0xFD3A, 'M', u'طم'), - (0xFD3B, 'M', u'ظم'), - (0xFD3C, 'M', u'اً'), - (0xFD3E, 'V'), - (0xFD40, 'X'), - (0xFD50, 'M', u'تجم'), - (0xFD51, 'M', u'تحج'), - (0xFD53, 'M', u'تحم'), - (0xFD54, 'M', u'تخم'), - (0xFD55, 'M', u'تمج'), - (0xFD56, 'M', u'تمح'), - (0xFD57, 'M', u'تمخ'), - (0xFD58, 'M', u'جمح'), - (0xFD5A, 'M', u'حمي'), - (0xFD5B, 'M', u'حمى'), - (0xFD5C, 'M', u'سحج'), - (0xFD5D, 'M', u'سجح'), - (0xFD5E, 'M', u'سجى'), - (0xFD5F, 'M', u'سمح'), - (0xFD61, 'M', u'سمج'), - (0xFD62, 'M', u'سمم'), - (0xFD64, 'M', u'صحح'), - (0xFD66, 'M', u'صمم'), - (0xFD67, 'M', u'شحم'), - (0xFD69, 'M', u'شجي'), - ] - -def _seg_48(): - return [ - (0xFD6A, 'M', u'شمخ'), - (0xFD6C, 'M', u'شمم'), - (0xFD6E, 'M', u'ضحى'), - (0xFD6F, 'M', u'ضخم'), - (0xFD71, 'M', u'طمح'), - (0xFD73, 'M', u'طمم'), - (0xFD74, 'M', u'طمي'), - (0xFD75, 'M', u'عجم'), - (0xFD76, 'M', u'عمم'), - (0xFD78, 'M', u'عمى'), - (0xFD79, 'M', u'غمم'), - (0xFD7A, 'M', u'غمي'), - (0xFD7B, 'M', u'غمى'), - (0xFD7C, 'M', u'فخم'), - (0xFD7E, 'M', u'قمح'), - (0xFD7F, 'M', u'قمم'), - (0xFD80, 'M', u'لحم'), - (0xFD81, 'M', u'لحي'), - (0xFD82, 'M', u'لحى'), - (0xFD83, 'M', u'لجج'), - (0xFD85, 'M', u'لخم'), - (0xFD87, 'M', u'لمح'), - (0xFD89, 'M', u'محج'), - (0xFD8A, 'M', u'محم'), - (0xFD8B, 'M', u'محي'), - (0xFD8C, 'M', u'مجح'), - (0xFD8D, 'M', u'مجم'), - (0xFD8E, 'M', u'مخج'), - (0xFD8F, 'M', u'مخم'), - (0xFD90, 'X'), - (0xFD92, 'M', u'مجخ'), - (0xFD93, 'M', u'همج'), - (0xFD94, 'M', u'همم'), - (0xFD95, 'M', u'نحم'), - (0xFD96, 'M', u'نحى'), - (0xFD97, 'M', u'نجم'), - (0xFD99, 'M', u'نجى'), - (0xFD9A, 'M', u'نمي'), - (0xFD9B, 'M', u'نمى'), - (0xFD9C, 'M', u'يمم'), - (0xFD9E, 'M', u'بخي'), - (0xFD9F, 'M', u'تجي'), - (0xFDA0, 'M', u'تجى'), - (0xFDA1, 'M', u'تخي'), - (0xFDA2, 'M', u'تخى'), - (0xFDA3, 'M', u'تمي'), - (0xFDA4, 'M', u'تمى'), - (0xFDA5, 'M', u'جمي'), - (0xFDA6, 'M', u'جحى'), - (0xFDA7, 'M', u'جمى'), - (0xFDA8, 'M', u'سخى'), - (0xFDA9, 'M', u'صحي'), - (0xFDAA, 'M', u'شحي'), - (0xFDAB, 'M', u'ضحي'), - (0xFDAC, 'M', u'لجي'), - (0xFDAD, 'M', u'لمي'), - (0xFDAE, 'M', u'يحي'), - (0xFDAF, 'M', u'يجي'), - (0xFDB0, 'M', u'يمي'), - (0xFDB1, 'M', u'ممي'), - (0xFDB2, 'M', u'قمي'), - (0xFDB3, 'M', u'نحي'), - (0xFDB4, 'M', u'قمح'), - (0xFDB5, 'M', u'لحم'), - (0xFDB6, 'M', u'عمي'), - (0xFDB7, 'M', u'كمي'), - (0xFDB8, 'M', u'نجح'), - (0xFDB9, 'M', u'مخي'), - (0xFDBA, 'M', u'لجم'), - (0xFDBB, 'M', u'كمم'), - (0xFDBC, 'M', u'لجم'), - (0xFDBD, 'M', u'نجح'), - (0xFDBE, 'M', u'جحي'), - (0xFDBF, 'M', u'حجي'), - (0xFDC0, 'M', u'مجي'), - (0xFDC1, 'M', u'فمي'), - (0xFDC2, 'M', u'بحي'), - (0xFDC3, 'M', u'كمم'), - (0xFDC4, 'M', u'عجم'), - (0xFDC5, 'M', u'صمم'), - (0xFDC6, 'M', u'سخي'), - (0xFDC7, 'M', u'نجي'), - (0xFDC8, 'X'), - (0xFDF0, 'M', u'صلے'), - (0xFDF1, 'M', u'قلے'), - (0xFDF2, 'M', u'الله'), - (0xFDF3, 'M', u'اكبر'), - (0xFDF4, 'M', u'محمد'), - (0xFDF5, 'M', u'صلعم'), - (0xFDF6, 'M', u'رسول'), - (0xFDF7, 'M', u'عليه'), - (0xFDF8, 'M', u'وسلم'), - (0xFDF9, 'M', u'صلى'), - (0xFDFA, '3', u'صلى الله عليه وسلم'), - (0xFDFB, '3', u'جل جلاله'), - (0xFDFC, 'M', u'ریال'), - (0xFDFD, 'V'), - (0xFDFE, 'X'), - (0xFE00, 'I'), - (0xFE10, '3', u','), - ] - -def _seg_49(): - return [ - (0xFE11, 'M', u'、'), - (0xFE12, 'X'), - (0xFE13, '3', u':'), - (0xFE14, '3', u';'), - (0xFE15, '3', u'!'), - (0xFE16, '3', u'?'), - (0xFE17, 'M', u'〖'), - (0xFE18, 'M', u'〗'), - (0xFE19, 'X'), - (0xFE20, 'V'), - (0xFE30, 'X'), - (0xFE31, 'M', u'—'), - (0xFE32, 'M', u'–'), - (0xFE33, '3', u'_'), - (0xFE35, '3', u'('), - (0xFE36, '3', u')'), - (0xFE37, '3', u'{'), - (0xFE38, '3', u'}'), - (0xFE39, 'M', u'〔'), - (0xFE3A, 'M', u'〕'), - (0xFE3B, 'M', u'【'), - (0xFE3C, 'M', u'】'), - (0xFE3D, 'M', u'《'), - (0xFE3E, 'M', u'》'), - (0xFE3F, 'M', u'〈'), - (0xFE40, 'M', u'〉'), - (0xFE41, 'M', u'「'), - (0xFE42, 'M', u'」'), - (0xFE43, 'M', u'『'), - (0xFE44, 'M', u'』'), - (0xFE45, 'V'), - (0xFE47, '3', u'['), - (0xFE48, '3', u']'), - (0xFE49, '3', u' ̅'), - (0xFE4D, '3', u'_'), - (0xFE50, '3', u','), - (0xFE51, 'M', u'、'), - (0xFE52, 'X'), - (0xFE54, '3', u';'), - (0xFE55, '3', u':'), - (0xFE56, '3', u'?'), - (0xFE57, '3', u'!'), - (0xFE58, 'M', u'—'), - (0xFE59, '3', u'('), - (0xFE5A, '3', u')'), - (0xFE5B, '3', u'{'), - (0xFE5C, '3', u'}'), - (0xFE5D, 'M', u'〔'), - (0xFE5E, 'M', u'〕'), - (0xFE5F, '3', u'#'), - (0xFE60, '3', u'&'), - (0xFE61, '3', u'*'), - (0xFE62, '3', u'+'), - (0xFE63, 'M', u'-'), - (0xFE64, '3', u'<'), - (0xFE65, '3', u'>'), - (0xFE66, '3', u'='), - (0xFE67, 'X'), - (0xFE68, '3', u'\\'), - (0xFE69, '3', u'$'), - (0xFE6A, '3', u'%'), - (0xFE6B, '3', u'@'), - (0xFE6C, 'X'), - (0xFE70, '3', u' ً'), - (0xFE71, 'M', u'ـً'), - (0xFE72, '3', u' ٌ'), - (0xFE73, 'V'), - (0xFE74, '3', u' ٍ'), - (0xFE75, 'X'), - (0xFE76, '3', u' َ'), - (0xFE77, 'M', u'ـَ'), - (0xFE78, '3', u' ُ'), - (0xFE79, 'M', u'ـُ'), - (0xFE7A, '3', u' ِ'), - (0xFE7B, 'M', u'ـِ'), - (0xFE7C, '3', u' ّ'), - (0xFE7D, 'M', u'ـّ'), - (0xFE7E, '3', u' ْ'), - (0xFE7F, 'M', u'ـْ'), - (0xFE80, 'M', u'ء'), - (0xFE81, 'M', u'آ'), - (0xFE83, 'M', u'أ'), - (0xFE85, 'M', u'ؤ'), - (0xFE87, 'M', u'إ'), - (0xFE89, 'M', u'ئ'), - (0xFE8D, 'M', u'ا'), - (0xFE8F, 'M', u'ب'), - (0xFE93, 'M', u'ة'), - (0xFE95, 'M', u'ت'), - (0xFE99, 'M', u'ث'), - (0xFE9D, 'M', u'ج'), - (0xFEA1, 'M', u'ح'), - (0xFEA5, 'M', u'خ'), - (0xFEA9, 'M', u'د'), - (0xFEAB, 'M', u'ذ'), - (0xFEAD, 'M', u'ر'), - (0xFEAF, 'M', u'ز'), - (0xFEB1, 'M', u'س'), - (0xFEB5, 'M', u'ش'), - (0xFEB9, 'M', u'ص'), - ] - -def _seg_50(): - return [ - (0xFEBD, 'M', u'ض'), - (0xFEC1, 'M', u'ط'), - (0xFEC5, 'M', u'ظ'), - (0xFEC9, 'M', u'ع'), - (0xFECD, 'M', u'غ'), - (0xFED1, 'M', u'ف'), - (0xFED5, 'M', u'ق'), - (0xFED9, 'M', u'ك'), - (0xFEDD, 'M', u'ل'), - (0xFEE1, 'M', u'م'), - (0xFEE5, 'M', u'ن'), - (0xFEE9, 'M', u'ه'), - (0xFEED, 'M', u'و'), - (0xFEEF, 'M', u'ى'), - (0xFEF1, 'M', u'ي'), - (0xFEF5, 'M', u'لآ'), - (0xFEF7, 'M', u'لأ'), - (0xFEF9, 'M', u'لإ'), - (0xFEFB, 'M', u'لا'), - (0xFEFD, 'X'), - (0xFEFF, 'I'), - (0xFF00, 'X'), - (0xFF01, '3', u'!'), - (0xFF02, '3', u'"'), - (0xFF03, '3', u'#'), - (0xFF04, '3', u'$'), - (0xFF05, '3', u'%'), - (0xFF06, '3', u'&'), - (0xFF07, '3', u'\''), - (0xFF08, '3', u'('), - (0xFF09, '3', u')'), - (0xFF0A, '3', u'*'), - (0xFF0B, '3', u'+'), - (0xFF0C, '3', u','), - (0xFF0D, 'M', u'-'), - (0xFF0E, 'M', u'.'), - (0xFF0F, '3', u'/'), - (0xFF10, 'M', u'0'), - (0xFF11, 'M', u'1'), - (0xFF12, 'M', u'2'), - (0xFF13, 'M', u'3'), - (0xFF14, 'M', u'4'), - (0xFF15, 'M', u'5'), - (0xFF16, 'M', u'6'), - (0xFF17, 'M', u'7'), - (0xFF18, 'M', u'8'), - (0xFF19, 'M', u'9'), - (0xFF1A, '3', u':'), - (0xFF1B, '3', u';'), - (0xFF1C, '3', u'<'), - (0xFF1D, '3', u'='), - (0xFF1E, '3', u'>'), - (0xFF1F, '3', u'?'), - (0xFF20, '3', u'@'), - (0xFF21, 'M', u'a'), - (0xFF22, 'M', u'b'), - (0xFF23, 'M', u'c'), - (0xFF24, 'M', u'd'), - (0xFF25, 'M', u'e'), - (0xFF26, 'M', u'f'), - (0xFF27, 'M', u'g'), - (0xFF28, 'M', u'h'), - (0xFF29, 'M', u'i'), - (0xFF2A, 'M', u'j'), - (0xFF2B, 'M', u'k'), - (0xFF2C, 'M', u'l'), - (0xFF2D, 'M', u'm'), - (0xFF2E, 'M', u'n'), - (0xFF2F, 'M', u'o'), - (0xFF30, 'M', u'p'), - (0xFF31, 'M', u'q'), - (0xFF32, 'M', u'r'), - (0xFF33, 'M', u's'), - (0xFF34, 'M', u't'), - (0xFF35, 'M', u'u'), - (0xFF36, 'M', u'v'), - (0xFF37, 'M', u'w'), - (0xFF38, 'M', u'x'), - (0xFF39, 'M', u'y'), - (0xFF3A, 'M', u'z'), - (0xFF3B, '3', u'['), - (0xFF3C, '3', u'\\'), - (0xFF3D, '3', u']'), - (0xFF3E, '3', u'^'), - (0xFF3F, '3', u'_'), - (0xFF40, '3', u'`'), - (0xFF41, 'M', u'a'), - (0xFF42, 'M', u'b'), - (0xFF43, 'M', u'c'), - (0xFF44, 'M', u'd'), - (0xFF45, 'M', u'e'), - (0xFF46, 'M', u'f'), - (0xFF47, 'M', u'g'), - (0xFF48, 'M', u'h'), - (0xFF49, 'M', u'i'), - (0xFF4A, 'M', u'j'), - (0xFF4B, 'M', u'k'), - (0xFF4C, 'M', u'l'), - (0xFF4D, 'M', u'm'), - (0xFF4E, 'M', u'n'), - ] - -def _seg_51(): - return [ - (0xFF4F, 'M', u'o'), - (0xFF50, 'M', u'p'), - (0xFF51, 'M', u'q'), - (0xFF52, 'M', u'r'), - (0xFF53, 'M', u's'), - (0xFF54, 'M', u't'), - (0xFF55, 'M', u'u'), - (0xFF56, 'M', u'v'), - (0xFF57, 'M', u'w'), - (0xFF58, 'M', u'x'), - (0xFF59, 'M', u'y'), - (0xFF5A, 'M', u'z'), - (0xFF5B, '3', u'{'), - (0xFF5C, '3', u'|'), - (0xFF5D, '3', u'}'), - (0xFF5E, '3', u'~'), - (0xFF5F, 'M', u'⦅'), - (0xFF60, 'M', u'⦆'), - (0xFF61, 'M', u'.'), - (0xFF62, 'M', u'「'), - (0xFF63, 'M', u'」'), - (0xFF64, 'M', u'、'), - (0xFF65, 'M', u'・'), - (0xFF66, 'M', u'ヲ'), - (0xFF67, 'M', u'ァ'), - (0xFF68, 'M', u'ィ'), - (0xFF69, 'M', u'ゥ'), - (0xFF6A, 'M', u'ェ'), - (0xFF6B, 'M', u'ォ'), - (0xFF6C, 'M', u'ャ'), - (0xFF6D, 'M', u'ュ'), - (0xFF6E, 'M', u'ョ'), - (0xFF6F, 'M', u'ッ'), - (0xFF70, 'M', u'ー'), - (0xFF71, 'M', u'ア'), - (0xFF72, 'M', u'イ'), - (0xFF73, 'M', u'ウ'), - (0xFF74, 'M', u'エ'), - (0xFF75, 'M', u'オ'), - (0xFF76, 'M', u'カ'), - (0xFF77, 'M', u'キ'), - (0xFF78, 'M', u'ク'), - (0xFF79, 'M', u'ケ'), - (0xFF7A, 'M', u'コ'), - (0xFF7B, 'M', u'サ'), - (0xFF7C, 'M', u'シ'), - (0xFF7D, 'M', u'ス'), - (0xFF7E, 'M', u'セ'), - (0xFF7F, 'M', u'ソ'), - (0xFF80, 'M', u'タ'), - (0xFF81, 'M', u'チ'), - (0xFF82, 'M', u'ツ'), - (0xFF83, 'M', u'テ'), - (0xFF84, 'M', u'ト'), - (0xFF85, 'M', u'ナ'), - (0xFF86, 'M', u'ニ'), - (0xFF87, 'M', u'ヌ'), - (0xFF88, 'M', u'ネ'), - (0xFF89, 'M', u'ノ'), - (0xFF8A, 'M', u'ハ'), - (0xFF8B, 'M', u'ヒ'), - (0xFF8C, 'M', u'フ'), - (0xFF8D, 'M', u'ヘ'), - (0xFF8E, 'M', u'ホ'), - (0xFF8F, 'M', u'マ'), - (0xFF90, 'M', u'ミ'), - (0xFF91, 'M', u'ム'), - (0xFF92, 'M', u'メ'), - (0xFF93, 'M', u'モ'), - (0xFF94, 'M', u'ヤ'), - (0xFF95, 'M', u'ユ'), - (0xFF96, 'M', u'ヨ'), - (0xFF97, 'M', u'ラ'), - (0xFF98, 'M', u'リ'), - (0xFF99, 'M', u'ル'), - (0xFF9A, 'M', u'レ'), - (0xFF9B, 'M', u'ロ'), - (0xFF9C, 'M', u'ワ'), - (0xFF9D, 'M', u'ン'), - (0xFF9E, 'M', u'゙'), - (0xFF9F, 'M', u'゚'), - (0xFFA0, 'X'), - (0xFFA1, 'M', u'ᄀ'), - (0xFFA2, 'M', u'ᄁ'), - (0xFFA3, 'M', u'ᆪ'), - (0xFFA4, 'M', u'ᄂ'), - (0xFFA5, 'M', u'ᆬ'), - (0xFFA6, 'M', u'ᆭ'), - (0xFFA7, 'M', u'ᄃ'), - (0xFFA8, 'M', u'ᄄ'), - (0xFFA9, 'M', u'ᄅ'), - (0xFFAA, 'M', u'ᆰ'), - (0xFFAB, 'M', u'ᆱ'), - (0xFFAC, 'M', u'ᆲ'), - (0xFFAD, 'M', u'ᆳ'), - (0xFFAE, 'M', u'ᆴ'), - (0xFFAF, 'M', u'ᆵ'), - (0xFFB0, 'M', u'ᄚ'), - (0xFFB1, 'M', u'ᄆ'), - (0xFFB2, 'M', u'ᄇ'), - ] - -def _seg_52(): - return [ - (0xFFB3, 'M', u'ᄈ'), - (0xFFB4, 'M', u'ᄡ'), - (0xFFB5, 'M', u'ᄉ'), - (0xFFB6, 'M', u'ᄊ'), - (0xFFB7, 'M', u'ᄋ'), - (0xFFB8, 'M', u'ᄌ'), - (0xFFB9, 'M', u'ᄍ'), - (0xFFBA, 'M', u'ᄎ'), - (0xFFBB, 'M', u'ᄏ'), - (0xFFBC, 'M', u'ᄐ'), - (0xFFBD, 'M', u'ᄑ'), - (0xFFBE, 'M', u'ᄒ'), - (0xFFBF, 'X'), - (0xFFC2, 'M', u'ᅡ'), - (0xFFC3, 'M', u'ᅢ'), - (0xFFC4, 'M', u'ᅣ'), - (0xFFC5, 'M', u'ᅤ'), - (0xFFC6, 'M', u'ᅥ'), - (0xFFC7, 'M', u'ᅦ'), - (0xFFC8, 'X'), - (0xFFCA, 'M', u'ᅧ'), - (0xFFCB, 'M', u'ᅨ'), - (0xFFCC, 'M', u'ᅩ'), - (0xFFCD, 'M', u'ᅪ'), - (0xFFCE, 'M', u'ᅫ'), - (0xFFCF, 'M', u'ᅬ'), - (0xFFD0, 'X'), - (0xFFD2, 'M', u'ᅭ'), - (0xFFD3, 'M', u'ᅮ'), - (0xFFD4, 'M', u'ᅯ'), - (0xFFD5, 'M', u'ᅰ'), - (0xFFD6, 'M', u'ᅱ'), - (0xFFD7, 'M', u'ᅲ'), - (0xFFD8, 'X'), - (0xFFDA, 'M', u'ᅳ'), - (0xFFDB, 'M', u'ᅴ'), - (0xFFDC, 'M', u'ᅵ'), - (0xFFDD, 'X'), - (0xFFE0, 'M', u'¢'), - (0xFFE1, 'M', u'£'), - (0xFFE2, 'M', u'¬'), - (0xFFE3, '3', u' ̄'), - (0xFFE4, 'M', u'¦'), - (0xFFE5, 'M', u'¥'), - (0xFFE6, 'M', u'₩'), - (0xFFE7, 'X'), - (0xFFE8, 'M', u'│'), - (0xFFE9, 'M', u'←'), - (0xFFEA, 'M', u'↑'), - (0xFFEB, 'M', u'→'), - (0xFFEC, 'M', u'↓'), - (0xFFED, 'M', u'■'), - (0xFFEE, 'M', u'○'), - (0xFFEF, 'X'), - (0x10000, 'V'), - (0x1000C, 'X'), - (0x1000D, 'V'), - (0x10027, 'X'), - (0x10028, 'V'), - (0x1003B, 'X'), - (0x1003C, 'V'), - (0x1003E, 'X'), - (0x1003F, 'V'), - (0x1004E, 'X'), - (0x10050, 'V'), - (0x1005E, 'X'), - (0x10080, 'V'), - (0x100FB, 'X'), - (0x10100, 'V'), - (0x10103, 'X'), - (0x10107, 'V'), - (0x10134, 'X'), - (0x10137, 'V'), - (0x1018F, 'X'), - (0x10190, 'V'), - (0x1019C, 'X'), - (0x101A0, 'V'), - (0x101A1, 'X'), - (0x101D0, 'V'), - (0x101FE, 'X'), - (0x10280, 'V'), - (0x1029D, 'X'), - (0x102A0, 'V'), - (0x102D1, 'X'), - (0x102E0, 'V'), - (0x102FC, 'X'), - (0x10300, 'V'), - (0x10324, 'X'), - (0x1032D, 'V'), - (0x1034B, 'X'), - (0x10350, 'V'), - (0x1037B, 'X'), - (0x10380, 'V'), - (0x1039E, 'X'), - (0x1039F, 'V'), - (0x103C4, 'X'), - (0x103C8, 'V'), - (0x103D6, 'X'), - (0x10400, 'M', u'𐐨'), - (0x10401, 'M', u'𐐩'), - ] - -def _seg_53(): - return [ - (0x10402, 'M', u'𐐪'), - (0x10403, 'M', u'𐐫'), - (0x10404, 'M', u'𐐬'), - (0x10405, 'M', u'𐐭'), - (0x10406, 'M', u'𐐮'), - (0x10407, 'M', u'𐐯'), - (0x10408, 'M', u'𐐰'), - (0x10409, 'M', u'𐐱'), - (0x1040A, 'M', u'𐐲'), - (0x1040B, 'M', u'𐐳'), - (0x1040C, 'M', u'𐐴'), - (0x1040D, 'M', u'𐐵'), - (0x1040E, 'M', u'𐐶'), - (0x1040F, 'M', u'𐐷'), - (0x10410, 'M', u'𐐸'), - (0x10411, 'M', u'𐐹'), - (0x10412, 'M', u'𐐺'), - (0x10413, 'M', u'𐐻'), - (0x10414, 'M', u'𐐼'), - (0x10415, 'M', u'𐐽'), - (0x10416, 'M', u'𐐾'), - (0x10417, 'M', u'𐐿'), - (0x10418, 'M', u'𐑀'), - (0x10419, 'M', u'𐑁'), - (0x1041A, 'M', u'𐑂'), - (0x1041B, 'M', u'𐑃'), - (0x1041C, 'M', u'𐑄'), - (0x1041D, 'M', u'𐑅'), - (0x1041E, 'M', u'𐑆'), - (0x1041F, 'M', u'𐑇'), - (0x10420, 'M', u'𐑈'), - (0x10421, 'M', u'𐑉'), - (0x10422, 'M', u'𐑊'), - (0x10423, 'M', u'𐑋'), - (0x10424, 'M', u'𐑌'), - (0x10425, 'M', u'𐑍'), - (0x10426, 'M', u'𐑎'), - (0x10427, 'M', u'𐑏'), - (0x10428, 'V'), - (0x1049E, 'X'), - (0x104A0, 'V'), - (0x104AA, 'X'), - (0x104B0, 'M', u'𐓘'), - (0x104B1, 'M', u'𐓙'), - (0x104B2, 'M', u'𐓚'), - (0x104B3, 'M', u'𐓛'), - (0x104B4, 'M', u'𐓜'), - (0x104B5, 'M', u'𐓝'), - (0x104B6, 'M', u'𐓞'), - (0x104B7, 'M', u'𐓟'), - (0x104B8, 'M', u'𐓠'), - (0x104B9, 'M', u'𐓡'), - (0x104BA, 'M', u'𐓢'), - (0x104BB, 'M', u'𐓣'), - (0x104BC, 'M', u'𐓤'), - (0x104BD, 'M', u'𐓥'), - (0x104BE, 'M', u'𐓦'), - (0x104BF, 'M', u'𐓧'), - (0x104C0, 'M', u'𐓨'), - (0x104C1, 'M', u'𐓩'), - (0x104C2, 'M', u'𐓪'), - (0x104C3, 'M', u'𐓫'), - (0x104C4, 'M', u'𐓬'), - (0x104C5, 'M', u'𐓭'), - (0x104C6, 'M', u'𐓮'), - (0x104C7, 'M', u'𐓯'), - (0x104C8, 'M', u'𐓰'), - (0x104C9, 'M', u'𐓱'), - (0x104CA, 'M', u'𐓲'), - (0x104CB, 'M', u'𐓳'), - (0x104CC, 'M', u'𐓴'), - (0x104CD, 'M', u'𐓵'), - (0x104CE, 'M', u'𐓶'), - (0x104CF, 'M', u'𐓷'), - (0x104D0, 'M', u'𐓸'), - (0x104D1, 'M', u'𐓹'), - (0x104D2, 'M', u'𐓺'), - (0x104D3, 'M', u'𐓻'), - (0x104D4, 'X'), - (0x104D8, 'V'), - (0x104FC, 'X'), - (0x10500, 'V'), - (0x10528, 'X'), - (0x10530, 'V'), - (0x10564, 'X'), - (0x1056F, 'V'), - (0x10570, 'X'), - (0x10600, 'V'), - (0x10737, 'X'), - (0x10740, 'V'), - (0x10756, 'X'), - (0x10760, 'V'), - (0x10768, 'X'), - (0x10800, 'V'), - (0x10806, 'X'), - (0x10808, 'V'), - (0x10809, 'X'), - (0x1080A, 'V'), - (0x10836, 'X'), - (0x10837, 'V'), - ] - -def _seg_54(): - return [ - (0x10839, 'X'), - (0x1083C, 'V'), - (0x1083D, 'X'), - (0x1083F, 'V'), - (0x10856, 'X'), - (0x10857, 'V'), - (0x1089F, 'X'), - (0x108A7, 'V'), - (0x108B0, 'X'), - (0x108E0, 'V'), - (0x108F3, 'X'), - (0x108F4, 'V'), - (0x108F6, 'X'), - (0x108FB, 'V'), - (0x1091C, 'X'), - (0x1091F, 'V'), - (0x1093A, 'X'), - (0x1093F, 'V'), - (0x10940, 'X'), - (0x10980, 'V'), - (0x109B8, 'X'), - (0x109BC, 'V'), - (0x109D0, 'X'), - (0x109D2, 'V'), - (0x10A04, 'X'), - (0x10A05, 'V'), - (0x10A07, 'X'), - (0x10A0C, 'V'), - (0x10A14, 'X'), - (0x10A15, 'V'), - (0x10A18, 'X'), - (0x10A19, 'V'), - (0x10A36, 'X'), - (0x10A38, 'V'), - (0x10A3B, 'X'), - (0x10A3F, 'V'), - (0x10A49, 'X'), - (0x10A50, 'V'), - (0x10A59, 'X'), - (0x10A60, 'V'), - (0x10AA0, 'X'), - (0x10AC0, 'V'), - (0x10AE7, 'X'), - (0x10AEB, 'V'), - (0x10AF7, 'X'), - (0x10B00, 'V'), - (0x10B36, 'X'), - (0x10B39, 'V'), - (0x10B56, 'X'), - (0x10B58, 'V'), - (0x10B73, 'X'), - (0x10B78, 'V'), - (0x10B92, 'X'), - (0x10B99, 'V'), - (0x10B9D, 'X'), - (0x10BA9, 'V'), - (0x10BB0, 'X'), - (0x10C00, 'V'), - (0x10C49, 'X'), - (0x10C80, 'M', u'𐳀'), - (0x10C81, 'M', u'𐳁'), - (0x10C82, 'M', u'𐳂'), - (0x10C83, 'M', u'𐳃'), - (0x10C84, 'M', u'𐳄'), - (0x10C85, 'M', u'𐳅'), - (0x10C86, 'M', u'𐳆'), - (0x10C87, 'M', u'𐳇'), - (0x10C88, 'M', u'𐳈'), - (0x10C89, 'M', u'𐳉'), - (0x10C8A, 'M', u'𐳊'), - (0x10C8B, 'M', u'𐳋'), - (0x10C8C, 'M', u'𐳌'), - (0x10C8D, 'M', u'𐳍'), - (0x10C8E, 'M', u'𐳎'), - (0x10C8F, 'M', u'𐳏'), - (0x10C90, 'M', u'𐳐'), - (0x10C91, 'M', u'𐳑'), - (0x10C92, 'M', u'𐳒'), - (0x10C93, 'M', u'𐳓'), - (0x10C94, 'M', u'𐳔'), - (0x10C95, 'M', u'𐳕'), - (0x10C96, 'M', u'𐳖'), - (0x10C97, 'M', u'𐳗'), - (0x10C98, 'M', u'𐳘'), - (0x10C99, 'M', u'𐳙'), - (0x10C9A, 'M', u'𐳚'), - (0x10C9B, 'M', u'𐳛'), - (0x10C9C, 'M', u'𐳜'), - (0x10C9D, 'M', u'𐳝'), - (0x10C9E, 'M', u'𐳞'), - (0x10C9F, 'M', u'𐳟'), - (0x10CA0, 'M', u'𐳠'), - (0x10CA1, 'M', u'𐳡'), - (0x10CA2, 'M', u'𐳢'), - (0x10CA3, 'M', u'𐳣'), - (0x10CA4, 'M', u'𐳤'), - (0x10CA5, 'M', u'𐳥'), - (0x10CA6, 'M', u'𐳦'), - (0x10CA7, 'M', u'𐳧'), - (0x10CA8, 'M', u'𐳨'), - ] - -def _seg_55(): - return [ - (0x10CA9, 'M', u'𐳩'), - (0x10CAA, 'M', u'𐳪'), - (0x10CAB, 'M', u'𐳫'), - (0x10CAC, 'M', u'𐳬'), - (0x10CAD, 'M', u'𐳭'), - (0x10CAE, 'M', u'𐳮'), - (0x10CAF, 'M', u'𐳯'), - (0x10CB0, 'M', u'𐳰'), - (0x10CB1, 'M', u'𐳱'), - (0x10CB2, 'M', u'𐳲'), - (0x10CB3, 'X'), - (0x10CC0, 'V'), - (0x10CF3, 'X'), - (0x10CFA, 'V'), - (0x10D28, 'X'), - (0x10D30, 'V'), - (0x10D3A, 'X'), - (0x10E60, 'V'), - (0x10E7F, 'X'), - (0x10F00, 'V'), - (0x10F28, 'X'), - (0x10F30, 'V'), - (0x10F5A, 'X'), - (0x11000, 'V'), - (0x1104E, 'X'), - (0x11052, 'V'), - (0x11070, 'X'), - (0x1107F, 'V'), - (0x110BD, 'X'), - (0x110BE, 'V'), - (0x110C2, 'X'), - (0x110D0, 'V'), - (0x110E9, 'X'), - (0x110F0, 'V'), - (0x110FA, 'X'), - (0x11100, 'V'), - (0x11135, 'X'), - (0x11136, 'V'), - (0x11147, 'X'), - (0x11150, 'V'), - (0x11177, 'X'), - (0x11180, 'V'), - (0x111CE, 'X'), - (0x111D0, 'V'), - (0x111E0, 'X'), - (0x111E1, 'V'), - (0x111F5, 'X'), - (0x11200, 'V'), - (0x11212, 'X'), - (0x11213, 'V'), - (0x1123F, 'X'), - (0x11280, 'V'), - (0x11287, 'X'), - (0x11288, 'V'), - (0x11289, 'X'), - (0x1128A, 'V'), - (0x1128E, 'X'), - (0x1128F, 'V'), - (0x1129E, 'X'), - (0x1129F, 'V'), - (0x112AA, 'X'), - (0x112B0, 'V'), - (0x112EB, 'X'), - (0x112F0, 'V'), - (0x112FA, 'X'), - (0x11300, 'V'), - (0x11304, 'X'), - (0x11305, 'V'), - (0x1130D, 'X'), - (0x1130F, 'V'), - (0x11311, 'X'), - (0x11313, 'V'), - (0x11329, 'X'), - (0x1132A, 'V'), - (0x11331, 'X'), - (0x11332, 'V'), - (0x11334, 'X'), - (0x11335, 'V'), - (0x1133A, 'X'), - (0x1133B, 'V'), - (0x11345, 'X'), - (0x11347, 'V'), - (0x11349, 'X'), - (0x1134B, 'V'), - (0x1134E, 'X'), - (0x11350, 'V'), - (0x11351, 'X'), - (0x11357, 'V'), - (0x11358, 'X'), - (0x1135D, 'V'), - (0x11364, 'X'), - (0x11366, 'V'), - (0x1136D, 'X'), - (0x11370, 'V'), - (0x11375, 'X'), - (0x11400, 'V'), - (0x1145A, 'X'), - (0x1145B, 'V'), - (0x1145C, 'X'), - (0x1145D, 'V'), - ] - -def _seg_56(): - return [ - (0x1145F, 'X'), - (0x11480, 'V'), - (0x114C8, 'X'), - (0x114D0, 'V'), - (0x114DA, 'X'), - (0x11580, 'V'), - (0x115B6, 'X'), - (0x115B8, 'V'), - (0x115DE, 'X'), - (0x11600, 'V'), - (0x11645, 'X'), - (0x11650, 'V'), - (0x1165A, 'X'), - (0x11660, 'V'), - (0x1166D, 'X'), - (0x11680, 'V'), - (0x116B8, 'X'), - (0x116C0, 'V'), - (0x116CA, 'X'), - (0x11700, 'V'), - (0x1171B, 'X'), - (0x1171D, 'V'), - (0x1172C, 'X'), - (0x11730, 'V'), - (0x11740, 'X'), - (0x11800, 'V'), - (0x1183C, 'X'), - (0x118A0, 'M', u'𑣀'), - (0x118A1, 'M', u'𑣁'), - (0x118A2, 'M', u'𑣂'), - (0x118A3, 'M', u'𑣃'), - (0x118A4, 'M', u'𑣄'), - (0x118A5, 'M', u'𑣅'), - (0x118A6, 'M', u'𑣆'), - (0x118A7, 'M', u'𑣇'), - (0x118A8, 'M', u'𑣈'), - (0x118A9, 'M', u'𑣉'), - (0x118AA, 'M', u'𑣊'), - (0x118AB, 'M', u'𑣋'), - (0x118AC, 'M', u'𑣌'), - (0x118AD, 'M', u'𑣍'), - (0x118AE, 'M', u'𑣎'), - (0x118AF, 'M', u'𑣏'), - (0x118B0, 'M', u'𑣐'), - (0x118B1, 'M', u'𑣑'), - (0x118B2, 'M', u'𑣒'), - (0x118B3, 'M', u'𑣓'), - (0x118B4, 'M', u'𑣔'), - (0x118B5, 'M', u'𑣕'), - (0x118B6, 'M', u'𑣖'), - (0x118B7, 'M', u'𑣗'), - (0x118B8, 'M', u'𑣘'), - (0x118B9, 'M', u'𑣙'), - (0x118BA, 'M', u'𑣚'), - (0x118BB, 'M', u'𑣛'), - (0x118BC, 'M', u'𑣜'), - (0x118BD, 'M', u'𑣝'), - (0x118BE, 'M', u'𑣞'), - (0x118BF, 'M', u'𑣟'), - (0x118C0, 'V'), - (0x118F3, 'X'), - (0x118FF, 'V'), - (0x11900, 'X'), - (0x11A00, 'V'), - (0x11A48, 'X'), - (0x11A50, 'V'), - (0x11A84, 'X'), - (0x11A86, 'V'), - (0x11AA3, 'X'), - (0x11AC0, 'V'), - (0x11AF9, 'X'), - (0x11C00, 'V'), - (0x11C09, 'X'), - (0x11C0A, 'V'), - (0x11C37, 'X'), - (0x11C38, 'V'), - (0x11C46, 'X'), - (0x11C50, 'V'), - (0x11C6D, 'X'), - (0x11C70, 'V'), - (0x11C90, 'X'), - (0x11C92, 'V'), - (0x11CA8, 'X'), - (0x11CA9, 'V'), - (0x11CB7, 'X'), - (0x11D00, 'V'), - (0x11D07, 'X'), - (0x11D08, 'V'), - (0x11D0A, 'X'), - (0x11D0B, 'V'), - (0x11D37, 'X'), - (0x11D3A, 'V'), - (0x11D3B, 'X'), - (0x11D3C, 'V'), - (0x11D3E, 'X'), - (0x11D3F, 'V'), - (0x11D48, 'X'), - (0x11D50, 'V'), - (0x11D5A, 'X'), - (0x11D60, 'V'), - ] - -def _seg_57(): - return [ - (0x11D66, 'X'), - (0x11D67, 'V'), - (0x11D69, 'X'), - (0x11D6A, 'V'), - (0x11D8F, 'X'), - (0x11D90, 'V'), - (0x11D92, 'X'), - (0x11D93, 'V'), - (0x11D99, 'X'), - (0x11DA0, 'V'), - (0x11DAA, 'X'), - (0x11EE0, 'V'), - (0x11EF9, 'X'), - (0x12000, 'V'), - (0x1239A, 'X'), - (0x12400, 'V'), - (0x1246F, 'X'), - (0x12470, 'V'), - (0x12475, 'X'), - (0x12480, 'V'), - (0x12544, 'X'), - (0x13000, 'V'), - (0x1342F, 'X'), - (0x14400, 'V'), - (0x14647, 'X'), - (0x16800, 'V'), - (0x16A39, 'X'), - (0x16A40, 'V'), - (0x16A5F, 'X'), - (0x16A60, 'V'), - (0x16A6A, 'X'), - (0x16A6E, 'V'), - (0x16A70, 'X'), - (0x16AD0, 'V'), - (0x16AEE, 'X'), - (0x16AF0, 'V'), - (0x16AF6, 'X'), - (0x16B00, 'V'), - (0x16B46, 'X'), - (0x16B50, 'V'), - (0x16B5A, 'X'), - (0x16B5B, 'V'), - (0x16B62, 'X'), - (0x16B63, 'V'), - (0x16B78, 'X'), - (0x16B7D, 'V'), - (0x16B90, 'X'), - (0x16E60, 'V'), - (0x16E9B, 'X'), - (0x16F00, 'V'), - (0x16F45, 'X'), - (0x16F50, 'V'), - (0x16F7F, 'X'), - (0x16F8F, 'V'), - (0x16FA0, 'X'), - (0x16FE0, 'V'), - (0x16FE2, 'X'), - (0x17000, 'V'), - (0x187F2, 'X'), - (0x18800, 'V'), - (0x18AF3, 'X'), - (0x1B000, 'V'), - (0x1B11F, 'X'), - (0x1B170, 'V'), - (0x1B2FC, 'X'), - (0x1BC00, 'V'), - (0x1BC6B, 'X'), - (0x1BC70, 'V'), - (0x1BC7D, 'X'), - (0x1BC80, 'V'), - (0x1BC89, 'X'), - (0x1BC90, 'V'), - (0x1BC9A, 'X'), - (0x1BC9C, 'V'), - (0x1BCA0, 'I'), - (0x1BCA4, 'X'), - (0x1D000, 'V'), - (0x1D0F6, 'X'), - (0x1D100, 'V'), - (0x1D127, 'X'), - (0x1D129, 'V'), - (0x1D15E, 'M', u'𝅗𝅥'), - (0x1D15F, 'M', u'𝅘𝅥'), - (0x1D160, 'M', u'𝅘𝅥𝅮'), - (0x1D161, 'M', u'𝅘𝅥𝅯'), - (0x1D162, 'M', u'𝅘𝅥𝅰'), - (0x1D163, 'M', u'𝅘𝅥𝅱'), - (0x1D164, 'M', u'𝅘𝅥𝅲'), - (0x1D165, 'V'), - (0x1D173, 'X'), - (0x1D17B, 'V'), - (0x1D1BB, 'M', u'𝆹𝅥'), - (0x1D1BC, 'M', u'𝆺𝅥'), - (0x1D1BD, 'M', u'𝆹𝅥𝅮'), - (0x1D1BE, 'M', u'𝆺𝅥𝅮'), - (0x1D1BF, 'M', u'𝆹𝅥𝅯'), - (0x1D1C0, 'M', u'𝆺𝅥𝅯'), - (0x1D1C1, 'V'), - (0x1D1E9, 'X'), - (0x1D200, 'V'), - ] - -def _seg_58(): - return [ - (0x1D246, 'X'), - (0x1D2E0, 'V'), - (0x1D2F4, 'X'), - (0x1D300, 'V'), - (0x1D357, 'X'), - (0x1D360, 'V'), - (0x1D379, 'X'), - (0x1D400, 'M', u'a'), - (0x1D401, 'M', u'b'), - (0x1D402, 'M', u'c'), - (0x1D403, 'M', u'd'), - (0x1D404, 'M', u'e'), - (0x1D405, 'M', u'f'), - (0x1D406, 'M', u'g'), - (0x1D407, 'M', u'h'), - (0x1D408, 'M', u'i'), - (0x1D409, 'M', u'j'), - (0x1D40A, 'M', u'k'), - (0x1D40B, 'M', u'l'), - (0x1D40C, 'M', u'm'), - (0x1D40D, 'M', u'n'), - (0x1D40E, 'M', u'o'), - (0x1D40F, 'M', u'p'), - (0x1D410, 'M', u'q'), - (0x1D411, 'M', u'r'), - (0x1D412, 'M', u's'), - (0x1D413, 'M', u't'), - (0x1D414, 'M', u'u'), - (0x1D415, 'M', u'v'), - (0x1D416, 'M', u'w'), - (0x1D417, 'M', u'x'), - (0x1D418, 'M', u'y'), - (0x1D419, 'M', u'z'), - (0x1D41A, 'M', u'a'), - (0x1D41B, 'M', u'b'), - (0x1D41C, 'M', u'c'), - (0x1D41D, 'M', u'd'), - (0x1D41E, 'M', u'e'), - (0x1D41F, 'M', u'f'), - (0x1D420, 'M', u'g'), - (0x1D421, 'M', u'h'), - (0x1D422, 'M', u'i'), - (0x1D423, 'M', u'j'), - (0x1D424, 'M', u'k'), - (0x1D425, 'M', u'l'), - (0x1D426, 'M', u'm'), - (0x1D427, 'M', u'n'), - (0x1D428, 'M', u'o'), - (0x1D429, 'M', u'p'), - (0x1D42A, 'M', u'q'), - (0x1D42B, 'M', u'r'), - (0x1D42C, 'M', u's'), - (0x1D42D, 'M', u't'), - (0x1D42E, 'M', u'u'), - (0x1D42F, 'M', u'v'), - (0x1D430, 'M', u'w'), - (0x1D431, 'M', u'x'), - (0x1D432, 'M', u'y'), - (0x1D433, 'M', u'z'), - (0x1D434, 'M', u'a'), - (0x1D435, 'M', u'b'), - (0x1D436, 'M', u'c'), - (0x1D437, 'M', u'd'), - (0x1D438, 'M', u'e'), - (0x1D439, 'M', u'f'), - (0x1D43A, 'M', u'g'), - (0x1D43B, 'M', u'h'), - (0x1D43C, 'M', u'i'), - (0x1D43D, 'M', u'j'), - (0x1D43E, 'M', u'k'), - (0x1D43F, 'M', u'l'), - (0x1D440, 'M', u'm'), - (0x1D441, 'M', u'n'), - (0x1D442, 'M', u'o'), - (0x1D443, 'M', u'p'), - (0x1D444, 'M', u'q'), - (0x1D445, 'M', u'r'), - (0x1D446, 'M', u's'), - (0x1D447, 'M', u't'), - (0x1D448, 'M', u'u'), - (0x1D449, 'M', u'v'), - (0x1D44A, 'M', u'w'), - (0x1D44B, 'M', u'x'), - (0x1D44C, 'M', u'y'), - (0x1D44D, 'M', u'z'), - (0x1D44E, 'M', u'a'), - (0x1D44F, 'M', u'b'), - (0x1D450, 'M', u'c'), - (0x1D451, 'M', u'd'), - (0x1D452, 'M', u'e'), - (0x1D453, 'M', u'f'), - (0x1D454, 'M', u'g'), - (0x1D455, 'X'), - (0x1D456, 'M', u'i'), - (0x1D457, 'M', u'j'), - (0x1D458, 'M', u'k'), - (0x1D459, 'M', u'l'), - (0x1D45A, 'M', u'm'), - (0x1D45B, 'M', u'n'), - (0x1D45C, 'M', u'o'), - ] - -def _seg_59(): - return [ - (0x1D45D, 'M', u'p'), - (0x1D45E, 'M', u'q'), - (0x1D45F, 'M', u'r'), - (0x1D460, 'M', u's'), - (0x1D461, 'M', u't'), - (0x1D462, 'M', u'u'), - (0x1D463, 'M', u'v'), - (0x1D464, 'M', u'w'), - (0x1D465, 'M', u'x'), - (0x1D466, 'M', u'y'), - (0x1D467, 'M', u'z'), - (0x1D468, 'M', u'a'), - (0x1D469, 'M', u'b'), - (0x1D46A, 'M', u'c'), - (0x1D46B, 'M', u'd'), - (0x1D46C, 'M', u'e'), - (0x1D46D, 'M', u'f'), - (0x1D46E, 'M', u'g'), - (0x1D46F, 'M', u'h'), - (0x1D470, 'M', u'i'), - (0x1D471, 'M', u'j'), - (0x1D472, 'M', u'k'), - (0x1D473, 'M', u'l'), - (0x1D474, 'M', u'm'), - (0x1D475, 'M', u'n'), - (0x1D476, 'M', u'o'), - (0x1D477, 'M', u'p'), - (0x1D478, 'M', u'q'), - (0x1D479, 'M', u'r'), - (0x1D47A, 'M', u's'), - (0x1D47B, 'M', u't'), - (0x1D47C, 'M', u'u'), - (0x1D47D, 'M', u'v'), - (0x1D47E, 'M', u'w'), - (0x1D47F, 'M', u'x'), - (0x1D480, 'M', u'y'), - (0x1D481, 'M', u'z'), - (0x1D482, 'M', u'a'), - (0x1D483, 'M', u'b'), - (0x1D484, 'M', u'c'), - (0x1D485, 'M', u'd'), - (0x1D486, 'M', u'e'), - (0x1D487, 'M', u'f'), - (0x1D488, 'M', u'g'), - (0x1D489, 'M', u'h'), - (0x1D48A, 'M', u'i'), - (0x1D48B, 'M', u'j'), - (0x1D48C, 'M', u'k'), - (0x1D48D, 'M', u'l'), - (0x1D48E, 'M', u'm'), - (0x1D48F, 'M', u'n'), - (0x1D490, 'M', u'o'), - (0x1D491, 'M', u'p'), - (0x1D492, 'M', u'q'), - (0x1D493, 'M', u'r'), - (0x1D494, 'M', u's'), - (0x1D495, 'M', u't'), - (0x1D496, 'M', u'u'), - (0x1D497, 'M', u'v'), - (0x1D498, 'M', u'w'), - (0x1D499, 'M', u'x'), - (0x1D49A, 'M', u'y'), - (0x1D49B, 'M', u'z'), - (0x1D49C, 'M', u'a'), - (0x1D49D, 'X'), - (0x1D49E, 'M', u'c'), - (0x1D49F, 'M', u'd'), - (0x1D4A0, 'X'), - (0x1D4A2, 'M', u'g'), - (0x1D4A3, 'X'), - (0x1D4A5, 'M', u'j'), - (0x1D4A6, 'M', u'k'), - (0x1D4A7, 'X'), - (0x1D4A9, 'M', u'n'), - (0x1D4AA, 'M', u'o'), - (0x1D4AB, 'M', u'p'), - (0x1D4AC, 'M', u'q'), - (0x1D4AD, 'X'), - (0x1D4AE, 'M', u's'), - (0x1D4AF, 'M', u't'), - (0x1D4B0, 'M', u'u'), - (0x1D4B1, 'M', u'v'), - (0x1D4B2, 'M', u'w'), - (0x1D4B3, 'M', u'x'), - (0x1D4B4, 'M', u'y'), - (0x1D4B5, 'M', u'z'), - (0x1D4B6, 'M', u'a'), - (0x1D4B7, 'M', u'b'), - (0x1D4B8, 'M', u'c'), - (0x1D4B9, 'M', u'd'), - (0x1D4BA, 'X'), - (0x1D4BB, 'M', u'f'), - (0x1D4BC, 'X'), - (0x1D4BD, 'M', u'h'), - (0x1D4BE, 'M', u'i'), - (0x1D4BF, 'M', u'j'), - (0x1D4C0, 'M', u'k'), - (0x1D4C1, 'M', u'l'), - (0x1D4C2, 'M', u'm'), - (0x1D4C3, 'M', u'n'), - ] - -def _seg_60(): - return [ - (0x1D4C4, 'X'), - (0x1D4C5, 'M', u'p'), - (0x1D4C6, 'M', u'q'), - (0x1D4C7, 'M', u'r'), - (0x1D4C8, 'M', u's'), - (0x1D4C9, 'M', u't'), - (0x1D4CA, 'M', u'u'), - (0x1D4CB, 'M', u'v'), - (0x1D4CC, 'M', u'w'), - (0x1D4CD, 'M', u'x'), - (0x1D4CE, 'M', u'y'), - (0x1D4CF, 'M', u'z'), - (0x1D4D0, 'M', u'a'), - (0x1D4D1, 'M', u'b'), - (0x1D4D2, 'M', u'c'), - (0x1D4D3, 'M', u'd'), - (0x1D4D4, 'M', u'e'), - (0x1D4D5, 'M', u'f'), - (0x1D4D6, 'M', u'g'), - (0x1D4D7, 'M', u'h'), - (0x1D4D8, 'M', u'i'), - (0x1D4D9, 'M', u'j'), - (0x1D4DA, 'M', u'k'), - (0x1D4DB, 'M', u'l'), - (0x1D4DC, 'M', u'm'), - (0x1D4DD, 'M', u'n'), - (0x1D4DE, 'M', u'o'), - (0x1D4DF, 'M', u'p'), - (0x1D4E0, 'M', u'q'), - (0x1D4E1, 'M', u'r'), - (0x1D4E2, 'M', u's'), - (0x1D4E3, 'M', u't'), - (0x1D4E4, 'M', u'u'), - (0x1D4E5, 'M', u'v'), - (0x1D4E6, 'M', u'w'), - (0x1D4E7, 'M', u'x'), - (0x1D4E8, 'M', u'y'), - (0x1D4E9, 'M', u'z'), - (0x1D4EA, 'M', u'a'), - (0x1D4EB, 'M', u'b'), - (0x1D4EC, 'M', u'c'), - (0x1D4ED, 'M', u'd'), - (0x1D4EE, 'M', u'e'), - (0x1D4EF, 'M', u'f'), - (0x1D4F0, 'M', u'g'), - (0x1D4F1, 'M', u'h'), - (0x1D4F2, 'M', u'i'), - (0x1D4F3, 'M', u'j'), - (0x1D4F4, 'M', u'k'), - (0x1D4F5, 'M', u'l'), - (0x1D4F6, 'M', u'm'), - (0x1D4F7, 'M', u'n'), - (0x1D4F8, 'M', u'o'), - (0x1D4F9, 'M', u'p'), - (0x1D4FA, 'M', u'q'), - (0x1D4FB, 'M', u'r'), - (0x1D4FC, 'M', u's'), - (0x1D4FD, 'M', u't'), - (0x1D4FE, 'M', u'u'), - (0x1D4FF, 'M', u'v'), - (0x1D500, 'M', u'w'), - (0x1D501, 'M', u'x'), - (0x1D502, 'M', u'y'), - (0x1D503, 'M', u'z'), - (0x1D504, 'M', u'a'), - (0x1D505, 'M', u'b'), - (0x1D506, 'X'), - (0x1D507, 'M', u'd'), - (0x1D508, 'M', u'e'), - (0x1D509, 'M', u'f'), - (0x1D50A, 'M', u'g'), - (0x1D50B, 'X'), - (0x1D50D, 'M', u'j'), - (0x1D50E, 'M', u'k'), - (0x1D50F, 'M', u'l'), - (0x1D510, 'M', u'm'), - (0x1D511, 'M', u'n'), - (0x1D512, 'M', u'o'), - (0x1D513, 'M', u'p'), - (0x1D514, 'M', u'q'), - (0x1D515, 'X'), - (0x1D516, 'M', u's'), - (0x1D517, 'M', u't'), - (0x1D518, 'M', u'u'), - (0x1D519, 'M', u'v'), - (0x1D51A, 'M', u'w'), - (0x1D51B, 'M', u'x'), - (0x1D51C, 'M', u'y'), - (0x1D51D, 'X'), - (0x1D51E, 'M', u'a'), - (0x1D51F, 'M', u'b'), - (0x1D520, 'M', u'c'), - (0x1D521, 'M', u'd'), - (0x1D522, 'M', u'e'), - (0x1D523, 'M', u'f'), - (0x1D524, 'M', u'g'), - (0x1D525, 'M', u'h'), - (0x1D526, 'M', u'i'), - (0x1D527, 'M', u'j'), - (0x1D528, 'M', u'k'), - ] - -def _seg_61(): - return [ - (0x1D529, 'M', u'l'), - (0x1D52A, 'M', u'm'), - (0x1D52B, 'M', u'n'), - (0x1D52C, 'M', u'o'), - (0x1D52D, 'M', u'p'), - (0x1D52E, 'M', u'q'), - (0x1D52F, 'M', u'r'), - (0x1D530, 'M', u's'), - (0x1D531, 'M', u't'), - (0x1D532, 'M', u'u'), - (0x1D533, 'M', u'v'), - (0x1D534, 'M', u'w'), - (0x1D535, 'M', u'x'), - (0x1D536, 'M', u'y'), - (0x1D537, 'M', u'z'), - (0x1D538, 'M', u'a'), - (0x1D539, 'M', u'b'), - (0x1D53A, 'X'), - (0x1D53B, 'M', u'd'), - (0x1D53C, 'M', u'e'), - (0x1D53D, 'M', u'f'), - (0x1D53E, 'M', u'g'), - (0x1D53F, 'X'), - (0x1D540, 'M', u'i'), - (0x1D541, 'M', u'j'), - (0x1D542, 'M', u'k'), - (0x1D543, 'M', u'l'), - (0x1D544, 'M', u'm'), - (0x1D545, 'X'), - (0x1D546, 'M', u'o'), - (0x1D547, 'X'), - (0x1D54A, 'M', u's'), - (0x1D54B, 'M', u't'), - (0x1D54C, 'M', u'u'), - (0x1D54D, 'M', u'v'), - (0x1D54E, 'M', u'w'), - (0x1D54F, 'M', u'x'), - (0x1D550, 'M', u'y'), - (0x1D551, 'X'), - (0x1D552, 'M', u'a'), - (0x1D553, 'M', u'b'), - (0x1D554, 'M', u'c'), - (0x1D555, 'M', u'd'), - (0x1D556, 'M', u'e'), - (0x1D557, 'M', u'f'), - (0x1D558, 'M', u'g'), - (0x1D559, 'M', u'h'), - (0x1D55A, 'M', u'i'), - (0x1D55B, 'M', u'j'), - (0x1D55C, 'M', u'k'), - (0x1D55D, 'M', u'l'), - (0x1D55E, 'M', u'm'), - (0x1D55F, 'M', u'n'), - (0x1D560, 'M', u'o'), - (0x1D561, 'M', u'p'), - (0x1D562, 'M', u'q'), - (0x1D563, 'M', u'r'), - (0x1D564, 'M', u's'), - (0x1D565, 'M', u't'), - (0x1D566, 'M', u'u'), - (0x1D567, 'M', u'v'), - (0x1D568, 'M', u'w'), - (0x1D569, 'M', u'x'), - (0x1D56A, 'M', u'y'), - (0x1D56B, 'M', u'z'), - (0x1D56C, 'M', u'a'), - (0x1D56D, 'M', u'b'), - (0x1D56E, 'M', u'c'), - (0x1D56F, 'M', u'd'), - (0x1D570, 'M', u'e'), - (0x1D571, 'M', u'f'), - (0x1D572, 'M', u'g'), - (0x1D573, 'M', u'h'), - (0x1D574, 'M', u'i'), - (0x1D575, 'M', u'j'), - (0x1D576, 'M', u'k'), - (0x1D577, 'M', u'l'), - (0x1D578, 'M', u'm'), - (0x1D579, 'M', u'n'), - (0x1D57A, 'M', u'o'), - (0x1D57B, 'M', u'p'), - (0x1D57C, 'M', u'q'), - (0x1D57D, 'M', u'r'), - (0x1D57E, 'M', u's'), - (0x1D57F, 'M', u't'), - (0x1D580, 'M', u'u'), - (0x1D581, 'M', u'v'), - (0x1D582, 'M', u'w'), - (0x1D583, 'M', u'x'), - (0x1D584, 'M', u'y'), - (0x1D585, 'M', u'z'), - (0x1D586, 'M', u'a'), - (0x1D587, 'M', u'b'), - (0x1D588, 'M', u'c'), - (0x1D589, 'M', u'd'), - (0x1D58A, 'M', u'e'), - (0x1D58B, 'M', u'f'), - (0x1D58C, 'M', u'g'), - (0x1D58D, 'M', u'h'), - (0x1D58E, 'M', u'i'), - ] - -def _seg_62(): - return [ - (0x1D58F, 'M', u'j'), - (0x1D590, 'M', u'k'), - (0x1D591, 'M', u'l'), - (0x1D592, 'M', u'm'), - (0x1D593, 'M', u'n'), - (0x1D594, 'M', u'o'), - (0x1D595, 'M', u'p'), - (0x1D596, 'M', u'q'), - (0x1D597, 'M', u'r'), - (0x1D598, 'M', u's'), - (0x1D599, 'M', u't'), - (0x1D59A, 'M', u'u'), - (0x1D59B, 'M', u'v'), - (0x1D59C, 'M', u'w'), - (0x1D59D, 'M', u'x'), - (0x1D59E, 'M', u'y'), - (0x1D59F, 'M', u'z'), - (0x1D5A0, 'M', u'a'), - (0x1D5A1, 'M', u'b'), - (0x1D5A2, 'M', u'c'), - (0x1D5A3, 'M', u'd'), - (0x1D5A4, 'M', u'e'), - (0x1D5A5, 'M', u'f'), - (0x1D5A6, 'M', u'g'), - (0x1D5A7, 'M', u'h'), - (0x1D5A8, 'M', u'i'), - (0x1D5A9, 'M', u'j'), - (0x1D5AA, 'M', u'k'), - (0x1D5AB, 'M', u'l'), - (0x1D5AC, 'M', u'm'), - (0x1D5AD, 'M', u'n'), - (0x1D5AE, 'M', u'o'), - (0x1D5AF, 'M', u'p'), - (0x1D5B0, 'M', u'q'), - (0x1D5B1, 'M', u'r'), - (0x1D5B2, 'M', u's'), - (0x1D5B3, 'M', u't'), - (0x1D5B4, 'M', u'u'), - (0x1D5B5, 'M', u'v'), - (0x1D5B6, 'M', u'w'), - (0x1D5B7, 'M', u'x'), - (0x1D5B8, 'M', u'y'), - (0x1D5B9, 'M', u'z'), - (0x1D5BA, 'M', u'a'), - (0x1D5BB, 'M', u'b'), - (0x1D5BC, 'M', u'c'), - (0x1D5BD, 'M', u'd'), - (0x1D5BE, 'M', u'e'), - (0x1D5BF, 'M', u'f'), - (0x1D5C0, 'M', u'g'), - (0x1D5C1, 'M', u'h'), - (0x1D5C2, 'M', u'i'), - (0x1D5C3, 'M', u'j'), - (0x1D5C4, 'M', u'k'), - (0x1D5C5, 'M', u'l'), - (0x1D5C6, 'M', u'm'), - (0x1D5C7, 'M', u'n'), - (0x1D5C8, 'M', u'o'), - (0x1D5C9, 'M', u'p'), - (0x1D5CA, 'M', u'q'), - (0x1D5CB, 'M', u'r'), - (0x1D5CC, 'M', u's'), - (0x1D5CD, 'M', u't'), - (0x1D5CE, 'M', u'u'), - (0x1D5CF, 'M', u'v'), - (0x1D5D0, 'M', u'w'), - (0x1D5D1, 'M', u'x'), - (0x1D5D2, 'M', u'y'), - (0x1D5D3, 'M', u'z'), - (0x1D5D4, 'M', u'a'), - (0x1D5D5, 'M', u'b'), - (0x1D5D6, 'M', u'c'), - (0x1D5D7, 'M', u'd'), - (0x1D5D8, 'M', u'e'), - (0x1D5D9, 'M', u'f'), - (0x1D5DA, 'M', u'g'), - (0x1D5DB, 'M', u'h'), - (0x1D5DC, 'M', u'i'), - (0x1D5DD, 'M', u'j'), - (0x1D5DE, 'M', u'k'), - (0x1D5DF, 'M', u'l'), - (0x1D5E0, 'M', u'm'), - (0x1D5E1, 'M', u'n'), - (0x1D5E2, 'M', u'o'), - (0x1D5E3, 'M', u'p'), - (0x1D5E4, 'M', u'q'), - (0x1D5E5, 'M', u'r'), - (0x1D5E6, 'M', u's'), - (0x1D5E7, 'M', u't'), - (0x1D5E8, 'M', u'u'), - (0x1D5E9, 'M', u'v'), - (0x1D5EA, 'M', u'w'), - (0x1D5EB, 'M', u'x'), - (0x1D5EC, 'M', u'y'), - (0x1D5ED, 'M', u'z'), - (0x1D5EE, 'M', u'a'), - (0x1D5EF, 'M', u'b'), - (0x1D5F0, 'M', u'c'), - (0x1D5F1, 'M', u'd'), - (0x1D5F2, 'M', u'e'), - ] - -def _seg_63(): - return [ - (0x1D5F3, 'M', u'f'), - (0x1D5F4, 'M', u'g'), - (0x1D5F5, 'M', u'h'), - (0x1D5F6, 'M', u'i'), - (0x1D5F7, 'M', u'j'), - (0x1D5F8, 'M', u'k'), - (0x1D5F9, 'M', u'l'), - (0x1D5FA, 'M', u'm'), - (0x1D5FB, 'M', u'n'), - (0x1D5FC, 'M', u'o'), - (0x1D5FD, 'M', u'p'), - (0x1D5FE, 'M', u'q'), - (0x1D5FF, 'M', u'r'), - (0x1D600, 'M', u's'), - (0x1D601, 'M', u't'), - (0x1D602, 'M', u'u'), - (0x1D603, 'M', u'v'), - (0x1D604, 'M', u'w'), - (0x1D605, 'M', u'x'), - (0x1D606, 'M', u'y'), - (0x1D607, 'M', u'z'), - (0x1D608, 'M', u'a'), - (0x1D609, 'M', u'b'), - (0x1D60A, 'M', u'c'), - (0x1D60B, 'M', u'd'), - (0x1D60C, 'M', u'e'), - (0x1D60D, 'M', u'f'), - (0x1D60E, 'M', u'g'), - (0x1D60F, 'M', u'h'), - (0x1D610, 'M', u'i'), - (0x1D611, 'M', u'j'), - (0x1D612, 'M', u'k'), - (0x1D613, 'M', u'l'), - (0x1D614, 'M', u'm'), - (0x1D615, 'M', u'n'), - (0x1D616, 'M', u'o'), - (0x1D617, 'M', u'p'), - (0x1D618, 'M', u'q'), - (0x1D619, 'M', u'r'), - (0x1D61A, 'M', u's'), - (0x1D61B, 'M', u't'), - (0x1D61C, 'M', u'u'), - (0x1D61D, 'M', u'v'), - (0x1D61E, 'M', u'w'), - (0x1D61F, 'M', u'x'), - (0x1D620, 'M', u'y'), - (0x1D621, 'M', u'z'), - (0x1D622, 'M', u'a'), - (0x1D623, 'M', u'b'), - (0x1D624, 'M', u'c'), - (0x1D625, 'M', u'd'), - (0x1D626, 'M', u'e'), - (0x1D627, 'M', u'f'), - (0x1D628, 'M', u'g'), - (0x1D629, 'M', u'h'), - (0x1D62A, 'M', u'i'), - (0x1D62B, 'M', u'j'), - (0x1D62C, 'M', u'k'), - (0x1D62D, 'M', u'l'), - (0x1D62E, 'M', u'm'), - (0x1D62F, 'M', u'n'), - (0x1D630, 'M', u'o'), - (0x1D631, 'M', u'p'), - (0x1D632, 'M', u'q'), - (0x1D633, 'M', u'r'), - (0x1D634, 'M', u's'), - (0x1D635, 'M', u't'), - (0x1D636, 'M', u'u'), - (0x1D637, 'M', u'v'), - (0x1D638, 'M', u'w'), - (0x1D639, 'M', u'x'), - (0x1D63A, 'M', u'y'), - (0x1D63B, 'M', u'z'), - (0x1D63C, 'M', u'a'), - (0x1D63D, 'M', u'b'), - (0x1D63E, 'M', u'c'), - (0x1D63F, 'M', u'd'), - (0x1D640, 'M', u'e'), - (0x1D641, 'M', u'f'), - (0x1D642, 'M', u'g'), - (0x1D643, 'M', u'h'), - (0x1D644, 'M', u'i'), - (0x1D645, 'M', u'j'), - (0x1D646, 'M', u'k'), - (0x1D647, 'M', u'l'), - (0x1D648, 'M', u'm'), - (0x1D649, 'M', u'n'), - (0x1D64A, 'M', u'o'), - (0x1D64B, 'M', u'p'), - (0x1D64C, 'M', u'q'), - (0x1D64D, 'M', u'r'), - (0x1D64E, 'M', u's'), - (0x1D64F, 'M', u't'), - (0x1D650, 'M', u'u'), - (0x1D651, 'M', u'v'), - (0x1D652, 'M', u'w'), - (0x1D653, 'M', u'x'), - (0x1D654, 'M', u'y'), - (0x1D655, 'M', u'z'), - (0x1D656, 'M', u'a'), - ] - -def _seg_64(): - return [ - (0x1D657, 'M', u'b'), - (0x1D658, 'M', u'c'), - (0x1D659, 'M', u'd'), - (0x1D65A, 'M', u'e'), - (0x1D65B, 'M', u'f'), - (0x1D65C, 'M', u'g'), - (0x1D65D, 'M', u'h'), - (0x1D65E, 'M', u'i'), - (0x1D65F, 'M', u'j'), - (0x1D660, 'M', u'k'), - (0x1D661, 'M', u'l'), - (0x1D662, 'M', u'm'), - (0x1D663, 'M', u'n'), - (0x1D664, 'M', u'o'), - (0x1D665, 'M', u'p'), - (0x1D666, 'M', u'q'), - (0x1D667, 'M', u'r'), - (0x1D668, 'M', u's'), - (0x1D669, 'M', u't'), - (0x1D66A, 'M', u'u'), - (0x1D66B, 'M', u'v'), - (0x1D66C, 'M', u'w'), - (0x1D66D, 'M', u'x'), - (0x1D66E, 'M', u'y'), - (0x1D66F, 'M', u'z'), - (0x1D670, 'M', u'a'), - (0x1D671, 'M', u'b'), - (0x1D672, 'M', u'c'), - (0x1D673, 'M', u'd'), - (0x1D674, 'M', u'e'), - (0x1D675, 'M', u'f'), - (0x1D676, 'M', u'g'), - (0x1D677, 'M', u'h'), - (0x1D678, 'M', u'i'), - (0x1D679, 'M', u'j'), - (0x1D67A, 'M', u'k'), - (0x1D67B, 'M', u'l'), - (0x1D67C, 'M', u'm'), - (0x1D67D, 'M', u'n'), - (0x1D67E, 'M', u'o'), - (0x1D67F, 'M', u'p'), - (0x1D680, 'M', u'q'), - (0x1D681, 'M', u'r'), - (0x1D682, 'M', u's'), - (0x1D683, 'M', u't'), - (0x1D684, 'M', u'u'), - (0x1D685, 'M', u'v'), - (0x1D686, 'M', u'w'), - (0x1D687, 'M', u'x'), - (0x1D688, 'M', u'y'), - (0x1D689, 'M', u'z'), - (0x1D68A, 'M', u'a'), - (0x1D68B, 'M', u'b'), - (0x1D68C, 'M', u'c'), - (0x1D68D, 'M', u'd'), - (0x1D68E, 'M', u'e'), - (0x1D68F, 'M', u'f'), - (0x1D690, 'M', u'g'), - (0x1D691, 'M', u'h'), - (0x1D692, 'M', u'i'), - (0x1D693, 'M', u'j'), - (0x1D694, 'M', u'k'), - (0x1D695, 'M', u'l'), - (0x1D696, 'M', u'm'), - (0x1D697, 'M', u'n'), - (0x1D698, 'M', u'o'), - (0x1D699, 'M', u'p'), - (0x1D69A, 'M', u'q'), - (0x1D69B, 'M', u'r'), - (0x1D69C, 'M', u's'), - (0x1D69D, 'M', u't'), - (0x1D69E, 'M', u'u'), - (0x1D69F, 'M', u'v'), - (0x1D6A0, 'M', u'w'), - (0x1D6A1, 'M', u'x'), - (0x1D6A2, 'M', u'y'), - (0x1D6A3, 'M', u'z'), - (0x1D6A4, 'M', u'ı'), - (0x1D6A5, 'M', u'ȷ'), - (0x1D6A6, 'X'), - (0x1D6A8, 'M', u'α'), - (0x1D6A9, 'M', u'β'), - (0x1D6AA, 'M', u'γ'), - (0x1D6AB, 'M', u'δ'), - (0x1D6AC, 'M', u'ε'), - (0x1D6AD, 'M', u'ζ'), - (0x1D6AE, 'M', u'η'), - (0x1D6AF, 'M', u'θ'), - (0x1D6B0, 'M', u'ι'), - (0x1D6B1, 'M', u'κ'), - (0x1D6B2, 'M', u'λ'), - (0x1D6B3, 'M', u'μ'), - (0x1D6B4, 'M', u'ν'), - (0x1D6B5, 'M', u'ξ'), - (0x1D6B6, 'M', u'ο'), - (0x1D6B7, 'M', u'π'), - (0x1D6B8, 'M', u'ρ'), - (0x1D6B9, 'M', u'θ'), - (0x1D6BA, 'M', u'σ'), - (0x1D6BB, 'M', u'τ'), - ] - -def _seg_65(): - return [ - (0x1D6BC, 'M', u'υ'), - (0x1D6BD, 'M', u'φ'), - (0x1D6BE, 'M', u'χ'), - (0x1D6BF, 'M', u'ψ'), - (0x1D6C0, 'M', u'ω'), - (0x1D6C1, 'M', u'∇'), - (0x1D6C2, 'M', u'α'), - (0x1D6C3, 'M', u'β'), - (0x1D6C4, 'M', u'γ'), - (0x1D6C5, 'M', u'δ'), - (0x1D6C6, 'M', u'ε'), - (0x1D6C7, 'M', u'ζ'), - (0x1D6C8, 'M', u'η'), - (0x1D6C9, 'M', u'θ'), - (0x1D6CA, 'M', u'ι'), - (0x1D6CB, 'M', u'κ'), - (0x1D6CC, 'M', u'λ'), - (0x1D6CD, 'M', u'μ'), - (0x1D6CE, 'M', u'ν'), - (0x1D6CF, 'M', u'ξ'), - (0x1D6D0, 'M', u'ο'), - (0x1D6D1, 'M', u'π'), - (0x1D6D2, 'M', u'ρ'), - (0x1D6D3, 'M', u'σ'), - (0x1D6D5, 'M', u'τ'), - (0x1D6D6, 'M', u'υ'), - (0x1D6D7, 'M', u'φ'), - (0x1D6D8, 'M', u'χ'), - (0x1D6D9, 'M', u'ψ'), - (0x1D6DA, 'M', u'ω'), - (0x1D6DB, 'M', u'∂'), - (0x1D6DC, 'M', u'ε'), - (0x1D6DD, 'M', u'θ'), - (0x1D6DE, 'M', u'κ'), - (0x1D6DF, 'M', u'φ'), - (0x1D6E0, 'M', u'ρ'), - (0x1D6E1, 'M', u'π'), - (0x1D6E2, 'M', u'α'), - (0x1D6E3, 'M', u'β'), - (0x1D6E4, 'M', u'γ'), - (0x1D6E5, 'M', u'δ'), - (0x1D6E6, 'M', u'ε'), - (0x1D6E7, 'M', u'ζ'), - (0x1D6E8, 'M', u'η'), - (0x1D6E9, 'M', u'θ'), - (0x1D6EA, 'M', u'ι'), - (0x1D6EB, 'M', u'κ'), - (0x1D6EC, 'M', u'λ'), - (0x1D6ED, 'M', u'μ'), - (0x1D6EE, 'M', u'ν'), - (0x1D6EF, 'M', u'ξ'), - (0x1D6F0, 'M', u'ο'), - (0x1D6F1, 'M', u'π'), - (0x1D6F2, 'M', u'ρ'), - (0x1D6F3, 'M', u'θ'), - (0x1D6F4, 'M', u'σ'), - (0x1D6F5, 'M', u'τ'), - (0x1D6F6, 'M', u'υ'), - (0x1D6F7, 'M', u'φ'), - (0x1D6F8, 'M', u'χ'), - (0x1D6F9, 'M', u'ψ'), - (0x1D6FA, 'M', u'ω'), - (0x1D6FB, 'M', u'∇'), - (0x1D6FC, 'M', u'α'), - (0x1D6FD, 'M', u'β'), - (0x1D6FE, 'M', u'γ'), - (0x1D6FF, 'M', u'δ'), - (0x1D700, 'M', u'ε'), - (0x1D701, 'M', u'ζ'), - (0x1D702, 'M', u'η'), - (0x1D703, 'M', u'θ'), - (0x1D704, 'M', u'ι'), - (0x1D705, 'M', u'κ'), - (0x1D706, 'M', u'λ'), - (0x1D707, 'M', u'μ'), - (0x1D708, 'M', u'ν'), - (0x1D709, 'M', u'ξ'), - (0x1D70A, 'M', u'ο'), - (0x1D70B, 'M', u'π'), - (0x1D70C, 'M', u'ρ'), - (0x1D70D, 'M', u'σ'), - (0x1D70F, 'M', u'τ'), - (0x1D710, 'M', u'υ'), - (0x1D711, 'M', u'φ'), - (0x1D712, 'M', u'χ'), - (0x1D713, 'M', u'ψ'), - (0x1D714, 'M', u'ω'), - (0x1D715, 'M', u'∂'), - (0x1D716, 'M', u'ε'), - (0x1D717, 'M', u'θ'), - (0x1D718, 'M', u'κ'), - (0x1D719, 'M', u'φ'), - (0x1D71A, 'M', u'ρ'), - (0x1D71B, 'M', u'π'), - (0x1D71C, 'M', u'α'), - (0x1D71D, 'M', u'β'), - (0x1D71E, 'M', u'γ'), - (0x1D71F, 'M', u'δ'), - (0x1D720, 'M', u'ε'), - (0x1D721, 'M', u'ζ'), - ] - -def _seg_66(): - return [ - (0x1D722, 'M', u'η'), - (0x1D723, 'M', u'θ'), - (0x1D724, 'M', u'ι'), - (0x1D725, 'M', u'κ'), - (0x1D726, 'M', u'λ'), - (0x1D727, 'M', u'μ'), - (0x1D728, 'M', u'ν'), - (0x1D729, 'M', u'ξ'), - (0x1D72A, 'M', u'ο'), - (0x1D72B, 'M', u'π'), - (0x1D72C, 'M', u'ρ'), - (0x1D72D, 'M', u'θ'), - (0x1D72E, 'M', u'σ'), - (0x1D72F, 'M', u'τ'), - (0x1D730, 'M', u'υ'), - (0x1D731, 'M', u'φ'), - (0x1D732, 'M', u'χ'), - (0x1D733, 'M', u'ψ'), - (0x1D734, 'M', u'ω'), - (0x1D735, 'M', u'∇'), - (0x1D736, 'M', u'α'), - (0x1D737, 'M', u'β'), - (0x1D738, 'M', u'γ'), - (0x1D739, 'M', u'δ'), - (0x1D73A, 'M', u'ε'), - (0x1D73B, 'M', u'ζ'), - (0x1D73C, 'M', u'η'), - (0x1D73D, 'M', u'θ'), - (0x1D73E, 'M', u'ι'), - (0x1D73F, 'M', u'κ'), - (0x1D740, 'M', u'λ'), - (0x1D741, 'M', u'μ'), - (0x1D742, 'M', u'ν'), - (0x1D743, 'M', u'ξ'), - (0x1D744, 'M', u'ο'), - (0x1D745, 'M', u'π'), - (0x1D746, 'M', u'ρ'), - (0x1D747, 'M', u'σ'), - (0x1D749, 'M', u'τ'), - (0x1D74A, 'M', u'υ'), - (0x1D74B, 'M', u'φ'), - (0x1D74C, 'M', u'χ'), - (0x1D74D, 'M', u'ψ'), - (0x1D74E, 'M', u'ω'), - (0x1D74F, 'M', u'∂'), - (0x1D750, 'M', u'ε'), - (0x1D751, 'M', u'θ'), - (0x1D752, 'M', u'κ'), - (0x1D753, 'M', u'φ'), - (0x1D754, 'M', u'ρ'), - (0x1D755, 'M', u'π'), - (0x1D756, 'M', u'α'), - (0x1D757, 'M', u'β'), - (0x1D758, 'M', u'γ'), - (0x1D759, 'M', u'δ'), - (0x1D75A, 'M', u'ε'), - (0x1D75B, 'M', u'ζ'), - (0x1D75C, 'M', u'η'), - (0x1D75D, 'M', u'θ'), - (0x1D75E, 'M', u'ι'), - (0x1D75F, 'M', u'κ'), - (0x1D760, 'M', u'λ'), - (0x1D761, 'M', u'μ'), - (0x1D762, 'M', u'ν'), - (0x1D763, 'M', u'ξ'), - (0x1D764, 'M', u'ο'), - (0x1D765, 'M', u'π'), - (0x1D766, 'M', u'ρ'), - (0x1D767, 'M', u'θ'), - (0x1D768, 'M', u'σ'), - (0x1D769, 'M', u'τ'), - (0x1D76A, 'M', u'υ'), - (0x1D76B, 'M', u'φ'), - (0x1D76C, 'M', u'χ'), - (0x1D76D, 'M', u'ψ'), - (0x1D76E, 'M', u'ω'), - (0x1D76F, 'M', u'∇'), - (0x1D770, 'M', u'α'), - (0x1D771, 'M', u'β'), - (0x1D772, 'M', u'γ'), - (0x1D773, 'M', u'δ'), - (0x1D774, 'M', u'ε'), - (0x1D775, 'M', u'ζ'), - (0x1D776, 'M', u'η'), - (0x1D777, 'M', u'θ'), - (0x1D778, 'M', u'ι'), - (0x1D779, 'M', u'κ'), - (0x1D77A, 'M', u'λ'), - (0x1D77B, 'M', u'μ'), - (0x1D77C, 'M', u'ν'), - (0x1D77D, 'M', u'ξ'), - (0x1D77E, 'M', u'ο'), - (0x1D77F, 'M', u'π'), - (0x1D780, 'M', u'ρ'), - (0x1D781, 'M', u'σ'), - (0x1D783, 'M', u'τ'), - (0x1D784, 'M', u'υ'), - (0x1D785, 'M', u'φ'), - (0x1D786, 'M', u'χ'), - (0x1D787, 'M', u'ψ'), - ] - -def _seg_67(): - return [ - (0x1D788, 'M', u'ω'), - (0x1D789, 'M', u'∂'), - (0x1D78A, 'M', u'ε'), - (0x1D78B, 'M', u'θ'), - (0x1D78C, 'M', u'κ'), - (0x1D78D, 'M', u'φ'), - (0x1D78E, 'M', u'ρ'), - (0x1D78F, 'M', u'π'), - (0x1D790, 'M', u'α'), - (0x1D791, 'M', u'β'), - (0x1D792, 'M', u'γ'), - (0x1D793, 'M', u'δ'), - (0x1D794, 'M', u'ε'), - (0x1D795, 'M', u'ζ'), - (0x1D796, 'M', u'η'), - (0x1D797, 'M', u'θ'), - (0x1D798, 'M', u'ι'), - (0x1D799, 'M', u'κ'), - (0x1D79A, 'M', u'λ'), - (0x1D79B, 'M', u'μ'), - (0x1D79C, 'M', u'ν'), - (0x1D79D, 'M', u'ξ'), - (0x1D79E, 'M', u'ο'), - (0x1D79F, 'M', u'π'), - (0x1D7A0, 'M', u'ρ'), - (0x1D7A1, 'M', u'θ'), - (0x1D7A2, 'M', u'σ'), - (0x1D7A3, 'M', u'τ'), - (0x1D7A4, 'M', u'υ'), - (0x1D7A5, 'M', u'φ'), - (0x1D7A6, 'M', u'χ'), - (0x1D7A7, 'M', u'ψ'), - (0x1D7A8, 'M', u'ω'), - (0x1D7A9, 'M', u'∇'), - (0x1D7AA, 'M', u'α'), - (0x1D7AB, 'M', u'β'), - (0x1D7AC, 'M', u'γ'), - (0x1D7AD, 'M', u'δ'), - (0x1D7AE, 'M', u'ε'), - (0x1D7AF, 'M', u'ζ'), - (0x1D7B0, 'M', u'η'), - (0x1D7B1, 'M', u'θ'), - (0x1D7B2, 'M', u'ι'), - (0x1D7B3, 'M', u'κ'), - (0x1D7B4, 'M', u'λ'), - (0x1D7B5, 'M', u'μ'), - (0x1D7B6, 'M', u'ν'), - (0x1D7B7, 'M', u'ξ'), - (0x1D7B8, 'M', u'ο'), - (0x1D7B9, 'M', u'π'), - (0x1D7BA, 'M', u'ρ'), - (0x1D7BB, 'M', u'σ'), - (0x1D7BD, 'M', u'τ'), - (0x1D7BE, 'M', u'υ'), - (0x1D7BF, 'M', u'φ'), - (0x1D7C0, 'M', u'χ'), - (0x1D7C1, 'M', u'ψ'), - (0x1D7C2, 'M', u'ω'), - (0x1D7C3, 'M', u'∂'), - (0x1D7C4, 'M', u'ε'), - (0x1D7C5, 'M', u'θ'), - (0x1D7C6, 'M', u'κ'), - (0x1D7C7, 'M', u'φ'), - (0x1D7C8, 'M', u'ρ'), - (0x1D7C9, 'M', u'π'), - (0x1D7CA, 'M', u'ϝ'), - (0x1D7CC, 'X'), - (0x1D7CE, 'M', u'0'), - (0x1D7CF, 'M', u'1'), - (0x1D7D0, 'M', u'2'), - (0x1D7D1, 'M', u'3'), - (0x1D7D2, 'M', u'4'), - (0x1D7D3, 'M', u'5'), - (0x1D7D4, 'M', u'6'), - (0x1D7D5, 'M', u'7'), - (0x1D7D6, 'M', u'8'), - (0x1D7D7, 'M', u'9'), - (0x1D7D8, 'M', u'0'), - (0x1D7D9, 'M', u'1'), - (0x1D7DA, 'M', u'2'), - (0x1D7DB, 'M', u'3'), - (0x1D7DC, 'M', u'4'), - (0x1D7DD, 'M', u'5'), - (0x1D7DE, 'M', u'6'), - (0x1D7DF, 'M', u'7'), - (0x1D7E0, 'M', u'8'), - (0x1D7E1, 'M', u'9'), - (0x1D7E2, 'M', u'0'), - (0x1D7E3, 'M', u'1'), - (0x1D7E4, 'M', u'2'), - (0x1D7E5, 'M', u'3'), - (0x1D7E6, 'M', u'4'), - (0x1D7E7, 'M', u'5'), - (0x1D7E8, 'M', u'6'), - (0x1D7E9, 'M', u'7'), - (0x1D7EA, 'M', u'8'), - (0x1D7EB, 'M', u'9'), - (0x1D7EC, 'M', u'0'), - (0x1D7ED, 'M', u'1'), - (0x1D7EE, 'M', u'2'), - ] - -def _seg_68(): - return [ - (0x1D7EF, 'M', u'3'), - (0x1D7F0, 'M', u'4'), - (0x1D7F1, 'M', u'5'), - (0x1D7F2, 'M', u'6'), - (0x1D7F3, 'M', u'7'), - (0x1D7F4, 'M', u'8'), - (0x1D7F5, 'M', u'9'), - (0x1D7F6, 'M', u'0'), - (0x1D7F7, 'M', u'1'), - (0x1D7F8, 'M', u'2'), - (0x1D7F9, 'M', u'3'), - (0x1D7FA, 'M', u'4'), - (0x1D7FB, 'M', u'5'), - (0x1D7FC, 'M', u'6'), - (0x1D7FD, 'M', u'7'), - (0x1D7FE, 'M', u'8'), - (0x1D7FF, 'M', u'9'), - (0x1D800, 'V'), - (0x1DA8C, 'X'), - (0x1DA9B, 'V'), - (0x1DAA0, 'X'), - (0x1DAA1, 'V'), - (0x1DAB0, 'X'), - (0x1E000, 'V'), - (0x1E007, 'X'), - (0x1E008, 'V'), - (0x1E019, 'X'), - (0x1E01B, 'V'), - (0x1E022, 'X'), - (0x1E023, 'V'), - (0x1E025, 'X'), - (0x1E026, 'V'), - (0x1E02B, 'X'), - (0x1E800, 'V'), - (0x1E8C5, 'X'), - (0x1E8C7, 'V'), - (0x1E8D7, 'X'), - (0x1E900, 'M', u'𞤢'), - (0x1E901, 'M', u'𞤣'), - (0x1E902, 'M', u'𞤤'), - (0x1E903, 'M', u'𞤥'), - (0x1E904, 'M', u'𞤦'), - (0x1E905, 'M', u'𞤧'), - (0x1E906, 'M', u'𞤨'), - (0x1E907, 'M', u'𞤩'), - (0x1E908, 'M', u'𞤪'), - (0x1E909, 'M', u'𞤫'), - (0x1E90A, 'M', u'𞤬'), - (0x1E90B, 'M', u'𞤭'), - (0x1E90C, 'M', u'𞤮'), - (0x1E90D, 'M', u'𞤯'), - (0x1E90E, 'M', u'𞤰'), - (0x1E90F, 'M', u'𞤱'), - (0x1E910, 'M', u'𞤲'), - (0x1E911, 'M', u'𞤳'), - (0x1E912, 'M', u'𞤴'), - (0x1E913, 'M', u'𞤵'), - (0x1E914, 'M', u'𞤶'), - (0x1E915, 'M', u'𞤷'), - (0x1E916, 'M', u'𞤸'), - (0x1E917, 'M', u'𞤹'), - (0x1E918, 'M', u'𞤺'), - (0x1E919, 'M', u'𞤻'), - (0x1E91A, 'M', u'𞤼'), - (0x1E91B, 'M', u'𞤽'), - (0x1E91C, 'M', u'𞤾'), - (0x1E91D, 'M', u'𞤿'), - (0x1E91E, 'M', u'𞥀'), - (0x1E91F, 'M', u'𞥁'), - (0x1E920, 'M', u'𞥂'), - (0x1E921, 'M', u'𞥃'), - (0x1E922, 'V'), - (0x1E94B, 'X'), - (0x1E950, 'V'), - (0x1E95A, 'X'), - (0x1E95E, 'V'), - (0x1E960, 'X'), - (0x1EC71, 'V'), - (0x1ECB5, 'X'), - (0x1EE00, 'M', u'ا'), - (0x1EE01, 'M', u'ب'), - (0x1EE02, 'M', u'ج'), - (0x1EE03, 'M', u'د'), - (0x1EE04, 'X'), - (0x1EE05, 'M', u'و'), - (0x1EE06, 'M', u'ز'), - (0x1EE07, 'M', u'ح'), - (0x1EE08, 'M', u'ط'), - (0x1EE09, 'M', u'ي'), - (0x1EE0A, 'M', u'ك'), - (0x1EE0B, 'M', u'ل'), - (0x1EE0C, 'M', u'م'), - (0x1EE0D, 'M', u'ن'), - (0x1EE0E, 'M', u'س'), - (0x1EE0F, 'M', u'ع'), - (0x1EE10, 'M', u'ف'), - (0x1EE11, 'M', u'ص'), - (0x1EE12, 'M', u'ق'), - (0x1EE13, 'M', u'ر'), - (0x1EE14, 'M', u'ش'), - ] - -def _seg_69(): - return [ - (0x1EE15, 'M', u'ت'), - (0x1EE16, 'M', u'ث'), - (0x1EE17, 'M', u'خ'), - (0x1EE18, 'M', u'ذ'), - (0x1EE19, 'M', u'ض'), - (0x1EE1A, 'M', u'ظ'), - (0x1EE1B, 'M', u'غ'), - (0x1EE1C, 'M', u'ٮ'), - (0x1EE1D, 'M', u'ں'), - (0x1EE1E, 'M', u'ڡ'), - (0x1EE1F, 'M', u'ٯ'), - (0x1EE20, 'X'), - (0x1EE21, 'M', u'ب'), - (0x1EE22, 'M', u'ج'), - (0x1EE23, 'X'), - (0x1EE24, 'M', u'ه'), - (0x1EE25, 'X'), - (0x1EE27, 'M', u'ح'), - (0x1EE28, 'X'), - (0x1EE29, 'M', u'ي'), - (0x1EE2A, 'M', u'ك'), - (0x1EE2B, 'M', u'ل'), - (0x1EE2C, 'M', u'م'), - (0x1EE2D, 'M', u'ن'), - (0x1EE2E, 'M', u'س'), - (0x1EE2F, 'M', u'ع'), - (0x1EE30, 'M', u'ف'), - (0x1EE31, 'M', u'ص'), - (0x1EE32, 'M', u'ق'), - (0x1EE33, 'X'), - (0x1EE34, 'M', u'ش'), - (0x1EE35, 'M', u'ت'), - (0x1EE36, 'M', u'ث'), - (0x1EE37, 'M', u'خ'), - (0x1EE38, 'X'), - (0x1EE39, 'M', u'ض'), - (0x1EE3A, 'X'), - (0x1EE3B, 'M', u'غ'), - (0x1EE3C, 'X'), - (0x1EE42, 'M', u'ج'), - (0x1EE43, 'X'), - (0x1EE47, 'M', u'ح'), - (0x1EE48, 'X'), - (0x1EE49, 'M', u'ي'), - (0x1EE4A, 'X'), - (0x1EE4B, 'M', u'ل'), - (0x1EE4C, 'X'), - (0x1EE4D, 'M', u'ن'), - (0x1EE4E, 'M', u'س'), - (0x1EE4F, 'M', u'ع'), - (0x1EE50, 'X'), - (0x1EE51, 'M', u'ص'), - (0x1EE52, 'M', u'ق'), - (0x1EE53, 'X'), - (0x1EE54, 'M', u'ش'), - (0x1EE55, 'X'), - (0x1EE57, 'M', u'خ'), - (0x1EE58, 'X'), - (0x1EE59, 'M', u'ض'), - (0x1EE5A, 'X'), - (0x1EE5B, 'M', u'غ'), - (0x1EE5C, 'X'), - (0x1EE5D, 'M', u'ں'), - (0x1EE5E, 'X'), - (0x1EE5F, 'M', u'ٯ'), - (0x1EE60, 'X'), - (0x1EE61, 'M', u'ب'), - (0x1EE62, 'M', u'ج'), - (0x1EE63, 'X'), - (0x1EE64, 'M', u'ه'), - (0x1EE65, 'X'), - (0x1EE67, 'M', u'ح'), - (0x1EE68, 'M', u'ط'), - (0x1EE69, 'M', u'ي'), - (0x1EE6A, 'M', u'ك'), - (0x1EE6B, 'X'), - (0x1EE6C, 'M', u'م'), - (0x1EE6D, 'M', u'ن'), - (0x1EE6E, 'M', u'س'), - (0x1EE6F, 'M', u'ع'), - (0x1EE70, 'M', u'ف'), - (0x1EE71, 'M', u'ص'), - (0x1EE72, 'M', u'ق'), - (0x1EE73, 'X'), - (0x1EE74, 'M', u'ش'), - (0x1EE75, 'M', u'ت'), - (0x1EE76, 'M', u'ث'), - (0x1EE77, 'M', u'خ'), - (0x1EE78, 'X'), - (0x1EE79, 'M', u'ض'), - (0x1EE7A, 'M', u'ظ'), - (0x1EE7B, 'M', u'غ'), - (0x1EE7C, 'M', u'ٮ'), - (0x1EE7D, 'X'), - (0x1EE7E, 'M', u'ڡ'), - (0x1EE7F, 'X'), - (0x1EE80, 'M', u'ا'), - (0x1EE81, 'M', u'ب'), - (0x1EE82, 'M', u'ج'), - (0x1EE83, 'M', u'د'), - ] - -def _seg_70(): - return [ - (0x1EE84, 'M', u'ه'), - (0x1EE85, 'M', u'و'), - (0x1EE86, 'M', u'ز'), - (0x1EE87, 'M', u'ح'), - (0x1EE88, 'M', u'ط'), - (0x1EE89, 'M', u'ي'), - (0x1EE8A, 'X'), - (0x1EE8B, 'M', u'ل'), - (0x1EE8C, 'M', u'م'), - (0x1EE8D, 'M', u'ن'), - (0x1EE8E, 'M', u'س'), - (0x1EE8F, 'M', u'ع'), - (0x1EE90, 'M', u'ف'), - (0x1EE91, 'M', u'ص'), - (0x1EE92, 'M', u'ق'), - (0x1EE93, 'M', u'ر'), - (0x1EE94, 'M', u'ش'), - (0x1EE95, 'M', u'ت'), - (0x1EE96, 'M', u'ث'), - (0x1EE97, 'M', u'خ'), - (0x1EE98, 'M', u'ذ'), - (0x1EE99, 'M', u'ض'), - (0x1EE9A, 'M', u'ظ'), - (0x1EE9B, 'M', u'غ'), - (0x1EE9C, 'X'), - (0x1EEA1, 'M', u'ب'), - (0x1EEA2, 'M', u'ج'), - (0x1EEA3, 'M', u'د'), - (0x1EEA4, 'X'), - (0x1EEA5, 'M', u'و'), - (0x1EEA6, 'M', u'ز'), - (0x1EEA7, 'M', u'ح'), - (0x1EEA8, 'M', u'ط'), - (0x1EEA9, 'M', u'ي'), - (0x1EEAA, 'X'), - (0x1EEAB, 'M', u'ل'), - (0x1EEAC, 'M', u'م'), - (0x1EEAD, 'M', u'ن'), - (0x1EEAE, 'M', u'س'), - (0x1EEAF, 'M', u'ع'), - (0x1EEB0, 'M', u'ف'), - (0x1EEB1, 'M', u'ص'), - (0x1EEB2, 'M', u'ق'), - (0x1EEB3, 'M', u'ر'), - (0x1EEB4, 'M', u'ش'), - (0x1EEB5, 'M', u'ت'), - (0x1EEB6, 'M', u'ث'), - (0x1EEB7, 'M', u'خ'), - (0x1EEB8, 'M', u'ذ'), - (0x1EEB9, 'M', u'ض'), - (0x1EEBA, 'M', u'ظ'), - (0x1EEBB, 'M', u'غ'), - (0x1EEBC, 'X'), - (0x1EEF0, 'V'), - (0x1EEF2, 'X'), - (0x1F000, 'V'), - (0x1F02C, 'X'), - (0x1F030, 'V'), - (0x1F094, 'X'), - (0x1F0A0, 'V'), - (0x1F0AF, 'X'), - (0x1F0B1, 'V'), - (0x1F0C0, 'X'), - (0x1F0C1, 'V'), - (0x1F0D0, 'X'), - (0x1F0D1, 'V'), - (0x1F0F6, 'X'), - (0x1F101, '3', u'0,'), - (0x1F102, '3', u'1,'), - (0x1F103, '3', u'2,'), - (0x1F104, '3', u'3,'), - (0x1F105, '3', u'4,'), - (0x1F106, '3', u'5,'), - (0x1F107, '3', u'6,'), - (0x1F108, '3', u'7,'), - (0x1F109, '3', u'8,'), - (0x1F10A, '3', u'9,'), - (0x1F10B, 'V'), - (0x1F10D, 'X'), - (0x1F110, '3', u'(a)'), - (0x1F111, '3', u'(b)'), - (0x1F112, '3', u'(c)'), - (0x1F113, '3', u'(d)'), - (0x1F114, '3', u'(e)'), - (0x1F115, '3', u'(f)'), - (0x1F116, '3', u'(g)'), - (0x1F117, '3', u'(h)'), - (0x1F118, '3', u'(i)'), - (0x1F119, '3', u'(j)'), - (0x1F11A, '3', u'(k)'), - (0x1F11B, '3', u'(l)'), - (0x1F11C, '3', u'(m)'), - (0x1F11D, '3', u'(n)'), - (0x1F11E, '3', u'(o)'), - (0x1F11F, '3', u'(p)'), - (0x1F120, '3', u'(q)'), - (0x1F121, '3', u'(r)'), - (0x1F122, '3', u'(s)'), - (0x1F123, '3', u'(t)'), - (0x1F124, '3', u'(u)'), - ] - -def _seg_71(): - return [ - (0x1F125, '3', u'(v)'), - (0x1F126, '3', u'(w)'), - (0x1F127, '3', u'(x)'), - (0x1F128, '3', u'(y)'), - (0x1F129, '3', u'(z)'), - (0x1F12A, 'M', u'〔s〕'), - (0x1F12B, 'M', u'c'), - (0x1F12C, 'M', u'r'), - (0x1F12D, 'M', u'cd'), - (0x1F12E, 'M', u'wz'), - (0x1F12F, 'V'), - (0x1F130, 'M', u'a'), - (0x1F131, 'M', u'b'), - (0x1F132, 'M', u'c'), - (0x1F133, 'M', u'd'), - (0x1F134, 'M', u'e'), - (0x1F135, 'M', u'f'), - (0x1F136, 'M', u'g'), - (0x1F137, 'M', u'h'), - (0x1F138, 'M', u'i'), - (0x1F139, 'M', u'j'), - (0x1F13A, 'M', u'k'), - (0x1F13B, 'M', u'l'), - (0x1F13C, 'M', u'm'), - (0x1F13D, 'M', u'n'), - (0x1F13E, 'M', u'o'), - (0x1F13F, 'M', u'p'), - (0x1F140, 'M', u'q'), - (0x1F141, 'M', u'r'), - (0x1F142, 'M', u's'), - (0x1F143, 'M', u't'), - (0x1F144, 'M', u'u'), - (0x1F145, 'M', u'v'), - (0x1F146, 'M', u'w'), - (0x1F147, 'M', u'x'), - (0x1F148, 'M', u'y'), - (0x1F149, 'M', u'z'), - (0x1F14A, 'M', u'hv'), - (0x1F14B, 'M', u'mv'), - (0x1F14C, 'M', u'sd'), - (0x1F14D, 'M', u'ss'), - (0x1F14E, 'M', u'ppv'), - (0x1F14F, 'M', u'wc'), - (0x1F150, 'V'), - (0x1F16A, 'M', u'mc'), - (0x1F16B, 'M', u'md'), - (0x1F16C, 'X'), - (0x1F170, 'V'), - (0x1F190, 'M', u'dj'), - (0x1F191, 'V'), - (0x1F1AD, 'X'), - (0x1F1E6, 'V'), - (0x1F200, 'M', u'ほか'), - (0x1F201, 'M', u'ココ'), - (0x1F202, 'M', u'サ'), - (0x1F203, 'X'), - (0x1F210, 'M', u'手'), - (0x1F211, 'M', u'字'), - (0x1F212, 'M', u'双'), - (0x1F213, 'M', u'デ'), - (0x1F214, 'M', u'二'), - (0x1F215, 'M', u'多'), - (0x1F216, 'M', u'解'), - (0x1F217, 'M', u'天'), - (0x1F218, 'M', u'交'), - (0x1F219, 'M', u'映'), - (0x1F21A, 'M', u'無'), - (0x1F21B, 'M', u'料'), - (0x1F21C, 'M', u'前'), - (0x1F21D, 'M', u'後'), - (0x1F21E, 'M', u'再'), - (0x1F21F, 'M', u'新'), - (0x1F220, 'M', u'初'), - (0x1F221, 'M', u'終'), - (0x1F222, 'M', u'生'), - (0x1F223, 'M', u'販'), - (0x1F224, 'M', u'声'), - (0x1F225, 'M', u'吹'), - (0x1F226, 'M', u'演'), - (0x1F227, 'M', u'投'), - (0x1F228, 'M', u'捕'), - (0x1F229, 'M', u'一'), - (0x1F22A, 'M', u'三'), - (0x1F22B, 'M', u'遊'), - (0x1F22C, 'M', u'左'), - (0x1F22D, 'M', u'中'), - (0x1F22E, 'M', u'右'), - (0x1F22F, 'M', u'指'), - (0x1F230, 'M', u'走'), - (0x1F231, 'M', u'打'), - (0x1F232, 'M', u'禁'), - (0x1F233, 'M', u'空'), - (0x1F234, 'M', u'合'), - (0x1F235, 'M', u'満'), - (0x1F236, 'M', u'有'), - (0x1F237, 'M', u'月'), - (0x1F238, 'M', u'申'), - (0x1F239, 'M', u'割'), - (0x1F23A, 'M', u'営'), - (0x1F23B, 'M', u'配'), - ] - -def _seg_72(): - return [ - (0x1F23C, 'X'), - (0x1F240, 'M', u'〔本〕'), - (0x1F241, 'M', u'〔三〕'), - (0x1F242, 'M', u'〔二〕'), - (0x1F243, 'M', u'〔安〕'), - (0x1F244, 'M', u'〔点〕'), - (0x1F245, 'M', u'〔打〕'), - (0x1F246, 'M', u'〔盗〕'), - (0x1F247, 'M', u'〔勝〕'), - (0x1F248, 'M', u'〔敗〕'), - (0x1F249, 'X'), - (0x1F250, 'M', u'得'), - (0x1F251, 'M', u'可'), - (0x1F252, 'X'), - (0x1F260, 'V'), - (0x1F266, 'X'), - (0x1F300, 'V'), - (0x1F6D5, 'X'), - (0x1F6E0, 'V'), - (0x1F6ED, 'X'), - (0x1F6F0, 'V'), - (0x1F6FA, 'X'), - (0x1F700, 'V'), - (0x1F774, 'X'), - (0x1F780, 'V'), - (0x1F7D9, 'X'), - (0x1F800, 'V'), - (0x1F80C, 'X'), - (0x1F810, 'V'), - (0x1F848, 'X'), - (0x1F850, 'V'), - (0x1F85A, 'X'), - (0x1F860, 'V'), - (0x1F888, 'X'), - (0x1F890, 'V'), - (0x1F8AE, 'X'), - (0x1F900, 'V'), - (0x1F90C, 'X'), - (0x1F910, 'V'), - (0x1F93F, 'X'), - (0x1F940, 'V'), - (0x1F971, 'X'), - (0x1F973, 'V'), - (0x1F977, 'X'), - (0x1F97A, 'V'), - (0x1F97B, 'X'), - (0x1F97C, 'V'), - (0x1F9A3, 'X'), - (0x1F9B0, 'V'), - (0x1F9BA, 'X'), - (0x1F9C0, 'V'), - (0x1F9C3, 'X'), - (0x1F9D0, 'V'), - (0x1FA00, 'X'), - (0x1FA60, 'V'), - (0x1FA6E, 'X'), - (0x20000, 'V'), - (0x2A6D7, 'X'), - (0x2A700, 'V'), - (0x2B735, 'X'), - (0x2B740, 'V'), - (0x2B81E, 'X'), - (0x2B820, 'V'), - (0x2CEA2, 'X'), - (0x2CEB0, 'V'), - (0x2EBE1, 'X'), - (0x2F800, 'M', u'丽'), - (0x2F801, 'M', u'丸'), - (0x2F802, 'M', u'乁'), - (0x2F803, 'M', u'𠄢'), - (0x2F804, 'M', u'你'), - (0x2F805, 'M', u'侮'), - (0x2F806, 'M', u'侻'), - (0x2F807, 'M', u'倂'), - (0x2F808, 'M', u'偺'), - (0x2F809, 'M', u'備'), - (0x2F80A, 'M', u'僧'), - (0x2F80B, 'M', u'像'), - (0x2F80C, 'M', u'㒞'), - (0x2F80D, 'M', u'𠘺'), - (0x2F80E, 'M', u'免'), - (0x2F80F, 'M', u'兔'), - (0x2F810, 'M', u'兤'), - (0x2F811, 'M', u'具'), - (0x2F812, 'M', u'𠔜'), - (0x2F813, 'M', u'㒹'), - (0x2F814, 'M', u'內'), - (0x2F815, 'M', u'再'), - (0x2F816, 'M', u'𠕋'), - (0x2F817, 'M', u'冗'), - (0x2F818, 'M', u'冤'), - (0x2F819, 'M', u'仌'), - (0x2F81A, 'M', u'冬'), - (0x2F81B, 'M', u'况'), - (0x2F81C, 'M', u'𩇟'), - (0x2F81D, 'M', u'凵'), - (0x2F81E, 'M', u'刃'), - (0x2F81F, 'M', u'㓟'), - (0x2F820, 'M', u'刻'), - (0x2F821, 'M', u'剆'), - ] - -def _seg_73(): - return [ - (0x2F822, 'M', u'割'), - (0x2F823, 'M', u'剷'), - (0x2F824, 'M', u'㔕'), - (0x2F825, 'M', u'勇'), - (0x2F826, 'M', u'勉'), - (0x2F827, 'M', u'勤'), - (0x2F828, 'M', u'勺'), - (0x2F829, 'M', u'包'), - (0x2F82A, 'M', u'匆'), - (0x2F82B, 'M', u'北'), - (0x2F82C, 'M', u'卉'), - (0x2F82D, 'M', u'卑'), - (0x2F82E, 'M', u'博'), - (0x2F82F, 'M', u'即'), - (0x2F830, 'M', u'卽'), - (0x2F831, 'M', u'卿'), - (0x2F834, 'M', u'𠨬'), - (0x2F835, 'M', u'灰'), - (0x2F836, 'M', u'及'), - (0x2F837, 'M', u'叟'), - (0x2F838, 'M', u'𠭣'), - (0x2F839, 'M', u'叫'), - (0x2F83A, 'M', u'叱'), - (0x2F83B, 'M', u'吆'), - (0x2F83C, 'M', u'咞'), - (0x2F83D, 'M', u'吸'), - (0x2F83E, 'M', u'呈'), - (0x2F83F, 'M', u'周'), - (0x2F840, 'M', u'咢'), - (0x2F841, 'M', u'哶'), - (0x2F842, 'M', u'唐'), - (0x2F843, 'M', u'啓'), - (0x2F844, 'M', u'啣'), - (0x2F845, 'M', u'善'), - (0x2F847, 'M', u'喙'), - (0x2F848, 'M', u'喫'), - (0x2F849, 'M', u'喳'), - (0x2F84A, 'M', u'嗂'), - (0x2F84B, 'M', u'圖'), - (0x2F84C, 'M', u'嘆'), - (0x2F84D, 'M', u'圗'), - (0x2F84E, 'M', u'噑'), - (0x2F84F, 'M', u'噴'), - (0x2F850, 'M', u'切'), - (0x2F851, 'M', u'壮'), - (0x2F852, 'M', u'城'), - (0x2F853, 'M', u'埴'), - (0x2F854, 'M', u'堍'), - (0x2F855, 'M', u'型'), - (0x2F856, 'M', u'堲'), - (0x2F857, 'M', u'報'), - (0x2F858, 'M', u'墬'), - (0x2F859, 'M', u'𡓤'), - (0x2F85A, 'M', u'売'), - (0x2F85B, 'M', u'壷'), - (0x2F85C, 'M', u'夆'), - (0x2F85D, 'M', u'多'), - (0x2F85E, 'M', u'夢'), - (0x2F85F, 'M', u'奢'), - (0x2F860, 'M', u'𡚨'), - (0x2F861, 'M', u'𡛪'), - (0x2F862, 'M', u'姬'), - (0x2F863, 'M', u'娛'), - (0x2F864, 'M', u'娧'), - (0x2F865, 'M', u'姘'), - (0x2F866, 'M', u'婦'), - (0x2F867, 'M', u'㛮'), - (0x2F868, 'X'), - (0x2F869, 'M', u'嬈'), - (0x2F86A, 'M', u'嬾'), - (0x2F86C, 'M', u'𡧈'), - (0x2F86D, 'M', u'寃'), - (0x2F86E, 'M', u'寘'), - (0x2F86F, 'M', u'寧'), - (0x2F870, 'M', u'寳'), - (0x2F871, 'M', u'𡬘'), - (0x2F872, 'M', u'寿'), - (0x2F873, 'M', u'将'), - (0x2F874, 'X'), - (0x2F875, 'M', u'尢'), - (0x2F876, 'M', u'㞁'), - (0x2F877, 'M', u'屠'), - (0x2F878, 'M', u'屮'), - (0x2F879, 'M', u'峀'), - (0x2F87A, 'M', u'岍'), - (0x2F87B, 'M', u'𡷤'), - (0x2F87C, 'M', u'嵃'), - (0x2F87D, 'M', u'𡷦'), - (0x2F87E, 'M', u'嵮'), - (0x2F87F, 'M', u'嵫'), - (0x2F880, 'M', u'嵼'), - (0x2F881, 'M', u'巡'), - (0x2F882, 'M', u'巢'), - (0x2F883, 'M', u'㠯'), - (0x2F884, 'M', u'巽'), - (0x2F885, 'M', u'帨'), - (0x2F886, 'M', u'帽'), - (0x2F887, 'M', u'幩'), - (0x2F888, 'M', u'㡢'), - (0x2F889, 'M', u'𢆃'), - ] - -def _seg_74(): - return [ - (0x2F88A, 'M', u'㡼'), - (0x2F88B, 'M', u'庰'), - (0x2F88C, 'M', u'庳'), - (0x2F88D, 'M', u'庶'), - (0x2F88E, 'M', u'廊'), - (0x2F88F, 'M', u'𪎒'), - (0x2F890, 'M', u'廾'), - (0x2F891, 'M', u'𢌱'), - (0x2F893, 'M', u'舁'), - (0x2F894, 'M', u'弢'), - (0x2F896, 'M', u'㣇'), - (0x2F897, 'M', u'𣊸'), - (0x2F898, 'M', u'𦇚'), - (0x2F899, 'M', u'形'), - (0x2F89A, 'M', u'彫'), - (0x2F89B, 'M', u'㣣'), - (0x2F89C, 'M', u'徚'), - (0x2F89D, 'M', u'忍'), - (0x2F89E, 'M', u'志'), - (0x2F89F, 'M', u'忹'), - (0x2F8A0, 'M', u'悁'), - (0x2F8A1, 'M', u'㤺'), - (0x2F8A2, 'M', u'㤜'), - (0x2F8A3, 'M', u'悔'), - (0x2F8A4, 'M', u'𢛔'), - (0x2F8A5, 'M', u'惇'), - (0x2F8A6, 'M', u'慈'), - (0x2F8A7, 'M', u'慌'), - (0x2F8A8, 'M', u'慎'), - (0x2F8A9, 'M', u'慌'), - (0x2F8AA, 'M', u'慺'), - (0x2F8AB, 'M', u'憎'), - (0x2F8AC, 'M', u'憲'), - (0x2F8AD, 'M', u'憤'), - (0x2F8AE, 'M', u'憯'), - (0x2F8AF, 'M', u'懞'), - (0x2F8B0, 'M', u'懲'), - (0x2F8B1, 'M', u'懶'), - (0x2F8B2, 'M', u'成'), - (0x2F8B3, 'M', u'戛'), - (0x2F8B4, 'M', u'扝'), - (0x2F8B5, 'M', u'抱'), - (0x2F8B6, 'M', u'拔'), - (0x2F8B7, 'M', u'捐'), - (0x2F8B8, 'M', u'𢬌'), - (0x2F8B9, 'M', u'挽'), - (0x2F8BA, 'M', u'拼'), - (0x2F8BB, 'M', u'捨'), - (0x2F8BC, 'M', u'掃'), - (0x2F8BD, 'M', u'揤'), - (0x2F8BE, 'M', u'𢯱'), - (0x2F8BF, 'M', u'搢'), - (0x2F8C0, 'M', u'揅'), - (0x2F8C1, 'M', u'掩'), - (0x2F8C2, 'M', u'㨮'), - (0x2F8C3, 'M', u'摩'), - (0x2F8C4, 'M', u'摾'), - (0x2F8C5, 'M', u'撝'), - (0x2F8C6, 'M', u'摷'), - (0x2F8C7, 'M', u'㩬'), - (0x2F8C8, 'M', u'敏'), - (0x2F8C9, 'M', u'敬'), - (0x2F8CA, 'M', u'𣀊'), - (0x2F8CB, 'M', u'旣'), - (0x2F8CC, 'M', u'書'), - (0x2F8CD, 'M', u'晉'), - (0x2F8CE, 'M', u'㬙'), - (0x2F8CF, 'M', u'暑'), - (0x2F8D0, 'M', u'㬈'), - (0x2F8D1, 'M', u'㫤'), - (0x2F8D2, 'M', u'冒'), - (0x2F8D3, 'M', u'冕'), - (0x2F8D4, 'M', u'最'), - (0x2F8D5, 'M', u'暜'), - (0x2F8D6, 'M', u'肭'), - (0x2F8D7, 'M', u'䏙'), - (0x2F8D8, 'M', u'朗'), - (0x2F8D9, 'M', u'望'), - (0x2F8DA, 'M', u'朡'), - (0x2F8DB, 'M', u'杞'), - (0x2F8DC, 'M', u'杓'), - (0x2F8DD, 'M', u'𣏃'), - (0x2F8DE, 'M', u'㭉'), - (0x2F8DF, 'M', u'柺'), - (0x2F8E0, 'M', u'枅'), - (0x2F8E1, 'M', u'桒'), - (0x2F8E2, 'M', u'梅'), - (0x2F8E3, 'M', u'𣑭'), - (0x2F8E4, 'M', u'梎'), - (0x2F8E5, 'M', u'栟'), - (0x2F8E6, 'M', u'椔'), - (0x2F8E7, 'M', u'㮝'), - (0x2F8E8, 'M', u'楂'), - (0x2F8E9, 'M', u'榣'), - (0x2F8EA, 'M', u'槪'), - (0x2F8EB, 'M', u'檨'), - (0x2F8EC, 'M', u'𣚣'), - (0x2F8ED, 'M', u'櫛'), - (0x2F8EE, 'M', u'㰘'), - (0x2F8EF, 'M', u'次'), - ] - -def _seg_75(): - return [ - (0x2F8F0, 'M', u'𣢧'), - (0x2F8F1, 'M', u'歔'), - (0x2F8F2, 'M', u'㱎'), - (0x2F8F3, 'M', u'歲'), - (0x2F8F4, 'M', u'殟'), - (0x2F8F5, 'M', u'殺'), - (0x2F8F6, 'M', u'殻'), - (0x2F8F7, 'M', u'𣪍'), - (0x2F8F8, 'M', u'𡴋'), - (0x2F8F9, 'M', u'𣫺'), - (0x2F8FA, 'M', u'汎'), - (0x2F8FB, 'M', u'𣲼'), - (0x2F8FC, 'M', u'沿'), - (0x2F8FD, 'M', u'泍'), - (0x2F8FE, 'M', u'汧'), - (0x2F8FF, 'M', u'洖'), - (0x2F900, 'M', u'派'), - (0x2F901, 'M', u'海'), - (0x2F902, 'M', u'流'), - (0x2F903, 'M', u'浩'), - (0x2F904, 'M', u'浸'), - (0x2F905, 'M', u'涅'), - (0x2F906, 'M', u'𣴞'), - (0x2F907, 'M', u'洴'), - (0x2F908, 'M', u'港'), - (0x2F909, 'M', u'湮'), - (0x2F90A, 'M', u'㴳'), - (0x2F90B, 'M', u'滋'), - (0x2F90C, 'M', u'滇'), - (0x2F90D, 'M', u'𣻑'), - (0x2F90E, 'M', u'淹'), - (0x2F90F, 'M', u'潮'), - (0x2F910, 'M', u'𣽞'), - (0x2F911, 'M', u'𣾎'), - (0x2F912, 'M', u'濆'), - (0x2F913, 'M', u'瀹'), - (0x2F914, 'M', u'瀞'), - (0x2F915, 'M', u'瀛'), - (0x2F916, 'M', u'㶖'), - (0x2F917, 'M', u'灊'), - (0x2F918, 'M', u'災'), - (0x2F919, 'M', u'灷'), - (0x2F91A, 'M', u'炭'), - (0x2F91B, 'M', u'𠔥'), - (0x2F91C, 'M', u'煅'), - (0x2F91D, 'M', u'𤉣'), - (0x2F91E, 'M', u'熜'), - (0x2F91F, 'X'), - (0x2F920, 'M', u'爨'), - (0x2F921, 'M', u'爵'), - (0x2F922, 'M', u'牐'), - (0x2F923, 'M', u'𤘈'), - (0x2F924, 'M', u'犀'), - (0x2F925, 'M', u'犕'), - (0x2F926, 'M', u'𤜵'), - (0x2F927, 'M', u'𤠔'), - (0x2F928, 'M', u'獺'), - (0x2F929, 'M', u'王'), - (0x2F92A, 'M', u'㺬'), - (0x2F92B, 'M', u'玥'), - (0x2F92C, 'M', u'㺸'), - (0x2F92E, 'M', u'瑇'), - (0x2F92F, 'M', u'瑜'), - (0x2F930, 'M', u'瑱'), - (0x2F931, 'M', u'璅'), - (0x2F932, 'M', u'瓊'), - (0x2F933, 'M', u'㼛'), - (0x2F934, 'M', u'甤'), - (0x2F935, 'M', u'𤰶'), - (0x2F936, 'M', u'甾'), - (0x2F937, 'M', u'𤲒'), - (0x2F938, 'M', u'異'), - (0x2F939, 'M', u'𢆟'), - (0x2F93A, 'M', u'瘐'), - (0x2F93B, 'M', u'𤾡'), - (0x2F93C, 'M', u'𤾸'), - (0x2F93D, 'M', u'𥁄'), - (0x2F93E, 'M', u'㿼'), - (0x2F93F, 'M', u'䀈'), - (0x2F940, 'M', u'直'), - (0x2F941, 'M', u'𥃳'), - (0x2F942, 'M', u'𥃲'), - (0x2F943, 'M', u'𥄙'), - (0x2F944, 'M', u'𥄳'), - (0x2F945, 'M', u'眞'), - (0x2F946, 'M', u'真'), - (0x2F948, 'M', u'睊'), - (0x2F949, 'M', u'䀹'), - (0x2F94A, 'M', u'瞋'), - (0x2F94B, 'M', u'䁆'), - (0x2F94C, 'M', u'䂖'), - (0x2F94D, 'M', u'𥐝'), - (0x2F94E, 'M', u'硎'), - (0x2F94F, 'M', u'碌'), - (0x2F950, 'M', u'磌'), - (0x2F951, 'M', u'䃣'), - (0x2F952, 'M', u'𥘦'), - (0x2F953, 'M', u'祖'), - (0x2F954, 'M', u'𥚚'), - (0x2F955, 'M', u'𥛅'), - ] - -def _seg_76(): - return [ - (0x2F956, 'M', u'福'), - (0x2F957, 'M', u'秫'), - (0x2F958, 'M', u'䄯'), - (0x2F959, 'M', u'穀'), - (0x2F95A, 'M', u'穊'), - (0x2F95B, 'M', u'穏'), - (0x2F95C, 'M', u'𥥼'), - (0x2F95D, 'M', u'𥪧'), - (0x2F95F, 'X'), - (0x2F960, 'M', u'䈂'), - (0x2F961, 'M', u'𥮫'), - (0x2F962, 'M', u'篆'), - (0x2F963, 'M', u'築'), - (0x2F964, 'M', u'䈧'), - (0x2F965, 'M', u'𥲀'), - (0x2F966, 'M', u'糒'), - (0x2F967, 'M', u'䊠'), - (0x2F968, 'M', u'糨'), - (0x2F969, 'M', u'糣'), - (0x2F96A, 'M', u'紀'), - (0x2F96B, 'M', u'𥾆'), - (0x2F96C, 'M', u'絣'), - (0x2F96D, 'M', u'䌁'), - (0x2F96E, 'M', u'緇'), - (0x2F96F, 'M', u'縂'), - (0x2F970, 'M', u'繅'), - (0x2F971, 'M', u'䌴'), - (0x2F972, 'M', u'𦈨'), - (0x2F973, 'M', u'𦉇'), - (0x2F974, 'M', u'䍙'), - (0x2F975, 'M', u'𦋙'), - (0x2F976, 'M', u'罺'), - (0x2F977, 'M', u'𦌾'), - (0x2F978, 'M', u'羕'), - (0x2F979, 'M', u'翺'), - (0x2F97A, 'M', u'者'), - (0x2F97B, 'M', u'𦓚'), - (0x2F97C, 'M', u'𦔣'), - (0x2F97D, 'M', u'聠'), - (0x2F97E, 'M', u'𦖨'), - (0x2F97F, 'M', u'聰'), - (0x2F980, 'M', u'𣍟'), - (0x2F981, 'M', u'䏕'), - (0x2F982, 'M', u'育'), - (0x2F983, 'M', u'脃'), - (0x2F984, 'M', u'䐋'), - (0x2F985, 'M', u'脾'), - (0x2F986, 'M', u'媵'), - (0x2F987, 'M', u'𦞧'), - (0x2F988, 'M', u'𦞵'), - (0x2F989, 'M', u'𣎓'), - (0x2F98A, 'M', u'𣎜'), - (0x2F98B, 'M', u'舁'), - (0x2F98C, 'M', u'舄'), - (0x2F98D, 'M', u'辞'), - (0x2F98E, 'M', u'䑫'), - (0x2F98F, 'M', u'芑'), - (0x2F990, 'M', u'芋'), - (0x2F991, 'M', u'芝'), - (0x2F992, 'M', u'劳'), - (0x2F993, 'M', u'花'), - (0x2F994, 'M', u'芳'), - (0x2F995, 'M', u'芽'), - (0x2F996, 'M', u'苦'), - (0x2F997, 'M', u'𦬼'), - (0x2F998, 'M', u'若'), - (0x2F999, 'M', u'茝'), - (0x2F99A, 'M', u'荣'), - (0x2F99B, 'M', u'莭'), - (0x2F99C, 'M', u'茣'), - (0x2F99D, 'M', u'莽'), - (0x2F99E, 'M', u'菧'), - (0x2F99F, 'M', u'著'), - (0x2F9A0, 'M', u'荓'), - (0x2F9A1, 'M', u'菊'), - (0x2F9A2, 'M', u'菌'), - (0x2F9A3, 'M', u'菜'), - (0x2F9A4, 'M', u'𦰶'), - (0x2F9A5, 'M', u'𦵫'), - (0x2F9A6, 'M', u'𦳕'), - (0x2F9A7, 'M', u'䔫'), - (0x2F9A8, 'M', u'蓱'), - (0x2F9A9, 'M', u'蓳'), - (0x2F9AA, 'M', u'蔖'), - (0x2F9AB, 'M', u'𧏊'), - (0x2F9AC, 'M', u'蕤'), - (0x2F9AD, 'M', u'𦼬'), - (0x2F9AE, 'M', u'䕝'), - (0x2F9AF, 'M', u'䕡'), - (0x2F9B0, 'M', u'𦾱'), - (0x2F9B1, 'M', u'𧃒'), - (0x2F9B2, 'M', u'䕫'), - (0x2F9B3, 'M', u'虐'), - (0x2F9B4, 'M', u'虜'), - (0x2F9B5, 'M', u'虧'), - (0x2F9B6, 'M', u'虩'), - (0x2F9B7, 'M', u'蚩'), - (0x2F9B8, 'M', u'蚈'), - (0x2F9B9, 'M', u'蜎'), - (0x2F9BA, 'M', u'蛢'), - ] - -def _seg_77(): - return [ - (0x2F9BB, 'M', u'蝹'), - (0x2F9BC, 'M', u'蜨'), - (0x2F9BD, 'M', u'蝫'), - (0x2F9BE, 'M', u'螆'), - (0x2F9BF, 'X'), - (0x2F9C0, 'M', u'蟡'), - (0x2F9C1, 'M', u'蠁'), - (0x2F9C2, 'M', u'䗹'), - (0x2F9C3, 'M', u'衠'), - (0x2F9C4, 'M', u'衣'), - (0x2F9C5, 'M', u'𧙧'), - (0x2F9C6, 'M', u'裗'), - (0x2F9C7, 'M', u'裞'), - (0x2F9C8, 'M', u'䘵'), - (0x2F9C9, 'M', u'裺'), - (0x2F9CA, 'M', u'㒻'), - (0x2F9CB, 'M', u'𧢮'), - (0x2F9CC, 'M', u'𧥦'), - (0x2F9CD, 'M', u'䚾'), - (0x2F9CE, 'M', u'䛇'), - (0x2F9CF, 'M', u'誠'), - (0x2F9D0, 'M', u'諭'), - (0x2F9D1, 'M', u'變'), - (0x2F9D2, 'M', u'豕'), - (0x2F9D3, 'M', u'𧲨'), - (0x2F9D4, 'M', u'貫'), - (0x2F9D5, 'M', u'賁'), - (0x2F9D6, 'M', u'贛'), - (0x2F9D7, 'M', u'起'), - (0x2F9D8, 'M', u'𧼯'), - (0x2F9D9, 'M', u'𠠄'), - (0x2F9DA, 'M', u'跋'), - (0x2F9DB, 'M', u'趼'), - (0x2F9DC, 'M', u'跰'), - (0x2F9DD, 'M', u'𠣞'), - (0x2F9DE, 'M', u'軔'), - (0x2F9DF, 'M', u'輸'), - (0x2F9E0, 'M', u'𨗒'), - (0x2F9E1, 'M', u'𨗭'), - (0x2F9E2, 'M', u'邔'), - (0x2F9E3, 'M', u'郱'), - (0x2F9E4, 'M', u'鄑'), - (0x2F9E5, 'M', u'𨜮'), - (0x2F9E6, 'M', u'鄛'), - (0x2F9E7, 'M', u'鈸'), - (0x2F9E8, 'M', u'鋗'), - (0x2F9E9, 'M', u'鋘'), - (0x2F9EA, 'M', u'鉼'), - (0x2F9EB, 'M', u'鏹'), - (0x2F9EC, 'M', u'鐕'), - (0x2F9ED, 'M', u'𨯺'), - (0x2F9EE, 'M', u'開'), - (0x2F9EF, 'M', u'䦕'), - (0x2F9F0, 'M', u'閷'), - (0x2F9F1, 'M', u'𨵷'), - (0x2F9F2, 'M', u'䧦'), - (0x2F9F3, 'M', u'雃'), - (0x2F9F4, 'M', u'嶲'), - (0x2F9F5, 'M', u'霣'), - (0x2F9F6, 'M', u'𩅅'), - (0x2F9F7, 'M', u'𩈚'), - (0x2F9F8, 'M', u'䩮'), - (0x2F9F9, 'M', u'䩶'), - (0x2F9FA, 'M', u'韠'), - (0x2F9FB, 'M', u'𩐊'), - (0x2F9FC, 'M', u'䪲'), - (0x2F9FD, 'M', u'𩒖'), - (0x2F9FE, 'M', u'頋'), - (0x2FA00, 'M', u'頩'), - (0x2FA01, 'M', u'𩖶'), - (0x2FA02, 'M', u'飢'), - (0x2FA03, 'M', u'䬳'), - (0x2FA04, 'M', u'餩'), - (0x2FA05, 'M', u'馧'), - (0x2FA06, 'M', u'駂'), - (0x2FA07, 'M', u'駾'), - (0x2FA08, 'M', u'䯎'), - (0x2FA09, 'M', u'𩬰'), - (0x2FA0A, 'M', u'鬒'), - (0x2FA0B, 'M', u'鱀'), - (0x2FA0C, 'M', u'鳽'), - (0x2FA0D, 'M', u'䳎'), - (0x2FA0E, 'M', u'䳭'), - (0x2FA0F, 'M', u'鵧'), - (0x2FA10, 'M', u'𪃎'), - (0x2FA11, 'M', u'䳸'), - (0x2FA12, 'M', u'𪄅'), - (0x2FA13, 'M', u'𪈎'), - (0x2FA14, 'M', u'𪊑'), - (0x2FA15, 'M', u'麻'), - (0x2FA16, 'M', u'䵖'), - (0x2FA17, 'M', u'黹'), - (0x2FA18, 'M', u'黾'), - (0x2FA19, 'M', u'鼅'), - (0x2FA1A, 'M', u'鼏'), - (0x2FA1B, 'M', u'鼖'), - (0x2FA1C, 'M', u'鼻'), - (0x2FA1D, 'M', u'𪘀'), - (0x2FA1E, 'X'), - (0xE0100, 'I'), - ] - -def _seg_78(): - return [ - (0xE01F0, 'X'), - ] - -uts46data = tuple( - _seg_0() - + _seg_1() - + _seg_2() - + _seg_3() - + _seg_4() - + _seg_5() - + _seg_6() - + _seg_7() - + _seg_8() - + _seg_9() - + _seg_10() - + _seg_11() - + _seg_12() - + _seg_13() - + _seg_14() - + _seg_15() - + _seg_16() - + _seg_17() - + _seg_18() - + _seg_19() - + _seg_20() - + _seg_21() - + _seg_22() - + _seg_23() - + _seg_24() - + _seg_25() - + _seg_26() - + _seg_27() - + _seg_28() - + _seg_29() - + _seg_30() - + _seg_31() - + _seg_32() - + _seg_33() - + _seg_34() - + _seg_35() - + _seg_36() - + _seg_37() - + _seg_38() - + _seg_39() - + _seg_40() - + _seg_41() - + _seg_42() - + _seg_43() - + _seg_44() - + _seg_45() - + _seg_46() - + _seg_47() - + _seg_48() - + _seg_49() - + _seg_50() - + _seg_51() - + _seg_52() - + _seg_53() - + _seg_54() - + _seg_55() - + _seg_56() - + _seg_57() - + _seg_58() - + _seg_59() - + _seg_60() - + _seg_61() - + _seg_62() - + _seg_63() - + _seg_64() - + _seg_65() - + _seg_66() - + _seg_67() - + _seg_68() - + _seg_69() - + _seg_70() - + _seg_71() - + _seg_72() - + _seg_73() - + _seg_74() - + _seg_75() - + _seg_76() - + _seg_77() - + _seg_78() -) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/ipaddress.py b/venv2/lib/python2.7/site-packages/pip/_vendor/ipaddress.py deleted file mode 100644 index f2d0766..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/ipaddress.py +++ /dev/null @@ -1,2419 +0,0 @@ -# Copyright 2007 Google Inc. -# Licensed to PSF under a Contributor Agreement. - -"""A fast, lightweight IPv4/IPv6 manipulation library in Python. - -This library is used to create/poke/manipulate IPv4 and IPv6 addresses -and networks. - -""" - -from __future__ import unicode_literals - - -import itertools -import struct - -__version__ = '1.0.22' - -# Compatibility functions -_compat_int_types = (int,) -try: - _compat_int_types = (int, long) -except NameError: - pass -try: - _compat_str = unicode -except NameError: - _compat_str = str - assert bytes != str -if b'\0'[0] == 0: # Python 3 semantics - def _compat_bytes_to_byte_vals(byt): - return byt -else: - def _compat_bytes_to_byte_vals(byt): - return [struct.unpack(b'!B', b)[0] for b in byt] -try: - _compat_int_from_byte_vals = int.from_bytes -except AttributeError: - def _compat_int_from_byte_vals(bytvals, endianess): - assert endianess == 'big' - res = 0 - for bv in bytvals: - assert isinstance(bv, _compat_int_types) - res = (res << 8) + bv - return res - - -def _compat_to_bytes(intval, length, endianess): - assert isinstance(intval, _compat_int_types) - assert endianess == 'big' - if length == 4: - if intval < 0 or intval >= 2 ** 32: - raise struct.error("integer out of range for 'I' format code") - return struct.pack(b'!I', intval) - elif length == 16: - if intval < 0 or intval >= 2 ** 128: - raise struct.error("integer out of range for 'QQ' format code") - return struct.pack(b'!QQ', intval >> 64, intval & 0xffffffffffffffff) - else: - raise NotImplementedError() - - -if hasattr(int, 'bit_length'): - # Not int.bit_length , since that won't work in 2.7 where long exists - def _compat_bit_length(i): - return i.bit_length() -else: - def _compat_bit_length(i): - for res in itertools.count(): - if i >> res == 0: - return res - - -def _compat_range(start, end, step=1): - assert step > 0 - i = start - while i < end: - yield i - i += step - - -class _TotalOrderingMixin(object): - __slots__ = () - - # Helper that derives the other comparison operations from - # __lt__ and __eq__ - # We avoid functools.total_ordering because it doesn't handle - # NotImplemented correctly yet (http://bugs.python.org/issue10042) - def __eq__(self, other): - raise NotImplementedError - - def __ne__(self, other): - equal = self.__eq__(other) - if equal is NotImplemented: - return NotImplemented - return not equal - - def __lt__(self, other): - raise NotImplementedError - - def __le__(self, other): - less = self.__lt__(other) - if less is NotImplemented or not less: - return self.__eq__(other) - return less - - def __gt__(self, other): - less = self.__lt__(other) - if less is NotImplemented: - return NotImplemented - equal = self.__eq__(other) - if equal is NotImplemented: - return NotImplemented - return not (less or equal) - - def __ge__(self, other): - less = self.__lt__(other) - if less is NotImplemented: - return NotImplemented - return not less - - -IPV4LENGTH = 32 -IPV6LENGTH = 128 - - -class AddressValueError(ValueError): - """A Value Error related to the address.""" - - -class NetmaskValueError(ValueError): - """A Value Error related to the netmask.""" - - -def ip_address(address): - """Take an IP string/int and return an object of the correct type. - - Args: - address: A string or integer, the IP address. Either IPv4 or - IPv6 addresses may be supplied; integers less than 2**32 will - be considered to be IPv4 by default. - - Returns: - An IPv4Address or IPv6Address object. - - Raises: - ValueError: if the *address* passed isn't either a v4 or a v6 - address - - """ - try: - return IPv4Address(address) - except (AddressValueError, NetmaskValueError): - pass - - try: - return IPv6Address(address) - except (AddressValueError, NetmaskValueError): - pass - - if isinstance(address, bytes): - raise AddressValueError( - '%r does not appear to be an IPv4 or IPv6 address. ' - 'Did you pass in a bytes (str in Python 2) instead of' - ' a unicode object?' % address) - - raise ValueError('%r does not appear to be an IPv4 or IPv6 address' % - address) - - -def ip_network(address, strict=True): - """Take an IP string/int and return an object of the correct type. - - Args: - address: A string or integer, the IP network. Either IPv4 or - IPv6 networks may be supplied; integers less than 2**32 will - be considered to be IPv4 by default. - - Returns: - An IPv4Network or IPv6Network object. - - Raises: - ValueError: if the string passed isn't either a v4 or a v6 - address. Or if the network has host bits set. - - """ - try: - return IPv4Network(address, strict) - except (AddressValueError, NetmaskValueError): - pass - - try: - return IPv6Network(address, strict) - except (AddressValueError, NetmaskValueError): - pass - - if isinstance(address, bytes): - raise AddressValueError( - '%r does not appear to be an IPv4 or IPv6 network. ' - 'Did you pass in a bytes (str in Python 2) instead of' - ' a unicode object?' % address) - - raise ValueError('%r does not appear to be an IPv4 or IPv6 network' % - address) - - -def ip_interface(address): - """Take an IP string/int and return an object of the correct type. - - Args: - address: A string or integer, the IP address. Either IPv4 or - IPv6 addresses may be supplied; integers less than 2**32 will - be considered to be IPv4 by default. - - Returns: - An IPv4Interface or IPv6Interface object. - - Raises: - ValueError: if the string passed isn't either a v4 or a v6 - address. - - Notes: - The IPv?Interface classes describe an Address on a particular - Network, so they're basically a combination of both the Address - and Network classes. - - """ - try: - return IPv4Interface(address) - except (AddressValueError, NetmaskValueError): - pass - - try: - return IPv6Interface(address) - except (AddressValueError, NetmaskValueError): - pass - - raise ValueError('%r does not appear to be an IPv4 or IPv6 interface' % - address) - - -def v4_int_to_packed(address): - """Represent an address as 4 packed bytes in network (big-endian) order. - - Args: - address: An integer representation of an IPv4 IP address. - - Returns: - The integer address packed as 4 bytes in network (big-endian) order. - - Raises: - ValueError: If the integer is negative or too large to be an - IPv4 IP address. - - """ - try: - return _compat_to_bytes(address, 4, 'big') - except (struct.error, OverflowError): - raise ValueError("Address negative or too large for IPv4") - - -def v6_int_to_packed(address): - """Represent an address as 16 packed bytes in network (big-endian) order. - - Args: - address: An integer representation of an IPv6 IP address. - - Returns: - The integer address packed as 16 bytes in network (big-endian) order. - - """ - try: - return _compat_to_bytes(address, 16, 'big') - except (struct.error, OverflowError): - raise ValueError("Address negative or too large for IPv6") - - -def _split_optional_netmask(address): - """Helper to split the netmask and raise AddressValueError if needed""" - addr = _compat_str(address).split('/') - if len(addr) > 2: - raise AddressValueError("Only one '/' permitted in %r" % address) - return addr - - -def _find_address_range(addresses): - """Find a sequence of sorted deduplicated IPv#Address. - - Args: - addresses: a list of IPv#Address objects. - - Yields: - A tuple containing the first and last IP addresses in the sequence. - - """ - it = iter(addresses) - first = last = next(it) - for ip in it: - if ip._ip != last._ip + 1: - yield first, last - first = ip - last = ip - yield first, last - - -def _count_righthand_zero_bits(number, bits): - """Count the number of zero bits on the right hand side. - - Args: - number: an integer. - bits: maximum number of bits to count. - - Returns: - The number of zero bits on the right hand side of the number. - - """ - if number == 0: - return bits - return min(bits, _compat_bit_length(~number & (number - 1))) - - -def summarize_address_range(first, last): - """Summarize a network range given the first and last IP addresses. - - Example: - >>> list(summarize_address_range(IPv4Address('192.0.2.0'), - ... IPv4Address('192.0.2.130'))) - ... #doctest: +NORMALIZE_WHITESPACE - [IPv4Network('192.0.2.0/25'), IPv4Network('192.0.2.128/31'), - IPv4Network('192.0.2.130/32')] - - Args: - first: the first IPv4Address or IPv6Address in the range. - last: the last IPv4Address or IPv6Address in the range. - - Returns: - An iterator of the summarized IPv(4|6) network objects. - - Raise: - TypeError: - If the first and last objects are not IP addresses. - If the first and last objects are not the same version. - ValueError: - If the last object is not greater than the first. - If the version of the first address is not 4 or 6. - - """ - if (not (isinstance(first, _BaseAddress) and - isinstance(last, _BaseAddress))): - raise TypeError('first and last must be IP addresses, not networks') - if first.version != last.version: - raise TypeError("%s and %s are not of the same version" % ( - first, last)) - if first > last: - raise ValueError('last IP address must be greater than first') - - if first.version == 4: - ip = IPv4Network - elif first.version == 6: - ip = IPv6Network - else: - raise ValueError('unknown IP version') - - ip_bits = first._max_prefixlen - first_int = first._ip - last_int = last._ip - while first_int <= last_int: - nbits = min(_count_righthand_zero_bits(first_int, ip_bits), - _compat_bit_length(last_int - first_int + 1) - 1) - net = ip((first_int, ip_bits - nbits)) - yield net - first_int += 1 << nbits - if first_int - 1 == ip._ALL_ONES: - break - - -def _collapse_addresses_internal(addresses): - """Loops through the addresses, collapsing concurrent netblocks. - - Example: - - ip1 = IPv4Network('192.0.2.0/26') - ip2 = IPv4Network('192.0.2.64/26') - ip3 = IPv4Network('192.0.2.128/26') - ip4 = IPv4Network('192.0.2.192/26') - - _collapse_addresses_internal([ip1, ip2, ip3, ip4]) -> - [IPv4Network('192.0.2.0/24')] - - This shouldn't be called directly; it is called via - collapse_addresses([]). - - Args: - addresses: A list of IPv4Network's or IPv6Network's - - Returns: - A list of IPv4Network's or IPv6Network's depending on what we were - passed. - - """ - # First merge - to_merge = list(addresses) - subnets = {} - while to_merge: - net = to_merge.pop() - supernet = net.supernet() - existing = subnets.get(supernet) - if existing is None: - subnets[supernet] = net - elif existing != net: - # Merge consecutive subnets - del subnets[supernet] - to_merge.append(supernet) - # Then iterate over resulting networks, skipping subsumed subnets - last = None - for net in sorted(subnets.values()): - if last is not None: - # Since they are sorted, - # last.network_address <= net.network_address is a given. - if last.broadcast_address >= net.broadcast_address: - continue - yield net - last = net - - -def collapse_addresses(addresses): - """Collapse a list of IP objects. - - Example: - collapse_addresses([IPv4Network('192.0.2.0/25'), - IPv4Network('192.0.2.128/25')]) -> - [IPv4Network('192.0.2.0/24')] - - Args: - addresses: An iterator of IPv4Network or IPv6Network objects. - - Returns: - An iterator of the collapsed IPv(4|6)Network objects. - - Raises: - TypeError: If passed a list of mixed version objects. - - """ - addrs = [] - ips = [] - nets = [] - - # split IP addresses and networks - for ip in addresses: - if isinstance(ip, _BaseAddress): - if ips and ips[-1]._version != ip._version: - raise TypeError("%s and %s are not of the same version" % ( - ip, ips[-1])) - ips.append(ip) - elif ip._prefixlen == ip._max_prefixlen: - if ips and ips[-1]._version != ip._version: - raise TypeError("%s and %s are not of the same version" % ( - ip, ips[-1])) - try: - ips.append(ip.ip) - except AttributeError: - ips.append(ip.network_address) - else: - if nets and nets[-1]._version != ip._version: - raise TypeError("%s and %s are not of the same version" % ( - ip, nets[-1])) - nets.append(ip) - - # sort and dedup - ips = sorted(set(ips)) - - # find consecutive address ranges in the sorted sequence and summarize them - if ips: - for first, last in _find_address_range(ips): - addrs.extend(summarize_address_range(first, last)) - - return _collapse_addresses_internal(addrs + nets) - - -def get_mixed_type_key(obj): - """Return a key suitable for sorting between networks and addresses. - - Address and Network objects are not sortable by default; they're - fundamentally different so the expression - - IPv4Address('192.0.2.0') <= IPv4Network('192.0.2.0/24') - - doesn't make any sense. There are some times however, where you may wish - to have ipaddress sort these for you anyway. If you need to do this, you - can use this function as the key= argument to sorted(). - - Args: - obj: either a Network or Address object. - Returns: - appropriate key. - - """ - if isinstance(obj, _BaseNetwork): - return obj._get_networks_key() - elif isinstance(obj, _BaseAddress): - return obj._get_address_key() - return NotImplemented - - -class _IPAddressBase(_TotalOrderingMixin): - - """The mother class.""" - - __slots__ = () - - @property - def exploded(self): - """Return the longhand version of the IP address as a string.""" - return self._explode_shorthand_ip_string() - - @property - def compressed(self): - """Return the shorthand version of the IP address as a string.""" - return _compat_str(self) - - @property - def reverse_pointer(self): - """The name of the reverse DNS pointer for the IP address, e.g.: - >>> ipaddress.ip_address("127.0.0.1").reverse_pointer - '1.0.0.127.in-addr.arpa' - >>> ipaddress.ip_address("2001:db8::1").reverse_pointer - '1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa' - - """ - return self._reverse_pointer() - - @property - def version(self): - msg = '%200s has no version specified' % (type(self),) - raise NotImplementedError(msg) - - def _check_int_address(self, address): - if address < 0: - msg = "%d (< 0) is not permitted as an IPv%d address" - raise AddressValueError(msg % (address, self._version)) - if address > self._ALL_ONES: - msg = "%d (>= 2**%d) is not permitted as an IPv%d address" - raise AddressValueError(msg % (address, self._max_prefixlen, - self._version)) - - def _check_packed_address(self, address, expected_len): - address_len = len(address) - if address_len != expected_len: - msg = ( - '%r (len %d != %d) is not permitted as an IPv%d address. ' - 'Did you pass in a bytes (str in Python 2) instead of' - ' a unicode object?') - raise AddressValueError(msg % (address, address_len, - expected_len, self._version)) - - @classmethod - def _ip_int_from_prefix(cls, prefixlen): - """Turn the prefix length into a bitwise netmask - - Args: - prefixlen: An integer, the prefix length. - - Returns: - An integer. - - """ - return cls._ALL_ONES ^ (cls._ALL_ONES >> prefixlen) - - @classmethod - def _prefix_from_ip_int(cls, ip_int): - """Return prefix length from the bitwise netmask. - - Args: - ip_int: An integer, the netmask in expanded bitwise format - - Returns: - An integer, the prefix length. - - Raises: - ValueError: If the input intermingles zeroes & ones - """ - trailing_zeroes = _count_righthand_zero_bits(ip_int, - cls._max_prefixlen) - prefixlen = cls._max_prefixlen - trailing_zeroes - leading_ones = ip_int >> trailing_zeroes - all_ones = (1 << prefixlen) - 1 - if leading_ones != all_ones: - byteslen = cls._max_prefixlen // 8 - details = _compat_to_bytes(ip_int, byteslen, 'big') - msg = 'Netmask pattern %r mixes zeroes & ones' - raise ValueError(msg % details) - return prefixlen - - @classmethod - def _report_invalid_netmask(cls, netmask_str): - msg = '%r is not a valid netmask' % netmask_str - raise NetmaskValueError(msg) - - @classmethod - def _prefix_from_prefix_string(cls, prefixlen_str): - """Return prefix length from a numeric string - - Args: - prefixlen_str: The string to be converted - - Returns: - An integer, the prefix length. - - Raises: - NetmaskValueError: If the input is not a valid netmask - """ - # int allows a leading +/- as well as surrounding whitespace, - # so we ensure that isn't the case - if not _BaseV4._DECIMAL_DIGITS.issuperset(prefixlen_str): - cls._report_invalid_netmask(prefixlen_str) - try: - prefixlen = int(prefixlen_str) - except ValueError: - cls._report_invalid_netmask(prefixlen_str) - if not (0 <= prefixlen <= cls._max_prefixlen): - cls._report_invalid_netmask(prefixlen_str) - return prefixlen - - @classmethod - def _prefix_from_ip_string(cls, ip_str): - """Turn a netmask/hostmask string into a prefix length - - Args: - ip_str: The netmask/hostmask to be converted - - Returns: - An integer, the prefix length. - - Raises: - NetmaskValueError: If the input is not a valid netmask/hostmask - """ - # Parse the netmask/hostmask like an IP address. - try: - ip_int = cls._ip_int_from_string(ip_str) - except AddressValueError: - cls._report_invalid_netmask(ip_str) - - # Try matching a netmask (this would be /1*0*/ as a bitwise regexp). - # Note that the two ambiguous cases (all-ones and all-zeroes) are - # treated as netmasks. - try: - return cls._prefix_from_ip_int(ip_int) - except ValueError: - pass - - # Invert the bits, and try matching a /0+1+/ hostmask instead. - ip_int ^= cls._ALL_ONES - try: - return cls._prefix_from_ip_int(ip_int) - except ValueError: - cls._report_invalid_netmask(ip_str) - - def __reduce__(self): - return self.__class__, (_compat_str(self),) - - -class _BaseAddress(_IPAddressBase): - - """A generic IP object. - - This IP class contains the version independent methods which are - used by single IP addresses. - """ - - __slots__ = () - - def __int__(self): - return self._ip - - def __eq__(self, other): - try: - return (self._ip == other._ip and - self._version == other._version) - except AttributeError: - return NotImplemented - - def __lt__(self, other): - if not isinstance(other, _IPAddressBase): - return NotImplemented - if not isinstance(other, _BaseAddress): - raise TypeError('%s and %s are not of the same type' % ( - self, other)) - if self._version != other._version: - raise TypeError('%s and %s are not of the same version' % ( - self, other)) - if self._ip != other._ip: - return self._ip < other._ip - return False - - # Shorthand for Integer addition and subtraction. This is not - # meant to ever support addition/subtraction of addresses. - def __add__(self, other): - if not isinstance(other, _compat_int_types): - return NotImplemented - return self.__class__(int(self) + other) - - def __sub__(self, other): - if not isinstance(other, _compat_int_types): - return NotImplemented - return self.__class__(int(self) - other) - - def __repr__(self): - return '%s(%r)' % (self.__class__.__name__, _compat_str(self)) - - def __str__(self): - return _compat_str(self._string_from_ip_int(self._ip)) - - def __hash__(self): - return hash(hex(int(self._ip))) - - def _get_address_key(self): - return (self._version, self) - - def __reduce__(self): - return self.__class__, (self._ip,) - - -class _BaseNetwork(_IPAddressBase): - - """A generic IP network object. - - This IP class contains the version independent methods which are - used by networks. - - """ - def __init__(self, address): - self._cache = {} - - def __repr__(self): - return '%s(%r)' % (self.__class__.__name__, _compat_str(self)) - - def __str__(self): - return '%s/%d' % (self.network_address, self.prefixlen) - - def hosts(self): - """Generate Iterator over usable hosts in a network. - - This is like __iter__ except it doesn't return the network - or broadcast addresses. - - """ - network = int(self.network_address) - broadcast = int(self.broadcast_address) - for x in _compat_range(network + 1, broadcast): - yield self._address_class(x) - - def __iter__(self): - network = int(self.network_address) - broadcast = int(self.broadcast_address) - for x in _compat_range(network, broadcast + 1): - yield self._address_class(x) - - def __getitem__(self, n): - network = int(self.network_address) - broadcast = int(self.broadcast_address) - if n >= 0: - if network + n > broadcast: - raise IndexError('address out of range') - return self._address_class(network + n) - else: - n += 1 - if broadcast + n < network: - raise IndexError('address out of range') - return self._address_class(broadcast + n) - - def __lt__(self, other): - if not isinstance(other, _IPAddressBase): - return NotImplemented - if not isinstance(other, _BaseNetwork): - raise TypeError('%s and %s are not of the same type' % ( - self, other)) - if self._version != other._version: - raise TypeError('%s and %s are not of the same version' % ( - self, other)) - if self.network_address != other.network_address: - return self.network_address < other.network_address - if self.netmask != other.netmask: - return self.netmask < other.netmask - return False - - def __eq__(self, other): - try: - return (self._version == other._version and - self.network_address == other.network_address and - int(self.netmask) == int(other.netmask)) - except AttributeError: - return NotImplemented - - def __hash__(self): - return hash(int(self.network_address) ^ int(self.netmask)) - - def __contains__(self, other): - # always false if one is v4 and the other is v6. - if self._version != other._version: - return False - # dealing with another network. - if isinstance(other, _BaseNetwork): - return False - # dealing with another address - else: - # address - return (int(self.network_address) <= int(other._ip) <= - int(self.broadcast_address)) - - def overlaps(self, other): - """Tell if self is partly contained in other.""" - return self.network_address in other or ( - self.broadcast_address in other or ( - other.network_address in self or ( - other.broadcast_address in self))) - - @property - def broadcast_address(self): - x = self._cache.get('broadcast_address') - if x is None: - x = self._address_class(int(self.network_address) | - int(self.hostmask)) - self._cache['broadcast_address'] = x - return x - - @property - def hostmask(self): - x = self._cache.get('hostmask') - if x is None: - x = self._address_class(int(self.netmask) ^ self._ALL_ONES) - self._cache['hostmask'] = x - return x - - @property - def with_prefixlen(self): - return '%s/%d' % (self.network_address, self._prefixlen) - - @property - def with_netmask(self): - return '%s/%s' % (self.network_address, self.netmask) - - @property - def with_hostmask(self): - return '%s/%s' % (self.network_address, self.hostmask) - - @property - def num_addresses(self): - """Number of hosts in the current subnet.""" - return int(self.broadcast_address) - int(self.network_address) + 1 - - @property - def _address_class(self): - # Returning bare address objects (rather than interfaces) allows for - # more consistent behaviour across the network address, broadcast - # address and individual host addresses. - msg = '%200s has no associated address class' % (type(self),) - raise NotImplementedError(msg) - - @property - def prefixlen(self): - return self._prefixlen - - def address_exclude(self, other): - """Remove an address from a larger block. - - For example: - - addr1 = ip_network('192.0.2.0/28') - addr2 = ip_network('192.0.2.1/32') - list(addr1.address_exclude(addr2)) = - [IPv4Network('192.0.2.0/32'), IPv4Network('192.0.2.2/31'), - IPv4Network('192.0.2.4/30'), IPv4Network('192.0.2.8/29')] - - or IPv6: - - addr1 = ip_network('2001:db8::1/32') - addr2 = ip_network('2001:db8::1/128') - list(addr1.address_exclude(addr2)) = - [ip_network('2001:db8::1/128'), - ip_network('2001:db8::2/127'), - ip_network('2001:db8::4/126'), - ip_network('2001:db8::8/125'), - ... - ip_network('2001:db8:8000::/33')] - - Args: - other: An IPv4Network or IPv6Network object of the same type. - - Returns: - An iterator of the IPv(4|6)Network objects which is self - minus other. - - Raises: - TypeError: If self and other are of differing address - versions, or if other is not a network object. - ValueError: If other is not completely contained by self. - - """ - if not self._version == other._version: - raise TypeError("%s and %s are not of the same version" % ( - self, other)) - - if not isinstance(other, _BaseNetwork): - raise TypeError("%s is not a network object" % other) - - if not other.subnet_of(self): - raise ValueError('%s not contained in %s' % (other, self)) - if other == self: - return - - # Make sure we're comparing the network of other. - other = other.__class__('%s/%s' % (other.network_address, - other.prefixlen)) - - s1, s2 = self.subnets() - while s1 != other and s2 != other: - if other.subnet_of(s1): - yield s2 - s1, s2 = s1.subnets() - elif other.subnet_of(s2): - yield s1 - s1, s2 = s2.subnets() - else: - # If we got here, there's a bug somewhere. - raise AssertionError('Error performing exclusion: ' - 's1: %s s2: %s other: %s' % - (s1, s2, other)) - if s1 == other: - yield s2 - elif s2 == other: - yield s1 - else: - # If we got here, there's a bug somewhere. - raise AssertionError('Error performing exclusion: ' - 's1: %s s2: %s other: %s' % - (s1, s2, other)) - - def compare_networks(self, other): - """Compare two IP objects. - - This is only concerned about the comparison of the integer - representation of the network addresses. This means that the - host bits aren't considered at all in this method. If you want - to compare host bits, you can easily enough do a - 'HostA._ip < HostB._ip' - - Args: - other: An IP object. - - Returns: - If the IP versions of self and other are the same, returns: - - -1 if self < other: - eg: IPv4Network('192.0.2.0/25') < IPv4Network('192.0.2.128/25') - IPv6Network('2001:db8::1000/124') < - IPv6Network('2001:db8::2000/124') - 0 if self == other - eg: IPv4Network('192.0.2.0/24') == IPv4Network('192.0.2.0/24') - IPv6Network('2001:db8::1000/124') == - IPv6Network('2001:db8::1000/124') - 1 if self > other - eg: IPv4Network('192.0.2.128/25') > IPv4Network('192.0.2.0/25') - IPv6Network('2001:db8::2000/124') > - IPv6Network('2001:db8::1000/124') - - Raises: - TypeError if the IP versions are different. - - """ - # does this need to raise a ValueError? - if self._version != other._version: - raise TypeError('%s and %s are not of the same type' % ( - self, other)) - # self._version == other._version below here: - if self.network_address < other.network_address: - return -1 - if self.network_address > other.network_address: - return 1 - # self.network_address == other.network_address below here: - if self.netmask < other.netmask: - return -1 - if self.netmask > other.netmask: - return 1 - return 0 - - def _get_networks_key(self): - """Network-only key function. - - Returns an object that identifies this address' network and - netmask. This function is a suitable "key" argument for sorted() - and list.sort(). - - """ - return (self._version, self.network_address, self.netmask) - - def subnets(self, prefixlen_diff=1, new_prefix=None): - """The subnets which join to make the current subnet. - - In the case that self contains only one IP - (self._prefixlen == 32 for IPv4 or self._prefixlen == 128 - for IPv6), yield an iterator with just ourself. - - Args: - prefixlen_diff: An integer, the amount the prefix length - should be increased by. This should not be set if - new_prefix is also set. - new_prefix: The desired new prefix length. This must be a - larger number (smaller prefix) than the existing prefix. - This should not be set if prefixlen_diff is also set. - - Returns: - An iterator of IPv(4|6) objects. - - Raises: - ValueError: The prefixlen_diff is too small or too large. - OR - prefixlen_diff and new_prefix are both set or new_prefix - is a smaller number than the current prefix (smaller - number means a larger network) - - """ - if self._prefixlen == self._max_prefixlen: - yield self - return - - if new_prefix is not None: - if new_prefix < self._prefixlen: - raise ValueError('new prefix must be longer') - if prefixlen_diff != 1: - raise ValueError('cannot set prefixlen_diff and new_prefix') - prefixlen_diff = new_prefix - self._prefixlen - - if prefixlen_diff < 0: - raise ValueError('prefix length diff must be > 0') - new_prefixlen = self._prefixlen + prefixlen_diff - - if new_prefixlen > self._max_prefixlen: - raise ValueError( - 'prefix length diff %d is invalid for netblock %s' % ( - new_prefixlen, self)) - - start = int(self.network_address) - end = int(self.broadcast_address) + 1 - step = (int(self.hostmask) + 1) >> prefixlen_diff - for new_addr in _compat_range(start, end, step): - current = self.__class__((new_addr, new_prefixlen)) - yield current - - def supernet(self, prefixlen_diff=1, new_prefix=None): - """The supernet containing the current network. - - Args: - prefixlen_diff: An integer, the amount the prefix length of - the network should be decreased by. For example, given a - /24 network and a prefixlen_diff of 3, a supernet with a - /21 netmask is returned. - - Returns: - An IPv4 network object. - - Raises: - ValueError: If self.prefixlen - prefixlen_diff < 0. I.e., you have - a negative prefix length. - OR - If prefixlen_diff and new_prefix are both set or new_prefix is a - larger number than the current prefix (larger number means a - smaller network) - - """ - if self._prefixlen == 0: - return self - - if new_prefix is not None: - if new_prefix > self._prefixlen: - raise ValueError('new prefix must be shorter') - if prefixlen_diff != 1: - raise ValueError('cannot set prefixlen_diff and new_prefix') - prefixlen_diff = self._prefixlen - new_prefix - - new_prefixlen = self.prefixlen - prefixlen_diff - if new_prefixlen < 0: - raise ValueError( - 'current prefixlen is %d, cannot have a prefixlen_diff of %d' % - (self.prefixlen, prefixlen_diff)) - return self.__class__(( - int(self.network_address) & (int(self.netmask) << prefixlen_diff), - new_prefixlen)) - - @property - def is_multicast(self): - """Test if the address is reserved for multicast use. - - Returns: - A boolean, True if the address is a multicast address. - See RFC 2373 2.7 for details. - - """ - return (self.network_address.is_multicast and - self.broadcast_address.is_multicast) - - @staticmethod - def _is_subnet_of(a, b): - try: - # Always false if one is v4 and the other is v6. - if a._version != b._version: - raise TypeError("%s and %s are not of the same version" (a, b)) - return (b.network_address <= a.network_address and - b.broadcast_address >= a.broadcast_address) - except AttributeError: - raise TypeError("Unable to test subnet containment " - "between %s and %s" % (a, b)) - - def subnet_of(self, other): - """Return True if this network is a subnet of other.""" - return self._is_subnet_of(self, other) - - def supernet_of(self, other): - """Return True if this network is a supernet of other.""" - return self._is_subnet_of(other, self) - - @property - def is_reserved(self): - """Test if the address is otherwise IETF reserved. - - Returns: - A boolean, True if the address is within one of the - reserved IPv6 Network ranges. - - """ - return (self.network_address.is_reserved and - self.broadcast_address.is_reserved) - - @property - def is_link_local(self): - """Test if the address is reserved for link-local. - - Returns: - A boolean, True if the address is reserved per RFC 4291. - - """ - return (self.network_address.is_link_local and - self.broadcast_address.is_link_local) - - @property - def is_private(self): - """Test if this address is allocated for private networks. - - Returns: - A boolean, True if the address is reserved per - iana-ipv4-special-registry or iana-ipv6-special-registry. - - """ - return (self.network_address.is_private and - self.broadcast_address.is_private) - - @property - def is_global(self): - """Test if this address is allocated for public networks. - - Returns: - A boolean, True if the address is not reserved per - iana-ipv4-special-registry or iana-ipv6-special-registry. - - """ - return not self.is_private - - @property - def is_unspecified(self): - """Test if the address is unspecified. - - Returns: - A boolean, True if this is the unspecified address as defined in - RFC 2373 2.5.2. - - """ - return (self.network_address.is_unspecified and - self.broadcast_address.is_unspecified) - - @property - def is_loopback(self): - """Test if the address is a loopback address. - - Returns: - A boolean, True if the address is a loopback address as defined in - RFC 2373 2.5.3. - - """ - return (self.network_address.is_loopback and - self.broadcast_address.is_loopback) - - -class _BaseV4(object): - - """Base IPv4 object. - - The following methods are used by IPv4 objects in both single IP - addresses and networks. - - """ - - __slots__ = () - _version = 4 - # Equivalent to 255.255.255.255 or 32 bits of 1's. - _ALL_ONES = (2 ** IPV4LENGTH) - 1 - _DECIMAL_DIGITS = frozenset('0123456789') - - # the valid octets for host and netmasks. only useful for IPv4. - _valid_mask_octets = frozenset([255, 254, 252, 248, 240, 224, 192, 128, 0]) - - _max_prefixlen = IPV4LENGTH - # There are only a handful of valid v4 netmasks, so we cache them all - # when constructed (see _make_netmask()). - _netmask_cache = {} - - def _explode_shorthand_ip_string(self): - return _compat_str(self) - - @classmethod - def _make_netmask(cls, arg): - """Make a (netmask, prefix_len) tuple from the given argument. - - Argument can be: - - an integer (the prefix length) - - a string representing the prefix length (e.g. "24") - - a string representing the prefix netmask (e.g. "255.255.255.0") - """ - if arg not in cls._netmask_cache: - if isinstance(arg, _compat_int_types): - prefixlen = arg - else: - try: - # Check for a netmask in prefix length form - prefixlen = cls._prefix_from_prefix_string(arg) - except NetmaskValueError: - # Check for a netmask or hostmask in dotted-quad form. - # This may raise NetmaskValueError. - prefixlen = cls._prefix_from_ip_string(arg) - netmask = IPv4Address(cls._ip_int_from_prefix(prefixlen)) - cls._netmask_cache[arg] = netmask, prefixlen - return cls._netmask_cache[arg] - - @classmethod - def _ip_int_from_string(cls, ip_str): - """Turn the given IP string into an integer for comparison. - - Args: - ip_str: A string, the IP ip_str. - - Returns: - The IP ip_str as an integer. - - Raises: - AddressValueError: if ip_str isn't a valid IPv4 Address. - - """ - if not ip_str: - raise AddressValueError('Address cannot be empty') - - octets = ip_str.split('.') - if len(octets) != 4: - raise AddressValueError("Expected 4 octets in %r" % ip_str) - - try: - return _compat_int_from_byte_vals( - map(cls._parse_octet, octets), 'big') - except ValueError as exc: - raise AddressValueError("%s in %r" % (exc, ip_str)) - - @classmethod - def _parse_octet(cls, octet_str): - """Convert a decimal octet into an integer. - - Args: - octet_str: A string, the number to parse. - - Returns: - The octet as an integer. - - Raises: - ValueError: if the octet isn't strictly a decimal from [0..255]. - - """ - if not octet_str: - raise ValueError("Empty octet not permitted") - # Whitelist the characters, since int() allows a lot of bizarre stuff. - if not cls._DECIMAL_DIGITS.issuperset(octet_str): - msg = "Only decimal digits permitted in %r" - raise ValueError(msg % octet_str) - # We do the length check second, since the invalid character error - # is likely to be more informative for the user - if len(octet_str) > 3: - msg = "At most 3 characters permitted in %r" - raise ValueError(msg % octet_str) - # Convert to integer (we know digits are legal) - octet_int = int(octet_str, 10) - # Any octets that look like they *might* be written in octal, - # and which don't look exactly the same in both octal and - # decimal are rejected as ambiguous - if octet_int > 7 and octet_str[0] == '0': - msg = "Ambiguous (octal/decimal) value in %r not permitted" - raise ValueError(msg % octet_str) - if octet_int > 255: - raise ValueError("Octet %d (> 255) not permitted" % octet_int) - return octet_int - - @classmethod - def _string_from_ip_int(cls, ip_int): - """Turns a 32-bit integer into dotted decimal notation. - - Args: - ip_int: An integer, the IP address. - - Returns: - The IP address as a string in dotted decimal notation. - - """ - return '.'.join(_compat_str(struct.unpack(b'!B', b)[0] - if isinstance(b, bytes) - else b) - for b in _compat_to_bytes(ip_int, 4, 'big')) - - def _is_hostmask(self, ip_str): - """Test if the IP string is a hostmask (rather than a netmask). - - Args: - ip_str: A string, the potential hostmask. - - Returns: - A boolean, True if the IP string is a hostmask. - - """ - bits = ip_str.split('.') - try: - parts = [x for x in map(int, bits) if x in self._valid_mask_octets] - except ValueError: - return False - if len(parts) != len(bits): - return False - if parts[0] < parts[-1]: - return True - return False - - def _reverse_pointer(self): - """Return the reverse DNS pointer name for the IPv4 address. - - This implements the method described in RFC1035 3.5. - - """ - reverse_octets = _compat_str(self).split('.')[::-1] - return '.'.join(reverse_octets) + '.in-addr.arpa' - - @property - def max_prefixlen(self): - return self._max_prefixlen - - @property - def version(self): - return self._version - - -class IPv4Address(_BaseV4, _BaseAddress): - - """Represent and manipulate single IPv4 Addresses.""" - - __slots__ = ('_ip', '__weakref__') - - def __init__(self, address): - - """ - Args: - address: A string or integer representing the IP - - Additionally, an integer can be passed, so - IPv4Address('192.0.2.1') == IPv4Address(3221225985). - or, more generally - IPv4Address(int(IPv4Address('192.0.2.1'))) == - IPv4Address('192.0.2.1') - - Raises: - AddressValueError: If ipaddress isn't a valid IPv4 address. - - """ - # Efficient constructor from integer. - if isinstance(address, _compat_int_types): - self._check_int_address(address) - self._ip = address - return - - # Constructing from a packed address - if isinstance(address, bytes): - self._check_packed_address(address, 4) - bvs = _compat_bytes_to_byte_vals(address) - self._ip = _compat_int_from_byte_vals(bvs, 'big') - return - - # Assume input argument to be string or any object representation - # which converts into a formatted IP string. - addr_str = _compat_str(address) - if '/' in addr_str: - raise AddressValueError("Unexpected '/' in %r" % address) - self._ip = self._ip_int_from_string(addr_str) - - @property - def packed(self): - """The binary representation of this address.""" - return v4_int_to_packed(self._ip) - - @property - def is_reserved(self): - """Test if the address is otherwise IETF reserved. - - Returns: - A boolean, True if the address is within the - reserved IPv4 Network range. - - """ - return self in self._constants._reserved_network - - @property - def is_private(self): - """Test if this address is allocated for private networks. - - Returns: - A boolean, True if the address is reserved per - iana-ipv4-special-registry. - - """ - return any(self in net for net in self._constants._private_networks) - - @property - def is_global(self): - return ( - self not in self._constants._public_network and - not self.is_private) - - @property - def is_multicast(self): - """Test if the address is reserved for multicast use. - - Returns: - A boolean, True if the address is multicast. - See RFC 3171 for details. - - """ - return self in self._constants._multicast_network - - @property - def is_unspecified(self): - """Test if the address is unspecified. - - Returns: - A boolean, True if this is the unspecified address as defined in - RFC 5735 3. - - """ - return self == self._constants._unspecified_address - - @property - def is_loopback(self): - """Test if the address is a loopback address. - - Returns: - A boolean, True if the address is a loopback per RFC 3330. - - """ - return self in self._constants._loopback_network - - @property - def is_link_local(self): - """Test if the address is reserved for link-local. - - Returns: - A boolean, True if the address is link-local per RFC 3927. - - """ - return self in self._constants._linklocal_network - - -class IPv4Interface(IPv4Address): - - def __init__(self, address): - if isinstance(address, (bytes, _compat_int_types)): - IPv4Address.__init__(self, address) - self.network = IPv4Network(self._ip) - self._prefixlen = self._max_prefixlen - return - - if isinstance(address, tuple): - IPv4Address.__init__(self, address[0]) - if len(address) > 1: - self._prefixlen = int(address[1]) - else: - self._prefixlen = self._max_prefixlen - - self.network = IPv4Network(address, strict=False) - self.netmask = self.network.netmask - self.hostmask = self.network.hostmask - return - - addr = _split_optional_netmask(address) - IPv4Address.__init__(self, addr[0]) - - self.network = IPv4Network(address, strict=False) - self._prefixlen = self.network._prefixlen - - self.netmask = self.network.netmask - self.hostmask = self.network.hostmask - - def __str__(self): - return '%s/%d' % (self._string_from_ip_int(self._ip), - self.network.prefixlen) - - def __eq__(self, other): - address_equal = IPv4Address.__eq__(self, other) - if not address_equal or address_equal is NotImplemented: - return address_equal - try: - return self.network == other.network - except AttributeError: - # An interface with an associated network is NOT the - # same as an unassociated address. That's why the hash - # takes the extra info into account. - return False - - def __lt__(self, other): - address_less = IPv4Address.__lt__(self, other) - if address_less is NotImplemented: - return NotImplemented - try: - return (self.network < other.network or - self.network == other.network and address_less) - except AttributeError: - # We *do* allow addresses and interfaces to be sorted. The - # unassociated address is considered less than all interfaces. - return False - - def __hash__(self): - return self._ip ^ self._prefixlen ^ int(self.network.network_address) - - __reduce__ = _IPAddressBase.__reduce__ - - @property - def ip(self): - return IPv4Address(self._ip) - - @property - def with_prefixlen(self): - return '%s/%s' % (self._string_from_ip_int(self._ip), - self._prefixlen) - - @property - def with_netmask(self): - return '%s/%s' % (self._string_from_ip_int(self._ip), - self.netmask) - - @property - def with_hostmask(self): - return '%s/%s' % (self._string_from_ip_int(self._ip), - self.hostmask) - - -class IPv4Network(_BaseV4, _BaseNetwork): - - """This class represents and manipulates 32-bit IPv4 network + addresses.. - - Attributes: [examples for IPv4Network('192.0.2.0/27')] - .network_address: IPv4Address('192.0.2.0') - .hostmask: IPv4Address('0.0.0.31') - .broadcast_address: IPv4Address('192.0.2.32') - .netmask: IPv4Address('255.255.255.224') - .prefixlen: 27 - - """ - # Class to use when creating address objects - _address_class = IPv4Address - - def __init__(self, address, strict=True): - - """Instantiate a new IPv4 network object. - - Args: - address: A string or integer representing the IP [& network]. - '192.0.2.0/24' - '192.0.2.0/255.255.255.0' - '192.0.0.2/0.0.0.255' - are all functionally the same in IPv4. Similarly, - '192.0.2.1' - '192.0.2.1/255.255.255.255' - '192.0.2.1/32' - are also functionally equivalent. That is to say, failing to - provide a subnetmask will create an object with a mask of /32. - - If the mask (portion after the / in the argument) is given in - dotted quad form, it is treated as a netmask if it starts with a - non-zero field (e.g. /255.0.0.0 == /8) and as a hostmask if it - starts with a zero field (e.g. 0.255.255.255 == /8), with the - single exception of an all-zero mask which is treated as a - netmask == /0. If no mask is given, a default of /32 is used. - - Additionally, an integer can be passed, so - IPv4Network('192.0.2.1') == IPv4Network(3221225985) - or, more generally - IPv4Interface(int(IPv4Interface('192.0.2.1'))) == - IPv4Interface('192.0.2.1') - - Raises: - AddressValueError: If ipaddress isn't a valid IPv4 address. - NetmaskValueError: If the netmask isn't valid for - an IPv4 address. - ValueError: If strict is True and a network address is not - supplied. - - """ - _BaseNetwork.__init__(self, address) - - # Constructing from a packed address or integer - if isinstance(address, (_compat_int_types, bytes)): - self.network_address = IPv4Address(address) - self.netmask, self._prefixlen = self._make_netmask( - self._max_prefixlen) - # fixme: address/network test here. - return - - if isinstance(address, tuple): - if len(address) > 1: - arg = address[1] - else: - # We weren't given an address[1] - arg = self._max_prefixlen - self.network_address = IPv4Address(address[0]) - self.netmask, self._prefixlen = self._make_netmask(arg) - packed = int(self.network_address) - if packed & int(self.netmask) != packed: - if strict: - raise ValueError('%s has host bits set' % self) - else: - self.network_address = IPv4Address(packed & - int(self.netmask)) - return - - # Assume input argument to be string or any object representation - # which converts into a formatted IP prefix string. - addr = _split_optional_netmask(address) - self.network_address = IPv4Address(self._ip_int_from_string(addr[0])) - - if len(addr) == 2: - arg = addr[1] - else: - arg = self._max_prefixlen - self.netmask, self._prefixlen = self._make_netmask(arg) - - if strict: - if (IPv4Address(int(self.network_address) & int(self.netmask)) != - self.network_address): - raise ValueError('%s has host bits set' % self) - self.network_address = IPv4Address(int(self.network_address) & - int(self.netmask)) - - if self._prefixlen == (self._max_prefixlen - 1): - self.hosts = self.__iter__ - - @property - def is_global(self): - """Test if this address is allocated for public networks. - - Returns: - A boolean, True if the address is not reserved per - iana-ipv4-special-registry. - - """ - return (not (self.network_address in IPv4Network('100.64.0.0/10') and - self.broadcast_address in IPv4Network('100.64.0.0/10')) and - not self.is_private) - - -class _IPv4Constants(object): - - _linklocal_network = IPv4Network('169.254.0.0/16') - - _loopback_network = IPv4Network('127.0.0.0/8') - - _multicast_network = IPv4Network('224.0.0.0/4') - - _public_network = IPv4Network('100.64.0.0/10') - - _private_networks = [ - IPv4Network('0.0.0.0/8'), - IPv4Network('10.0.0.0/8'), - IPv4Network('127.0.0.0/8'), - IPv4Network('169.254.0.0/16'), - IPv4Network('172.16.0.0/12'), - IPv4Network('192.0.0.0/29'), - IPv4Network('192.0.0.170/31'), - IPv4Network('192.0.2.0/24'), - IPv4Network('192.168.0.0/16'), - IPv4Network('198.18.0.0/15'), - IPv4Network('198.51.100.0/24'), - IPv4Network('203.0.113.0/24'), - IPv4Network('240.0.0.0/4'), - IPv4Network('255.255.255.255/32'), - ] - - _reserved_network = IPv4Network('240.0.0.0/4') - - _unspecified_address = IPv4Address('0.0.0.0') - - -IPv4Address._constants = _IPv4Constants - - -class _BaseV6(object): - - """Base IPv6 object. - - The following methods are used by IPv6 objects in both single IP - addresses and networks. - - """ - - __slots__ = () - _version = 6 - _ALL_ONES = (2 ** IPV6LENGTH) - 1 - _HEXTET_COUNT = 8 - _HEX_DIGITS = frozenset('0123456789ABCDEFabcdef') - _max_prefixlen = IPV6LENGTH - - # There are only a bunch of valid v6 netmasks, so we cache them all - # when constructed (see _make_netmask()). - _netmask_cache = {} - - @classmethod - def _make_netmask(cls, arg): - """Make a (netmask, prefix_len) tuple from the given argument. - - Argument can be: - - an integer (the prefix length) - - a string representing the prefix length (e.g. "24") - - a string representing the prefix netmask (e.g. "255.255.255.0") - """ - if arg not in cls._netmask_cache: - if isinstance(arg, _compat_int_types): - prefixlen = arg - else: - prefixlen = cls._prefix_from_prefix_string(arg) - netmask = IPv6Address(cls._ip_int_from_prefix(prefixlen)) - cls._netmask_cache[arg] = netmask, prefixlen - return cls._netmask_cache[arg] - - @classmethod - def _ip_int_from_string(cls, ip_str): - """Turn an IPv6 ip_str into an integer. - - Args: - ip_str: A string, the IPv6 ip_str. - - Returns: - An int, the IPv6 address - - Raises: - AddressValueError: if ip_str isn't a valid IPv6 Address. - - """ - if not ip_str: - raise AddressValueError('Address cannot be empty') - - parts = ip_str.split(':') - - # An IPv6 address needs at least 2 colons (3 parts). - _min_parts = 3 - if len(parts) < _min_parts: - msg = "At least %d parts expected in %r" % (_min_parts, ip_str) - raise AddressValueError(msg) - - # If the address has an IPv4-style suffix, convert it to hexadecimal. - if '.' in parts[-1]: - try: - ipv4_int = IPv4Address(parts.pop())._ip - except AddressValueError as exc: - raise AddressValueError("%s in %r" % (exc, ip_str)) - parts.append('%x' % ((ipv4_int >> 16) & 0xFFFF)) - parts.append('%x' % (ipv4_int & 0xFFFF)) - - # An IPv6 address can't have more than 8 colons (9 parts). - # The extra colon comes from using the "::" notation for a single - # leading or trailing zero part. - _max_parts = cls._HEXTET_COUNT + 1 - if len(parts) > _max_parts: - msg = "At most %d colons permitted in %r" % ( - _max_parts - 1, ip_str) - raise AddressValueError(msg) - - # Disregarding the endpoints, find '::' with nothing in between. - # This indicates that a run of zeroes has been skipped. - skip_index = None - for i in _compat_range(1, len(parts) - 1): - if not parts[i]: - if skip_index is not None: - # Can't have more than one '::' - msg = "At most one '::' permitted in %r" % ip_str - raise AddressValueError(msg) - skip_index = i - - # parts_hi is the number of parts to copy from above/before the '::' - # parts_lo is the number of parts to copy from below/after the '::' - if skip_index is not None: - # If we found a '::', then check if it also covers the endpoints. - parts_hi = skip_index - parts_lo = len(parts) - skip_index - 1 - if not parts[0]: - parts_hi -= 1 - if parts_hi: - msg = "Leading ':' only permitted as part of '::' in %r" - raise AddressValueError(msg % ip_str) # ^: requires ^:: - if not parts[-1]: - parts_lo -= 1 - if parts_lo: - msg = "Trailing ':' only permitted as part of '::' in %r" - raise AddressValueError(msg % ip_str) # :$ requires ::$ - parts_skipped = cls._HEXTET_COUNT - (parts_hi + parts_lo) - if parts_skipped < 1: - msg = "Expected at most %d other parts with '::' in %r" - raise AddressValueError(msg % (cls._HEXTET_COUNT - 1, ip_str)) - else: - # Otherwise, allocate the entire address to parts_hi. The - # endpoints could still be empty, but _parse_hextet() will check - # for that. - if len(parts) != cls._HEXTET_COUNT: - msg = "Exactly %d parts expected without '::' in %r" - raise AddressValueError(msg % (cls._HEXTET_COUNT, ip_str)) - if not parts[0]: - msg = "Leading ':' only permitted as part of '::' in %r" - raise AddressValueError(msg % ip_str) # ^: requires ^:: - if not parts[-1]: - msg = "Trailing ':' only permitted as part of '::' in %r" - raise AddressValueError(msg % ip_str) # :$ requires ::$ - parts_hi = len(parts) - parts_lo = 0 - parts_skipped = 0 - - try: - # Now, parse the hextets into a 128-bit integer. - ip_int = 0 - for i in range(parts_hi): - ip_int <<= 16 - ip_int |= cls._parse_hextet(parts[i]) - ip_int <<= 16 * parts_skipped - for i in range(-parts_lo, 0): - ip_int <<= 16 - ip_int |= cls._parse_hextet(parts[i]) - return ip_int - except ValueError as exc: - raise AddressValueError("%s in %r" % (exc, ip_str)) - - @classmethod - def _parse_hextet(cls, hextet_str): - """Convert an IPv6 hextet string into an integer. - - Args: - hextet_str: A string, the number to parse. - - Returns: - The hextet as an integer. - - Raises: - ValueError: if the input isn't strictly a hex number from - [0..FFFF]. - - """ - # Whitelist the characters, since int() allows a lot of bizarre stuff. - if not cls._HEX_DIGITS.issuperset(hextet_str): - raise ValueError("Only hex digits permitted in %r" % hextet_str) - # We do the length check second, since the invalid character error - # is likely to be more informative for the user - if len(hextet_str) > 4: - msg = "At most 4 characters permitted in %r" - raise ValueError(msg % hextet_str) - # Length check means we can skip checking the integer value - return int(hextet_str, 16) - - @classmethod - def _compress_hextets(cls, hextets): - """Compresses a list of hextets. - - Compresses a list of strings, replacing the longest continuous - sequence of "0" in the list with "" and adding empty strings at - the beginning or at the end of the string such that subsequently - calling ":".join(hextets) will produce the compressed version of - the IPv6 address. - - Args: - hextets: A list of strings, the hextets to compress. - - Returns: - A list of strings. - - """ - best_doublecolon_start = -1 - best_doublecolon_len = 0 - doublecolon_start = -1 - doublecolon_len = 0 - for index, hextet in enumerate(hextets): - if hextet == '0': - doublecolon_len += 1 - if doublecolon_start == -1: - # Start of a sequence of zeros. - doublecolon_start = index - if doublecolon_len > best_doublecolon_len: - # This is the longest sequence of zeros so far. - best_doublecolon_len = doublecolon_len - best_doublecolon_start = doublecolon_start - else: - doublecolon_len = 0 - doublecolon_start = -1 - - if best_doublecolon_len > 1: - best_doublecolon_end = (best_doublecolon_start + - best_doublecolon_len) - # For zeros at the end of the address. - if best_doublecolon_end == len(hextets): - hextets += [''] - hextets[best_doublecolon_start:best_doublecolon_end] = [''] - # For zeros at the beginning of the address. - if best_doublecolon_start == 0: - hextets = [''] + hextets - - return hextets - - @classmethod - def _string_from_ip_int(cls, ip_int=None): - """Turns a 128-bit integer into hexadecimal notation. - - Args: - ip_int: An integer, the IP address. - - Returns: - A string, the hexadecimal representation of the address. - - Raises: - ValueError: The address is bigger than 128 bits of all ones. - - """ - if ip_int is None: - ip_int = int(cls._ip) - - if ip_int > cls._ALL_ONES: - raise ValueError('IPv6 address is too large') - - hex_str = '%032x' % ip_int - hextets = ['%x' % int(hex_str[x:x + 4], 16) for x in range(0, 32, 4)] - - hextets = cls._compress_hextets(hextets) - return ':'.join(hextets) - - def _explode_shorthand_ip_string(self): - """Expand a shortened IPv6 address. - - Args: - ip_str: A string, the IPv6 address. - - Returns: - A string, the expanded IPv6 address. - - """ - if isinstance(self, IPv6Network): - ip_str = _compat_str(self.network_address) - elif isinstance(self, IPv6Interface): - ip_str = _compat_str(self.ip) - else: - ip_str = _compat_str(self) - - ip_int = self._ip_int_from_string(ip_str) - hex_str = '%032x' % ip_int - parts = [hex_str[x:x + 4] for x in range(0, 32, 4)] - if isinstance(self, (_BaseNetwork, IPv6Interface)): - return '%s/%d' % (':'.join(parts), self._prefixlen) - return ':'.join(parts) - - def _reverse_pointer(self): - """Return the reverse DNS pointer name for the IPv6 address. - - This implements the method described in RFC3596 2.5. - - """ - reverse_chars = self.exploded[::-1].replace(':', '') - return '.'.join(reverse_chars) + '.ip6.arpa' - - @property - def max_prefixlen(self): - return self._max_prefixlen - - @property - def version(self): - return self._version - - -class IPv6Address(_BaseV6, _BaseAddress): - - """Represent and manipulate single IPv6 Addresses.""" - - __slots__ = ('_ip', '__weakref__') - - def __init__(self, address): - """Instantiate a new IPv6 address object. - - Args: - address: A string or integer representing the IP - - Additionally, an integer can be passed, so - IPv6Address('2001:db8::') == - IPv6Address(42540766411282592856903984951653826560) - or, more generally - IPv6Address(int(IPv6Address('2001:db8::'))) == - IPv6Address('2001:db8::') - - Raises: - AddressValueError: If address isn't a valid IPv6 address. - - """ - # Efficient constructor from integer. - if isinstance(address, _compat_int_types): - self._check_int_address(address) - self._ip = address - return - - # Constructing from a packed address - if isinstance(address, bytes): - self._check_packed_address(address, 16) - bvs = _compat_bytes_to_byte_vals(address) - self._ip = _compat_int_from_byte_vals(bvs, 'big') - return - - # Assume input argument to be string or any object representation - # which converts into a formatted IP string. - addr_str = _compat_str(address) - if '/' in addr_str: - raise AddressValueError("Unexpected '/' in %r" % address) - self._ip = self._ip_int_from_string(addr_str) - - @property - def packed(self): - """The binary representation of this address.""" - return v6_int_to_packed(self._ip) - - @property - def is_multicast(self): - """Test if the address is reserved for multicast use. - - Returns: - A boolean, True if the address is a multicast address. - See RFC 2373 2.7 for details. - - """ - return self in self._constants._multicast_network - - @property - def is_reserved(self): - """Test if the address is otherwise IETF reserved. - - Returns: - A boolean, True if the address is within one of the - reserved IPv6 Network ranges. - - """ - return any(self in x for x in self._constants._reserved_networks) - - @property - def is_link_local(self): - """Test if the address is reserved for link-local. - - Returns: - A boolean, True if the address is reserved per RFC 4291. - - """ - return self in self._constants._linklocal_network - - @property - def is_site_local(self): - """Test if the address is reserved for site-local. - - Note that the site-local address space has been deprecated by RFC 3879. - Use is_private to test if this address is in the space of unique local - addresses as defined by RFC 4193. - - Returns: - A boolean, True if the address is reserved per RFC 3513 2.5.6. - - """ - return self in self._constants._sitelocal_network - - @property - def is_private(self): - """Test if this address is allocated for private networks. - - Returns: - A boolean, True if the address is reserved per - iana-ipv6-special-registry. - - """ - return any(self in net for net in self._constants._private_networks) - - @property - def is_global(self): - """Test if this address is allocated for public networks. - - Returns: - A boolean, true if the address is not reserved per - iana-ipv6-special-registry. - - """ - return not self.is_private - - @property - def is_unspecified(self): - """Test if the address is unspecified. - - Returns: - A boolean, True if this is the unspecified address as defined in - RFC 2373 2.5.2. - - """ - return self._ip == 0 - - @property - def is_loopback(self): - """Test if the address is a loopback address. - - Returns: - A boolean, True if the address is a loopback address as defined in - RFC 2373 2.5.3. - - """ - return self._ip == 1 - - @property - def ipv4_mapped(self): - """Return the IPv4 mapped address. - - Returns: - If the IPv6 address is a v4 mapped address, return the - IPv4 mapped address. Return None otherwise. - - """ - if (self._ip >> 32) != 0xFFFF: - return None - return IPv4Address(self._ip & 0xFFFFFFFF) - - @property - def teredo(self): - """Tuple of embedded teredo IPs. - - Returns: - Tuple of the (server, client) IPs or None if the address - doesn't appear to be a teredo address (doesn't start with - 2001::/32) - - """ - if (self._ip >> 96) != 0x20010000: - return None - return (IPv4Address((self._ip >> 64) & 0xFFFFFFFF), - IPv4Address(~self._ip & 0xFFFFFFFF)) - - @property - def sixtofour(self): - """Return the IPv4 6to4 embedded address. - - Returns: - The IPv4 6to4-embedded address if present or None if the - address doesn't appear to contain a 6to4 embedded address. - - """ - if (self._ip >> 112) != 0x2002: - return None - return IPv4Address((self._ip >> 80) & 0xFFFFFFFF) - - -class IPv6Interface(IPv6Address): - - def __init__(self, address): - if isinstance(address, (bytes, _compat_int_types)): - IPv6Address.__init__(self, address) - self.network = IPv6Network(self._ip) - self._prefixlen = self._max_prefixlen - return - if isinstance(address, tuple): - IPv6Address.__init__(self, address[0]) - if len(address) > 1: - self._prefixlen = int(address[1]) - else: - self._prefixlen = self._max_prefixlen - self.network = IPv6Network(address, strict=False) - self.netmask = self.network.netmask - self.hostmask = self.network.hostmask - return - - addr = _split_optional_netmask(address) - IPv6Address.__init__(self, addr[0]) - self.network = IPv6Network(address, strict=False) - self.netmask = self.network.netmask - self._prefixlen = self.network._prefixlen - self.hostmask = self.network.hostmask - - def __str__(self): - return '%s/%d' % (self._string_from_ip_int(self._ip), - self.network.prefixlen) - - def __eq__(self, other): - address_equal = IPv6Address.__eq__(self, other) - if not address_equal or address_equal is NotImplemented: - return address_equal - try: - return self.network == other.network - except AttributeError: - # An interface with an associated network is NOT the - # same as an unassociated address. That's why the hash - # takes the extra info into account. - return False - - def __lt__(self, other): - address_less = IPv6Address.__lt__(self, other) - if address_less is NotImplemented: - return NotImplemented - try: - return (self.network < other.network or - self.network == other.network and address_less) - except AttributeError: - # We *do* allow addresses and interfaces to be sorted. The - # unassociated address is considered less than all interfaces. - return False - - def __hash__(self): - return self._ip ^ self._prefixlen ^ int(self.network.network_address) - - __reduce__ = _IPAddressBase.__reduce__ - - @property - def ip(self): - return IPv6Address(self._ip) - - @property - def with_prefixlen(self): - return '%s/%s' % (self._string_from_ip_int(self._ip), - self._prefixlen) - - @property - def with_netmask(self): - return '%s/%s' % (self._string_from_ip_int(self._ip), - self.netmask) - - @property - def with_hostmask(self): - return '%s/%s' % (self._string_from_ip_int(self._ip), - self.hostmask) - - @property - def is_unspecified(self): - return self._ip == 0 and self.network.is_unspecified - - @property - def is_loopback(self): - return self._ip == 1 and self.network.is_loopback - - -class IPv6Network(_BaseV6, _BaseNetwork): - - """This class represents and manipulates 128-bit IPv6 networks. - - Attributes: [examples for IPv6('2001:db8::1000/124')] - .network_address: IPv6Address('2001:db8::1000') - .hostmask: IPv6Address('::f') - .broadcast_address: IPv6Address('2001:db8::100f') - .netmask: IPv6Address('ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff0') - .prefixlen: 124 - - """ - - # Class to use when creating address objects - _address_class = IPv6Address - - def __init__(self, address, strict=True): - """Instantiate a new IPv6 Network object. - - Args: - address: A string or integer representing the IPv6 network or the - IP and prefix/netmask. - '2001:db8::/128' - '2001:db8:0000:0000:0000:0000:0000:0000/128' - '2001:db8::' - are all functionally the same in IPv6. That is to say, - failing to provide a subnetmask will create an object with - a mask of /128. - - Additionally, an integer can be passed, so - IPv6Network('2001:db8::') == - IPv6Network(42540766411282592856903984951653826560) - or, more generally - IPv6Network(int(IPv6Network('2001:db8::'))) == - IPv6Network('2001:db8::') - - strict: A boolean. If true, ensure that we have been passed - A true network address, eg, 2001:db8::1000/124 and not an - IP address on a network, eg, 2001:db8::1/124. - - Raises: - AddressValueError: If address isn't a valid IPv6 address. - NetmaskValueError: If the netmask isn't valid for - an IPv6 address. - ValueError: If strict was True and a network address was not - supplied. - - """ - _BaseNetwork.__init__(self, address) - - # Efficient constructor from integer or packed address - if isinstance(address, (bytes, _compat_int_types)): - self.network_address = IPv6Address(address) - self.netmask, self._prefixlen = self._make_netmask( - self._max_prefixlen) - return - - if isinstance(address, tuple): - if len(address) > 1: - arg = address[1] - else: - arg = self._max_prefixlen - self.netmask, self._prefixlen = self._make_netmask(arg) - self.network_address = IPv6Address(address[0]) - packed = int(self.network_address) - if packed & int(self.netmask) != packed: - if strict: - raise ValueError('%s has host bits set' % self) - else: - self.network_address = IPv6Address(packed & - int(self.netmask)) - return - - # Assume input argument to be string or any object representation - # which converts into a formatted IP prefix string. - addr = _split_optional_netmask(address) - - self.network_address = IPv6Address(self._ip_int_from_string(addr[0])) - - if len(addr) == 2: - arg = addr[1] - else: - arg = self._max_prefixlen - self.netmask, self._prefixlen = self._make_netmask(arg) - - if strict: - if (IPv6Address(int(self.network_address) & int(self.netmask)) != - self.network_address): - raise ValueError('%s has host bits set' % self) - self.network_address = IPv6Address(int(self.network_address) & - int(self.netmask)) - - if self._prefixlen == (self._max_prefixlen - 1): - self.hosts = self.__iter__ - - def hosts(self): - """Generate Iterator over usable hosts in a network. - - This is like __iter__ except it doesn't return the - Subnet-Router anycast address. - - """ - network = int(self.network_address) - broadcast = int(self.broadcast_address) - for x in _compat_range(network + 1, broadcast + 1): - yield self._address_class(x) - - @property - def is_site_local(self): - """Test if the address is reserved for site-local. - - Note that the site-local address space has been deprecated by RFC 3879. - Use is_private to test if this address is in the space of unique local - addresses as defined by RFC 4193. - - Returns: - A boolean, True if the address is reserved per RFC 3513 2.5.6. - - """ - return (self.network_address.is_site_local and - self.broadcast_address.is_site_local) - - -class _IPv6Constants(object): - - _linklocal_network = IPv6Network('fe80::/10') - - _multicast_network = IPv6Network('ff00::/8') - - _private_networks = [ - IPv6Network('::1/128'), - IPv6Network('::/128'), - IPv6Network('::ffff:0:0/96'), - IPv6Network('100::/64'), - IPv6Network('2001::/23'), - IPv6Network('2001:2::/48'), - IPv6Network('2001:db8::/32'), - IPv6Network('2001:10::/28'), - IPv6Network('fc00::/7'), - IPv6Network('fe80::/10'), - ] - - _reserved_networks = [ - IPv6Network('::/8'), IPv6Network('100::/8'), - IPv6Network('200::/7'), IPv6Network('400::/6'), - IPv6Network('800::/5'), IPv6Network('1000::/4'), - IPv6Network('4000::/3'), IPv6Network('6000::/3'), - IPv6Network('8000::/3'), IPv6Network('A000::/3'), - IPv6Network('C000::/3'), IPv6Network('E000::/4'), - IPv6Network('F000::/5'), IPv6Network('F800::/6'), - IPv6Network('FE00::/9'), - ] - - _sitelocal_network = IPv6Network('fec0::/10') - - -IPv6Address._constants = _IPv6Constants diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/__init__.py deleted file mode 100644 index a6f44a5..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/__init__.py +++ /dev/null @@ -1,347 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -lockfile.py - Platform-independent advisory file locks. - -Requires Python 2.5 unless you apply 2.4.diff -Locking is done on a per-thread basis instead of a per-process basis. - -Usage: - ->>> lock = LockFile('somefile') ->>> try: -... lock.acquire() -... except AlreadyLocked: -... print 'somefile', 'is locked already.' -... except LockFailed: -... print 'somefile', 'can\\'t be locked.' -... else: -... print 'got lock' -got lock ->>> print lock.is_locked() -True ->>> lock.release() - ->>> lock = LockFile('somefile') ->>> print lock.is_locked() -False ->>> with lock: -... print lock.is_locked() -True ->>> print lock.is_locked() -False - ->>> lock = LockFile('somefile') ->>> # It is okay to lock twice from the same thread... ->>> with lock: -... lock.acquire() -... ->>> # Though no counter is kept, so you can't unlock multiple times... ->>> print lock.is_locked() -False - -Exceptions: - - Error - base class for other exceptions - LockError - base class for all locking exceptions - AlreadyLocked - Another thread or process already holds the lock - LockFailed - Lock failed for some other reason - UnlockError - base class for all unlocking exceptions - AlreadyUnlocked - File was not locked. - NotMyLock - File was locked but not by the current thread/process -""" - -from __future__ import absolute_import - -import functools -import os -import socket -import threading -import warnings - -# Work with PEP8 and non-PEP8 versions of threading module. -if not hasattr(threading, "current_thread"): - threading.current_thread = threading.currentThread -if not hasattr(threading.Thread, "get_name"): - threading.Thread.get_name = threading.Thread.getName - -__all__ = ['Error', 'LockError', 'LockTimeout', 'AlreadyLocked', - 'LockFailed', 'UnlockError', 'NotLocked', 'NotMyLock', - 'LinkFileLock', 'MkdirFileLock', 'SQLiteFileLock', - 'LockBase', 'locked'] - - -class Error(Exception): - """ - Base class for other exceptions. - - >>> try: - ... raise Error - ... except Exception: - ... pass - """ - pass - - -class LockError(Error): - """ - Base class for error arising from attempts to acquire the lock. - - >>> try: - ... raise LockError - ... except Error: - ... pass - """ - pass - - -class LockTimeout(LockError): - """Raised when lock creation fails within a user-defined period of time. - - >>> try: - ... raise LockTimeout - ... except LockError: - ... pass - """ - pass - - -class AlreadyLocked(LockError): - """Some other thread/process is locking the file. - - >>> try: - ... raise AlreadyLocked - ... except LockError: - ... pass - """ - pass - - -class LockFailed(LockError): - """Lock file creation failed for some other reason. - - >>> try: - ... raise LockFailed - ... except LockError: - ... pass - """ - pass - - -class UnlockError(Error): - """ - Base class for errors arising from attempts to release the lock. - - >>> try: - ... raise UnlockError - ... except Error: - ... pass - """ - pass - - -class NotLocked(UnlockError): - """Raised when an attempt is made to unlock an unlocked file. - - >>> try: - ... raise NotLocked - ... except UnlockError: - ... pass - """ - pass - - -class NotMyLock(UnlockError): - """Raised when an attempt is made to unlock a file someone else locked. - - >>> try: - ... raise NotMyLock - ... except UnlockError: - ... pass - """ - pass - - -class _SharedBase(object): - def __init__(self, path): - self.path = path - - def acquire(self, timeout=None): - """ - Acquire the lock. - - * If timeout is omitted (or None), wait forever trying to lock the - file. - - * If timeout > 0, try to acquire the lock for that many seconds. If - the lock period expires and the file is still locked, raise - LockTimeout. - - * If timeout <= 0, raise AlreadyLocked immediately if the file is - already locked. - """ - raise NotImplemented("implement in subclass") - - def release(self): - """ - Release the lock. - - If the file is not locked, raise NotLocked. - """ - raise NotImplemented("implement in subclass") - - def __enter__(self): - """ - Context manager support. - """ - self.acquire() - return self - - def __exit__(self, *_exc): - """ - Context manager support. - """ - self.release() - - def __repr__(self): - return "<%s: %r>" % (self.__class__.__name__, self.path) - - -class LockBase(_SharedBase): - """Base class for platform-specific lock classes.""" - def __init__(self, path, threaded=True, timeout=None): - """ - >>> lock = LockBase('somefile') - >>> lock = LockBase('somefile', threaded=False) - """ - super(LockBase, self).__init__(path) - self.lock_file = os.path.abspath(path) + ".lock" - self.hostname = socket.gethostname() - self.pid = os.getpid() - if threaded: - t = threading.current_thread() - # Thread objects in Python 2.4 and earlier do not have ident - # attrs. Worm around that. - ident = getattr(t, "ident", hash(t)) - self.tname = "-%x" % (ident & 0xffffffff) - else: - self.tname = "" - dirname = os.path.dirname(self.lock_file) - - # unique name is mostly about the current process, but must - # also contain the path -- otherwise, two adjacent locked - # files conflict (one file gets locked, creating lock-file and - # unique file, the other one gets locked, creating lock-file - # and overwriting the already existing lock-file, then one - # gets unlocked, deleting both lock-file and unique file, - # finally the last lock errors out upon releasing. - self.unique_name = os.path.join(dirname, - "%s%s.%s%s" % (self.hostname, - self.tname, - self.pid, - hash(self.path))) - self.timeout = timeout - - def is_locked(self): - """ - Tell whether or not the file is locked. - """ - raise NotImplemented("implement in subclass") - - def i_am_locking(self): - """ - Return True if this object is locking the file. - """ - raise NotImplemented("implement in subclass") - - def break_lock(self): - """ - Remove a lock. Useful if a locking thread failed to unlock. - """ - raise NotImplemented("implement in subclass") - - def __repr__(self): - return "<%s: %r -- %r>" % (self.__class__.__name__, self.unique_name, - self.path) - - -def _fl_helper(cls, mod, *args, **kwds): - warnings.warn("Import from %s module instead of lockfile package" % mod, - DeprecationWarning, stacklevel=2) - # This is a bit funky, but it's only for awhile. The way the unit tests - # are constructed this function winds up as an unbound method, so it - # actually takes three args, not two. We want to toss out self. - if not isinstance(args[0], str): - # We are testing, avoid the first arg - args = args[1:] - if len(args) == 1 and not kwds: - kwds["threaded"] = True - return cls(*args, **kwds) - - -def LinkFileLock(*args, **kwds): - """Factory function provided for backwards compatibility. - - Do not use in new code. Instead, import LinkLockFile from the - lockfile.linklockfile module. - """ - from . import linklockfile - return _fl_helper(linklockfile.LinkLockFile, "lockfile.linklockfile", - *args, **kwds) - - -def MkdirFileLock(*args, **kwds): - """Factory function provided for backwards compatibility. - - Do not use in new code. Instead, import MkdirLockFile from the - lockfile.mkdirlockfile module. - """ - from . import mkdirlockfile - return _fl_helper(mkdirlockfile.MkdirLockFile, "lockfile.mkdirlockfile", - *args, **kwds) - - -def SQLiteFileLock(*args, **kwds): - """Factory function provided for backwards compatibility. - - Do not use in new code. Instead, import SQLiteLockFile from the - lockfile.mkdirlockfile module. - """ - from . import sqlitelockfile - return _fl_helper(sqlitelockfile.SQLiteLockFile, "lockfile.sqlitelockfile", - *args, **kwds) - - -def locked(path, timeout=None): - """Decorator which enables locks for decorated function. - - Arguments: - - path: path for lockfile. - - timeout (optional): Timeout for acquiring lock. - - Usage: - @locked('/var/run/myname', timeout=0) - def myname(...): - ... - """ - def decor(func): - @functools.wraps(func) - def wrapper(*args, **kwargs): - lock = FileLock(path, timeout=timeout) - lock.acquire() - try: - return func(*args, **kwargs) - finally: - lock.release() - return wrapper - return decor - - -if hasattr(os, "link"): - from . import linklockfile as _llf - LockFile = _llf.LinkLockFile -else: - from . import mkdirlockfile as _mlf - LockFile = _mlf.MkdirLockFile - -FileLock = LockFile diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/linklockfile.py b/venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/linklockfile.py deleted file mode 100644 index 2ca9be0..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/linklockfile.py +++ /dev/null @@ -1,73 +0,0 @@ -from __future__ import absolute_import - -import time -import os - -from . import (LockBase, LockFailed, NotLocked, NotMyLock, LockTimeout, - AlreadyLocked) - - -class LinkLockFile(LockBase): - """Lock access to a file using atomic property of link(2). - - >>> lock = LinkLockFile('somefile') - >>> lock = LinkLockFile('somefile', threaded=False) - """ - - def acquire(self, timeout=None): - try: - open(self.unique_name, "wb").close() - except IOError: - raise LockFailed("failed to create %s" % self.unique_name) - - timeout = timeout if timeout is not None else self.timeout - end_time = time.time() - if timeout is not None and timeout > 0: - end_time += timeout - - while True: - # Try and create a hard link to it. - try: - os.link(self.unique_name, self.lock_file) - except OSError: - # Link creation failed. Maybe we've double-locked? - nlinks = os.stat(self.unique_name).st_nlink - if nlinks == 2: - # The original link plus the one I created == 2. We're - # good to go. - return - else: - # Otherwise the lock creation failed. - if timeout is not None and time.time() > end_time: - os.unlink(self.unique_name) - if timeout > 0: - raise LockTimeout("Timeout waiting to acquire" - " lock for %s" % - self.path) - else: - raise AlreadyLocked("%s is already locked" % - self.path) - time.sleep(timeout is not None and timeout / 10 or 0.1) - else: - # Link creation succeeded. We're good to go. - return - - def release(self): - if not self.is_locked(): - raise NotLocked("%s is not locked" % self.path) - elif not os.path.exists(self.unique_name): - raise NotMyLock("%s is locked, but not by me" % self.path) - os.unlink(self.unique_name) - os.unlink(self.lock_file) - - def is_locked(self): - return os.path.exists(self.lock_file) - - def i_am_locking(self): - return (self.is_locked() and - os.path.exists(self.unique_name) and - os.stat(self.unique_name).st_nlink == 2) - - def break_lock(self): - if os.path.exists(self.lock_file): - os.unlink(self.lock_file) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/mkdirlockfile.py b/venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/mkdirlockfile.py deleted file mode 100644 index 05a8c96..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/mkdirlockfile.py +++ /dev/null @@ -1,84 +0,0 @@ -from __future__ import absolute_import, division - -import time -import os -import sys -import errno - -from . import (LockBase, LockFailed, NotLocked, NotMyLock, LockTimeout, - AlreadyLocked) - - -class MkdirLockFile(LockBase): - """Lock file by creating a directory.""" - def __init__(self, path, threaded=True, timeout=None): - """ - >>> lock = MkdirLockFile('somefile') - >>> lock = MkdirLockFile('somefile', threaded=False) - """ - LockBase.__init__(self, path, threaded, timeout) - # Lock file itself is a directory. Place the unique file name into - # it. - self.unique_name = os.path.join(self.lock_file, - "%s.%s%s" % (self.hostname, - self.tname, - self.pid)) - - def acquire(self, timeout=None): - timeout = timeout if timeout is not None else self.timeout - end_time = time.time() - if timeout is not None and timeout > 0: - end_time += timeout - - if timeout is None: - wait = 0.1 - else: - wait = max(0, timeout / 10) - - while True: - try: - os.mkdir(self.lock_file) - except OSError: - err = sys.exc_info()[1] - if err.errno == errno.EEXIST: - # Already locked. - if os.path.exists(self.unique_name): - # Already locked by me. - return - if timeout is not None and time.time() > end_time: - if timeout > 0: - raise LockTimeout("Timeout waiting to acquire" - " lock for %s" % - self.path) - else: - # Someone else has the lock. - raise AlreadyLocked("%s is already locked" % - self.path) - time.sleep(wait) - else: - # Couldn't create the lock for some other reason - raise LockFailed("failed to create %s" % self.lock_file) - else: - open(self.unique_name, "wb").close() - return - - def release(self): - if not self.is_locked(): - raise NotLocked("%s is not locked" % self.path) - elif not os.path.exists(self.unique_name): - raise NotMyLock("%s is locked, but not by me" % self.path) - os.unlink(self.unique_name) - os.rmdir(self.lock_file) - - def is_locked(self): - return os.path.exists(self.lock_file) - - def i_am_locking(self): - return (self.is_locked() and - os.path.exists(self.unique_name)) - - def break_lock(self): - if os.path.exists(self.lock_file): - for name in os.listdir(self.lock_file): - os.unlink(os.path.join(self.lock_file, name)) - os.rmdir(self.lock_file) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/pidlockfile.py b/venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/pidlockfile.py deleted file mode 100644 index 069e85b..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/pidlockfile.py +++ /dev/null @@ -1,190 +0,0 @@ -# -*- coding: utf-8 -*- - -# pidlockfile.py -# -# Copyright © 2008–2009 Ben Finney <ben+python@benfinney.id.au> -# -# This is free software: you may copy, modify, and/or distribute this work -# under the terms of the Python Software Foundation License, version 2 or -# later as published by the Python Software Foundation. -# No warranty expressed or implied. See the file LICENSE.PSF-2 for details. - -""" Lockfile behaviour implemented via Unix PID files. - """ - -from __future__ import absolute_import - -import errno -import os -import time - -from . import (LockBase, AlreadyLocked, LockFailed, NotLocked, NotMyLock, - LockTimeout) - - -class PIDLockFile(LockBase): - """ Lockfile implemented as a Unix PID file. - - The lock file is a normal file named by the attribute `path`. - A lock's PID file contains a single line of text, containing - the process ID (PID) of the process that acquired the lock. - - >>> lock = PIDLockFile('somefile') - >>> lock = PIDLockFile('somefile') - """ - - def __init__(self, path, threaded=False, timeout=None): - # pid lockfiles don't support threaded operation, so always force - # False as the threaded arg. - LockBase.__init__(self, path, False, timeout) - self.unique_name = self.path - - def read_pid(self): - """ Get the PID from the lock file. - """ - return read_pid_from_pidfile(self.path) - - def is_locked(self): - """ Test if the lock is currently held. - - The lock is held if the PID file for this lock exists. - - """ - return os.path.exists(self.path) - - def i_am_locking(self): - """ Test if the lock is held by the current process. - - Returns ``True`` if the current process ID matches the - number stored in the PID file. - """ - return self.is_locked() and os.getpid() == self.read_pid() - - def acquire(self, timeout=None): - """ Acquire the lock. - - Creates the PID file for this lock, or raises an error if - the lock could not be acquired. - """ - - timeout = timeout if timeout is not None else self.timeout - end_time = time.time() - if timeout is not None and timeout > 0: - end_time += timeout - - while True: - try: - write_pid_to_pidfile(self.path) - except OSError as exc: - if exc.errno == errno.EEXIST: - # The lock creation failed. Maybe sleep a bit. - if time.time() > end_time: - if timeout is not None and timeout > 0: - raise LockTimeout("Timeout waiting to acquire" - " lock for %s" % - self.path) - else: - raise AlreadyLocked("%s is already locked" % - self.path) - time.sleep(timeout is not None and timeout / 10 or 0.1) - else: - raise LockFailed("failed to create %s" % self.path) - else: - return - - def release(self): - """ Release the lock. - - Removes the PID file to release the lock, or raises an - error if the current process does not hold the lock. - - """ - if not self.is_locked(): - raise NotLocked("%s is not locked" % self.path) - if not self.i_am_locking(): - raise NotMyLock("%s is locked, but not by me" % self.path) - remove_existing_pidfile(self.path) - - def break_lock(self): - """ Break an existing lock. - - Removes the PID file if it already exists, otherwise does - nothing. - - """ - remove_existing_pidfile(self.path) - - -def read_pid_from_pidfile(pidfile_path): - """ Read the PID recorded in the named PID file. - - Read and return the numeric PID recorded as text in the named - PID file. If the PID file cannot be read, or if the content is - not a valid PID, return ``None``. - - """ - pid = None - try: - pidfile = open(pidfile_path, 'r') - except IOError: - pass - else: - # According to the FHS 2.3 section on PID files in /var/run: - # - # The file must consist of the process identifier in - # ASCII-encoded decimal, followed by a newline character. - # - # Programs that read PID files should be somewhat flexible - # in what they accept; i.e., they should ignore extra - # whitespace, leading zeroes, absence of the trailing - # newline, or additional lines in the PID file. - - line = pidfile.readline().strip() - try: - pid = int(line) - except ValueError: - pass - pidfile.close() - - return pid - - -def write_pid_to_pidfile(pidfile_path): - """ Write the PID in the named PID file. - - Get the numeric process ID (“PID”) of the current process - and write it to the named file as a line of text. - - """ - open_flags = (os.O_CREAT | os.O_EXCL | os.O_WRONLY) - open_mode = 0o644 - pidfile_fd = os.open(pidfile_path, open_flags, open_mode) - pidfile = os.fdopen(pidfile_fd, 'w') - - # According to the FHS 2.3 section on PID files in /var/run: - # - # The file must consist of the process identifier in - # ASCII-encoded decimal, followed by a newline character. For - # example, if crond was process number 25, /var/run/crond.pid - # would contain three characters: two, five, and newline. - - pid = os.getpid() - pidfile.write("%s\n" % pid) - pidfile.close() - - -def remove_existing_pidfile(pidfile_path): - """ Remove the named PID file if it exists. - - Removing a PID file that doesn't already exist puts us in the - desired state, so we ignore the condition if the file does not - exist. - - """ - try: - os.remove(pidfile_path) - except OSError as exc: - if exc.errno == errno.ENOENT: - pass - else: - raise diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/sqlitelockfile.py b/venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/sqlitelockfile.py deleted file mode 100644 index f997e24..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/sqlitelockfile.py +++ /dev/null @@ -1,156 +0,0 @@ -from __future__ import absolute_import, division - -import time -import os - -try: - unicode -except NameError: - unicode = str - -from . import LockBase, NotLocked, NotMyLock, LockTimeout, AlreadyLocked - - -class SQLiteLockFile(LockBase): - "Demonstrate SQL-based locking." - - testdb = None - - def __init__(self, path, threaded=True, timeout=None): - """ - >>> lock = SQLiteLockFile('somefile') - >>> lock = SQLiteLockFile('somefile', threaded=False) - """ - LockBase.__init__(self, path, threaded, timeout) - self.lock_file = unicode(self.lock_file) - self.unique_name = unicode(self.unique_name) - - if SQLiteLockFile.testdb is None: - import tempfile - _fd, testdb = tempfile.mkstemp() - os.close(_fd) - os.unlink(testdb) - del _fd, tempfile - SQLiteLockFile.testdb = testdb - - import sqlite3 - self.connection = sqlite3.connect(SQLiteLockFile.testdb) - - c = self.connection.cursor() - try: - c.execute("create table locks" - "(" - " lock_file varchar(32)," - " unique_name varchar(32)" - ")") - except sqlite3.OperationalError: - pass - else: - self.connection.commit() - import atexit - atexit.register(os.unlink, SQLiteLockFile.testdb) - - def acquire(self, timeout=None): - timeout = timeout if timeout is not None else self.timeout - end_time = time.time() - if timeout is not None and timeout > 0: - end_time += timeout - - if timeout is None: - wait = 0.1 - elif timeout <= 0: - wait = 0 - else: - wait = timeout / 10 - - cursor = self.connection.cursor() - - while True: - if not self.is_locked(): - # Not locked. Try to lock it. - cursor.execute("insert into locks" - " (lock_file, unique_name)" - " values" - " (?, ?)", - (self.lock_file, self.unique_name)) - self.connection.commit() - - # Check to see if we are the only lock holder. - cursor.execute("select * from locks" - " where unique_name = ?", - (self.unique_name,)) - rows = cursor.fetchall() - if len(rows) > 1: - # Nope. Someone else got there. Remove our lock. - cursor.execute("delete from locks" - " where unique_name = ?", - (self.unique_name,)) - self.connection.commit() - else: - # Yup. We're done, so go home. - return - else: - # Check to see if we are the only lock holder. - cursor.execute("select * from locks" - " where unique_name = ?", - (self.unique_name,)) - rows = cursor.fetchall() - if len(rows) == 1: - # We're the locker, so go home. - return - - # Maybe we should wait a bit longer. - if timeout is not None and time.time() > end_time: - if timeout > 0: - # No more waiting. - raise LockTimeout("Timeout waiting to acquire" - " lock for %s" % - self.path) - else: - # Someone else has the lock and we are impatient.. - raise AlreadyLocked("%s is already locked" % self.path) - - # Well, okay. We'll give it a bit longer. - time.sleep(wait) - - def release(self): - if not self.is_locked(): - raise NotLocked("%s is not locked" % self.path) - if not self.i_am_locking(): - raise NotMyLock("%s is locked, but not by me (by %s)" % - (self.unique_name, self._who_is_locking())) - cursor = self.connection.cursor() - cursor.execute("delete from locks" - " where unique_name = ?", - (self.unique_name,)) - self.connection.commit() - - def _who_is_locking(self): - cursor = self.connection.cursor() - cursor.execute("select unique_name from locks" - " where lock_file = ?", - (self.lock_file,)) - return cursor.fetchone()[0] - - def is_locked(self): - cursor = self.connection.cursor() - cursor.execute("select * from locks" - " where lock_file = ?", - (self.lock_file,)) - rows = cursor.fetchall() - return not not rows - - def i_am_locking(self): - cursor = self.connection.cursor() - cursor.execute("select * from locks" - " where lock_file = ?" - " and unique_name = ?", - (self.lock_file, self.unique_name)) - return not not cursor.fetchall() - - def break_lock(self): - cursor = self.connection.cursor() - cursor.execute("delete from locks" - " where lock_file = ?", - (self.lock_file,)) - self.connection.commit() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/symlinklockfile.py b/venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/symlinklockfile.py deleted file mode 100644 index 23b41f5..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/lockfile/symlinklockfile.py +++ /dev/null @@ -1,70 +0,0 @@ -from __future__ import absolute_import - -import os -import time - -from . import (LockBase, NotLocked, NotMyLock, LockTimeout, - AlreadyLocked) - - -class SymlinkLockFile(LockBase): - """Lock access to a file using symlink(2).""" - - def __init__(self, path, threaded=True, timeout=None): - # super(SymlinkLockFile).__init(...) - LockBase.__init__(self, path, threaded, timeout) - # split it back! - self.unique_name = os.path.split(self.unique_name)[1] - - def acquire(self, timeout=None): - # Hopefully unnecessary for symlink. - # try: - # open(self.unique_name, "wb").close() - # except IOError: - # raise LockFailed("failed to create %s" % self.unique_name) - timeout = timeout if timeout is not None else self.timeout - end_time = time.time() - if timeout is not None and timeout > 0: - end_time += timeout - - while True: - # Try and create a symbolic link to it. - try: - os.symlink(self.unique_name, self.lock_file) - except OSError: - # Link creation failed. Maybe we've double-locked? - if self.i_am_locking(): - # Linked to out unique name. Proceed. - return - else: - # Otherwise the lock creation failed. - if timeout is not None and time.time() > end_time: - if timeout > 0: - raise LockTimeout("Timeout waiting to acquire" - " lock for %s" % - self.path) - else: - raise AlreadyLocked("%s is already locked" % - self.path) - time.sleep(timeout / 10 if timeout is not None else 0.1) - else: - # Link creation succeeded. We're good to go. - return - - def release(self): - if not self.is_locked(): - raise NotLocked("%s is not locked" % self.path) - elif not self.i_am_locking(): - raise NotMyLock("%s is locked, but not by me" % self.path) - os.unlink(self.lock_file) - - def is_locked(self): - return os.path.islink(self.lock_file) - - def i_am_locking(self): - return (os.path.islink(self.lock_file) - and os.readlink(self.lock_file) == self.unique_name) - - def break_lock(self): - if os.path.islink(self.lock_file): # exists && link - os.unlink(self.lock_file) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/msgpack/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/msgpack/__init__.py deleted file mode 100644 index 2afca5a..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/msgpack/__init__.py +++ /dev/null @@ -1,66 +0,0 @@ -# coding: utf-8 -from pip._vendor.msgpack._version import version -from pip._vendor.msgpack.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 pip._vendor.msgpack.fallback import Packer, unpackb, Unpacker -else: - try: - from pip._vendor.msgpack._packer import Packer - from pip._vendor.msgpack._unpacker import unpackb, Unpacker - except ImportError: - from pip._vendor.msgpack.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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/msgpack/_version.py b/venv2/lib/python2.7/site-packages/pip/_vendor/msgpack/_version.py deleted file mode 100644 index d28f0de..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/msgpack/_version.py +++ /dev/null @@ -1 +0,0 @@ -version = (0, 5, 6) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/msgpack/exceptions.py b/venv2/lib/python2.7/site-packages/pip/_vendor/msgpack/exceptions.py deleted file mode 100644 index 9766881..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/msgpack/exceptions.py +++ /dev/null @@ -1,41 +0,0 @@ -class UnpackException(Exception): - """Deprecated. Use Exception instead to catch all exception during unpacking.""" - - -class BufferFull(UnpackException): - pass - - -class OutOfData(UnpackException): - pass - - -class UnpackValueError(UnpackException, ValueError): - """Deprecated. Use ValueError instead.""" - - -class ExtraData(UnpackValueError): - def __init__(self, unpacked, extra): - self.unpacked = unpacked - self.extra = extra - - def __str__(self): - return "unpack(b) received extra data." - - -class PackException(Exception): - """Deprecated. Use Exception instead to catch all exception during packing.""" - - -class PackValueError(PackException, ValueError): - """PackValueError is raised when type of input data is supported but it's value is unsupported. - - Deprecated. Use ValueError instead. - """ - - -class PackOverflowError(PackValueError, OverflowError): - """PackOverflowError is raised when integer value is out of range of msgpack support [-2**31, 2**32). - - Deprecated. Use ValueError instead. - """ diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/msgpack/fallback.py b/venv2/lib/python2.7/site-packages/pip/_vendor/msgpack/fallback.py deleted file mode 100644 index 9418421..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/msgpack/fallback.py +++ /dev/null @@ -1,977 +0,0 @@ -"""Fallback pure Python implementation of msgpack""" - -import sys -import struct -import warnings - -if sys.version_info[0] == 3: - PY3 = True - int_types = int - Unicode = str - xrange = range - def dict_iteritems(d): - return d.items() -else: - PY3 = False - int_types = (int, long) - Unicode = unicode - def dict_iteritems(d): - return d.iteritems() - - -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 pip._vendor.msgpack.exceptions import ( - BufferFull, - OutOfData, - UnpackValueError, - PackValueError, - PackOverflowError, - ExtraData) - -from pip._vendor.msgpack 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 not PY3: - 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) - 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.", - PendingDeprecationWarning) - data = stream.read() - return unpackb(data, **kwargs) - - -def unpackb(packed, **kwargs): - """ - Unpack an object from `packed`. - - Raises `ExtraData` when `packed` contains extra bytes. - See :class:`Unpacker` for options. - """ - unpacker = Unpacker(None, **kwargs) - unpacker.feed(packed) - try: - ret = unpacker._unpack() - except OutOfData: - raise UnpackValueError("Data is not enough.") - if unpacker._got_extradata(): - raise ExtraData(ret, unpacker._get_extradata()) - return ret - - -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 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: - Limits max length of str. (default: 2**31-1) - - :param int max_bin_len: - Limits max length of bin. (default: 2**31-1) - - :param int max_array_len: - Limits max length of array. (default: 2**31-1) - - :param int max_map_len: - Limits max length of map. (default: 2**31-1) - - - example of streaming deserialize from file-like object:: - - unpacker = Unpacker(file_like, raw=False) - for o in unpacker: - process(o) - - example of streaming deserialize from socket:: - - unpacker = Unpacker(raw=False) - while True: - buf = sock.recv(1024**2) - if not buf: - break - unpacker.feed(buf) - for o in unpacker: - process(o) - """ - - def __init__(self, file_like=None, read_size=0, use_list=True, raw=True, - 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=2147483647, # 2**32-1 - max_bin_len=2147483647, - max_array_len=2147483647, - max_map_len=2147483647, - max_ext_len=2147483647): - - if encoding is not None: - warnings.warn( - "encoding is deprecated, Use raw=False instead.", - PendingDeprecationWarning) - - 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() - # Some very old pythons don't support `struct.unpack_from()` with a - # `bytearray`. So we wrap it in a `buffer()` there. - if sys.version_info < (2, 7, 6): - self._buffer_view = buffer(self._buffer) - else: - self._buffer_view = self._buffer - #: 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 - - 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._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 - - self._buffer += 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 UnpackValueError("%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 UnpackValueError("%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 UnpackValueError("%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 UnpackValueError("%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 = struct.unpack_from(">H", self._buffer_view, self._buff_i)[0] - self._buff_i += 2 - if n > self._max_bin_len: - raise UnpackValueError("%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 = struct.unpack_from(">I", self._buffer_view, self._buff_i)[0] - self._buff_i += 4 - if n > self._max_bin_len: - raise UnpackValueError("%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 = struct.unpack_from('Bb', self._buffer_view, self._buff_i) - self._buff_i += 2 - if L > self._max_ext_len: - raise UnpackValueError("%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 = struct.unpack_from('>Hb', self._buffer_view, self._buff_i) - self._buff_i += 3 - if L > self._max_ext_len: - raise UnpackValueError("%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 = struct.unpack_from('>Ib', self._buffer_view, self._buff_i) - self._buff_i += 5 - if L > self._max_ext_len: - raise UnpackValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len)) - obj = self._read(L) - elif b == 0xca: - self._reserve(4) - obj = struct.unpack_from(">f", self._buffer_view, self._buff_i)[0] - self._buff_i += 4 - elif b == 0xcb: - self._reserve(8) - obj = struct.unpack_from(">d", self._buffer_view, 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 = struct.unpack_from(">H", self._buffer_view, self._buff_i)[0] - self._buff_i += 2 - elif b == 0xce: - self._reserve(4) - obj = struct.unpack_from(">I", self._buffer_view, self._buff_i)[0] - self._buff_i += 4 - elif b == 0xcf: - self._reserve(8) - obj = struct.unpack_from(">Q", self._buffer_view, self._buff_i)[0] - self._buff_i += 8 - elif b == 0xd0: - self._reserve(1) - obj = struct.unpack_from("b", self._buffer_view, self._buff_i)[0] - self._buff_i += 1 - elif b == 0xd1: - self._reserve(2) - obj = struct.unpack_from(">h", self._buffer_view, self._buff_i)[0] - self._buff_i += 2 - elif b == 0xd2: - self._reserve(4) - obj = struct.unpack_from(">i", self._buffer_view, self._buff_i)[0] - self._buff_i += 4 - elif b == 0xd3: - self._reserve(8) - obj = struct.unpack_from(">q", self._buffer_view, self._buff_i)[0] - self._buff_i += 8 - elif b == 0xd4: # fixext 1 - typ = TYPE_EXT - if self._max_ext_len < 1: - raise UnpackValueError("%s exceeds max_ext_len(%s)" % (1, self._max_ext_len)) - self._reserve(2) - n, obj = struct.unpack_from("b1s", self._buffer_view, self._buff_i) - self._buff_i += 2 - elif b == 0xd5: # fixext 2 - typ = TYPE_EXT - if self._max_ext_len < 2: - raise UnpackValueError("%s exceeds max_ext_len(%s)" % (2, self._max_ext_len)) - self._reserve(3) - n, obj = struct.unpack_from("b2s", self._buffer_view, self._buff_i) - self._buff_i += 3 - elif b == 0xd6: # fixext 4 - typ = TYPE_EXT - if self._max_ext_len < 4: - raise UnpackValueError("%s exceeds max_ext_len(%s)" % (4, self._max_ext_len)) - self._reserve(5) - n, obj = struct.unpack_from("b4s", self._buffer_view, self._buff_i) - self._buff_i += 5 - elif b == 0xd7: # fixext 8 - typ = TYPE_EXT - if self._max_ext_len < 8: - raise UnpackValueError("%s exceeds max_ext_len(%s)" % (8, self._max_ext_len)) - self._reserve(9) - n, obj = struct.unpack_from("b8s", self._buffer_view, self._buff_i) - self._buff_i += 9 - elif b == 0xd8: # fixext 16 - typ = TYPE_EXT - if self._max_ext_len < 16: - raise UnpackValueError("%s exceeds max_ext_len(%s)" % (16, self._max_ext_len)) - self._reserve(17) - n, obj = struct.unpack_from("b16s", self._buffer_view, 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 UnpackValueError("%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, = struct.unpack_from(">H", self._buffer_view, self._buff_i) - self._buff_i += 2 - if n > self._max_str_len: - raise UnpackValueError("%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, = struct.unpack_from(">I", self._buffer_view, self._buff_i) - self._buff_i += 4 - if n > self._max_str_len: - raise UnpackValueError("%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, = struct.unpack_from(">H", self._buffer_view, self._buff_i) - self._buff_i += 2 - if n > self._max_array_len: - raise UnpackValueError("%s exceeds max_array_len(%s)", n, self._max_array_len) - elif b == 0xdd: - typ = TYPE_ARRAY - self._reserve(4) - n, = struct.unpack_from(">I", self._buffer_view, self._buff_i) - self._buff_i += 4 - if n > self._max_array_len: - raise UnpackValueError("%s exceeds max_array_len(%s)", n, self._max_array_len) - elif b == 0xde: - self._reserve(2) - n, = struct.unpack_from(">H", self._buffer_view, self._buff_i) - self._buff_i += 2 - if n > self._max_map_len: - raise UnpackValueError("%s exceeds max_map_len(%s)", n, self._max_map_len) - typ = TYPE_MAP - elif b == 0xdf: - self._reserve(4) - n, = struct.unpack_from(">I", self._buffer_view, self._buff_i) - self._buff_i += 4 - if n > self._max_map_len: - raise UnpackValueError("%s exceeds max_map_len(%s)", n, self._max_map_len) - typ = TYPE_MAP - else: - raise UnpackValueError("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 UnpackValueError("Expected array") - return n - if execute == EX_READ_MAP_HEADER: - if typ != TYPE_MAP: - raise UnpackValueError("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) - 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 - - next = __next__ - - def skip(self, write_bytes=None): - self._unpack(EX_SKIP) - if write_bytes is not None: - warnings.warn("`write_bytes` option is deprecated. Use `.tell()` instead.", DeprecationWarning) - write_bytes(self._buffer[self._buf_checkpoint:self._buff_i]) - self._consume() - - def unpack(self, write_bytes=None): - ret = self._unpack(EX_CONSTRUCT) - if write_bytes is not None: - warnings.warn("`write_bytes` option is deprecated. Use `.tell()` instead.", DeprecationWarning) - write_bytes(self._buffer[self._buf_checkpoint:self._buff_i]) - self._consume() - return ret - - def read_array_header(self, write_bytes=None): - ret = self._unpack(EX_READ_ARRAY_HEADER) - if write_bytes is not None: - warnings.warn("`write_bytes` option is deprecated. Use `.tell()` instead.", DeprecationWarning) - write_bytes(self._buffer[self._buf_checkpoint:self._buff_i]) - self._consume() - return ret - - def read_map_header(self, write_bytes=None): - ret = self._unpack(EX_READ_MAP_HEADER) - if write_bytes is not None: - warnings.warn("`write_bytes` option is deprecated. Use `.tell()` instead.", DeprecationWarning) - write_bytes(self._buffer[self._buf_checkpoint:self._buff_i]) - 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.", - PendingDeprecationWarning) - - 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 PackValueError("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 PackOverflowError("Integer value out of range") - if check(obj, (bytes, bytearray)): - n = len(obj) - if n >= 2**32: - raise PackValueError("%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 PackValueError("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 PackValueError("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 - ret = self._buffer.getvalue() - if self._autoreset: - self._buffer = StringIO() - elif USING_STRINGBUILDER: - self._buffer = StringIO(ret) - return ret - - def pack_map_pairs(self, pairs): - self._pack_map_pairs(len(pairs), pairs) - ret = self._buffer.getvalue() - if self._autoreset: - self._buffer = StringIO() - elif USING_STRINGBUILDER: - self._buffer = StringIO(ret) - return ret - - def pack_array_header(self, n): - if n >= 2**32: - raise PackValueError - self._pack_array_header(n) - ret = self._buffer.getvalue() - if self._autoreset: - self._buffer = StringIO() - elif USING_STRINGBUILDER: - self._buffer = StringIO(ret) - return ret - - def pack_map_header(self, n): - if n >= 2**32: - raise PackValueError - self._pack_map_header(n) - ret = self._buffer.getvalue() - if self._autoreset: - self._buffer = StringIO() - elif USING_STRINGBUILDER: - self._buffer = StringIO(ret) - 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 PackValueError("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 PackValueError("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 PackValueError("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 PackValueError('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 PackValueError('Bin is too large') - - def bytes(self): - return self._buffer.getvalue() - - def reset(self): - self._buffer = StringIO() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/__about__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/__about__.py deleted file mode 100644 index 7481c9e..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/__about__.py +++ /dev/null @@ -1,27 +0,0 @@ -# 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.0" - -__author__ = "Donald Stufft and individual contributors" -__email__ = "donald@stufft.io" - -__license__ = "BSD or Apache License, Version 2.0" -__copyright__ = "Copyright 2014-2019 %s" % __author__ diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/__init__.py deleted file mode 100644 index a0cf67d..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# 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__", -] diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/_compat.py b/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/_compat.py deleted file mode 100644 index 25da473..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/_compat.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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", (), {}) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/_structures.py b/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/_structures.py deleted file mode 100644 index 68dcca6..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/_structures.py +++ /dev/null @@ -1,68 +0,0 @@ -# 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() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/markers.py b/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/markers.py deleted file mode 100644 index 5482476..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/markers.py +++ /dev/null @@ -1,296 +0,0 @@ -# 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": platform.python_version()[:3], - "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 "<Marker({0!r})>".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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/requirements.py b/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/requirements.py deleted file mode 100644 index dbc5f11..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/requirements.py +++ /dev/null @@ -1,138 +0,0 @@ -# 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 "<Requirement({0!r})>".format(str(self)) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/specifiers.py b/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/specifiers.py deleted file mode 100644 index 743576a..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/specifiers.py +++ /dev/null @@ -1,749 +0,0 @@ -# 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<operator>(==|!=|<=|>=|<|>)) - \s* - (?P<version> - [^,;\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<operator>(~=|==|!=|<=|>=|<|>|===)) - (?P<version> - (?: - # 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. - (?<!==|!=|~=) # We have special cases for these - # operators so we want to make sure they - # don't match here. - - \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]*) - )? - (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release - ) - ) - """ - - _regex = re.compile(r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) - - _operators = { - "~=": "compatible", - "==": "equal", - "!=": "not_equal", - "<=": "less_than_equal", - ">=": "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 "<SpecifierSet({0!r}{1})>".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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/utils.py b/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/utils.py deleted file mode 100644 index 8841878..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/utils.py +++ /dev/null @@ -1,57 +0,0 @@ -# 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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/version.py b/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/version.py deleted file mode 100644 index 95157a1..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/packaging/version.py +++ /dev/null @@ -1,420 +0,0 @@ -# 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 "<LegacyVersion({0})>".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<epoch>[0-9]+)!)? # epoch - (?P<release>[0-9]+(?:\.[0-9]+)*) # release segment - (?P<pre> # pre-release - [-_\.]? - (?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview)) - [-_\.]? - (?P<pre_n>[0-9]+)? - )? - (?P<post> # post release - (?:-(?P<post_n1>[0-9]+)) - | - (?: - [-_\.]? - (?P<post_l>post|rev|r) - [-_\.]? - (?P<post_n2>[0-9]+)? - ) - )? - (?P<dev> # dev release - [-_\.]? - (?P<dev_l>dev) - [-_\.]? - (?P<dev_n>[0-9]+)? - )? - ) - (?:\+(?P<local>[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 "<Version({0})>".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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/__init__.py deleted file mode 100644 index 9c1a098..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -"""Wrappers to build Python packages using PEP 517 hooks -""" - -__version__ = '0.5.0' diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/_in_process.py b/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/_in_process.py deleted file mode 100644 index d6524b6..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/_in_process.py +++ /dev/null @@ -1,207 +0,0 @@ -"""This is invoked in a subprocess to call the build backend hooks. - -It expects: -- Command line args: hook_name, control_dir -- Environment variable: PEP517_BUILD_BACKEND=entry.point:spec -- control_dir/input.json: - - {"kwargs": {...}} - -Results: -- control_dir/output.json - - {"return_val": ...} -""" -from glob import glob -from importlib import import_module -import os -from os.path import join as pjoin -import re -import shutil -import sys - -# This is run as a script, not a module, so it can't do a relative import -import compat - - -class BackendUnavailable(Exception): - """Raised if we cannot import the backend""" - - -def _build_backend(): - """Find and load the build backend""" - ep = os.environ['PEP517_BUILD_BACKEND'] - mod_path, _, obj_path = ep.partition(':') - try: - obj = import_module(mod_path) - except ImportError: - raise BackendUnavailable - if obj_path: - for path_part in obj_path.split('.'): - obj = getattr(obj, path_part) - return obj - - -def get_requires_for_build_wheel(config_settings): - """Invoke the optional get_requires_for_build_wheel hook - - Returns [] if the hook is not defined. - """ - backend = _build_backend() - try: - hook = backend.get_requires_for_build_wheel - except AttributeError: - return [] - else: - return hook(config_settings) - - -def prepare_metadata_for_build_wheel(metadata_directory, config_settings): - """Invoke optional prepare_metadata_for_build_wheel - - Implements a fallback by building a wheel if the hook isn't defined. - """ - backend = _build_backend() - try: - hook = backend.prepare_metadata_for_build_wheel - except AttributeError: - return _get_wheel_metadata_from_wheel(backend, metadata_directory, - config_settings) - else: - return hook(metadata_directory, config_settings) - - -WHEEL_BUILT_MARKER = 'PEP517_ALREADY_BUILT_WHEEL' - - -def _dist_info_files(whl_zip): - """Identify the .dist-info folder inside a wheel ZipFile.""" - res = [] - for path in whl_zip.namelist(): - m = re.match(r'[^/\\]+-[^/\\]+\.dist-info/', path) - if m: - res.append(path) - if res: - return res - raise Exception("No .dist-info folder found in wheel") - - -def _get_wheel_metadata_from_wheel( - backend, metadata_directory, config_settings): - """Build a wheel and extract the metadata from it. - - Fallback for when the build backend does not - define the 'get_wheel_metadata' hook. - """ - from zipfile import ZipFile - whl_basename = backend.build_wheel(metadata_directory, config_settings) - with open(os.path.join(metadata_directory, WHEEL_BUILT_MARKER), 'wb'): - pass # Touch marker file - - whl_file = os.path.join(metadata_directory, whl_basename) - with ZipFile(whl_file) as zipf: - dist_info = _dist_info_files(zipf) - zipf.extractall(path=metadata_directory, members=dist_info) - return dist_info[0].split('/')[0] - - -def _find_already_built_wheel(metadata_directory): - """Check for a wheel already built during the get_wheel_metadata hook. - """ - if not metadata_directory: - return None - metadata_parent = os.path.dirname(metadata_directory) - if not os.path.isfile(pjoin(metadata_parent, WHEEL_BUILT_MARKER)): - return None - - whl_files = glob(os.path.join(metadata_parent, '*.whl')) - if not whl_files: - print('Found wheel built marker, but no .whl files') - return None - if len(whl_files) > 1: - print('Found multiple .whl files; unspecified behaviour. ' - 'Will call build_wheel.') - return None - - # Exactly one .whl file - return whl_files[0] - - -def build_wheel(wheel_directory, config_settings, metadata_directory=None): - """Invoke the mandatory build_wheel hook. - - If a wheel was already built in the - prepare_metadata_for_build_wheel fallback, this - will copy it rather than rebuilding the wheel. - """ - prebuilt_whl = _find_already_built_wheel(metadata_directory) - if prebuilt_whl: - shutil.copy2(prebuilt_whl, wheel_directory) - return os.path.basename(prebuilt_whl) - - return _build_backend().build_wheel(wheel_directory, config_settings, - metadata_directory) - - -def get_requires_for_build_sdist(config_settings): - """Invoke the optional get_requires_for_build_wheel hook - - Returns [] if the hook is not defined. - """ - backend = _build_backend() - try: - hook = backend.get_requires_for_build_sdist - except AttributeError: - return [] - else: - return hook(config_settings) - - -class _DummyException(Exception): - """Nothing should ever raise this exception""" - - -class GotUnsupportedOperation(Exception): - """For internal use when backend raises UnsupportedOperation""" - - -def build_sdist(sdist_directory, config_settings): - """Invoke the mandatory build_sdist hook.""" - backend = _build_backend() - try: - return backend.build_sdist(sdist_directory, config_settings) - except getattr(backend, 'UnsupportedOperation', _DummyException): - raise GotUnsupportedOperation - - -HOOK_NAMES = { - 'get_requires_for_build_wheel', - 'prepare_metadata_for_build_wheel', - 'build_wheel', - 'get_requires_for_build_sdist', - 'build_sdist', -} - - -def main(): - if len(sys.argv) < 3: - sys.exit("Needs args: hook_name, control_dir") - hook_name = sys.argv[1] - control_dir = sys.argv[2] - if hook_name not in HOOK_NAMES: - sys.exit("Unknown hook: %s" % hook_name) - hook = globals()[hook_name] - - hook_input = compat.read_json(pjoin(control_dir, 'input.json')) - - json_out = {'unsupported': False, 'return_val': None} - try: - json_out['return_val'] = hook(**hook_input['kwargs']) - except BackendUnavailable: - json_out['no_backend'] = True - except GotUnsupportedOperation: - json_out['unsupported'] = True - - compat.write_json(json_out, pjoin(control_dir, 'output.json'), indent=2) - - -if __name__ == '__main__': - main() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/build.py b/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/build.py deleted file mode 100644 index ac6c949..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/build.py +++ /dev/null @@ -1,108 +0,0 @@ -"""Build a project using PEP 517 hooks. -""" -import argparse -import logging -import os -import contextlib -from pip._vendor import pytoml -import shutil -import errno -import tempfile - -from .envbuild import BuildEnvironment -from .wrappers import Pep517HookCaller - -log = logging.getLogger(__name__) - - -@contextlib.contextmanager -def tempdir(): - td = tempfile.mkdtemp() - try: - yield td - finally: - shutil.rmtree(td) - - -def _do_build(hooks, env, dist, dest): - get_requires_name = 'get_requires_for_build_{dist}'.format(**locals()) - get_requires = getattr(hooks, get_requires_name) - reqs = get_requires({}) - log.info('Got build requires: %s', reqs) - - env.pip_install(reqs) - log.info('Installed dynamic build dependencies') - - with tempdir() as td: - log.info('Trying to build %s in %s', dist, td) - build_name = 'build_{dist}'.format(**locals()) - build = getattr(hooks, build_name) - filename = build(td, {}) - source = os.path.join(td, filename) - shutil.move(source, os.path.join(dest, os.path.basename(filename))) - - -def mkdir_p(*args, **kwargs): - """Like `mkdir`, but does not raise an exception if the - directory already exists. - """ - try: - return os.mkdir(*args, **kwargs) - except OSError as exc: - if exc.errno != errno.EEXIST: - raise - - -def build(source_dir, dist, dest=None): - pyproject = os.path.join(source_dir, 'pyproject.toml') - dest = os.path.join(source_dir, dest or 'dist') - mkdir_p(dest) - - with open(pyproject) as f: - pyproject_data = pytoml.load(f) - # Ensure the mandatory data can be loaded - buildsys = pyproject_data['build-system'] - requires = buildsys['requires'] - backend = buildsys['build-backend'] - - hooks = Pep517HookCaller(source_dir, backend) - - with BuildEnvironment() as env: - env.pip_install(requires) - _do_build(hooks, env, dist, dest) - - -parser = argparse.ArgumentParser() -parser.add_argument( - 'source_dir', - help="A directory containing pyproject.toml", -) -parser.add_argument( - '--binary', '-b', - action='store_true', - default=False, -) -parser.add_argument( - '--source', '-s', - action='store_true', - default=False, -) -parser.add_argument( - '--out-dir', '-o', - help="Destination in which to save the builds relative to source dir", -) - - -def main(args): - # determine which dists to build - dists = list(filter(None, ( - 'sdist' if args.source or not args.binary else None, - 'wheel' if args.binary or not args.source else None, - ))) - - for dist in dists: - build(args.source_dir, dist, args.out_dir) - - -if __name__ == '__main__': - main(parser.parse_args()) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/check.py b/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/check.py deleted file mode 100644 index f4cdc6b..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/check.py +++ /dev/null @@ -1,202 +0,0 @@ -"""Check a project and backend by attempting to build using PEP 517 hooks. -""" -import argparse -import logging -import os -from os.path import isfile, join as pjoin -from pip._vendor.pytoml import TomlError, load as toml_load -import shutil -from subprocess import CalledProcessError -import sys -import tarfile -from tempfile import mkdtemp -import zipfile - -from .colorlog import enable_colourful_output -from .envbuild import BuildEnvironment -from .wrappers import Pep517HookCaller - -log = logging.getLogger(__name__) - - -def check_build_sdist(hooks, build_sys_requires): - with BuildEnvironment() as env: - try: - env.pip_install(build_sys_requires) - log.info('Installed static build dependencies') - except CalledProcessError: - log.error('Failed to install static build dependencies') - return False - - try: - reqs = hooks.get_requires_for_build_sdist({}) - log.info('Got build requires: %s', reqs) - except Exception: - log.error('Failure in get_requires_for_build_sdist', exc_info=True) - return False - - try: - env.pip_install(reqs) - log.info('Installed dynamic build dependencies') - except CalledProcessError: - log.error('Failed to install dynamic build dependencies') - return False - - td = mkdtemp() - log.info('Trying to build sdist in %s', td) - try: - try: - filename = hooks.build_sdist(td, {}) - log.info('build_sdist returned %r', filename) - except Exception: - log.info('Failure in build_sdist', exc_info=True) - return False - - if not filename.endswith('.tar.gz'): - log.error( - "Filename %s doesn't have .tar.gz extension", filename) - return False - - path = pjoin(td, filename) - if isfile(path): - log.info("Output file %s exists", path) - else: - log.error("Output file %s does not exist", path) - return False - - if tarfile.is_tarfile(path): - log.info("Output file is a tar file") - else: - log.error("Output file is not a tar file") - return False - - finally: - shutil.rmtree(td) - - return True - - -def check_build_wheel(hooks, build_sys_requires): - with BuildEnvironment() as env: - try: - env.pip_install(build_sys_requires) - log.info('Installed static build dependencies') - except CalledProcessError: - log.error('Failed to install static build dependencies') - return False - - try: - reqs = hooks.get_requires_for_build_wheel({}) - log.info('Got build requires: %s', reqs) - except Exception: - log.error('Failure in get_requires_for_build_sdist', exc_info=True) - return False - - try: - env.pip_install(reqs) - log.info('Installed dynamic build dependencies') - except CalledProcessError: - log.error('Failed to install dynamic build dependencies') - return False - - td = mkdtemp() - log.info('Trying to build wheel in %s', td) - try: - try: - filename = hooks.build_wheel(td, {}) - log.info('build_wheel returned %r', filename) - except Exception: - log.info('Failure in build_wheel', exc_info=True) - return False - - if not filename.endswith('.whl'): - log.error("Filename %s doesn't have .whl extension", filename) - return False - - path = pjoin(td, filename) - if isfile(path): - log.info("Output file %s exists", path) - else: - log.error("Output file %s does not exist", path) - return False - - if zipfile.is_zipfile(path): - log.info("Output file is a zip file") - else: - log.error("Output file is not a zip file") - return False - - finally: - shutil.rmtree(td) - - return True - - -def check(source_dir): - pyproject = pjoin(source_dir, 'pyproject.toml') - if isfile(pyproject): - log.info('Found pyproject.toml') - else: - log.error('Missing pyproject.toml') - return False - - try: - with open(pyproject) as f: - pyproject_data = toml_load(f) - # Ensure the mandatory data can be loaded - buildsys = pyproject_data['build-system'] - requires = buildsys['requires'] - backend = buildsys['build-backend'] - log.info('Loaded pyproject.toml') - except (TomlError, KeyError): - log.error("Invalid pyproject.toml", exc_info=True) - return False - - hooks = Pep517HookCaller(source_dir, backend) - - sdist_ok = check_build_sdist(hooks, requires) - wheel_ok = check_build_wheel(hooks, requires) - - if not sdist_ok: - log.warning('Sdist checks failed; scroll up to see') - if not wheel_ok: - log.warning('Wheel checks failed') - - return sdist_ok - - -def main(argv=None): - ap = argparse.ArgumentParser() - ap.add_argument( - 'source_dir', - help="A directory containing pyproject.toml") - args = ap.parse_args(argv) - - enable_colourful_output() - - ok = check(args.source_dir) - - if ok: - print(ansi('Checks passed', 'green')) - else: - print(ansi('Checks failed', 'red')) - sys.exit(1) - - -ansi_codes = { - 'reset': '\x1b[0m', - 'bold': '\x1b[1m', - 'red': '\x1b[31m', - 'green': '\x1b[32m', -} - - -def ansi(s, attr): - if os.name != 'nt' and sys.stdout.isatty(): - return ansi_codes[attr] + str(s) + ansi_codes['reset'] - else: - return str(s) - - -if __name__ == '__main__': - main() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/colorlog.py b/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/colorlog.py deleted file mode 100644 index 69c8a59..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/colorlog.py +++ /dev/null @@ -1,115 +0,0 @@ -"""Nicer log formatting with colours. - -Code copied from Tornado, Apache licensed. -""" -# Copyright 2012 Facebook -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging -import sys - -try: - import curses -except ImportError: - curses = None - - -def _stderr_supports_color(): - color = False - if curses and hasattr(sys.stderr, 'isatty') and sys.stderr.isatty(): - try: - curses.setupterm() - if curses.tigetnum("colors") > 0: - color = True - except Exception: - pass - return color - - -class LogFormatter(logging.Formatter): - """Log formatter with colour support - """ - DEFAULT_COLORS = { - logging.INFO: 2, # Green - logging.WARNING: 3, # Yellow - logging.ERROR: 1, # Red - logging.CRITICAL: 1, - } - - def __init__(self, color=True, datefmt=None): - r""" - :arg bool color: Enables color support. - :arg string fmt: Log message format. - It will be applied to the attributes dict of log records. The - text between ``%(color)s`` and ``%(end_color)s`` will be colored - depending on the level if color support is on. - :arg dict colors: color mappings from logging level to terminal color - code - :arg string datefmt: Datetime format. - Used for formatting ``(asctime)`` placeholder in ``prefix_fmt``. - .. versionchanged:: 3.2 - Added ``fmt`` and ``datefmt`` arguments. - """ - logging.Formatter.__init__(self, datefmt=datefmt) - self._colors = {} - if color and _stderr_supports_color(): - # The curses module has some str/bytes confusion in - # python3. Until version 3.2.3, most methods return - # bytes, but only accept strings. In addition, we want to - # output these strings with the logging module, which - # works with unicode strings. The explicit calls to - # unicode() below are harmless in python2 but will do the - # right conversion in python 3. - fg_color = (curses.tigetstr("setaf") or - curses.tigetstr("setf") or "") - if (3, 0) < sys.version_info < (3, 2, 3): - fg_color = str(fg_color, "ascii") - - for levelno, code in self.DEFAULT_COLORS.items(): - self._colors[levelno] = str( - curses.tparm(fg_color, code), "ascii") - self._normal = str(curses.tigetstr("sgr0"), "ascii") - - scr = curses.initscr() - self.termwidth = scr.getmaxyx()[1] - curses.endwin() - else: - self._normal = '' - # Default width is usually 80, but too wide is - # worse than too narrow - self.termwidth = 70 - - def formatMessage(self, record): - mlen = len(record.message) - right_text = '{initial}-{name}'.format(initial=record.levelname[0], - name=record.name) - if mlen + len(right_text) < self.termwidth: - space = ' ' * (self.termwidth - (mlen + len(right_text))) - else: - space = ' ' - - if record.levelno in self._colors: - start_color = self._colors[record.levelno] - end_color = self._normal - else: - start_color = end_color = '' - - return record.message + space + start_color + right_text + end_color - - -def enable_colourful_output(level=logging.INFO): - handler = logging.StreamHandler() - handler.setFormatter(LogFormatter()) - logging.root.addHandler(handler) - logging.root.setLevel(level) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/compat.py b/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/compat.py deleted file mode 100644 index 01c66fc..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/compat.py +++ /dev/null @@ -1,23 +0,0 @@ -"""Handle reading and writing JSON in UTF-8, on Python 3 and 2.""" -import json -import sys - -if sys.version_info[0] >= 3: - # Python 3 - def write_json(obj, path, **kwargs): - with open(path, 'w', encoding='utf-8') as f: - json.dump(obj, f, **kwargs) - - def read_json(path): - with open(path, 'r', encoding='utf-8') as f: - return json.load(f) - -else: - # Python 2 - def write_json(obj, path, **kwargs): - with open(path, 'wb') as f: - json.dump(obj, f, encoding='utf-8', **kwargs) - - def read_json(path): - with open(path, 'rb') as f: - return json.load(f) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/envbuild.py b/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/envbuild.py deleted file mode 100644 index f7ac5f4..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/envbuild.py +++ /dev/null @@ -1,158 +0,0 @@ -"""Build wheels/sdists by installing build deps to a temporary environment. -""" - -import os -import logging -from pip._vendor import pytoml -import shutil -from subprocess import check_call -import sys -from sysconfig import get_paths -from tempfile import mkdtemp - -from .wrappers import Pep517HookCaller - -log = logging.getLogger(__name__) - - -def _load_pyproject(source_dir): - with open(os.path.join(source_dir, 'pyproject.toml')) as f: - pyproject_data = pytoml.load(f) - buildsys = pyproject_data['build-system'] - return buildsys['requires'], buildsys['build-backend'] - - -class BuildEnvironment(object): - """Context manager to install build deps in a simple temporary environment - - Based on code I wrote for pip, which is MIT licensed. - """ - # Copyright (c) 2008-2016 The pip developers (see AUTHORS.txt file) - # - # 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. - - path = None - - def __init__(self, cleanup=True): - self._cleanup = cleanup - - def __enter__(self): - self.path = mkdtemp(prefix='pep517-build-env-') - log.info('Temporary build environment: %s', self.path) - - self.save_path = os.environ.get('PATH', None) - self.save_pythonpath = os.environ.get('PYTHONPATH', None) - - install_scheme = 'nt' if (os.name == 'nt') else 'posix_prefix' - install_dirs = get_paths(install_scheme, vars={ - 'base': self.path, - 'platbase': self.path, - }) - - scripts = install_dirs['scripts'] - if self.save_path: - os.environ['PATH'] = scripts + os.pathsep + self.save_path - else: - os.environ['PATH'] = scripts + os.pathsep + os.defpath - - if install_dirs['purelib'] == install_dirs['platlib']: - lib_dirs = install_dirs['purelib'] - else: - lib_dirs = install_dirs['purelib'] + os.pathsep + \ - install_dirs['platlib'] - if self.save_pythonpath: - os.environ['PYTHONPATH'] = lib_dirs + os.pathsep + \ - self.save_pythonpath - else: - os.environ['PYTHONPATH'] = lib_dirs - - return self - - def pip_install(self, reqs): - """Install dependencies into this env by calling pip in a subprocess""" - if not reqs: - return - log.info('Calling pip to install %s', reqs) - check_call([ - sys.executable, '-m', 'pip', 'install', '--ignore-installed', - '--prefix', self.path] + list(reqs)) - - def __exit__(self, exc_type, exc_val, exc_tb): - needs_cleanup = ( - self._cleanup and - self.path is not None and - os.path.isdir(self.path) - ) - if needs_cleanup: - shutil.rmtree(self.path) - - if self.save_path is None: - os.environ.pop('PATH', None) - else: - os.environ['PATH'] = self.save_path - - if self.save_pythonpath is None: - os.environ.pop('PYTHONPATH', None) - else: - os.environ['PYTHONPATH'] = self.save_pythonpath - - -def build_wheel(source_dir, wheel_dir, config_settings=None): - """Build a wheel from a source directory using PEP 517 hooks. - - :param str source_dir: Source directory containing pyproject.toml - :param str wheel_dir: Target directory to create wheel in - :param dict config_settings: Options to pass to build backend - - This is a blocking function which will run pip in a subprocess to install - build requirements. - """ - if config_settings is None: - config_settings = {} - requires, backend = _load_pyproject(source_dir) - hooks = Pep517HookCaller(source_dir, backend) - - with BuildEnvironment() as env: - env.pip_install(requires) - reqs = hooks.get_requires_for_build_wheel(config_settings) - env.pip_install(reqs) - return hooks.build_wheel(wheel_dir, config_settings) - - -def build_sdist(source_dir, sdist_dir, config_settings=None): - """Build an sdist from a source directory using PEP 517 hooks. - - :param str source_dir: Source directory containing pyproject.toml - :param str sdist_dir: Target directory to place sdist in - :param dict config_settings: Options to pass to build backend - - This is a blocking function which will run pip in a subprocess to install - build requirements. - """ - if config_settings is None: - config_settings = {} - requires, backend = _load_pyproject(source_dir) - hooks = Pep517HookCaller(source_dir, backend) - - with BuildEnvironment() as env: - env.pip_install(requires) - reqs = hooks.get_requires_for_build_sdist(config_settings) - env.pip_install(reqs) - return hooks.build_sdist(sdist_dir, config_settings) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/wrappers.py b/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/wrappers.py deleted file mode 100644 index b14b899..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/pep517/wrappers.py +++ /dev/null @@ -1,163 +0,0 @@ -from contextlib import contextmanager -import os -from os.path import dirname, abspath, join as pjoin -import shutil -from subprocess import check_call -import sys -from tempfile import mkdtemp - -from . import compat - -_in_proc_script = pjoin(dirname(abspath(__file__)), '_in_process.py') - - -@contextmanager -def tempdir(): - td = mkdtemp() - try: - yield td - finally: - shutil.rmtree(td) - - -class BackendUnavailable(Exception): - """Will be raised if the backend cannot be imported in the hook process.""" - - -class UnsupportedOperation(Exception): - """May be raised by build_sdist if the backend indicates that it can't.""" - - -def default_subprocess_runner(cmd, cwd=None, extra_environ=None): - """The default method of calling the wrapper subprocess.""" - env = os.environ.copy() - if extra_environ: - env.update(extra_environ) - - check_call(cmd, cwd=cwd, env=env) - - -class Pep517HookCaller(object): - """A wrapper around a source directory to be built with a PEP 517 backend. - - source_dir : The path to the source directory, containing pyproject.toml. - backend : The build backend spec, as per PEP 517, from pyproject.toml. - """ - def __init__(self, source_dir, build_backend): - self.source_dir = abspath(source_dir) - self.build_backend = build_backend - self._subprocess_runner = default_subprocess_runner - - # TODO: Is this over-engineered? Maybe frontends only need to - # set this when creating the wrapper, not on every call. - @contextmanager - def subprocess_runner(self, runner): - prev = self._subprocess_runner - self._subprocess_runner = runner - yield - self._subprocess_runner = prev - - def get_requires_for_build_wheel(self, config_settings=None): - """Identify packages required for building a wheel - - Returns a list of dependency specifications, e.g.: - ["wheel >= 0.25", "setuptools"] - - This does not include requirements specified in pyproject.toml. - It returns the result of calling the equivalently named hook in a - subprocess. - """ - return self._call_hook('get_requires_for_build_wheel', { - 'config_settings': config_settings - }) - - def prepare_metadata_for_build_wheel( - self, metadata_directory, config_settings=None): - """Prepare a *.dist-info folder with metadata for this project. - - Returns the name of the newly created folder. - - If the build backend defines a hook with this name, it will be called - in a subprocess. If not, the backend will be asked to build a wheel, - and the dist-info extracted from that. - """ - return self._call_hook('prepare_metadata_for_build_wheel', { - 'metadata_directory': abspath(metadata_directory), - 'config_settings': config_settings, - }) - - def build_wheel( - self, wheel_directory, config_settings=None, - metadata_directory=None): - """Build a wheel from this project. - - Returns the name of the newly created file. - - In general, this will call the 'build_wheel' hook in the backend. - However, if that was previously called by - 'prepare_metadata_for_build_wheel', and the same metadata_directory is - used, the previously built wheel will be copied to wheel_directory. - """ - if metadata_directory is not None: - metadata_directory = abspath(metadata_directory) - return self._call_hook('build_wheel', { - 'wheel_directory': abspath(wheel_directory), - 'config_settings': config_settings, - 'metadata_directory': metadata_directory, - }) - - def get_requires_for_build_sdist(self, config_settings=None): - """Identify packages required for building a wheel - - Returns a list of dependency specifications, e.g.: - ["setuptools >= 26"] - - This does not include requirements specified in pyproject.toml. - It returns the result of calling the equivalently named hook in a - subprocess. - """ - return self._call_hook('get_requires_for_build_sdist', { - 'config_settings': config_settings - }) - - def build_sdist(self, sdist_directory, config_settings=None): - """Build an sdist from this project. - - Returns the name of the newly created file. - - This calls the 'build_sdist' backend hook in a subprocess. - """ - return self._call_hook('build_sdist', { - 'sdist_directory': abspath(sdist_directory), - 'config_settings': config_settings, - }) - - def _call_hook(self, hook_name, kwargs): - # On Python 2, pytoml returns Unicode values (which is correct) but the - # environment passed to check_call needs to contain string values. We - # convert here by encoding using ASCII (the backend can only contain - # letters, digits and _, . and : characters, and will be used as a - # Python identifier, so non-ASCII content is wrong on Python 2 in - # any case). - if sys.version_info[0] == 2: - build_backend = self.build_backend.encode('ASCII') - else: - build_backend = self.build_backend - - with tempdir() as td: - compat.write_json({'kwargs': kwargs}, pjoin(td, 'input.json'), - indent=2) - - # Run the hook in a subprocess - self._subprocess_runner( - [sys.executable, _in_proc_script, hook_name, td], - cwd=self.source_dir, - extra_environ={'PEP517_BUILD_BACKEND': build_backend} - ) - - data = compat.read_json(pjoin(td, 'output.json')) - if data.get('unsupported'): - raise UnsupportedOperation - if data.get('no_backend'): - raise BackendUnavailable - return data['return_val'] diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/pkg_resources/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/pkg_resources/__init__.py deleted file mode 100644 index fdd40de..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/pkg_resources/__init__.py +++ /dev/null @@ -1,3286 +0,0 @@ -# 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 pip._vendor import six -from pip._vendor.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 pip._vendor import appdirs -from pip._vendor import packaging -__import__('pip._vendor.packaging.version') -__import__('pip._vendor.packaging.specifiers') -__import__('pip._vendor.packaging.requirements') -__import__('pip._vendor.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 = sys.version[:3] -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 "" - value = self._get(self._fn(self.egg_info, name)) - return value.decode('utf-8') if six.PY3 else value - - 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<name>[^-]+) ( - -(?P<ver>[^-]+) ( - -py(?P<pyver>[^-]+) ( - -(?P<plat>.+) - )? - )? - )? - """, - 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<name>.+?)\s*' - r'=\s*' - r'(?P<module>[\w.]+)\s*' - r'(:\s*(?P<attr>[\w.]+))?\s*' - r'(?P<extras>\[.*\])?\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.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. - """ diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/pkg_resources/py31compat.py b/venv2/lib/python2.7/site-packages/pip/_vendor/pkg_resources/py31compat.py deleted file mode 100644 index a2d3007..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/pkg_resources/py31compat.py +++ /dev/null @@ -1,23 +0,0 @@ -import os -import errno -import sys - -from pip._vendor import six - - -def _makedirs_31(path, exist_ok=False): - try: - os.makedirs(path) - except OSError as exc: - if not exist_ok or exc.errno != errno.EEXIST: - raise - - -# rely on compatibility behavior until mode considerations -# and exists_ok considerations are disentangled. -# See https://github.com/pypa/setuptools/pull/1083#issuecomment-315168663 -needs_makedirs = ( - six.PY2 or - (3, 4) <= sys.version_info < (3, 4, 1) -) -makedirs = _makedirs_31 if needs_makedirs else os.makedirs diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/progress/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/progress/__init__.py deleted file mode 100644 index e434c25..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/progress/__init__.py +++ /dev/null @@ -1,177 +0,0 @@ -# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com> -# -# 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() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/progress/bar.py b/venv2/lib/python2.7/site-packages/pip/_vendor/progress/bar.py deleted file mode 100644 index 8819efd..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/progress/bar.py +++ /dev/null @@ -1,91 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com> -# -# 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 = (' ', '░', '▒', '▓', '█') diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/progress/counter.py b/venv2/lib/python2.7/site-packages/pip/_vendor/progress/counter.py deleted file mode 100644 index d955ca4..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/progress/counter.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com> -# -# 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 = ('○', '◔', '◑', '◕', '●') diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/progress/spinner.py b/venv2/lib/python2.7/site-packages/pip/_vendor/progress/spinner.py deleted file mode 100644 index 4e100ca..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/progress/spinner.py +++ /dev/null @@ -1,43 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com> -# -# 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 = ['⣾', '⣷', '⣯', '⣟', '⡿', '⢿', '⣻', '⣽'] diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/pyparsing.py b/venv2/lib/python2.7/site-packages/pip/_vendor/pyparsing.py deleted file mode 100644 index 9d6a01d..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/pyparsing.py +++ /dev/null @@ -1,6493 +0,0 @@ -#-*- coding: utf-8 -*- -# module pyparsing.py -# -# Copyright (c) 2003-2019 Paul T. McGuire -# -# 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. -# - -__doc__ = \ -""" -pyparsing module - Classes and methods to define and execute parsing grammars -============================================================================= - -The pyparsing module is an alternative approach to creating and -executing simple grammars, vs. the traditional lex/yacc approach, or the -use of regular expressions. With pyparsing, you don't need to learn -a new syntax for defining grammars or matching expressions - the parsing -module provides a library of classes that you use to construct the -grammar directly in Python. - -Here is a program to parse "Hello, World!" (or any greeting of the form -``"<salutation>, <addressee>!"``), built up using :class:`Word`, -:class:`Literal`, and :class:`And` elements -(the :class:`'+'<ParserElement.__add__>` operators create :class:`And` expressions, -and the strings are auto-converted to :class:`Literal` expressions):: - - from pip._vendor.pyparsing import Word, alphas - - # define grammar of a greeting - greet = Word(alphas) + "," + Word(alphas) + "!" - - hello = "Hello, World!" - print (hello, "->", greet.parseString(hello)) - -The program outputs the following:: - - Hello, World! -> ['Hello', ',', 'World', '!'] - -The Python representation of the grammar is quite readable, owing to the -self-explanatory class names, and the use of '+', '|' and '^' operators. - -The :class:`ParseResults` object returned from -:class:`ParserElement.parseString` can be -accessed as a nested list, a dictionary, or an object with named -attributes. - -The pyparsing module handles some of the problems that are typically -vexing when writing text parsers: - - - extra or missing whitespace (the above program will also handle - "Hello,World!", "Hello , World !", etc.) - - quoted strings - - embedded comments - - -Getting Started - ------------------ -Visit the classes :class:`ParserElement` and :class:`ParseResults` to -see the base classes that most other pyparsing -classes inherit from. Use the docstrings for examples of how to: - - - construct literal match expressions from :class:`Literal` and - :class:`CaselessLiteral` classes - - construct character word-group expressions using the :class:`Word` - class - - see how to create repetitive expressions using :class:`ZeroOrMore` - and :class:`OneOrMore` classes - - use :class:`'+'<And>`, :class:`'|'<MatchFirst>`, :class:`'^'<Or>`, - and :class:`'&'<Each>` operators to combine simple expressions into - more complex ones - - associate names with your parsed results using - :class:`ParserElement.setResultsName` - - find some helpful expression short-cuts like :class:`delimitedList` - and :class:`oneOf` - - find more useful common expressions in the :class:`pyparsing_common` - namespace class -""" - -__version__ = "2.4.0" -__versionTime__ = "07 Apr 2019 18:28 UTC" -__author__ = "Paul McGuire <ptmcg@users.sourceforge.net>" - -import string -from weakref import ref as wkref -import copy -import sys -import warnings -import re -import sre_constants -import collections -import pprint -import traceback -import types -from datetime import datetime - -try: - # Python 3 - from itertools import filterfalse -except ImportError: - from itertools import ifilterfalse as filterfalse - -try: - from _thread import RLock -except ImportError: - from threading import RLock - -try: - # Python 3 - from collections.abc import Iterable - from collections.abc import MutableMapping -except ImportError: - # Python 2.7 - from collections import Iterable - from collections import MutableMapping - -try: - from collections import OrderedDict as _OrderedDict -except ImportError: - try: - from ordereddict import OrderedDict as _OrderedDict - except ImportError: - _OrderedDict = None - -try: - from types import SimpleNamespace -except ImportError: - class SimpleNamespace: pass - -# version compatibility configuration -__compat__ = SimpleNamespace() -__compat__.__doc__ = """ - A cross-version compatibility configuration for pyparsing features that will be - released in a future version. By setting values in this configuration to True, - those features can be enabled in prior versions for compatibility development - and testing. - - - collect_all_And_tokens - flag to enable fix for Issue #63 that fixes erroneous grouping - of results names when an And expression is nested within an Or or MatchFirst; set to - True to enable bugfix to be released in pyparsing 2.4 -""" -__compat__.collect_all_And_tokens = True - - -#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) ) - -__all__ = [ '__version__', '__versionTime__', '__author__', '__compat__', -'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty', -'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal', -'PrecededBy', 'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or', -'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException', -'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException', -'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', -'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore', 'Char', -'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col', -'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString', -'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'hexnums', -'htmlComment', 'javaStyleComment', 'line', 'lineEnd', 'lineStart', 'lineno', -'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral', -'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables', -'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', -'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd', -'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute', -'indentedBlock', 'originalTextFor', 'ungroup', 'infixNotation','locatedExpr', 'withClass', -'CloseMatch', 'tokenMap', 'pyparsing_common', 'pyparsing_unicode', 'unicode_set', -] - -system_version = tuple(sys.version_info)[:3] -PY_3 = system_version[0] == 3 -if PY_3: - _MAX_INT = sys.maxsize - basestring = str - unichr = chr - unicode = str - _ustr = str - - # build list of single arg builtins, that can be used as parse actions - singleArgBuiltins = [sum, len, sorted, reversed, list, tuple, set, any, all, min, max] - -else: - _MAX_INT = sys.maxint - range = xrange - - def _ustr(obj): - """Drop-in replacement for str(obj) that tries to be Unicode - friendly. It first tries str(obj). If that fails with - a UnicodeEncodeError, then it tries unicode(obj). It then - < returns the unicode object | encodes it with the default - encoding | ... >. - """ - if isinstance(obj,unicode): - return obj - - try: - # If this works, then _ustr(obj) has the same behaviour as str(obj), so - # it won't break any existing code. - return str(obj) - - except UnicodeEncodeError: - # Else encode it - ret = unicode(obj).encode(sys.getdefaultencoding(), 'xmlcharrefreplace') - xmlcharref = Regex(r'&#\d+;') - xmlcharref.setParseAction(lambda t: '\\u' + hex(int(t[0][2:-1]))[2:]) - return xmlcharref.transformString(ret) - - # build list of single arg builtins, tolerant of Python version, that can be used as parse actions - singleArgBuiltins = [] - import __builtin__ - for fname in "sum len sorted reversed list tuple set any all min max".split(): - try: - singleArgBuiltins.append(getattr(__builtin__,fname)) - except AttributeError: - continue - -_generatorType = type((y for y in range(1))) - -def _xml_escape(data): - """Escape &, <, >, ", ', etc. in a string of data.""" - - # ampersand must be replaced first - from_symbols = '&><"\'' - to_symbols = ('&'+s+';' for s in "amp gt lt quot apos".split()) - for from_,to_ in zip(from_symbols, to_symbols): - data = data.replace(from_, to_) - return data - -alphas = string.ascii_uppercase + string.ascii_lowercase -nums = "0123456789" -hexnums = nums + "ABCDEFabcdef" -alphanums = alphas + nums -_bslash = chr(92) -printables = "".join(c for c in string.printable if c not in string.whitespace) - -class ParseBaseException(Exception): - """base exception class for all parsing runtime exceptions""" - # Performance tuning: we construct a *lot* of these, so keep this - # constructor as small and fast as possible - def __init__( self, pstr, loc=0, msg=None, elem=None ): - self.loc = loc - if msg is None: - self.msg = pstr - self.pstr = "" - else: - self.msg = msg - self.pstr = pstr - self.parserElement = elem - self.args = (pstr, loc, msg) - - @classmethod - def _from_exception(cls, pe): - """ - internal factory method to simplify creating one type of ParseException - from another - avoids having __init__ signature conflicts among subclasses - """ - return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement) - - def __getattr__( self, aname ): - """supported attributes by name are: - - lineno - returns the line number of the exception text - - col - returns the column number of the exception text - - line - returns the line containing the exception text - """ - if( aname == "lineno" ): - return lineno( self.loc, self.pstr ) - elif( aname in ("col", "column") ): - return col( self.loc, self.pstr ) - elif( aname == "line" ): - return line( self.loc, self.pstr ) - else: - raise AttributeError(aname) - - def __str__( self ): - return "%s (at char %d), (line:%d, col:%d)" % \ - ( self.msg, self.loc, self.lineno, self.column ) - def __repr__( self ): - return _ustr(self) - def markInputline( self, markerString = ">!<" ): - """Extracts the exception line from the input string, and marks - the location of the exception with a special symbol. - """ - line_str = self.line - line_column = self.column - 1 - if markerString: - line_str = "".join((line_str[:line_column], - markerString, line_str[line_column:])) - return line_str.strip() - def __dir__(self): - return "lineno col line".split() + dir(type(self)) - -class ParseException(ParseBaseException): - """ - Exception thrown when parse expressions don't match class; - supported attributes by name are: - - lineno - returns the line number of the exception text - - col - returns the column number of the exception text - - line - returns the line containing the exception text - - Example:: - - try: - Word(nums).setName("integer").parseString("ABC") - except ParseException as pe: - print(pe) - print("column: {}".format(pe.col)) - - prints:: - - Expected integer (at char 0), (line:1, col:1) - column: 1 - - """ - - @staticmethod - def explain(exc, depth=16): - """ - Method to take an exception and translate the Python internal traceback into a list - of the pyparsing expressions that caused the exception to be raised. - - Parameters: - - - exc - exception raised during parsing (need not be a ParseException, in support - of Python exceptions that might be raised in a parse action) - - depth (default=16) - number of levels back in the stack trace to list expression - and function names; if None, the full stack trace names will be listed; if 0, only - the failing input line, marker, and exception string will be shown - - Returns a multi-line string listing the ParserElements and/or function names in the - exception's stack trace. - - Note: the diagnostic output will include string representations of the expressions - that failed to parse. These representations will be more helpful if you use `setName` to - give identifiable names to your expressions. Otherwise they will use the default string - forms, which may be cryptic to read. - - explain() is only supported under Python 3. - """ - import inspect - - if depth is None: - depth = sys.getrecursionlimit() - ret = [] - if isinstance(exc, ParseBaseException): - ret.append(exc.line) - ret.append(' ' * (exc.col - 1) + '^') - ret.append("{0}: {1}".format(type(exc).__name__, exc)) - - if depth > 0: - callers = inspect.getinnerframes(exc.__traceback__, context=depth) - seen = set() - for i, ff in enumerate(callers[-depth:]): - frm = ff[0] - - f_self = frm.f_locals.get('self', None) - if isinstance(f_self, ParserElement): - if frm.f_code.co_name not in ('parseImpl', '_parseNoCache'): - continue - if f_self in seen: - continue - seen.add(f_self) - - self_type = type(f_self) - ret.append("{0}.{1} - {2}".format(self_type.__module__, - self_type.__name__, - f_self)) - elif f_self is not None: - self_type = type(f_self) - ret.append("{0}.{1}".format(self_type.__module__, - self_type.__name__)) - else: - code = frm.f_code - if code.co_name in ('wrapper', '<module>'): - continue - - ret.append("{0}".format(code.co_name)) - - depth -= 1 - if not depth: - break - - return '\n'.join(ret) - - -class ParseFatalException(ParseBaseException): - """user-throwable exception thrown when inconsistent parse content - is found; stops all parsing immediately""" - pass - -class ParseSyntaxException(ParseFatalException): - """just like :class:`ParseFatalException`, but thrown internally - when an :class:`ErrorStop<And._ErrorStop>` ('-' operator) indicates - that parsing is to stop immediately because an unbacktrackable - syntax error has been found. - """ - pass - -#~ class ReparseException(ParseBaseException): - #~ """Experimental class - parse actions can raise this exception to cause - #~ pyparsing to reparse the input string: - #~ - with a modified input string, and/or - #~ - with a modified start location - #~ Set the values of the ReparseException in the constructor, and raise the - #~ exception in a parse action to cause pyparsing to use the new string/location. - #~ Setting the values as None causes no change to be made. - #~ """ - #~ def __init_( self, newstring, restartLoc ): - #~ self.newParseText = newstring - #~ self.reparseLoc = restartLoc - -class RecursiveGrammarException(Exception): - """exception thrown by :class:`ParserElement.validate` if the - grammar could be improperly recursive - """ - def __init__( self, parseElementList ): - self.parseElementTrace = parseElementList - - def __str__( self ): - return "RecursiveGrammarException: %s" % self.parseElementTrace - -class _ParseResultsWithOffset(object): - def __init__(self,p1,p2): - self.tup = (p1,p2) - def __getitem__(self,i): - return self.tup[i] - def __repr__(self): - return repr(self.tup[0]) - def setOffset(self,i): - self.tup = (self.tup[0],i) - -class ParseResults(object): - """Structured parse results, to provide multiple means of access to - the parsed data: - - - as a list (``len(results)``) - - by list index (``results[0], results[1]``, etc.) - - by attribute (``results.<resultsName>`` - see :class:`ParserElement.setResultsName`) - - Example:: - - integer = Word(nums) - date_str = (integer.setResultsName("year") + '/' - + integer.setResultsName("month") + '/' - + integer.setResultsName("day")) - # equivalent form: - # date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - # parseString returns a ParseResults object - result = date_str.parseString("1999/12/31") - - def test(s, fn=repr): - print("%s -> %s" % (s, fn(eval(s)))) - test("list(result)") - test("result[0]") - test("result['month']") - test("result.day") - test("'month' in result") - test("'minutes' in result") - test("result.dump()", str) - - prints:: - - list(result) -> ['1999', '/', '12', '/', '31'] - result[0] -> '1999' - result['month'] -> '12' - result.day -> '31' - 'month' in result -> True - 'minutes' in result -> False - result.dump() -> ['1999', '/', '12', '/', '31'] - - day: 31 - - month: 12 - - year: 1999 - """ - def __new__(cls, toklist=None, name=None, asList=True, modal=True ): - if isinstance(toklist, cls): - return toklist - retobj = object.__new__(cls) - retobj.__doinit = True - return retobj - - # Performance tuning: we construct a *lot* of these, so keep this - # constructor as small and fast as possible - def __init__( self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance ): - if self.__doinit: - self.__doinit = False - self.__name = None - self.__parent = None - self.__accumNames = {} - self.__asList = asList - self.__modal = modal - if toklist is None: - toklist = [] - if isinstance(toklist, list): - self.__toklist = toklist[:] - elif isinstance(toklist, _generatorType): - self.__toklist = list(toklist) - else: - self.__toklist = [toklist] - self.__tokdict = dict() - - if name is not None and name: - if not modal: - self.__accumNames[name] = 0 - if isinstance(name,int): - name = _ustr(name) # will always return a str, but use _ustr for consistency - self.__name = name - if not (isinstance(toklist, (type(None), basestring, list)) and toklist in (None,'',[])): - if isinstance(toklist,basestring): - toklist = [ toklist ] - if asList: - if isinstance(toklist,ParseResults): - self[name] = _ParseResultsWithOffset(ParseResults(toklist.__toklist), 0) - else: - self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0) - self[name].__name = name - else: - try: - self[name] = toklist[0] - except (KeyError,TypeError,IndexError): - self[name] = toklist - - def __getitem__( self, i ): - if isinstance( i, (int,slice) ): - return self.__toklist[i] - else: - if i not in self.__accumNames: - return self.__tokdict[i][-1][0] - else: - return ParseResults([ v[0] for v in self.__tokdict[i] ]) - - def __setitem__( self, k, v, isinstance=isinstance ): - if isinstance(v,_ParseResultsWithOffset): - self.__tokdict[k] = self.__tokdict.get(k,list()) + [v] - sub = v[0] - elif isinstance(k,(int,slice)): - self.__toklist[k] = v - sub = v - else: - self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)] - sub = v - if isinstance(sub,ParseResults): - sub.__parent = wkref(self) - - def __delitem__( self, i ): - if isinstance(i,(int,slice)): - mylen = len( self.__toklist ) - del self.__toklist[i] - - # convert int to slice - if isinstance(i, int): - if i < 0: - i += mylen - i = slice(i, i+1) - # get removed indices - removed = list(range(*i.indices(mylen))) - removed.reverse() - # fixup indices in token dictionary - for name,occurrences in self.__tokdict.items(): - for j in removed: - for k, (value, position) in enumerate(occurrences): - occurrences[k] = _ParseResultsWithOffset(value, position - (position > j)) - else: - del self.__tokdict[i] - - def __contains__( self, k ): - return k in self.__tokdict - - def __len__( self ): return len( self.__toklist ) - def __bool__(self): return ( not not self.__toklist ) - __nonzero__ = __bool__ - def __iter__( self ): return iter( self.__toklist ) - def __reversed__( self ): return iter( self.__toklist[::-1] ) - def _iterkeys( self ): - if hasattr(self.__tokdict, "iterkeys"): - return self.__tokdict.iterkeys() - else: - return iter(self.__tokdict) - - def _itervalues( self ): - return (self[k] for k in self._iterkeys()) - - def _iteritems( self ): - return ((k, self[k]) for k in self._iterkeys()) - - if PY_3: - keys = _iterkeys - """Returns an iterator of all named result keys.""" - - values = _itervalues - """Returns an iterator of all named result values.""" - - items = _iteritems - """Returns an iterator of all named result key-value tuples.""" - - else: - iterkeys = _iterkeys - """Returns an iterator of all named result keys (Python 2.x only).""" - - itervalues = _itervalues - """Returns an iterator of all named result values (Python 2.x only).""" - - iteritems = _iteritems - """Returns an iterator of all named result key-value tuples (Python 2.x only).""" - - def keys( self ): - """Returns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x).""" - return list(self.iterkeys()) - - def values( self ): - """Returns all named result values (as a list in Python 2.x, as an iterator in Python 3.x).""" - return list(self.itervalues()) - - def items( self ): - """Returns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x).""" - return list(self.iteritems()) - - def haskeys( self ): - """Since keys() returns an iterator, this method is helpful in bypassing - code that looks for the existence of any defined results names.""" - return bool(self.__tokdict) - - def pop( self, *args, **kwargs): - """ - Removes and returns item at specified index (default= ``last``). - Supports both ``list`` and ``dict`` semantics for ``pop()``. If - passed no argument or an integer argument, it will use ``list`` - semantics and pop tokens from the list of parsed tokens. If passed - a non-integer argument (most likely a string), it will use ``dict`` - semantics and pop the corresponding value from any defined results - names. A second default return value argument is supported, just as in - ``dict.pop()``. - - Example:: - - def remove_first(tokens): - tokens.pop(0) - print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] - print(OneOrMore(Word(nums)).addParseAction(remove_first).parseString("0 123 321")) # -> ['123', '321'] - - label = Word(alphas) - patt = label("LABEL") + OneOrMore(Word(nums)) - print(patt.parseString("AAB 123 321").dump()) - - # Use pop() in a parse action to remove named result (note that corresponding value is not - # removed from list form of results) - def remove_LABEL(tokens): - tokens.pop("LABEL") - return tokens - patt.addParseAction(remove_LABEL) - print(patt.parseString("AAB 123 321").dump()) - - prints:: - - ['AAB', '123', '321'] - - LABEL: AAB - - ['AAB', '123', '321'] - """ - if not args: - args = [-1] - for k,v in kwargs.items(): - if k == 'default': - args = (args[0], v) - else: - raise TypeError("pop() got an unexpected keyword argument '%s'" % k) - if (isinstance(args[0], int) or - len(args) == 1 or - args[0] in self): - index = args[0] - ret = self[index] - del self[index] - return ret - else: - defaultvalue = args[1] - return defaultvalue - - def get(self, key, defaultValue=None): - """ - Returns named result matching the given key, or if there is no - such name, then returns the given ``defaultValue`` or ``None`` if no - ``defaultValue`` is specified. - - Similar to ``dict.get()``. - - Example:: - - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - result = date_str.parseString("1999/12/31") - print(result.get("year")) # -> '1999' - print(result.get("hour", "not specified")) # -> 'not specified' - print(result.get("hour")) # -> None - """ - if key in self: - return self[key] - else: - return defaultValue - - def insert( self, index, insStr ): - """ - Inserts new element at location index in the list of parsed tokens. - - Similar to ``list.insert()``. - - Example:: - - print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] - - # use a parse action to insert the parse location in the front of the parsed results - def insert_locn(locn, tokens): - tokens.insert(0, locn) - print(OneOrMore(Word(nums)).addParseAction(insert_locn).parseString("0 123 321")) # -> [0, '0', '123', '321'] - """ - self.__toklist.insert(index, insStr) - # fixup indices in token dictionary - for name,occurrences in self.__tokdict.items(): - for k, (value, position) in enumerate(occurrences): - occurrences[k] = _ParseResultsWithOffset(value, position + (position > index)) - - def append( self, item ): - """ - Add single element to end of ParseResults list of elements. - - Example:: - - print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] - - # use a parse action to compute the sum of the parsed integers, and add it to the end - def append_sum(tokens): - tokens.append(sum(map(int, tokens))) - print(OneOrMore(Word(nums)).addParseAction(append_sum).parseString("0 123 321")) # -> ['0', '123', '321', 444] - """ - self.__toklist.append(item) - - def extend( self, itemseq ): - """ - Add sequence of elements to end of ParseResults list of elements. - - Example:: - - patt = OneOrMore(Word(alphas)) - - # use a parse action to append the reverse of the matched strings, to make a palindrome - def make_palindrome(tokens): - tokens.extend(reversed([t[::-1] for t in tokens])) - return ''.join(tokens) - print(patt.addParseAction(make_palindrome).parseString("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl' - """ - if isinstance(itemseq, ParseResults): - self.__iadd__(itemseq) - else: - self.__toklist.extend(itemseq) - - def clear( self ): - """ - Clear all elements and results names. - """ - del self.__toklist[:] - self.__tokdict.clear() - - def __getattr__( self, name ): - try: - return self[name] - except KeyError: - return "" - - if name in self.__tokdict: - if name not in self.__accumNames: - return self.__tokdict[name][-1][0] - else: - return ParseResults([ v[0] for v in self.__tokdict[name] ]) - else: - return "" - - def __add__( self, other ): - ret = self.copy() - ret += other - return ret - - def __iadd__( self, other ): - if other.__tokdict: - offset = len(self.__toklist) - addoffset = lambda a: offset if a<0 else a+offset - otheritems = other.__tokdict.items() - otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) ) - for (k,vlist) in otheritems for v in vlist] - for k,v in otherdictitems: - self[k] = v - if isinstance(v[0],ParseResults): - v[0].__parent = wkref(self) - - self.__toklist += other.__toklist - self.__accumNames.update( other.__accumNames ) - return self - - def __radd__(self, other): - if isinstance(other,int) and other == 0: - # useful for merging many ParseResults using sum() builtin - return self.copy() - else: - # this may raise a TypeError - so be it - return other + self - - def __repr__( self ): - return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) ) - - def __str__( self ): - return '[' + ', '.join(_ustr(i) if isinstance(i, ParseResults) else repr(i) for i in self.__toklist) + ']' - - def _asStringList( self, sep='' ): - out = [] - for item in self.__toklist: - if out and sep: - out.append(sep) - if isinstance( item, ParseResults ): - out += item._asStringList() - else: - out.append( _ustr(item) ) - return out - - def asList( self ): - """ - Returns the parse results as a nested list of matching tokens, all converted to strings. - - Example:: - - patt = OneOrMore(Word(alphas)) - result = patt.parseString("sldkj lsdkj sldkj") - # even though the result prints in string-like form, it is actually a pyparsing ParseResults - print(type(result), result) # -> <class 'pyparsing.ParseResults'> ['sldkj', 'lsdkj', 'sldkj'] - - # Use asList() to create an actual list - result_list = result.asList() - print(type(result_list), result_list) # -> <class 'list'> ['sldkj', 'lsdkj', 'sldkj'] - """ - return [res.asList() if isinstance(res,ParseResults) else res for res in self.__toklist] - - def asDict( self ): - """ - Returns the named parse results as a nested dictionary. - - Example:: - - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - result = date_str.parseString('12/31/1999') - print(type(result), repr(result)) # -> <class 'pyparsing.ParseResults'> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]}) - - result_dict = result.asDict() - print(type(result_dict), repr(result_dict)) # -> <class 'dict'> {'day': '1999', 'year': '12', 'month': '31'} - - # even though a ParseResults supports dict-like access, sometime you just need to have a dict - import json - print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable - print(json.dumps(result.asDict())) # -> {"month": "31", "day": "1999", "year": "12"} - """ - if PY_3: - item_fn = self.items - else: - item_fn = self.iteritems - - def toItem(obj): - if isinstance(obj, ParseResults): - if obj.haskeys(): - return obj.asDict() - else: - return [toItem(v) for v in obj] - else: - return obj - - return dict((k,toItem(v)) for k,v in item_fn()) - - def copy( self ): - """ - Returns a new copy of a :class:`ParseResults` object. - """ - ret = ParseResults( self.__toklist ) - ret.__tokdict = dict(self.__tokdict.items()) - ret.__parent = self.__parent - ret.__accumNames.update( self.__accumNames ) - ret.__name = self.__name - return ret - - def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ): - """ - (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names. - """ - nl = "\n" - out = [] - namedItems = dict((v[1],k) for (k,vlist) in self.__tokdict.items() - for v in vlist) - nextLevelIndent = indent + " " - - # collapse out indents if formatting is not desired - if not formatted: - indent = "" - nextLevelIndent = "" - nl = "" - - selfTag = None - if doctag is not None: - selfTag = doctag - else: - if self.__name: - selfTag = self.__name - - if not selfTag: - if namedItemsOnly: - return "" - else: - selfTag = "ITEM" - - out += [ nl, indent, "<", selfTag, ">" ] - - for i,res in enumerate(self.__toklist): - if isinstance(res,ParseResults): - if i in namedItems: - out += [ res.asXML(namedItems[i], - namedItemsOnly and doctag is None, - nextLevelIndent, - formatted)] - else: - out += [ res.asXML(None, - namedItemsOnly and doctag is None, - nextLevelIndent, - formatted)] - else: - # individual token, see if there is a name for it - resTag = None - if i in namedItems: - resTag = namedItems[i] - if not resTag: - if namedItemsOnly: - continue - else: - resTag = "ITEM" - xmlBodyText = _xml_escape(_ustr(res)) - out += [ nl, nextLevelIndent, "<", resTag, ">", - xmlBodyText, - "</", resTag, ">" ] - - out += [ nl, indent, "</", selfTag, ">" ] - return "".join(out) - - def __lookup(self,sub): - for k,vlist in self.__tokdict.items(): - for v,loc in vlist: - if sub is v: - return k - return None - - def getName(self): - r""" - Returns the results name for this token expression. Useful when several - different expressions might match at a particular location. - - Example:: - - integer = Word(nums) - ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d") - house_number_expr = Suppress('#') + Word(nums, alphanums) - user_data = (Group(house_number_expr)("house_number") - | Group(ssn_expr)("ssn") - | Group(integer)("age")) - user_info = OneOrMore(user_data) - - result = user_info.parseString("22 111-22-3333 #221B") - for item in result: - print(item.getName(), ':', item[0]) - - prints:: - - age : 22 - ssn : 111-22-3333 - house_number : 221B - """ - if self.__name: - return self.__name - elif self.__parent: - par = self.__parent() - if par: - return par.__lookup(self) - else: - return None - elif (len(self) == 1 and - len(self.__tokdict) == 1 and - next(iter(self.__tokdict.values()))[0][1] in (0,-1)): - return next(iter(self.__tokdict.keys())) - else: - return None - - def dump(self, indent='', depth=0, full=True): - """ - Diagnostic method for listing out the contents of - a :class:`ParseResults`. Accepts an optional ``indent`` argument so - that this string can be embedded in a nested display of other data. - - Example:: - - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - result = date_str.parseString('12/31/1999') - print(result.dump()) - - prints:: - - ['12', '/', '31', '/', '1999'] - - day: 1999 - - month: 31 - - year: 12 - """ - out = [] - NL = '\n' - out.append( indent+_ustr(self.asList()) ) - if full: - if self.haskeys(): - items = sorted((str(k), v) for k,v in self.items()) - for k,v in items: - if out: - out.append(NL) - out.append( "%s%s- %s: " % (indent,(' '*depth), k) ) - if isinstance(v,ParseResults): - if v: - out.append( v.dump(indent,depth+1) ) - else: - out.append(_ustr(v)) - else: - out.append(repr(v)) - elif any(isinstance(vv,ParseResults) for vv in self): - v = self - for i,vv in enumerate(v): - if isinstance(vv,ParseResults): - out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),vv.dump(indent,depth+1) )) - else: - out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),_ustr(vv))) - - return "".join(out) - - def pprint(self, *args, **kwargs): - """ - Pretty-printer for parsed results as a list, using the - `pprint <https://docs.python.org/3/library/pprint.html>`_ module. - Accepts additional positional or keyword args as defined for - `pprint.pprint <https://docs.python.org/3/library/pprint.html#pprint.pprint>`_ . - - Example:: - - ident = Word(alphas, alphanums) - num = Word(nums) - func = Forward() - term = ident | num | Group('(' + func + ')') - func <<= ident + Group(Optional(delimitedList(term))) - result = func.parseString("fna a,b,(fnb c,d,200),100") - result.pprint(width=40) - - prints:: - - ['fna', - ['a', - 'b', - ['(', 'fnb', ['c', 'd', '200'], ')'], - '100']] - """ - pprint.pprint(self.asList(), *args, **kwargs) - - # add support for pickle protocol - def __getstate__(self): - return ( self.__toklist, - ( self.__tokdict.copy(), - self.__parent is not None and self.__parent() or None, - self.__accumNames, - self.__name ) ) - - def __setstate__(self,state): - self.__toklist = state[0] - (self.__tokdict, - par, - inAccumNames, - self.__name) = state[1] - self.__accumNames = {} - self.__accumNames.update(inAccumNames) - if par is not None: - self.__parent = wkref(par) - else: - self.__parent = None - - def __getnewargs__(self): - return self.__toklist, self.__name, self.__asList, self.__modal - - def __dir__(self): - return (dir(type(self)) + list(self.keys())) - -MutableMapping.register(ParseResults) - -def col (loc,strg): - """Returns current column within a string, counting newlines as line separators. - The first column is number 1. - - Note: the default parsing behavior is to expand tabs in the input string - before starting the parsing process. See - :class:`ParserElement.parseString` for more - information on parsing strings containing ``<TAB>`` s, and suggested - methods to maintain a consistent view of the parsed string, the parse - location, and line and column positions within the parsed string. - """ - s = strg - return 1 if 0<loc<len(s) and s[loc-1] == '\n' else loc - s.rfind("\n", 0, loc) - -def lineno(loc,strg): - """Returns current line number within a string, counting newlines as line separators. - The first line is number 1. - - Note - the default parsing behavior is to expand tabs in the input string - before starting the parsing process. See :class:`ParserElement.parseString` - for more information on parsing strings containing ``<TAB>`` s, and - suggested methods to maintain a consistent view of the parsed string, the - parse location, and line and column positions within the parsed string. - """ - return strg.count("\n",0,loc) + 1 - -def line( loc, strg ): - """Returns the line of text containing loc within a string, counting newlines as line separators. - """ - lastCR = strg.rfind("\n", 0, loc) - nextCR = strg.find("\n", loc) - if nextCR >= 0: - return strg[lastCR+1:nextCR] - else: - return strg[lastCR+1:] - -def _defaultStartDebugAction( instring, loc, expr ): - print (("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ))) - -def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ): - print ("Matched " + _ustr(expr) + " -> " + str(toks.asList())) - -def _defaultExceptionDebugAction( instring, loc, expr, exc ): - print ("Exception raised:" + _ustr(exc)) - -def nullDebugAction(*args): - """'Do-nothing' debug action, to suppress debugging output during parsing.""" - pass - -# Only works on Python 3.x - nonlocal is toxic to Python 2 installs -#~ 'decorator to trim function calls to match the arity of the target' -#~ def _trim_arity(func, maxargs=3): - #~ if func in singleArgBuiltins: - #~ return lambda s,l,t: func(t) - #~ limit = 0 - #~ foundArity = False - #~ def wrapper(*args): - #~ nonlocal limit,foundArity - #~ while 1: - #~ try: - #~ ret = func(*args[limit:]) - #~ foundArity = True - #~ return ret - #~ except TypeError: - #~ if limit == maxargs or foundArity: - #~ raise - #~ limit += 1 - #~ continue - #~ return wrapper - -# this version is Python 2.x-3.x cross-compatible -'decorator to trim function calls to match the arity of the target' -def _trim_arity(func, maxargs=2): - if func in singleArgBuiltins: - return lambda s,l,t: func(t) - limit = [0] - foundArity = [False] - - # traceback return data structure changed in Py3.5 - normalize back to plain tuples - if system_version[:2] >= (3,5): - def extract_stack(limit=0): - # special handling for Python 3.5.0 - extra deep call stack by 1 - offset = -3 if system_version == (3,5,0) else -2 - frame_summary = traceback.extract_stack(limit=-offset+limit-1)[offset] - return [frame_summary[:2]] - def extract_tb(tb, limit=0): - frames = traceback.extract_tb(tb, limit=limit) - frame_summary = frames[-1] - return [frame_summary[:2]] - else: - extract_stack = traceback.extract_stack - extract_tb = traceback.extract_tb - - # synthesize what would be returned by traceback.extract_stack at the call to - # user's parse action 'func', so that we don't incur call penalty at parse time - - LINE_DIFF = 6 - # IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND - # THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!! - this_line = extract_stack(limit=2)[-1] - pa_call_line_synth = (this_line[0], this_line[1]+LINE_DIFF) - - def wrapper(*args): - while 1: - try: - ret = func(*args[limit[0]:]) - foundArity[0] = True - return ret - except TypeError: - # re-raise TypeErrors if they did not come from our arity testing - if foundArity[0]: - raise - else: - try: - tb = sys.exc_info()[-1] - if not extract_tb(tb, limit=2)[-1][:2] == pa_call_line_synth: - raise - finally: - del tb - - if limit[0] <= maxargs: - limit[0] += 1 - continue - raise - - # copy func name to wrapper for sensible debug output - func_name = "<parse action>" - try: - func_name = getattr(func, '__name__', - getattr(func, '__class__').__name__) - except Exception: - func_name = str(func) - wrapper.__name__ = func_name - - return wrapper - -class ParserElement(object): - """Abstract base level parser element class.""" - DEFAULT_WHITE_CHARS = " \n\t\r" - verbose_stacktrace = False - - @staticmethod - def setDefaultWhitespaceChars( chars ): - r""" - Overrides the default whitespace chars - - Example:: - - # default whitespace chars are space, <TAB> and newline - OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def', 'ghi', 'jkl'] - - # change to just treat newline as significant - ParserElement.setDefaultWhitespaceChars(" \t") - OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def'] - """ - ParserElement.DEFAULT_WHITE_CHARS = chars - - @staticmethod - def inlineLiteralsUsing(cls): - """ - Set class to be used for inclusion of string literals into a parser. - - Example:: - - # default literal class used is Literal - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] - - - # change to Suppress - ParserElement.inlineLiteralsUsing(Suppress) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - date_str.parseString("1999/12/31") # -> ['1999', '12', '31'] - """ - ParserElement._literalStringClass = cls - - def __init__( self, savelist=False ): - self.parseAction = list() - self.failAction = None - #~ self.name = "<unknown>" # don't define self.name, let subclasses try/except upcall - self.strRepr = None - self.resultsName = None - self.saveAsList = savelist - self.skipWhitespace = True - self.whiteChars = set(ParserElement.DEFAULT_WHITE_CHARS) - self.copyDefaultWhiteChars = True - self.mayReturnEmpty = False # used when checking for left-recursion - self.keepTabs = False - self.ignoreExprs = list() - self.debug = False - self.streamlined = False - self.mayIndexError = True # used to optimize exception handling for subclasses that don't advance parse index - self.errmsg = "" - self.modalResults = True # used to mark results names as modal (report only last) or cumulative (list all) - self.debugActions = ( None, None, None ) #custom debug actions - self.re = None - self.callPreparse = True # used to avoid redundant calls to preParse - self.callDuringTry = False - - def copy( self ): - """ - Make a copy of this :class:`ParserElement`. Useful for defining - different parse actions for the same parsing pattern, using copies of - the original parse element. - - Example:: - - integer = Word(nums).setParseAction(lambda toks: int(toks[0])) - integerK = integer.copy().addParseAction(lambda toks: toks[0]*1024) + Suppress("K") - integerM = integer.copy().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") - - print(OneOrMore(integerK | integerM | integer).parseString("5K 100 640K 256M")) - - prints:: - - [5120, 100, 655360, 268435456] - - Equivalent form of ``expr.copy()`` is just ``expr()``:: - - integerM = integer().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") - """ - cpy = copy.copy( self ) - cpy.parseAction = self.parseAction[:] - cpy.ignoreExprs = self.ignoreExprs[:] - if self.copyDefaultWhiteChars: - cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS - return cpy - - def setName( self, name ): - """ - Define name for this expression, makes debugging and exception messages clearer. - - Example:: - - Word(nums).parseString("ABC") # -> Exception: Expected W:(0123...) (at char 0), (line:1, col:1) - Word(nums).setName("integer").parseString("ABC") # -> Exception: Expected integer (at char 0), (line:1, col:1) - """ - self.name = name - self.errmsg = "Expected " + self.name - if hasattr(self,"exception"): - self.exception.msg = self.errmsg - return self - - def setResultsName( self, name, listAllMatches=False ): - """ - Define name for referencing matching tokens as a nested attribute - of the returned parse results. - NOTE: this returns a *copy* of the original :class:`ParserElement` object; - this is so that the client can define a basic element, such as an - integer, and reference it in multiple places with different names. - - You can also set results names using the abbreviated syntax, - ``expr("name")`` in place of ``expr.setResultsName("name")`` - - see :class:`__call__`. - - Example:: - - date_str = (integer.setResultsName("year") + '/' - + integer.setResultsName("month") + '/' - + integer.setResultsName("day")) - - # equivalent form: - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - """ - newself = self.copy() - if name.endswith("*"): - name = name[:-1] - listAllMatches=True - newself.resultsName = name - newself.modalResults = not listAllMatches - return newself - - def setBreak(self,breakFlag = True): - """Method to invoke the Python pdb debugger when this element is - about to be parsed. Set ``breakFlag`` to True to enable, False to - disable. - """ - if breakFlag: - _parseMethod = self._parse - def breaker(instring, loc, doActions=True, callPreParse=True): - import pdb - pdb.set_trace() - return _parseMethod( instring, loc, doActions, callPreParse ) - breaker._originalParseMethod = _parseMethod - self._parse = breaker - else: - if hasattr(self._parse,"_originalParseMethod"): - self._parse = self._parse._originalParseMethod - return self - - def setParseAction( self, *fns, **kwargs ): - """ - Define one or more actions to perform when successfully matching parse element definition. - Parse action fn is a callable method with 0-3 arguments, called as ``fn(s,loc,toks)`` , - ``fn(loc,toks)`` , ``fn(toks)`` , or just ``fn()`` , where: - - - s = the original string being parsed (see note below) - - loc = the location of the matching substring - - toks = a list of the matched tokens, packaged as a :class:`ParseResults` object - - If the functions in fns modify the tokens, they can return them as the return - value from fn, and the modified list of tokens will replace the original. - Otherwise, fn does not need to return any value. - - Optional keyword arguments: - - callDuringTry = (default= ``False`` ) indicate if parse action should be run during lookaheads and alternate testing - - Note: the default parsing behavior is to expand tabs in the input string - before starting the parsing process. See :class:`parseString for more - information on parsing strings containing ``<TAB>`` s, and suggested - methods to maintain a consistent view of the parsed string, the parse - location, and line and column positions within the parsed string. - - Example:: - - integer = Word(nums) - date_str = integer + '/' + integer + '/' + integer - - date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] - - # use parse action to convert to ints at parse time - integer = Word(nums).setParseAction(lambda toks: int(toks[0])) - date_str = integer + '/' + integer + '/' + integer - - # note that integer fields are now ints, not strings - date_str.parseString("1999/12/31") # -> [1999, '/', 12, '/', 31] - """ - self.parseAction = list(map(_trim_arity, list(fns))) - self.callDuringTry = kwargs.get("callDuringTry", False) - return self - - def addParseAction( self, *fns, **kwargs ): - """ - Add one or more parse actions to expression's list of parse actions. See :class:`setParseAction`. - - See examples in :class:`copy`. - """ - self.parseAction += list(map(_trim_arity, list(fns))) - self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) - return self - - def addCondition(self, *fns, **kwargs): - """Add a boolean predicate function to expression's list of parse actions. See - :class:`setParseAction` for function call signatures. Unlike ``setParseAction``, - functions passed to ``addCondition`` need to return boolean success/fail of the condition. - - Optional keyword arguments: - - message = define a custom message to be used in the raised exception - - fatal = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException - - Example:: - - integer = Word(nums).setParseAction(lambda toks: int(toks[0])) - year_int = integer.copy() - year_int.addCondition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later") - date_str = year_int + '/' + integer + '/' + integer - - result = date_str.parseString("1999/12/31") # -> Exception: Only support years 2000 and later (at char 0), (line:1, col:1) - """ - msg = kwargs.get("message", "failed user-defined condition") - exc_type = ParseFatalException if kwargs.get("fatal", False) else ParseException - for fn in fns: - fn = _trim_arity(fn) - def pa(s,l,t): - if not bool(fn(s,l,t)): - raise exc_type(s,l,msg) - self.parseAction.append(pa) - self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) - return self - - def setFailAction( self, fn ): - """Define action to perform if parsing fails at this expression. - Fail acton fn is a callable function that takes the arguments - ``fn(s,loc,expr,err)`` where: - - s = string being parsed - - loc = location where expression match was attempted and failed - - expr = the parse expression that failed - - err = the exception thrown - The function returns no value. It may throw :class:`ParseFatalException` - if it is desired to stop parsing immediately.""" - self.failAction = fn - return self - - def _skipIgnorables( self, instring, loc ): - exprsFound = True - while exprsFound: - exprsFound = False - for e in self.ignoreExprs: - try: - while 1: - loc,dummy = e._parse( instring, loc ) - exprsFound = True - except ParseException: - pass - return loc - - def preParse( self, instring, loc ): - if self.ignoreExprs: - loc = self._skipIgnorables( instring, loc ) - - if self.skipWhitespace: - wt = self.whiteChars - instrlen = len(instring) - while loc < instrlen and instring[loc] in wt: - loc += 1 - - return loc - - def parseImpl( self, instring, loc, doActions=True ): - return loc, [] - - def postParse( self, instring, loc, tokenlist ): - return tokenlist - - #~ @profile - def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ): - debugging = ( self.debug ) #and doActions ) - - if debugging or self.failAction: - #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )) - if (self.debugActions[0] ): - self.debugActions[0]( instring, loc, self ) - if callPreParse and self.callPreparse: - preloc = self.preParse( instring, loc ) - else: - preloc = loc - tokensStart = preloc - try: - try: - loc,tokens = self.parseImpl( instring, preloc, doActions ) - except IndexError: - raise ParseException( instring, len(instring), self.errmsg, self ) - except ParseBaseException as err: - #~ print ("Exception raised:", err) - if self.debugActions[2]: - self.debugActions[2]( instring, tokensStart, self, err ) - if self.failAction: - self.failAction( instring, tokensStart, self, err ) - raise - else: - if callPreParse and self.callPreparse: - preloc = self.preParse( instring, loc ) - else: - preloc = loc - tokensStart = preloc - if self.mayIndexError or preloc >= len(instring): - try: - loc,tokens = self.parseImpl( instring, preloc, doActions ) - except IndexError: - raise ParseException( instring, len(instring), self.errmsg, self ) - else: - loc,tokens = self.parseImpl( instring, preloc, doActions ) - - tokens = self.postParse( instring, loc, tokens ) - - retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults ) - if self.parseAction and (doActions or self.callDuringTry): - if debugging: - try: - for fn in self.parseAction: - try: - tokens = fn( instring, tokensStart, retTokens ) - except IndexError as parse_action_exc: - exc = ParseException("exception raised in parse action") - exc.__cause__ = parse_action_exc - raise exc - - if tokens is not None and tokens is not retTokens: - retTokens = ParseResults( tokens, - self.resultsName, - asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), - modal=self.modalResults ) - except ParseBaseException as err: - #~ print "Exception raised in user parse action:", err - if (self.debugActions[2] ): - self.debugActions[2]( instring, tokensStart, self, err ) - raise - else: - for fn in self.parseAction: - try: - tokens = fn( instring, tokensStart, retTokens ) - except IndexError as parse_action_exc: - exc = ParseException("exception raised in parse action") - exc.__cause__ = parse_action_exc - raise exc - - if tokens is not None and tokens is not retTokens: - retTokens = ParseResults( tokens, - self.resultsName, - asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), - modal=self.modalResults ) - if debugging: - #~ print ("Matched",self,"->",retTokens.asList()) - if (self.debugActions[1] ): - self.debugActions[1]( instring, tokensStart, loc, self, retTokens ) - - return loc, retTokens - - def tryParse( self, instring, loc ): - try: - return self._parse( instring, loc, doActions=False )[0] - except ParseFatalException: - raise ParseException( instring, loc, self.errmsg, self) - - def canParseNext(self, instring, loc): - try: - self.tryParse(instring, loc) - except (ParseException, IndexError): - return False - else: - return True - - class _UnboundedCache(object): - def __init__(self): - cache = {} - self.not_in_cache = not_in_cache = object() - - def get(self, key): - return cache.get(key, not_in_cache) - - def set(self, key, value): - cache[key] = value - - def clear(self): - cache.clear() - - def cache_len(self): - return len(cache) - - self.get = types.MethodType(get, self) - self.set = types.MethodType(set, self) - self.clear = types.MethodType(clear, self) - self.__len__ = types.MethodType(cache_len, self) - - if _OrderedDict is not None: - class _FifoCache(object): - def __init__(self, size): - self.not_in_cache = not_in_cache = object() - - cache = _OrderedDict() - - def get(self, key): - return cache.get(key, not_in_cache) - - def set(self, key, value): - cache[key] = value - while len(cache) > size: - try: - cache.popitem(False) - except KeyError: - pass - - def clear(self): - cache.clear() - - def cache_len(self): - return len(cache) - - self.get = types.MethodType(get, self) - self.set = types.MethodType(set, self) - self.clear = types.MethodType(clear, self) - self.__len__ = types.MethodType(cache_len, self) - - else: - class _FifoCache(object): - def __init__(self, size): - self.not_in_cache = not_in_cache = object() - - cache = {} - key_fifo = collections.deque([], size) - - def get(self, key): - return cache.get(key, not_in_cache) - - def set(self, key, value): - cache[key] = value - while len(key_fifo) > size: - cache.pop(key_fifo.popleft(), None) - key_fifo.append(key) - - def clear(self): - cache.clear() - key_fifo.clear() - - def cache_len(self): - return len(cache) - - self.get = types.MethodType(get, self) - self.set = types.MethodType(set, self) - self.clear = types.MethodType(clear, self) - self.__len__ = types.MethodType(cache_len, self) - - # argument cache for optimizing repeated calls when backtracking through recursive expressions - packrat_cache = {} # this is set later by enabledPackrat(); this is here so that resetCache() doesn't fail - packrat_cache_lock = RLock() - packrat_cache_stats = [0, 0] - - # this method gets repeatedly called during backtracking with the same arguments - - # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression - def _parseCache( self, instring, loc, doActions=True, callPreParse=True ): - HIT, MISS = 0, 1 - lookup = (self, instring, loc, callPreParse, doActions) - with ParserElement.packrat_cache_lock: - cache = ParserElement.packrat_cache - value = cache.get(lookup) - if value is cache.not_in_cache: - ParserElement.packrat_cache_stats[MISS] += 1 - try: - value = self._parseNoCache(instring, loc, doActions, callPreParse) - except ParseBaseException as pe: - # cache a copy of the exception, without the traceback - cache.set(lookup, pe.__class__(*pe.args)) - raise - else: - cache.set(lookup, (value[0], value[1].copy())) - return value - else: - ParserElement.packrat_cache_stats[HIT] += 1 - if isinstance(value, Exception): - raise value - return (value[0], value[1].copy()) - - _parse = _parseNoCache - - @staticmethod - def resetCache(): - ParserElement.packrat_cache.clear() - ParserElement.packrat_cache_stats[:] = [0] * len(ParserElement.packrat_cache_stats) - - _packratEnabled = False - @staticmethod - def enablePackrat(cache_size_limit=128): - """Enables "packrat" parsing, which adds memoizing to the parsing logic. - Repeated parse attempts at the same string location (which happens - often in many complex grammars) can immediately return a cached value, - instead of re-executing parsing/validating code. Memoizing is done of - both valid results and parsing exceptions. - - Parameters: - - - cache_size_limit - (default= ``128``) - if an integer value is provided - will limit the size of the packrat cache; if None is passed, then - the cache size will be unbounded; if 0 is passed, the cache will - be effectively disabled. - - This speedup may break existing programs that use parse actions that - have side-effects. For this reason, packrat parsing is disabled when - you first import pyparsing. To activate the packrat feature, your - program must call the class method :class:`ParserElement.enablePackrat`. - For best results, call ``enablePackrat()`` immediately after - importing pyparsing. - - Example:: - - from pip._vendor import pyparsing - pyparsing.ParserElement.enablePackrat() - """ - if not ParserElement._packratEnabled: - ParserElement._packratEnabled = True - if cache_size_limit is None: - ParserElement.packrat_cache = ParserElement._UnboundedCache() - else: - ParserElement.packrat_cache = ParserElement._FifoCache(cache_size_limit) - ParserElement._parse = ParserElement._parseCache - - def parseString( self, instring, parseAll=False ): - """ - Execute the parse expression with the given string. - This is the main interface to the client code, once the complete - expression has been built. - - If you want the grammar to require that the entire input string be - successfully parsed, then set ``parseAll`` to True (equivalent to ending - the grammar with ``StringEnd()``). - - Note: ``parseString`` implicitly calls ``expandtabs()`` on the input string, - in order to report proper column numbers in parse actions. - If the input string contains tabs and - the grammar uses parse actions that use the ``loc`` argument to index into the - string being parsed, you can ensure you have a consistent view of the input - string by: - - - calling ``parseWithTabs`` on your grammar before calling ``parseString`` - (see :class:`parseWithTabs`) - - define your parse action using the full ``(s,loc,toks)`` signature, and - reference the input string using the parse action's ``s`` argument - - explictly expand the tabs in your input string before calling - ``parseString`` - - Example:: - - Word('a').parseString('aaaaabaaa') # -> ['aaaaa'] - Word('a').parseString('aaaaabaaa', parseAll=True) # -> Exception: Expected end of text - """ - ParserElement.resetCache() - if not self.streamlined: - self.streamline() - #~ self.saveAsList = True - for e in self.ignoreExprs: - e.streamline() - if not self.keepTabs: - instring = instring.expandtabs() - try: - loc, tokens = self._parse( instring, 0 ) - if parseAll: - loc = self.preParse( instring, loc ) - se = Empty() + StringEnd() - se._parse( instring, loc ) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - else: - return tokens - - def scanString( self, instring, maxMatches=_MAX_INT, overlap=False ): - """ - Scan the input string for expression matches. Each match will return the - matching tokens, start location, and end location. May be called with optional - ``maxMatches`` argument, to clip scanning after 'n' matches are found. If - ``overlap`` is specified, then overlapping matches will be reported. - - Note that the start and end locations are reported relative to the string - being parsed. See :class:`parseString` for more information on parsing - strings with embedded tabs. - - Example:: - - source = "sldjf123lsdjjkf345sldkjf879lkjsfd987" - print(source) - for tokens,start,end in Word(alphas).scanString(source): - print(' '*start + '^'*(end-start)) - print(' '*start + tokens[0]) - - prints:: - - sldjf123lsdjjkf345sldkjf879lkjsfd987 - ^^^^^ - sldjf - ^^^^^^^ - lsdjjkf - ^^^^^^ - sldkjf - ^^^^^^ - lkjsfd - """ - if not self.streamlined: - self.streamline() - for e in self.ignoreExprs: - e.streamline() - - if not self.keepTabs: - instring = _ustr(instring).expandtabs() - instrlen = len(instring) - loc = 0 - preparseFn = self.preParse - parseFn = self._parse - ParserElement.resetCache() - matches = 0 - try: - while loc <= instrlen and matches < maxMatches: - try: - preloc = preparseFn( instring, loc ) - nextLoc,tokens = parseFn( instring, preloc, callPreParse=False ) - except ParseException: - loc = preloc+1 - else: - if nextLoc > loc: - matches += 1 - yield tokens, preloc, nextLoc - if overlap: - nextloc = preparseFn( instring, loc ) - if nextloc > loc: - loc = nextLoc - else: - loc += 1 - else: - loc = nextLoc - else: - loc = preloc+1 - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - - def transformString( self, instring ): - """ - Extension to :class:`scanString`, to modify matching text with modified tokens that may - be returned from a parse action. To use ``transformString``, define a grammar and - attach a parse action to it that modifies the returned token list. - Invoking ``transformString()`` on a target string will then scan for matches, - and replace the matched text patterns according to the logic in the parse - action. ``transformString()`` returns the resulting transformed string. - - Example:: - - wd = Word(alphas) - wd.setParseAction(lambda toks: toks[0].title()) - - print(wd.transformString("now is the winter of our discontent made glorious summer by this sun of york.")) - - prints:: - - Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York. - """ - out = [] - lastE = 0 - # force preservation of <TAB>s, to minimize unwanted transformation of string, and to - # keep string locs straight between transformString and scanString - self.keepTabs = True - try: - for t,s,e in self.scanString( instring ): - out.append( instring[lastE:s] ) - if t: - if isinstance(t,ParseResults): - out += t.asList() - elif isinstance(t,list): - out += t - else: - out.append(t) - lastE = e - out.append(instring[lastE:]) - out = [o for o in out if o] - return "".join(map(_ustr,_flatten(out))) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - - def searchString( self, instring, maxMatches=_MAX_INT ): - """ - Another extension to :class:`scanString`, simplifying the access to the tokens found - to match the given parse expression. May be called with optional - ``maxMatches`` argument, to clip searching after 'n' matches are found. - - Example:: - - # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters - cap_word = Word(alphas.upper(), alphas.lower()) - - print(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity")) - - # the sum() builtin can be used to merge results into a single ParseResults object - print(sum(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity"))) - - prints:: - - [['More'], ['Iron'], ['Lead'], ['Gold'], ['I'], ['Electricity']] - ['More', 'Iron', 'Lead', 'Gold', 'I', 'Electricity'] - """ - try: - return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ]) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - - def split(self, instring, maxsplit=_MAX_INT, includeSeparators=False): - """ - Generator method to split a string using the given expression as a separator. - May be called with optional ``maxsplit`` argument, to limit the number of splits; - and the optional ``includeSeparators`` argument (default= ``False``), if the separating - matching text should be included in the split results. - - Example:: - - punc = oneOf(list(".,;:/-!?")) - print(list(punc.split("This, this?, this sentence, is badly punctuated!"))) - - prints:: - - ['This', ' this', '', ' this sentence', ' is badly punctuated', ''] - """ - splits = 0 - last = 0 - for t,s,e in self.scanString(instring, maxMatches=maxsplit): - yield instring[last:s] - if includeSeparators: - yield t[0] - last = e - yield instring[last:] - - def __add__(self, other ): - """ - Implementation of + operator - returns :class:`And`. Adding strings to a ParserElement - converts them to :class:`Literal`s by default. - - Example:: - - greet = Word(alphas) + "," + Word(alphas) + "!" - hello = "Hello, World!" - print (hello, "->", greet.parseString(hello)) - - prints:: - - Hello, World! -> ['Hello', ',', 'World', '!'] - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return And( [ self, other ] ) - - def __radd__(self, other ): - """ - Implementation of + operator when left operand is not a :class:`ParserElement` - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other + self - - def __sub__(self, other): - """ - Implementation of - operator, returns :class:`And` with error stop - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return self + And._ErrorStop() + other - - def __rsub__(self, other ): - """ - Implementation of - operator when left operand is not a :class:`ParserElement` - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other - self - - def __mul__(self,other): - """ - Implementation of * operator, allows use of ``expr * 3`` in place of - ``expr + expr + expr``. Expressions may also me multiplied by a 2-integer - tuple, similar to ``{min,max}`` multipliers in regular expressions. Tuples - may also include ``None`` as in: - - ``expr*(n,None)`` or ``expr*(n,)`` is equivalent - to ``expr*n + ZeroOrMore(expr)`` - (read as "at least n instances of ``expr``") - - ``expr*(None,n)`` is equivalent to ``expr*(0,n)`` - (read as "0 to n instances of ``expr``") - - ``expr*(None,None)`` is equivalent to ``ZeroOrMore(expr)`` - - ``expr*(1,None)`` is equivalent to ``OneOrMore(expr)`` - - Note that ``expr*(None,n)`` does not raise an exception if - more than n exprs exist in the input stream; that is, - ``expr*(None,n)`` does not enforce a maximum number of expr - occurrences. If this behavior is desired, then write - ``expr*(None,n) + ~expr`` - """ - if isinstance(other,int): - minElements, optElements = other,0 - elif isinstance(other,tuple): - other = (other + (None, None))[:2] - if other[0] is None: - other = (0, other[1]) - if isinstance(other[0],int) and other[1] is None: - if other[0] == 0: - return ZeroOrMore(self) - if other[0] == 1: - return OneOrMore(self) - else: - return self*other[0] + ZeroOrMore(self) - elif isinstance(other[0],int) and isinstance(other[1],int): - minElements, optElements = other - optElements -= minElements - else: - raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1])) - else: - raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other)) - - if minElements < 0: - raise ValueError("cannot multiply ParserElement by negative value") - if optElements < 0: - raise ValueError("second tuple value must be greater or equal to first tuple value") - if minElements == optElements == 0: - raise ValueError("cannot multiply ParserElement by 0 or (0,0)") - - if (optElements): - def makeOptionalList(n): - if n>1: - return Optional(self + makeOptionalList(n-1)) - else: - return Optional(self) - if minElements: - if minElements == 1: - ret = self + makeOptionalList(optElements) - else: - ret = And([self]*minElements) + makeOptionalList(optElements) - else: - ret = makeOptionalList(optElements) - else: - if minElements == 1: - ret = self - else: - ret = And([self]*minElements) - return ret - - def __rmul__(self, other): - return self.__mul__(other) - - def __or__(self, other ): - """ - Implementation of | operator - returns :class:`MatchFirst` - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return MatchFirst( [ self, other ] ) - - def __ror__(self, other ): - """ - Implementation of | operator when left operand is not a :class:`ParserElement` - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other | self - - def __xor__(self, other ): - """ - Implementation of ^ operator - returns :class:`Or` - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return Or( [ self, other ] ) - - def __rxor__(self, other ): - """ - Implementation of ^ operator when left operand is not a :class:`ParserElement` - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other ^ self - - def __and__(self, other ): - """ - Implementation of & operator - returns :class:`Each` - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return Each( [ self, other ] ) - - def __rand__(self, other ): - """ - Implementation of & operator when left operand is not a :class:`ParserElement` - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other & self - - def __invert__( self ): - """ - Implementation of ~ operator - returns :class:`NotAny` - """ - return NotAny( self ) - - def __call__(self, name=None): - """ - Shortcut for :class:`setResultsName`, with ``listAllMatches=False``. - - If ``name`` is given with a trailing ``'*'`` character, then ``listAllMatches`` will be - passed as ``True``. - - If ``name` is omitted, same as calling :class:`copy`. - - Example:: - - # these are equivalent - userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno") - userdata = Word(alphas)("name") + Word(nums+"-")("socsecno") - """ - if name is not None: - return self.setResultsName(name) - else: - return self.copy() - - def suppress( self ): - """ - Suppresses the output of this :class:`ParserElement`; useful to keep punctuation from - cluttering up returned output. - """ - return Suppress( self ) - - def leaveWhitespace( self ): - """ - Disables the skipping of whitespace before matching the characters in the - :class:`ParserElement`'s defined pattern. This is normally only used internally by - the pyparsing module, but may be needed in some whitespace-sensitive grammars. - """ - self.skipWhitespace = False - return self - - def setWhitespaceChars( self, chars ): - """ - Overrides the default whitespace chars - """ - self.skipWhitespace = True - self.whiteChars = chars - self.copyDefaultWhiteChars = False - return self - - def parseWithTabs( self ): - """ - Overrides default behavior to expand ``<TAB>``s to spaces before parsing the input string. - Must be called before ``parseString`` when the input grammar contains elements that - match ``<TAB>`` characters. - """ - self.keepTabs = True - return self - - def ignore( self, other ): - """ - Define expression to be ignored (e.g., comments) while doing pattern - matching; may be called repeatedly, to define multiple comment or other - ignorable patterns. - - Example:: - - patt = OneOrMore(Word(alphas)) - patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj'] - - patt.ignore(cStyleComment) - patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd'] - """ - if isinstance(other, basestring): - other = Suppress(other) - - if isinstance( other, Suppress ): - if other not in self.ignoreExprs: - self.ignoreExprs.append(other) - else: - self.ignoreExprs.append( Suppress( other.copy() ) ) - return self - - def setDebugActions( self, startAction, successAction, exceptionAction ): - """ - Enable display of debugging messages while doing pattern matching. - """ - self.debugActions = (startAction or _defaultStartDebugAction, - successAction or _defaultSuccessDebugAction, - exceptionAction or _defaultExceptionDebugAction) - self.debug = True - return self - - def setDebug( self, flag=True ): - """ - Enable display of debugging messages while doing pattern matching. - Set ``flag`` to True to enable, False to disable. - - Example:: - - wd = Word(alphas).setName("alphaword") - integer = Word(nums).setName("numword") - term = wd | integer - - # turn on debugging for wd - wd.setDebug() - - OneOrMore(term).parseString("abc 123 xyz 890") - - prints:: - - Match alphaword at loc 0(1,1) - Matched alphaword -> ['abc'] - Match alphaword at loc 3(1,4) - Exception raised:Expected alphaword (at char 4), (line:1, col:5) - Match alphaword at loc 7(1,8) - Matched alphaword -> ['xyz'] - Match alphaword at loc 11(1,12) - Exception raised:Expected alphaword (at char 12), (line:1, col:13) - Match alphaword at loc 15(1,16) - Exception raised:Expected alphaword (at char 15), (line:1, col:16) - - The output shown is that produced by the default debug actions - custom debug actions can be - specified using :class:`setDebugActions`. Prior to attempting - to match the ``wd`` expression, the debugging message ``"Match <exprname> at loc <n>(<line>,<col>)"`` - is shown. Then if the parse succeeds, a ``"Matched"`` message is shown, or an ``"Exception raised"`` - message is shown. Also note the use of :class:`setName` to assign a human-readable name to the expression, - which makes debugging and exception messages easier to understand - for instance, the default - name created for the :class:`Word` expression without calling ``setName`` is ``"W:(ABCD...)"``. - """ - if flag: - self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction ) - else: - self.debug = False - return self - - def __str__( self ): - return self.name - - def __repr__( self ): - return _ustr(self) - - def streamline( self ): - self.streamlined = True - self.strRepr = None - return self - - def checkRecursion( self, parseElementList ): - pass - - def validate( self, validateTrace=[] ): - """ - Check defined expressions for valid structure, check for infinite recursive definitions. - """ - self.checkRecursion( [] ) - - def parseFile( self, file_or_filename, parseAll=False ): - """ - Execute the parse expression on the given file or filename. - If a filename is specified (instead of a file object), - the entire file is opened, read, and closed before parsing. - """ - try: - file_contents = file_or_filename.read() - except AttributeError: - with open(file_or_filename, "r") as f: - file_contents = f.read() - try: - return self.parseString(file_contents, parseAll) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - - def __eq__(self,other): - if isinstance(other, ParserElement): - return self is other or vars(self) == vars(other) - elif isinstance(other, basestring): - return self.matches(other) - else: - return super(ParserElement,self)==other - - def __ne__(self,other): - return not (self == other) - - def __hash__(self): - return hash(id(self)) - - def __req__(self,other): - return self == other - - def __rne__(self,other): - return not (self == other) - - def matches(self, testString, parseAll=True): - """ - Method for quick testing of a parser against a test string. Good for simple - inline microtests of sub expressions while building up larger parser. - - Parameters: - - testString - to test against this expression for a match - - parseAll - (default= ``True``) - flag to pass to :class:`parseString` when running tests - - Example:: - - expr = Word(nums) - assert expr.matches("100") - """ - try: - self.parseString(_ustr(testString), parseAll=parseAll) - return True - except ParseBaseException: - return False - - def runTests(self, tests, parseAll=True, comment='#', - fullDump=True, printResults=True, failureTests=False, postParse=None): - """ - Execute the parse expression on a series of test strings, showing each - test, the parsed results or where the parse failed. Quick and easy way to - run a parse expression against a list of sample strings. - - Parameters: - - tests - a list of separate test strings, or a multiline string of test strings - - parseAll - (default= ``True``) - flag to pass to :class:`parseString` when running tests - - comment - (default= ``'#'``) - expression for indicating embedded comments in the test - string; pass None to disable comment filtering - - fullDump - (default= ``True``) - dump results as list followed by results names in nested outline; - if False, only dump nested list - - printResults - (default= ``True``) prints test output to stdout - - failureTests - (default= ``False``) indicates if these tests are expected to fail parsing - - postParse - (default= ``None``) optional callback for successful parse results; called as - `fn(test_string, parse_results)` and returns a string to be added to the test output - - Returns: a (success, results) tuple, where success indicates that all tests succeeded - (or failed if ``failureTests`` is True), and the results contain a list of lines of each - test's output - - Example:: - - number_expr = pyparsing_common.number.copy() - - result = number_expr.runTests(''' - # unsigned integer - 100 - # negative integer - -100 - # float with scientific notation - 6.02e23 - # integer with scientific notation - 1e-12 - ''') - print("Success" if result[0] else "Failed!") - - result = number_expr.runTests(''' - # stray character - 100Z - # missing leading digit before '.' - -.100 - # too many '.' - 3.14.159 - ''', failureTests=True) - print("Success" if result[0] else "Failed!") - - prints:: - - # unsigned integer - 100 - [100] - - # negative integer - -100 - [-100] - - # float with scientific notation - 6.02e23 - [6.02e+23] - - # integer with scientific notation - 1e-12 - [1e-12] - - Success - - # stray character - 100Z - ^ - FAIL: Expected end of text (at char 3), (line:1, col:4) - - # missing leading digit before '.' - -.100 - ^ - FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1) - - # too many '.' - 3.14.159 - ^ - FAIL: Expected end of text (at char 4), (line:1, col:5) - - Success - - Each test string must be on a single line. If you want to test a string that spans multiple - lines, create a test like this:: - - expr.runTest(r"this is a test\\n of strings that spans \\n 3 lines") - - (Note that this is a raw string literal, you must include the leading 'r'.) - """ - if isinstance(tests, basestring): - tests = list(map(str.strip, tests.rstrip().splitlines())) - if isinstance(comment, basestring): - comment = Literal(comment) - allResults = [] - comments = [] - success = True - for t in tests: - if comment is not None and comment.matches(t, False) or comments and not t: - comments.append(t) - continue - if not t: - continue - out = ['\n'.join(comments), t] - comments = [] - try: - # convert newline marks to actual newlines, and strip leading BOM if present - NL = Literal(r'\n').addParseAction(replaceWith('\n')).ignore(quotedString) - BOM = '\ufeff' - t = NL.transformString(t.lstrip(BOM)) - result = self.parseString(t, parseAll=parseAll) - out.append(result.dump(full=fullDump)) - success = success and not failureTests - if postParse is not None: - try: - pp_value = postParse(t, result) - if pp_value is not None: - out.append(str(pp_value)) - except Exception as e: - out.append("{0} failed: {1}: {2}".format(postParse.__name__, type(e).__name__, e)) - except ParseBaseException as pe: - fatal = "(FATAL)" if isinstance(pe, ParseFatalException) else "" - if '\n' in t: - out.append(line(pe.loc, t)) - out.append(' '*(col(pe.loc,t)-1) + '^' + fatal) - else: - out.append(' '*pe.loc + '^' + fatal) - out.append("FAIL: " + str(pe)) - success = success and failureTests - result = pe - except Exception as exc: - out.append("FAIL-EXCEPTION: " + str(exc)) - success = success and failureTests - result = exc - - if printResults: - if fullDump: - out.append('') - print('\n'.join(out)) - - allResults.append((t, result)) - - return success, allResults - - -class Token(ParserElement): - """Abstract :class:`ParserElement` subclass, for defining atomic - matching patterns. - """ - def __init__( self ): - super(Token,self).__init__( savelist=False ) - - -class Empty(Token): - """An empty token, will always match. - """ - def __init__( self ): - super(Empty,self).__init__() - self.name = "Empty" - self.mayReturnEmpty = True - self.mayIndexError = False - - -class NoMatch(Token): - """A token that will never match. - """ - def __init__( self ): - super(NoMatch,self).__init__() - self.name = "NoMatch" - self.mayReturnEmpty = True - self.mayIndexError = False - self.errmsg = "Unmatchable token" - - def parseImpl( self, instring, loc, doActions=True ): - raise ParseException(instring, loc, self.errmsg, self) - - -class Literal(Token): - """Token to exactly match a specified string. - - Example:: - - Literal('blah').parseString('blah') # -> ['blah'] - Literal('blah').parseString('blahfooblah') # -> ['blah'] - Literal('blah').parseString('bla') # -> Exception: Expected "blah" - - For case-insensitive matching, use :class:`CaselessLiteral`. - - For keyword matching (force word break before and after the matched string), - use :class:`Keyword` or :class:`CaselessKeyword`. - """ - def __init__( self, matchString ): - super(Literal,self).__init__() - self.match = matchString - self.matchLen = len(matchString) - try: - self.firstMatchChar = matchString[0] - except IndexError: - warnings.warn("null string passed to Literal; use Empty() instead", - SyntaxWarning, stacklevel=2) - self.__class__ = Empty - self.name = '"%s"' % _ustr(self.match) - self.errmsg = "Expected " + self.name - self.mayReturnEmpty = False - self.mayIndexError = False - - # Performance tuning: this routine gets called a *lot* - # if this is a single character match string and the first character matches, - # short-circuit as quickly as possible, and avoid calling startswith - #~ @profile - def parseImpl( self, instring, loc, doActions=True ): - if (instring[loc] == self.firstMatchChar and - (self.matchLen==1 or instring.startswith(self.match,loc)) ): - return loc+self.matchLen, self.match - raise ParseException(instring, loc, self.errmsg, self) -_L = Literal -ParserElement._literalStringClass = Literal - -class Keyword(Token): - """Token to exactly match a specified string as a keyword, that is, - it must be immediately followed by a non-keyword character. Compare - with :class:`Literal`: - - - ``Literal("if")`` will match the leading ``'if'`` in - ``'ifAndOnlyIf'``. - - ``Keyword("if")`` will not; it will only match the leading - ``'if'`` in ``'if x=1'``, or ``'if(y==2)'`` - - Accepts two optional constructor arguments in addition to the - keyword string: - - - ``identChars`` is a string of characters that would be valid - identifier characters, defaulting to all alphanumerics + "_" and - "$" - - ``caseless`` allows case-insensitive matching, default is ``False``. - - Example:: - - Keyword("start").parseString("start") # -> ['start'] - Keyword("start").parseString("starting") # -> Exception - - For case-insensitive matching, use :class:`CaselessKeyword`. - """ - DEFAULT_KEYWORD_CHARS = alphanums+"_$" - - def __init__( self, matchString, identChars=None, caseless=False ): - super(Keyword,self).__init__() - if identChars is None: - identChars = Keyword.DEFAULT_KEYWORD_CHARS - self.match = matchString - self.matchLen = len(matchString) - try: - self.firstMatchChar = matchString[0] - except IndexError: - warnings.warn("null string passed to Keyword; use Empty() instead", - SyntaxWarning, stacklevel=2) - self.name = '"%s"' % self.match - self.errmsg = "Expected " + self.name - self.mayReturnEmpty = False - self.mayIndexError = False - self.caseless = caseless - if caseless: - self.caselessmatch = matchString.upper() - identChars = identChars.upper() - self.identChars = set(identChars) - - def parseImpl( self, instring, loc, doActions=True ): - if self.caseless: - if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and - (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and - (loc == 0 or instring[loc-1].upper() not in self.identChars) ): - return loc+self.matchLen, self.match - else: - if (instring[loc] == self.firstMatchChar and - (self.matchLen==1 or instring.startswith(self.match,loc)) and - (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and - (loc == 0 or instring[loc-1] not in self.identChars) ): - return loc+self.matchLen, self.match - raise ParseException(instring, loc, self.errmsg, self) - - def copy(self): - c = super(Keyword,self).copy() - c.identChars = Keyword.DEFAULT_KEYWORD_CHARS - return c - - @staticmethod - def setDefaultKeywordChars( chars ): - """Overrides the default Keyword chars - """ - Keyword.DEFAULT_KEYWORD_CHARS = chars - -class CaselessLiteral(Literal): - """Token to match a specified string, ignoring case of letters. - Note: the matched results will always be in the case of the given - match string, NOT the case of the input text. - - Example:: - - OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD'] - - (Contrast with example for :class:`CaselessKeyword`.) - """ - def __init__( self, matchString ): - super(CaselessLiteral,self).__init__( matchString.upper() ) - # Preserve the defining literal. - self.returnString = matchString - self.name = "'%s'" % self.returnString - self.errmsg = "Expected " + self.name - - def parseImpl( self, instring, loc, doActions=True ): - if instring[ loc:loc+self.matchLen ].upper() == self.match: - return loc+self.matchLen, self.returnString - raise ParseException(instring, loc, self.errmsg, self) - -class CaselessKeyword(Keyword): - """ - Caseless version of :class:`Keyword`. - - Example:: - - OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD'] - - (Contrast with example for :class:`CaselessLiteral`.) - """ - def __init__( self, matchString, identChars=None ): - super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True ) - -class CloseMatch(Token): - """A variation on :class:`Literal` which matches "close" matches, - that is, strings with at most 'n' mismatching characters. - :class:`CloseMatch` takes parameters: - - - ``match_string`` - string to be matched - - ``maxMismatches`` - (``default=1``) maximum number of - mismatches allowed to count as a match - - The results from a successful parse will contain the matched text - from the input string and the following named results: - - - ``mismatches`` - a list of the positions within the - match_string where mismatches were found - - ``original`` - the original match_string used to compare - against the input string - - If ``mismatches`` is an empty list, then the match was an exact - match. - - Example:: - - patt = CloseMatch("ATCATCGAATGGA") - patt.parseString("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']}) - patt.parseString("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1) - - # exact match - patt.parseString("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']}) - - # close match allowing up to 2 mismatches - patt = CloseMatch("ATCATCGAATGGA", maxMismatches=2) - patt.parseString("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']}) - """ - def __init__(self, match_string, maxMismatches=1): - super(CloseMatch,self).__init__() - self.name = match_string - self.match_string = match_string - self.maxMismatches = maxMismatches - self.errmsg = "Expected %r (with up to %d mismatches)" % (self.match_string, self.maxMismatches) - self.mayIndexError = False - self.mayReturnEmpty = False - - def parseImpl( self, instring, loc, doActions=True ): - start = loc - instrlen = len(instring) - maxloc = start + len(self.match_string) - - if maxloc <= instrlen: - match_string = self.match_string - match_stringloc = 0 - mismatches = [] - maxMismatches = self.maxMismatches - - for match_stringloc,s_m in enumerate(zip(instring[loc:maxloc], self.match_string)): - src,mat = s_m - if src != mat: - mismatches.append(match_stringloc) - if len(mismatches) > maxMismatches: - break - else: - loc = match_stringloc + 1 - results = ParseResults([instring[start:loc]]) - results['original'] = self.match_string - results['mismatches'] = mismatches - return loc, results - - raise ParseException(instring, loc, self.errmsg, self) - - -class Word(Token): - """Token for matching words composed of allowed character sets. - Defined with string containing all allowed initial characters, an - optional string containing allowed body characters (if omitted, - defaults to the initial character set), and an optional minimum, - maximum, and/or exact length. The default value for ``min`` is - 1 (a minimum value < 1 is not valid); the default values for - ``max`` and ``exact`` are 0, meaning no maximum or exact - length restriction. An optional ``excludeChars`` parameter can - list characters that might be found in the input ``bodyChars`` - string; useful to define a word of all printables except for one or - two characters, for instance. - - :class:`srange` is useful for defining custom character set strings - for defining ``Word`` expressions, using range notation from - regular expression character sets. - - A common mistake is to use :class:`Word` to match a specific literal - string, as in ``Word("Address")``. Remember that :class:`Word` - uses the string argument to define *sets* of matchable characters. - This expression would match "Add", "AAA", "dAred", or any other word - made up of the characters 'A', 'd', 'r', 'e', and 's'. To match an - exact literal string, use :class:`Literal` or :class:`Keyword`. - - pyparsing includes helper strings for building Words: - - - :class:`alphas` - - :class:`nums` - - :class:`alphanums` - - :class:`hexnums` - - :class:`alphas8bit` (alphabetic characters in ASCII range 128-255 - - accented, tilded, umlauted, etc.) - - :class:`punc8bit` (non-alphabetic characters in ASCII range - 128-255 - currency, symbols, superscripts, diacriticals, etc.) - - :class:`printables` (any non-whitespace character) - - Example:: - - # a word composed of digits - integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9")) - - # a word with a leading capital, and zero or more lowercase - capital_word = Word(alphas.upper(), alphas.lower()) - - # hostnames are alphanumeric, with leading alpha, and '-' - hostname = Word(alphas, alphanums+'-') - - # roman numeral (not a strict parser, accepts invalid mix of characters) - roman = Word("IVXLCDM") - - # any string of non-whitespace characters, except for ',' - csv_value = Word(printables, excludeChars=",") - """ - def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0, asKeyword=False, excludeChars=None ): - super(Word,self).__init__() - if excludeChars: - excludeChars = set(excludeChars) - initChars = ''.join(c for c in initChars if c not in excludeChars) - if bodyChars: - bodyChars = ''.join(c for c in bodyChars if c not in excludeChars) - self.initCharsOrig = initChars - self.initChars = set(initChars) - if bodyChars : - self.bodyCharsOrig = bodyChars - self.bodyChars = set(bodyChars) - else: - self.bodyCharsOrig = initChars - self.bodyChars = set(initChars) - - self.maxSpecified = max > 0 - - if min < 1: - raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted") - - self.minLen = min - - if max > 0: - self.maxLen = max - else: - self.maxLen = _MAX_INT - - if exact > 0: - self.maxLen = exact - self.minLen = exact - - self.name = _ustr(self) - self.errmsg = "Expected " + self.name - self.mayIndexError = False - self.asKeyword = asKeyword - - if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0): - if self.bodyCharsOrig == self.initCharsOrig: - self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig) - elif len(self.initCharsOrig) == 1: - self.reString = "%s[%s]*" % \ - (re.escape(self.initCharsOrig), - _escapeRegexRangeChars(self.bodyCharsOrig),) - else: - self.reString = "[%s][%s]*" % \ - (_escapeRegexRangeChars(self.initCharsOrig), - _escapeRegexRangeChars(self.bodyCharsOrig),) - if self.asKeyword: - self.reString = r"\b"+self.reString+r"\b" - try: - self.re = re.compile( self.reString ) - except Exception: - self.re = None - - def parseImpl( self, instring, loc, doActions=True ): - if self.re: - result = self.re.match(instring,loc) - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - return loc, result.group() - - if instring[loc] not in self.initChars: - raise ParseException(instring, loc, self.errmsg, self) - - start = loc - loc += 1 - instrlen = len(instring) - bodychars = self.bodyChars - maxloc = start + self.maxLen - maxloc = min( maxloc, instrlen ) - while loc < maxloc and instring[loc] in bodychars: - loc += 1 - - throwException = False - if loc - start < self.minLen: - throwException = True - elif self.maxSpecified and loc < instrlen and instring[loc] in bodychars: - throwException = True - elif self.asKeyword: - if (start>0 and instring[start-1] in bodychars) or (loc<instrlen and instring[loc] in bodychars): - throwException = True - - if throwException: - raise ParseException(instring, loc, self.errmsg, self) - - return loc, instring[start:loc] - - def __str__( self ): - try: - return super(Word,self).__str__() - except Exception: - pass - - - if self.strRepr is None: - - def charsAsStr(s): - if len(s)>4: - return s[:4]+"..." - else: - return s - - if ( self.initCharsOrig != self.bodyCharsOrig ): - self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) ) - else: - self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig) - - return self.strRepr - - -class Char(Word): - """A short-cut class for defining ``Word(characters, exact=1)``, - when defining a match of any single character in a string of - characters. - """ - def __init__(self, charset, asKeyword=False, excludeChars=None): - super(Char, self).__init__(charset, exact=1, asKeyword=asKeyword, excludeChars=excludeChars) - self.reString = "[%s]" % _escapeRegexRangeChars(self.initCharsOrig) - self.re = re.compile( self.reString ) - - -class Regex(Token): - r"""Token for matching strings that match a given regular - expression. Defined with string specifying the regular expression in - a form recognized by the stdlib Python `re module <https://docs.python.org/3/library/re.html>`_. - If the given regex contains named groups (defined using ``(?P<name>...)``), - these will be preserved as named parse results. - - Example:: - - realnum = Regex(r"[+-]?\d+\.\d*") - date = Regex(r'(?P<year>\d{4})-(?P<month>\d\d?)-(?P<day>\d\d?)') - # ref: https://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression - roman = Regex(r"M{0,4}(CM|CD|D?{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})") - """ - compiledREtype = type(re.compile("[A-Z]")) - def __init__( self, pattern, flags=0, asGroupList=False, asMatch=False): - """The parameters ``pattern`` and ``flags`` are passed - to the ``re.compile()`` function as-is. See the Python - `re module <https://docs.python.org/3/library/re.html>`_ module for an - explanation of the acceptable patterns and flags. - """ - super(Regex,self).__init__() - - if isinstance(pattern, basestring): - if not pattern: - warnings.warn("null string passed to Regex; use Empty() instead", - SyntaxWarning, stacklevel=2) - - self.pattern = pattern - self.flags = flags - - try: - self.re = re.compile(self.pattern, self.flags) - self.reString = self.pattern - except sre_constants.error: - warnings.warn("invalid pattern (%s) passed to Regex" % pattern, - SyntaxWarning, stacklevel=2) - raise - - elif isinstance(pattern, Regex.compiledREtype): - self.re = pattern - self.pattern = \ - self.reString = str(pattern) - self.flags = flags - - else: - raise ValueError("Regex may only be constructed with a string or a compiled RE object") - - self.name = _ustr(self) - self.errmsg = "Expected " + self.name - self.mayIndexError = False - self.mayReturnEmpty = True - self.asGroupList = asGroupList - self.asMatch = asMatch - if self.asGroupList: - self.parseImpl = self.parseImplAsGroupList - if self.asMatch: - self.parseImpl = self.parseImplAsMatch - - def parseImpl(self, instring, loc, doActions=True): - result = self.re.match(instring,loc) - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - ret = ParseResults(result.group()) - d = result.groupdict() - if d: - for k, v in d.items(): - ret[k] = v - return loc, ret - - def parseImplAsGroupList(self, instring, loc, doActions=True): - result = self.re.match(instring,loc) - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - ret = result.groups() - return loc, ret - - def parseImplAsMatch(self, instring, loc, doActions=True): - result = self.re.match(instring,loc) - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - ret = result - return loc, ret - - def __str__( self ): - try: - return super(Regex,self).__str__() - except Exception: - pass - - if self.strRepr is None: - self.strRepr = "Re:(%s)" % repr(self.pattern) - - return self.strRepr - - def sub(self, repl): - r""" - Return Regex with an attached parse action to transform the parsed - result as if called using `re.sub(expr, repl, string) <https://docs.python.org/3/library/re.html#re.sub>`_. - - Example:: - - make_html = Regex(r"(\w+):(.*?):").sub(r"<\1>\2</\1>") - print(make_html.transformString("h1:main title:")) - # prints "<h1>main title</h1>" - """ - if self.asGroupList: - warnings.warn("cannot use sub() with Regex(asGroupList=True)", - SyntaxWarning, stacklevel=2) - raise SyntaxError() - - if self.asMatch and callable(repl): - warnings.warn("cannot use sub() with a callable with Regex(asMatch=True)", - SyntaxWarning, stacklevel=2) - raise SyntaxError() - - if self.asMatch: - def pa(tokens): - return tokens[0].expand(repl) - else: - def pa(tokens): - return self.re.sub(repl, tokens[0]) - return self.addParseAction(pa) - -class QuotedString(Token): - r""" - Token for matching strings that are delimited by quoting characters. - - Defined with the following parameters: - - - quoteChar - string of one or more characters defining the - quote delimiting string - - escChar - character to escape quotes, typically backslash - (default= ``None`` ) - - escQuote - special quote sequence to escape an embedded quote - string (such as SQL's ``""`` to escape an embedded ``"``) - (default= ``None`` ) - - multiline - boolean indicating whether quotes can span - multiple lines (default= ``False`` ) - - unquoteResults - boolean indicating whether the matched text - should be unquoted (default= ``True`` ) - - endQuoteChar - string of one or more characters defining the - end of the quote delimited string (default= ``None`` => same as - quoteChar) - - convertWhitespaceEscapes - convert escaped whitespace - (``'\t'``, ``'\n'``, etc.) to actual whitespace - (default= ``True`` ) - - Example:: - - qs = QuotedString('"') - print(qs.searchString('lsjdf "This is the quote" sldjf')) - complex_qs = QuotedString('{{', endQuoteChar='}}') - print(complex_qs.searchString('lsjdf {{This is the "quote"}} sldjf')) - sql_qs = QuotedString('"', escQuote='""') - print(sql_qs.searchString('lsjdf "This is the quote with ""embedded"" quotes" sldjf')) - - prints:: - - [['This is the quote']] - [['This is the "quote"']] - [['This is the quote with "embedded" quotes']] - """ - def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None, convertWhitespaceEscapes=True): - super(QuotedString,self).__init__() - - # remove white space from quote chars - wont work anyway - quoteChar = quoteChar.strip() - if not quoteChar: - warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) - raise SyntaxError() - - if endQuoteChar is None: - endQuoteChar = quoteChar - else: - endQuoteChar = endQuoteChar.strip() - if not endQuoteChar: - warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) - raise SyntaxError() - - self.quoteChar = quoteChar - self.quoteCharLen = len(quoteChar) - self.firstQuoteChar = quoteChar[0] - self.endQuoteChar = endQuoteChar - self.endQuoteCharLen = len(endQuoteChar) - self.escChar = escChar - self.escQuote = escQuote - self.unquoteResults = unquoteResults - self.convertWhitespaceEscapes = convertWhitespaceEscapes - - if multiline: - self.flags = re.MULTILINE | re.DOTALL - self.pattern = r'%s(?:[^%s%s]' % \ - ( re.escape(self.quoteChar), - _escapeRegexRangeChars(self.endQuoteChar[0]), - (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) - else: - self.flags = 0 - self.pattern = r'%s(?:[^%s\n\r%s]' % \ - ( re.escape(self.quoteChar), - _escapeRegexRangeChars(self.endQuoteChar[0]), - (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) - if len(self.endQuoteChar) > 1: - self.pattern += ( - '|(?:' + ')|(?:'.join("%s[^%s]" % (re.escape(self.endQuoteChar[:i]), - _escapeRegexRangeChars(self.endQuoteChar[i])) - for i in range(len(self.endQuoteChar)-1,0,-1)) + ')' - ) - if escQuote: - self.pattern += (r'|(?:%s)' % re.escape(escQuote)) - if escChar: - self.pattern += (r'|(?:%s.)' % re.escape(escChar)) - self.escCharReplacePattern = re.escape(self.escChar)+"(.)" - self.pattern += (r')*%s' % re.escape(self.endQuoteChar)) - - try: - self.re = re.compile(self.pattern, self.flags) - self.reString = self.pattern - except sre_constants.error: - warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern, - SyntaxWarning, stacklevel=2) - raise - - self.name = _ustr(self) - self.errmsg = "Expected " + self.name - self.mayIndexError = False - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - ret = result.group() - - if self.unquoteResults: - - # strip off quotes - ret = ret[self.quoteCharLen:-self.endQuoteCharLen] - - if isinstance(ret,basestring): - # replace escaped whitespace - if '\\' in ret and self.convertWhitespaceEscapes: - ws_map = { - r'\t' : '\t', - r'\n' : '\n', - r'\f' : '\f', - r'\r' : '\r', - } - for wslit,wschar in ws_map.items(): - ret = ret.replace(wslit, wschar) - - # replace escaped characters - if self.escChar: - ret = re.sub(self.escCharReplacePattern, r"\g<1>", ret) - - # replace escaped quotes - if self.escQuote: - ret = ret.replace(self.escQuote, self.endQuoteChar) - - return loc, ret - - def __str__( self ): - try: - return super(QuotedString,self).__str__() - except Exception: - pass - - if self.strRepr is None: - self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar) - - return self.strRepr - - -class CharsNotIn(Token): - """Token for matching words composed of characters *not* in a given - set (will include whitespace in matched characters if not listed in - the provided exclusion set - see example). Defined with string - containing all disallowed characters, and an optional minimum, - maximum, and/or exact length. The default value for ``min`` is - 1 (a minimum value < 1 is not valid); the default values for - ``max`` and ``exact`` are 0, meaning no maximum or exact - length restriction. - - Example:: - - # define a comma-separated-value as anything that is not a ',' - csv_value = CharsNotIn(',') - print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213")) - - prints:: - - ['dkls', 'lsdkjf', 's12 34', '@!#', '213'] - """ - def __init__( self, notChars, min=1, max=0, exact=0 ): - super(CharsNotIn,self).__init__() - self.skipWhitespace = False - self.notChars = notChars - - if min < 1: - raise ValueError( - "cannot specify a minimum length < 1; use " + - "Optional(CharsNotIn()) if zero-length char group is permitted") - - self.minLen = min - - if max > 0: - self.maxLen = max - else: - self.maxLen = _MAX_INT - - if exact > 0: - self.maxLen = exact - self.minLen = exact - - self.name = _ustr(self) - self.errmsg = "Expected " + self.name - self.mayReturnEmpty = ( self.minLen == 0 ) - self.mayIndexError = False - - def parseImpl( self, instring, loc, doActions=True ): - if instring[loc] in self.notChars: - raise ParseException(instring, loc, self.errmsg, self) - - start = loc - loc += 1 - notchars = self.notChars - maxlen = min( start+self.maxLen, len(instring) ) - while loc < maxlen and \ - (instring[loc] not in notchars): - loc += 1 - - if loc - start < self.minLen: - raise ParseException(instring, loc, self.errmsg, self) - - return loc, instring[start:loc] - - def __str__( self ): - try: - return super(CharsNotIn, self).__str__() - except Exception: - pass - - if self.strRepr is None: - if len(self.notChars) > 4: - self.strRepr = "!W:(%s...)" % self.notChars[:4] - else: - self.strRepr = "!W:(%s)" % self.notChars - - return self.strRepr - -class White(Token): - """Special matching class for matching whitespace. Normally, - whitespace is ignored by pyparsing grammars. This class is included - when some whitespace structures are significant. Define with - a string containing the whitespace characters to be matched; default - is ``" \\t\\r\\n"``. Also takes optional ``min``, - ``max``, and ``exact`` arguments, as defined for the - :class:`Word` class. - """ - whiteStrs = { - ' ' : '<SP>', - '\t': '<TAB>', - '\n': '<LF>', - '\r': '<CR>', - '\f': '<FF>', - 'u\00A0': '<NBSP>', - 'u\1680': '<OGHAM_SPACE_MARK>', - 'u\180E': '<MONGOLIAN_VOWEL_SEPARATOR>', - 'u\2000': '<EN_QUAD>', - 'u\2001': '<EM_QUAD>', - 'u\2002': '<EN_SPACE>', - 'u\2003': '<EM_SPACE>', - 'u\2004': '<THREE-PER-EM_SPACE>', - 'u\2005': '<FOUR-PER-EM_SPACE>', - 'u\2006': '<SIX-PER-EM_SPACE>', - 'u\2007': '<FIGURE_SPACE>', - 'u\2008': '<PUNCTUATION_SPACE>', - 'u\2009': '<THIN_SPACE>', - 'u\200A': '<HAIR_SPACE>', - 'u\200B': '<ZERO_WIDTH_SPACE>', - 'u\202F': '<NNBSP>', - 'u\205F': '<MMSP>', - 'u\3000': '<IDEOGRAPHIC_SPACE>', - } - def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0): - super(White,self).__init__() - self.matchWhite = ws - self.setWhitespaceChars( "".join(c for c in self.whiteChars if c not in self.matchWhite) ) - #~ self.leaveWhitespace() - self.name = ("".join(White.whiteStrs[c] for c in self.matchWhite)) - self.mayReturnEmpty = True - self.errmsg = "Expected " + self.name - - self.minLen = min - - if max > 0: - self.maxLen = max - else: - self.maxLen = _MAX_INT - - if exact > 0: - self.maxLen = exact - self.minLen = exact - - def parseImpl( self, instring, loc, doActions=True ): - if instring[loc] not in self.matchWhite: - raise ParseException(instring, loc, self.errmsg, self) - start = loc - loc += 1 - maxloc = start + self.maxLen - maxloc = min( maxloc, len(instring) ) - while loc < maxloc and instring[loc] in self.matchWhite: - loc += 1 - - if loc - start < self.minLen: - raise ParseException(instring, loc, self.errmsg, self) - - return loc, instring[start:loc] - - -class _PositionToken(Token): - def __init__( self ): - super(_PositionToken,self).__init__() - self.name=self.__class__.__name__ - self.mayReturnEmpty = True - self.mayIndexError = False - -class GoToColumn(_PositionToken): - """Token to advance to a specific column of input text; useful for - tabular report scraping. - """ - def __init__( self, colno ): - super(GoToColumn,self).__init__() - self.col = colno - - def preParse( self, instring, loc ): - if col(loc,instring) != self.col: - instrlen = len(instring) - if self.ignoreExprs: - loc = self._skipIgnorables( instring, loc ) - while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col : - loc += 1 - return loc - - def parseImpl( self, instring, loc, doActions=True ): - thiscol = col( loc, instring ) - if thiscol > self.col: - raise ParseException( instring, loc, "Text not in expected column", self ) - newloc = loc + self.col - thiscol - ret = instring[ loc: newloc ] - return newloc, ret - - -class LineStart(_PositionToken): - r"""Matches if current position is at the beginning of a line within - the parse string - - Example:: - - test = '''\ - AAA this line - AAA and this line - AAA but not this one - B AAA and definitely not this one - ''' - - for t in (LineStart() + 'AAA' + restOfLine).searchString(test): - print(t) - - prints:: - - ['AAA', ' this line'] - ['AAA', ' and this line'] - - """ - def __init__( self ): - super(LineStart,self).__init__() - self.errmsg = "Expected start of line" - - def parseImpl( self, instring, loc, doActions=True ): - if col(loc, instring) == 1: - return loc, [] - raise ParseException(instring, loc, self.errmsg, self) - -class LineEnd(_PositionToken): - """Matches if current position is at the end of a line within the - parse string - """ - def __init__( self ): - super(LineEnd,self).__init__() - self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") ) - self.errmsg = "Expected end of line" - - def parseImpl( self, instring, loc, doActions=True ): - if loc<len(instring): - if instring[loc] == "\n": - return loc+1, "\n" - else: - raise ParseException(instring, loc, self.errmsg, self) - elif loc == len(instring): - return loc+1, [] - else: - raise ParseException(instring, loc, self.errmsg, self) - -class StringStart(_PositionToken): - """Matches if current position is at the beginning of the parse - string - """ - def __init__( self ): - super(StringStart,self).__init__() - self.errmsg = "Expected start of text" - - def parseImpl( self, instring, loc, doActions=True ): - if loc != 0: - # see if entire string up to here is just whitespace and ignoreables - if loc != self.preParse( instring, 0 ): - raise ParseException(instring, loc, self.errmsg, self) - return loc, [] - -class StringEnd(_PositionToken): - """Matches if current position is at the end of the parse string - """ - def __init__( self ): - super(StringEnd,self).__init__() - self.errmsg = "Expected end of text" - - def parseImpl( self, instring, loc, doActions=True ): - if loc < len(instring): - raise ParseException(instring, loc, self.errmsg, self) - elif loc == len(instring): - return loc+1, [] - elif loc > len(instring): - return loc, [] - else: - raise ParseException(instring, loc, self.errmsg, self) - -class WordStart(_PositionToken): - """Matches if the current position is at the beginning of a Word, - and is not preceded by any character in a given set of - ``wordChars`` (default= ``printables``). To emulate the - ``\b`` behavior of regular expressions, use - ``WordStart(alphanums)``. ``WordStart`` will also match at - the beginning of the string being parsed, or at the beginning of - a line. - """ - def __init__(self, wordChars = printables): - super(WordStart,self).__init__() - self.wordChars = set(wordChars) - self.errmsg = "Not at the start of a word" - - def parseImpl(self, instring, loc, doActions=True ): - if loc != 0: - if (instring[loc-1] in self.wordChars or - instring[loc] not in self.wordChars): - raise ParseException(instring, loc, self.errmsg, self) - return loc, [] - -class WordEnd(_PositionToken): - """Matches if the current position is at the end of a Word, and is - not followed by any character in a given set of ``wordChars`` - (default= ``printables``). To emulate the ``\b`` behavior of - regular expressions, use ``WordEnd(alphanums)``. ``WordEnd`` - will also match at the end of the string being parsed, or at the end - of a line. - """ - def __init__(self, wordChars = printables): - super(WordEnd,self).__init__() - self.wordChars = set(wordChars) - self.skipWhitespace = False - self.errmsg = "Not at the end of a word" - - def parseImpl(self, instring, loc, doActions=True ): - instrlen = len(instring) - if instrlen>0 and loc<instrlen: - if (instring[loc] in self.wordChars or - instring[loc-1] not in self.wordChars): - raise ParseException(instring, loc, self.errmsg, self) - return loc, [] - - -class ParseExpression(ParserElement): - """Abstract subclass of ParserElement, for combining and - post-processing parsed tokens. - """ - def __init__( self, exprs, savelist = False ): - super(ParseExpression,self).__init__(savelist) - if isinstance( exprs, _generatorType ): - exprs = list(exprs) - - if isinstance( exprs, basestring ): - self.exprs = [ ParserElement._literalStringClass( exprs ) ] - elif isinstance( exprs, Iterable ): - exprs = list(exprs) - # if sequence of strings provided, wrap with Literal - if all(isinstance(expr, basestring) for expr in exprs): - exprs = map(ParserElement._literalStringClass, exprs) - self.exprs = list(exprs) - else: - try: - self.exprs = list( exprs ) - except TypeError: - self.exprs = [ exprs ] - self.callPreparse = False - - def __getitem__( self, i ): - return self.exprs[i] - - def append( self, other ): - self.exprs.append( other ) - self.strRepr = None - return self - - def leaveWhitespace( self ): - """Extends ``leaveWhitespace`` defined in base class, and also invokes ``leaveWhitespace`` on - all contained expressions.""" - self.skipWhitespace = False - self.exprs = [ e.copy() for e in self.exprs ] - for e in self.exprs: - e.leaveWhitespace() - return self - - def ignore( self, other ): - if isinstance( other, Suppress ): - if other not in self.ignoreExprs: - super( ParseExpression, self).ignore( other ) - for e in self.exprs: - e.ignore( self.ignoreExprs[-1] ) - else: - super( ParseExpression, self).ignore( other ) - for e in self.exprs: - e.ignore( self.ignoreExprs[-1] ) - return self - - def __str__( self ): - try: - return super(ParseExpression,self).__str__() - except Exception: - pass - - if self.strRepr is None: - self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.exprs) ) - return self.strRepr - - def streamline( self ): - super(ParseExpression,self).streamline() - - for e in self.exprs: - e.streamline() - - # collapse nested And's of the form And( And( And( a,b), c), d) to And( a,b,c,d ) - # but only if there are no parse actions or resultsNames on the nested And's - # (likewise for Or's and MatchFirst's) - if ( len(self.exprs) == 2 ): - other = self.exprs[0] - if ( isinstance( other, self.__class__ ) and - not(other.parseAction) and - other.resultsName is None and - not other.debug ): - self.exprs = other.exprs[:] + [ self.exprs[1] ] - self.strRepr = None - self.mayReturnEmpty |= other.mayReturnEmpty - self.mayIndexError |= other.mayIndexError - - other = self.exprs[-1] - if ( isinstance( other, self.__class__ ) and - not(other.parseAction) and - other.resultsName is None and - not other.debug ): - self.exprs = self.exprs[:-1] + other.exprs[:] - self.strRepr = None - self.mayReturnEmpty |= other.mayReturnEmpty - self.mayIndexError |= other.mayIndexError - - self.errmsg = "Expected " + _ustr(self) - - return self - - def validate( self, validateTrace=[] ): - tmp = validateTrace[:]+[self] - for e in self.exprs: - e.validate(tmp) - self.checkRecursion( [] ) - - def copy(self): - ret = super(ParseExpression,self).copy() - ret.exprs = [e.copy() for e in self.exprs] - return ret - -class And(ParseExpression): - """ - Requires all given :class:`ParseExpression` s to be found in the given order. - Expressions may be separated by whitespace. - May be constructed using the ``'+'`` operator. - May also be constructed using the ``'-'`` operator, which will - suppress backtracking. - - Example:: - - integer = Word(nums) - name_expr = OneOrMore(Word(alphas)) - - expr = And([integer("id"),name_expr("name"),integer("age")]) - # more easily written as: - expr = integer("id") + name_expr("name") + integer("age") - """ - - class _ErrorStop(Empty): - def __init__(self, *args, **kwargs): - super(And._ErrorStop,self).__init__(*args, **kwargs) - self.name = '-' - self.leaveWhitespace() - - def __init__( self, exprs, savelist = True ): - super(And,self).__init__(exprs, savelist) - self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) - self.setWhitespaceChars( self.exprs[0].whiteChars ) - self.skipWhitespace = self.exprs[0].skipWhitespace - self.callPreparse = True - - def streamline(self): - super(And, self).streamline() - self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) - return self - - def parseImpl( self, instring, loc, doActions=True ): - # pass False as last arg to _parse for first element, since we already - # pre-parsed the string as part of our And pre-parsing - loc, resultlist = self.exprs[0]._parse( instring, loc, doActions, callPreParse=False ) - errorStop = False - for e in self.exprs[1:]: - if isinstance(e, And._ErrorStop): - errorStop = True - continue - if errorStop: - try: - loc, exprtokens = e._parse( instring, loc, doActions ) - except ParseSyntaxException: - raise - except ParseBaseException as pe: - pe.__traceback__ = None - raise ParseSyntaxException._from_exception(pe) - except IndexError: - raise ParseSyntaxException(instring, len(instring), self.errmsg, self) - else: - loc, exprtokens = e._parse( instring, loc, doActions ) - if exprtokens or exprtokens.haskeys(): - resultlist += exprtokens - return loc, resultlist - - def __iadd__(self, other ): - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - return self.append( other ) #And( [ self, other ] ) - - def checkRecursion( self, parseElementList ): - subRecCheckList = parseElementList[:] + [ self ] - for e in self.exprs: - e.checkRecursion( subRecCheckList ) - if not e.mayReturnEmpty: - break - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + " ".join(_ustr(e) for e in self.exprs) + "}" - - return self.strRepr - - -class Or(ParseExpression): - """Requires that at least one :class:`ParseExpression` is found. If - two expressions match, the expression that matches the longest - string will be used. May be constructed using the ``'^'`` - operator. - - Example:: - - # construct Or using '^' operator - - number = Word(nums) ^ Combine(Word(nums) + '.' + Word(nums)) - print(number.searchString("123 3.1416 789")) - - prints:: - - [['123'], ['3.1416'], ['789']] - """ - def __init__( self, exprs, savelist = False ): - super(Or,self).__init__(exprs, savelist) - if self.exprs: - self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) - else: - self.mayReturnEmpty = True - - def streamline(self): - super(Or, self).streamline() - if __compat__.collect_all_And_tokens: - self.saveAsList = any(e.saveAsList for e in self.exprs) - return self - - def parseImpl( self, instring, loc, doActions=True ): - maxExcLoc = -1 - maxException = None - matches = [] - for e in self.exprs: - try: - loc2 = e.tryParse( instring, loc ) - except ParseException as err: - err.__traceback__ = None - if err.loc > maxExcLoc: - maxException = err - maxExcLoc = err.loc - except IndexError: - if len(instring) > maxExcLoc: - maxException = ParseException(instring,len(instring),e.errmsg,self) - maxExcLoc = len(instring) - else: - # save match among all matches, to retry longest to shortest - matches.append((loc2, e)) - - if matches: - matches.sort(key=lambda x: -x[0]) - for _,e in matches: - try: - return e._parse( instring, loc, doActions ) - except ParseException as err: - err.__traceback__ = None - if err.loc > maxExcLoc: - maxException = err - maxExcLoc = err.loc - - if maxException is not None: - maxException.msg = self.errmsg - raise maxException - else: - raise ParseException(instring, loc, "no defined alternatives to match", self) - - - def __ixor__(self, other ): - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - return self.append( other ) #Or( [ self, other ] ) - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + " ^ ".join(_ustr(e) for e in self.exprs) + "}" - - return self.strRepr - - def checkRecursion( self, parseElementList ): - subRecCheckList = parseElementList[:] + [ self ] - for e in self.exprs: - e.checkRecursion( subRecCheckList ) - - -class MatchFirst(ParseExpression): - """Requires that at least one :class:`ParseExpression` is found. If - two expressions match, the first one listed is the one that will - match. May be constructed using the ``'|'`` operator. - - Example:: - - # construct MatchFirst using '|' operator - - # watch the order of expressions to match - number = Word(nums) | Combine(Word(nums) + '.' + Word(nums)) - print(number.searchString("123 3.1416 789")) # Fail! -> [['123'], ['3'], ['1416'], ['789']] - - # put more selective expression first - number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums) - print(number.searchString("123 3.1416 789")) # Better -> [['123'], ['3.1416'], ['789']] - """ - def __init__( self, exprs, savelist = False ): - super(MatchFirst,self).__init__(exprs, savelist) - if self.exprs: - self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) - else: - self.mayReturnEmpty = True - - def streamline(self): - super(MatchFirst, self).streamline() - if __compat__.collect_all_And_tokens: - self.saveAsList = any(e.saveAsList for e in self.exprs) - return self - - def parseImpl( self, instring, loc, doActions=True ): - maxExcLoc = -1 - maxException = None - for e in self.exprs: - try: - ret = e._parse( instring, loc, doActions ) - return ret - except ParseException as err: - if err.loc > maxExcLoc: - maxException = err - maxExcLoc = err.loc - except IndexError: - if len(instring) > maxExcLoc: - maxException = ParseException(instring,len(instring),e.errmsg,self) - maxExcLoc = len(instring) - - # only got here if no expression matched, raise exception for match that made it the furthest - else: - if maxException is not None: - maxException.msg = self.errmsg - raise maxException - else: - raise ParseException(instring, loc, "no defined alternatives to match", self) - - def __ior__(self, other ): - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - return self.append( other ) #MatchFirst( [ self, other ] ) - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + " | ".join(_ustr(e) for e in self.exprs) + "}" - - return self.strRepr - - def checkRecursion( self, parseElementList ): - subRecCheckList = parseElementList[:] + [ self ] - for e in self.exprs: - e.checkRecursion( subRecCheckList ) - - -class Each(ParseExpression): - """Requires all given :class:`ParseExpression` s to be found, but in - any order. Expressions may be separated by whitespace. - - May be constructed using the ``'&'`` operator. - - Example:: - - color = oneOf("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN") - shape_type = oneOf("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON") - integer = Word(nums) - shape_attr = "shape:" + shape_type("shape") - posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn") - color_attr = "color:" + color("color") - size_attr = "size:" + integer("size") - - # use Each (using operator '&') to accept attributes in any order - # (shape and posn are required, color and size are optional) - shape_spec = shape_attr & posn_attr & Optional(color_attr) & Optional(size_attr) - - shape_spec.runTests(''' - shape: SQUARE color: BLACK posn: 100, 120 - shape: CIRCLE size: 50 color: BLUE posn: 50,80 - color:GREEN size:20 shape:TRIANGLE posn:20,40 - ''' - ) - - prints:: - - shape: SQUARE color: BLACK posn: 100, 120 - ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']] - - color: BLACK - - posn: ['100', ',', '120'] - - x: 100 - - y: 120 - - shape: SQUARE - - - shape: CIRCLE size: 50 color: BLUE posn: 50,80 - ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']] - - color: BLUE - - posn: ['50', ',', '80'] - - x: 50 - - y: 80 - - shape: CIRCLE - - size: 50 - - - color: GREEN size: 20 shape: TRIANGLE posn: 20,40 - ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']] - - color: GREEN - - posn: ['20', ',', '40'] - - x: 20 - - y: 40 - - shape: TRIANGLE - - size: 20 - """ - def __init__( self, exprs, savelist = True ): - super(Each,self).__init__(exprs, savelist) - self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) - self.skipWhitespace = True - self.initExprGroups = True - self.saveAsList = True - - def streamline(self): - super(Each, self).streamline() - self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) - return self - - def parseImpl( self, instring, loc, doActions=True ): - if self.initExprGroups: - self.opt1map = dict((id(e.expr),e) for e in self.exprs if isinstance(e,Optional)) - opt1 = [ e.expr for e in self.exprs if isinstance(e,Optional) ] - opt2 = [ e for e in self.exprs if e.mayReturnEmpty and not isinstance(e,Optional)] - self.optionals = opt1 + opt2 - self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ] - self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ] - self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ] - self.required += self.multirequired - self.initExprGroups = False - tmpLoc = loc - tmpReqd = self.required[:] - tmpOpt = self.optionals[:] - matchOrder = [] - - keepMatching = True - while keepMatching: - tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired - failed = [] - for e in tmpExprs: - try: - tmpLoc = e.tryParse( instring, tmpLoc ) - except ParseException: - failed.append(e) - else: - matchOrder.append(self.opt1map.get(id(e),e)) - if e in tmpReqd: - tmpReqd.remove(e) - elif e in tmpOpt: - tmpOpt.remove(e) - if len(failed) == len(tmpExprs): - keepMatching = False - - if tmpReqd: - missing = ", ".join(_ustr(e) for e in tmpReqd) - raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing ) - - # add any unmatched Optionals, in case they have default values defined - matchOrder += [e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt] - - resultlist = [] - for e in matchOrder: - loc,results = e._parse(instring,loc,doActions) - resultlist.append(results) - - finalResults = sum(resultlist, ParseResults([])) - return loc, finalResults - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + " & ".join(_ustr(e) for e in self.exprs) + "}" - - return self.strRepr - - def checkRecursion( self, parseElementList ): - subRecCheckList = parseElementList[:] + [ self ] - for e in self.exprs: - e.checkRecursion( subRecCheckList ) - - -class ParseElementEnhance(ParserElement): - """Abstract subclass of :class:`ParserElement`, for combining and - post-processing parsed tokens. - """ - def __init__( self, expr, savelist=False ): - super(ParseElementEnhance,self).__init__(savelist) - if isinstance( expr, basestring ): - if issubclass(ParserElement._literalStringClass, Token): - expr = ParserElement._literalStringClass(expr) - else: - expr = ParserElement._literalStringClass(Literal(expr)) - self.expr = expr - self.strRepr = None - if expr is not None: - self.mayIndexError = expr.mayIndexError - self.mayReturnEmpty = expr.mayReturnEmpty - self.setWhitespaceChars( expr.whiteChars ) - self.skipWhitespace = expr.skipWhitespace - self.saveAsList = expr.saveAsList - self.callPreparse = expr.callPreparse - self.ignoreExprs.extend(expr.ignoreExprs) - - def parseImpl( self, instring, loc, doActions=True ): - if self.expr is not None: - return self.expr._parse( instring, loc, doActions, callPreParse=False ) - else: - raise ParseException("",loc,self.errmsg,self) - - def leaveWhitespace( self ): - self.skipWhitespace = False - self.expr = self.expr.copy() - if self.expr is not None: - self.expr.leaveWhitespace() - return self - - def ignore( self, other ): - if isinstance( other, Suppress ): - if other not in self.ignoreExprs: - super( ParseElementEnhance, self).ignore( other ) - if self.expr is not None: - self.expr.ignore( self.ignoreExprs[-1] ) - else: - super( ParseElementEnhance, self).ignore( other ) - if self.expr is not None: - self.expr.ignore( self.ignoreExprs[-1] ) - return self - - def streamline( self ): - super(ParseElementEnhance,self).streamline() - if self.expr is not None: - self.expr.streamline() - return self - - def checkRecursion( self, parseElementList ): - if self in parseElementList: - raise RecursiveGrammarException( parseElementList+[self] ) - subRecCheckList = parseElementList[:] + [ self ] - if self.expr is not None: - self.expr.checkRecursion( subRecCheckList ) - - def validate( self, validateTrace=[] ): - tmp = validateTrace[:]+[self] - if self.expr is not None: - self.expr.validate(tmp) - self.checkRecursion( [] ) - - def __str__( self ): - try: - return super(ParseElementEnhance,self).__str__() - except Exception: - pass - - if self.strRepr is None and self.expr is not None: - self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) ) - return self.strRepr - - -class FollowedBy(ParseElementEnhance): - """Lookahead matching of the given parse expression. - ``FollowedBy`` does *not* advance the parsing position within - the input string, it only verifies that the specified parse - expression matches at the current position. ``FollowedBy`` - always returns a null token list. If any results names are defined - in the lookahead expression, those *will* be returned for access by - name. - - Example:: - - # use FollowedBy to match a label only if it is followed by a ':' - data_word = Word(alphas) - label = data_word + FollowedBy(':') - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) - - OneOrMore(attr_expr).parseString("shape: SQUARE color: BLACK posn: upper left").pprint() - - prints:: - - [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']] - """ - def __init__( self, expr ): - super(FollowedBy,self).__init__(expr) - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - _, ret = self.expr._parse(instring, loc, doActions=doActions) - del ret[:] - return loc, ret - - -class PrecededBy(ParseElementEnhance): - """Lookbehind matching of the given parse expression. - ``PrecededBy`` does not advance the parsing position within the - input string, it only verifies that the specified parse expression - matches prior to the current position. ``PrecededBy`` always - returns a null token list, but if a results name is defined on the - given expression, it is returned. - - Parameters: - - - expr - expression that must match prior to the current parse - location - - retreat - (default= ``None``) - (int) maximum number of characters - to lookbehind prior to the current parse location - - If the lookbehind expression is a string, Literal, Keyword, or - a Word or CharsNotIn with a specified exact or maximum length, then - the retreat parameter is not required. Otherwise, retreat must be - specified to give a maximum number of characters to look back from - the current parse position for a lookbehind match. - - Example:: - - # VB-style variable names with type prefixes - int_var = PrecededBy("#") + pyparsing_common.identifier - str_var = PrecededBy("$") + pyparsing_common.identifier - - """ - def __init__(self, expr, retreat=None): - super(PrecededBy, self).__init__(expr) - self.expr = self.expr().leaveWhitespace() - self.mayReturnEmpty = True - self.mayIndexError = False - self.exact = False - if isinstance(expr, str): - retreat = len(expr) - self.exact = True - elif isinstance(expr, (Literal, Keyword)): - retreat = expr.matchLen - self.exact = True - elif isinstance(expr, (Word, CharsNotIn)) and expr.maxLen != _MAX_INT: - retreat = expr.maxLen - self.exact = True - elif isinstance(expr, _PositionToken): - retreat = 0 - self.exact = True - self.retreat = retreat - self.errmsg = "not preceded by " + str(expr) - self.skipWhitespace = False - - def parseImpl(self, instring, loc=0, doActions=True): - if self.exact: - if loc < self.retreat: - raise ParseException(instring, loc, self.errmsg) - start = loc - self.retreat - _, ret = self.expr._parse(instring, start) - else: - # retreat specified a maximum lookbehind window, iterate - test_expr = self.expr + StringEnd() - instring_slice = instring[:loc] - last_expr = ParseException(instring, loc, self.errmsg) - for offset in range(1, min(loc, self.retreat+1)): - try: - _, ret = test_expr._parse(instring_slice, loc-offset) - except ParseBaseException as pbe: - last_expr = pbe - else: - break - else: - raise last_expr - # return empty list of tokens, but preserve any defined results names - del ret[:] - return loc, ret - - -class NotAny(ParseElementEnhance): - """Lookahead to disallow matching with the given parse expression. - ``NotAny`` does *not* advance the parsing position within the - input string, it only verifies that the specified parse expression - does *not* match at the current position. Also, ``NotAny`` does - *not* skip over leading whitespace. ``NotAny`` always returns - a null token list. May be constructed using the '~' operator. - - Example:: - - AND, OR, NOT = map(CaselessKeyword, "AND OR NOT".split()) - - # take care not to mistake keywords for identifiers - ident = ~(AND | OR | NOT) + Word(alphas) - boolean_term = Optional(NOT) + ident - - # very crude boolean expression - to support parenthesis groups and - # operation hierarchy, use infixNotation - boolean_expr = boolean_term + ZeroOrMore((AND | OR) + boolean_term) - - # integers that are followed by "." are actually floats - integer = Word(nums) + ~Char(".") - """ - def __init__( self, expr ): - super(NotAny,self).__init__(expr) - #~ self.leaveWhitespace() - self.skipWhitespace = False # do NOT use self.leaveWhitespace(), don't want to propagate to exprs - self.mayReturnEmpty = True - self.errmsg = "Found unwanted token, "+_ustr(self.expr) - - def parseImpl( self, instring, loc, doActions=True ): - if self.expr.canParseNext(instring, loc): - raise ParseException(instring, loc, self.errmsg, self) - return loc, [] - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "~{" + _ustr(self.expr) + "}" - - return self.strRepr - -class _MultipleMatch(ParseElementEnhance): - def __init__( self, expr, stopOn=None): - super(_MultipleMatch, self).__init__(expr) - self.saveAsList = True - ender = stopOn - if isinstance(ender, basestring): - ender = ParserElement._literalStringClass(ender) - self.not_ender = ~ender if ender is not None else None - - def parseImpl( self, instring, loc, doActions=True ): - self_expr_parse = self.expr._parse - self_skip_ignorables = self._skipIgnorables - check_ender = self.not_ender is not None - if check_ender: - try_not_ender = self.not_ender.tryParse - - # must be at least one (but first see if we are the stopOn sentinel; - # if so, fail) - if check_ender: - try_not_ender(instring, loc) - loc, tokens = self_expr_parse( instring, loc, doActions, callPreParse=False ) - try: - hasIgnoreExprs = (not not self.ignoreExprs) - while 1: - if check_ender: - try_not_ender(instring, loc) - if hasIgnoreExprs: - preloc = self_skip_ignorables( instring, loc ) - else: - preloc = loc - loc, tmptokens = self_expr_parse( instring, preloc, doActions ) - if tmptokens or tmptokens.haskeys(): - tokens += tmptokens - except (ParseException,IndexError): - pass - - return loc, tokens - -class OneOrMore(_MultipleMatch): - """Repetition of one or more of the given expression. - - Parameters: - - expr - expression that must match one or more times - - stopOn - (default= ``None``) - expression for a terminating sentinel - (only required if the sentinel would ordinarily match the repetition - expression) - - Example:: - - data_word = Word(alphas) - label = data_word + FollowedBy(':') - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) - - text = "shape: SQUARE posn: upper left color: BLACK" - OneOrMore(attr_expr).parseString(text).pprint() # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']] - - # use stopOn attribute for OneOrMore to avoid reading label string as part of the data - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) - OneOrMore(attr_expr).parseString(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']] - - # could also be written as - (attr_expr * (1,)).parseString(text).pprint() - """ - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + _ustr(self.expr) + "}..." - - return self.strRepr - -class ZeroOrMore(_MultipleMatch): - """Optional repetition of zero or more of the given expression. - - Parameters: - - expr - expression that must match zero or more times - - stopOn - (default= ``None``) - expression for a terminating sentinel - (only required if the sentinel would ordinarily match the repetition - expression) - - Example: similar to :class:`OneOrMore` - """ - def __init__( self, expr, stopOn=None): - super(ZeroOrMore,self).__init__(expr, stopOn=stopOn) - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - try: - return super(ZeroOrMore, self).parseImpl(instring, loc, doActions) - except (ParseException,IndexError): - return loc, [] - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "[" + _ustr(self.expr) + "]..." - - return self.strRepr - -class _NullToken(object): - def __bool__(self): - return False - __nonzero__ = __bool__ - def __str__(self): - return "" - -_optionalNotMatched = _NullToken() -class Optional(ParseElementEnhance): - """Optional matching of the given expression. - - Parameters: - - expr - expression that must match zero or more times - - default (optional) - value to be returned if the optional expression is not found. - - Example:: - - # US postal code can be a 5-digit zip, plus optional 4-digit qualifier - zip = Combine(Word(nums, exact=5) + Optional('-' + Word(nums, exact=4))) - zip.runTests(''' - # traditional ZIP code - 12345 - - # ZIP+4 form - 12101-0001 - - # invalid ZIP - 98765- - ''') - - prints:: - - # traditional ZIP code - 12345 - ['12345'] - - # ZIP+4 form - 12101-0001 - ['12101-0001'] - - # invalid ZIP - 98765- - ^ - FAIL: Expected end of text (at char 5), (line:1, col:6) - """ - def __init__( self, expr, default=_optionalNotMatched ): - super(Optional,self).__init__( expr, savelist=False ) - self.saveAsList = self.expr.saveAsList - self.defaultValue = default - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - try: - loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False ) - except (ParseException,IndexError): - if self.defaultValue is not _optionalNotMatched: - if self.expr.resultsName: - tokens = ParseResults([ self.defaultValue ]) - tokens[self.expr.resultsName] = self.defaultValue - else: - tokens = [ self.defaultValue ] - else: - tokens = [] - return loc, tokens - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "[" + _ustr(self.expr) + "]" - - return self.strRepr - -class SkipTo(ParseElementEnhance): - """Token for skipping over all undefined text until the matched - expression is found. - - Parameters: - - expr - target expression marking the end of the data to be skipped - - include - (default= ``False``) if True, the target expression is also parsed - (the skipped text and target expression are returned as a 2-element list). - - ignore - (default= ``None``) used to define grammars (typically quoted strings and - comments) that might contain false matches to the target expression - - failOn - (default= ``None``) define expressions that are not allowed to be - included in the skipped test; if found before the target expression is found, - the SkipTo is not a match - - Example:: - - report = ''' - Outstanding Issues Report - 1 Jan 2000 - - # | Severity | Description | Days Open - -----+----------+-------------------------------------------+----------- - 101 | Critical | Intermittent system crash | 6 - 94 | Cosmetic | Spelling error on Login ('log|n') | 14 - 79 | Minor | System slow when running too many reports | 47 - ''' - integer = Word(nums) - SEP = Suppress('|') - # use SkipTo to simply match everything up until the next SEP - # - ignore quoted strings, so that a '|' character inside a quoted string does not match - # - parse action will call token.strip() for each matched token, i.e., the description body - string_data = SkipTo(SEP, ignore=quotedString) - string_data.setParseAction(tokenMap(str.strip)) - ticket_expr = (integer("issue_num") + SEP - + string_data("sev") + SEP - + string_data("desc") + SEP - + integer("days_open")) - - for tkt in ticket_expr.searchString(report): - print tkt.dump() - - prints:: - - ['101', 'Critical', 'Intermittent system crash', '6'] - - days_open: 6 - - desc: Intermittent system crash - - issue_num: 101 - - sev: Critical - ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14'] - - days_open: 14 - - desc: Spelling error on Login ('log|n') - - issue_num: 94 - - sev: Cosmetic - ['79', 'Minor', 'System slow when running too many reports', '47'] - - days_open: 47 - - desc: System slow when running too many reports - - issue_num: 79 - - sev: Minor - """ - def __init__( self, other, include=False, ignore=None, failOn=None ): - super( SkipTo, self ).__init__( other ) - self.ignoreExpr = ignore - self.mayReturnEmpty = True - self.mayIndexError = False - self.includeMatch = include - self.saveAsList = False - if isinstance(failOn, basestring): - self.failOn = ParserElement._literalStringClass(failOn) - else: - self.failOn = failOn - self.errmsg = "No match found for "+_ustr(self.expr) - - def parseImpl( self, instring, loc, doActions=True ): - startloc = loc - instrlen = len(instring) - expr = self.expr - expr_parse = self.expr._parse - self_failOn_canParseNext = self.failOn.canParseNext if self.failOn is not None else None - self_ignoreExpr_tryParse = self.ignoreExpr.tryParse if self.ignoreExpr is not None else None - - tmploc = loc - while tmploc <= instrlen: - if self_failOn_canParseNext is not None: - # break if failOn expression matches - if self_failOn_canParseNext(instring, tmploc): - break - - if self_ignoreExpr_tryParse is not None: - # advance past ignore expressions - while 1: - try: - tmploc = self_ignoreExpr_tryParse(instring, tmploc) - except ParseBaseException: - break - - try: - expr_parse(instring, tmploc, doActions=False, callPreParse=False) - except (ParseException, IndexError): - # no match, advance loc in string - tmploc += 1 - else: - # matched skipto expr, done - break - - else: - # ran off the end of the input string without matching skipto expr, fail - raise ParseException(instring, loc, self.errmsg, self) - - # build up return values - loc = tmploc - skiptext = instring[startloc:loc] - skipresult = ParseResults(skiptext) - - if self.includeMatch: - loc, mat = expr_parse(instring,loc,doActions,callPreParse=False) - skipresult += mat - - return loc, skipresult - -class Forward(ParseElementEnhance): - """Forward declaration of an expression to be defined later - - used for recursive grammars, such as algebraic infix notation. - When the expression is known, it is assigned to the ``Forward`` - variable using the '<<' operator. - - Note: take care when assigning to ``Forward`` not to overlook - precedence of operators. - - Specifically, '|' has a lower precedence than '<<', so that:: - - fwdExpr << a | b | c - - will actually be evaluated as:: - - (fwdExpr << a) | b | c - - thereby leaving b and c out as parseable alternatives. It is recommended that you - explicitly group the values inserted into the ``Forward``:: - - fwdExpr << (a | b | c) - - Converting to use the '<<=' operator instead will avoid this problem. - - See :class:`ParseResults.pprint` for an example of a recursive - parser created using ``Forward``. - """ - def __init__( self, other=None ): - super(Forward,self).__init__( other, savelist=False ) - - def __lshift__( self, other ): - if isinstance( other, basestring ): - other = ParserElement._literalStringClass(other) - self.expr = other - self.strRepr = None - self.mayIndexError = self.expr.mayIndexError - self.mayReturnEmpty = self.expr.mayReturnEmpty - self.setWhitespaceChars( self.expr.whiteChars ) - self.skipWhitespace = self.expr.skipWhitespace - self.saveAsList = self.expr.saveAsList - self.ignoreExprs.extend(self.expr.ignoreExprs) - return self - - def __ilshift__(self, other): - return self << other - - def leaveWhitespace( self ): - self.skipWhitespace = False - return self - - def streamline( self ): - if not self.streamlined: - self.streamlined = True - if self.expr is not None: - self.expr.streamline() - return self - - def validate( self, validateTrace=[] ): - if self not in validateTrace: - tmp = validateTrace[:]+[self] - if self.expr is not None: - self.expr.validate(tmp) - self.checkRecursion([]) - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - # Avoid infinite recursion by setting a temporary name - self.name = self.__class__.__name__ + ": ..." - - # Use the string representation of main expression. - try: - if self.expr is not None: - retString = _ustr(self.expr) - else: - retString = "None" - finally: - del self.name - return self.__class__.__name__ + ": " + retString - - def copy(self): - if self.expr is not None: - return super(Forward,self).copy() - else: - ret = Forward() - ret <<= self - return ret - -class TokenConverter(ParseElementEnhance): - """ - Abstract subclass of :class:`ParseExpression`, for converting parsed results. - """ - def __init__( self, expr, savelist=False ): - super(TokenConverter,self).__init__( expr )#, savelist ) - self.saveAsList = False - -class Combine(TokenConverter): - """Converter to concatenate all matching tokens to a single string. - By default, the matching patterns must also be contiguous in the - input string; this can be disabled by specifying - ``'adjacent=False'`` in the constructor. - - Example:: - - real = Word(nums) + '.' + Word(nums) - print(real.parseString('3.1416')) # -> ['3', '.', '1416'] - # will also erroneously match the following - print(real.parseString('3. 1416')) # -> ['3', '.', '1416'] - - real = Combine(Word(nums) + '.' + Word(nums)) - print(real.parseString('3.1416')) # -> ['3.1416'] - # no match when there are internal spaces - print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...) - """ - def __init__( self, expr, joinString="", adjacent=True ): - super(Combine,self).__init__( expr ) - # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself - if adjacent: - self.leaveWhitespace() - self.adjacent = adjacent - self.skipWhitespace = True - self.joinString = joinString - self.callPreparse = True - - def ignore( self, other ): - if self.adjacent: - ParserElement.ignore(self, other) - else: - super( Combine, self).ignore( other ) - return self - - def postParse( self, instring, loc, tokenlist ): - retToks = tokenlist.copy() - del retToks[:] - retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults) - - if self.resultsName and retToks.haskeys(): - return [ retToks ] - else: - return retToks - -class Group(TokenConverter): - """Converter to return the matched tokens as a list - useful for - returning tokens of :class:`ZeroOrMore` and :class:`OneOrMore` expressions. - - Example:: - - ident = Word(alphas) - num = Word(nums) - term = ident | num - func = ident + Optional(delimitedList(term)) - print(func.parseString("fn a,b,100")) # -> ['fn', 'a', 'b', '100'] - - func = ident + Group(Optional(delimitedList(term))) - print(func.parseString("fn a,b,100")) # -> ['fn', ['a', 'b', '100']] - """ - def __init__( self, expr ): - super(Group,self).__init__( expr ) - self.saveAsList = True - - def postParse( self, instring, loc, tokenlist ): - return [ tokenlist ] - -class Dict(TokenConverter): - """Converter to return a repetitive expression as a list, but also - as a dictionary. Each element can also be referenced using the first - token in the expression as its key. Useful for tabular report - scraping when the first column can be used as a item key. - - Example:: - - data_word = Word(alphas) - label = data_word + FollowedBy(':') - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) - - text = "shape: SQUARE posn: upper left color: light blue texture: burlap" - attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) - - # print attributes as plain groups - print(OneOrMore(attr_expr).parseString(text).dump()) - - # instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names - result = Dict(OneOrMore(Group(attr_expr))).parseString(text) - print(result.dump()) - - # access named fields as dict entries, or output as dict - print(result['shape']) - print(result.asDict()) - - prints:: - - ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap'] - [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] - - color: light blue - - posn: upper left - - shape: SQUARE - - texture: burlap - SQUARE - {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'} - - See more examples at :class:`ParseResults` of accessing fields by results name. - """ - def __init__( self, expr ): - super(Dict,self).__init__( expr ) - self.saveAsList = True - - def postParse( self, instring, loc, tokenlist ): - for i,tok in enumerate(tokenlist): - if len(tok) == 0: - continue - ikey = tok[0] - if isinstance(ikey,int): - ikey = _ustr(tok[0]).strip() - if len(tok)==1: - tokenlist[ikey] = _ParseResultsWithOffset("",i) - elif len(tok)==2 and not isinstance(tok[1],ParseResults): - tokenlist[ikey] = _ParseResultsWithOffset(tok[1],i) - else: - dictvalue = tok.copy() #ParseResults(i) - del dictvalue[0] - if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.haskeys()): - tokenlist[ikey] = _ParseResultsWithOffset(dictvalue,i) - else: - tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0],i) - - if self.resultsName: - return [ tokenlist ] - else: - return tokenlist - - -class Suppress(TokenConverter): - """Converter for ignoring the results of a parsed expression. - - Example:: - - source = "a, b, c,d" - wd = Word(alphas) - wd_list1 = wd + ZeroOrMore(',' + wd) - print(wd_list1.parseString(source)) - - # often, delimiters that are useful during parsing are just in the - # way afterward - use Suppress to keep them out of the parsed output - wd_list2 = wd + ZeroOrMore(Suppress(',') + wd) - print(wd_list2.parseString(source)) - - prints:: - - ['a', ',', 'b', ',', 'c', ',', 'd'] - ['a', 'b', 'c', 'd'] - - (See also :class:`delimitedList`.) - """ - def postParse( self, instring, loc, tokenlist ): - return [] - - def suppress( self ): - return self - - -class OnlyOnce(object): - """Wrapper for parse actions, to ensure they are only called once. - """ - def __init__(self, methodCall): - self.callable = _trim_arity(methodCall) - self.called = False - def __call__(self,s,l,t): - if not self.called: - results = self.callable(s,l,t) - self.called = True - return results - raise ParseException(s,l,"") - def reset(self): - self.called = False - -def traceParseAction(f): - """Decorator for debugging parse actions. - - When the parse action is called, this decorator will print - ``">> entering method-name(line:<current_source_line>, <parse_location>, <matched_tokens>)"``. - When the parse action completes, the decorator will print - ``"<<"`` followed by the returned value, or any exception that the parse action raised. - - Example:: - - wd = Word(alphas) - - @traceParseAction - def remove_duplicate_chars(tokens): - return ''.join(sorted(set(''.join(tokens)))) - - wds = OneOrMore(wd).setParseAction(remove_duplicate_chars) - print(wds.parseString("slkdjs sld sldd sdlf sdljf")) - - prints:: - - >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {})) - <<leaving remove_duplicate_chars (ret: 'dfjkls') - ['dfjkls'] - """ - f = _trim_arity(f) - def z(*paArgs): - thisFunc = f.__name__ - s,l,t = paArgs[-3:] - if len(paArgs)>3: - thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc - sys.stderr.write( ">>entering %s(line: '%s', %d, %r)\n" % (thisFunc,line(l,s),l,t) ) - try: - ret = f(*paArgs) - except Exception as exc: - sys.stderr.write( "<<leaving %s (exception: %s)\n" % (thisFunc,exc) ) - raise - sys.stderr.write( "<<leaving %s (ret: %r)\n" % (thisFunc,ret) ) - return ret - try: - z.__name__ = f.__name__ - except AttributeError: - pass - return z - -# -# global helpers -# -def delimitedList( expr, delim=",", combine=False ): - """Helper to define a delimited list of expressions - the delimiter - defaults to ','. By default, the list elements and delimiters can - have intervening whitespace, and comments, but this can be - overridden by passing ``combine=True`` in the constructor. If - ``combine`` is set to ``True``, the matching tokens are - returned as a single token string, with the delimiters included; - otherwise, the matching tokens are returned as a list of tokens, - with the delimiters suppressed. - - Example:: - - delimitedList(Word(alphas)).parseString("aa,bb,cc") # -> ['aa', 'bb', 'cc'] - delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE'] - """ - dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..." - if combine: - return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName) - else: - return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName) - -def countedArray( expr, intExpr=None ): - """Helper to define a counted list of expressions. - - This helper defines a pattern of the form:: - - integer expr expr expr... - - where the leading integer tells how many expr expressions follow. - The matched tokens returns the array of expr tokens as a list - the - leading count token is suppressed. - - If ``intExpr`` is specified, it should be a pyparsing expression - that produces an integer value. - - Example:: - - countedArray(Word(alphas)).parseString('2 ab cd ef') # -> ['ab', 'cd'] - - # in this parser, the leading integer value is given in binary, - # '10' indicating that 2 values are in the array - binaryConstant = Word('01').setParseAction(lambda t: int(t[0], 2)) - countedArray(Word(alphas), intExpr=binaryConstant).parseString('10 ab cd ef') # -> ['ab', 'cd'] - """ - arrayExpr = Forward() - def countFieldParseAction(s,l,t): - n = t[0] - arrayExpr << (n and Group(And([expr]*n)) or Group(empty)) - return [] - if intExpr is None: - intExpr = Word(nums).setParseAction(lambda t:int(t[0])) - else: - intExpr = intExpr.copy() - intExpr.setName("arrayLen") - intExpr.addParseAction(countFieldParseAction, callDuringTry=True) - return ( intExpr + arrayExpr ).setName('(len) ' + _ustr(expr) + '...') - -def _flatten(L): - ret = [] - for i in L: - if isinstance(i,list): - ret.extend(_flatten(i)) - else: - ret.append(i) - return ret - -def matchPreviousLiteral(expr): - """Helper to define an expression that is indirectly defined from - the tokens matched in a previous expression, that is, it looks for - a 'repeat' of a previous expression. For example:: - - first = Word(nums) - second = matchPreviousLiteral(first) - matchExpr = first + ":" + second - - will match ``"1:1"``, but not ``"1:2"``. Because this - matches a previous literal, will also match the leading - ``"1:1"`` in ``"1:10"``. If this is not desired, use - :class:`matchPreviousExpr`. Do *not* use with packrat parsing - enabled. - """ - rep = Forward() - def copyTokenToRepeater(s,l,t): - if t: - if len(t) == 1: - rep << t[0] - else: - # flatten t tokens - tflat = _flatten(t.asList()) - rep << And(Literal(tt) for tt in tflat) - else: - rep << Empty() - expr.addParseAction(copyTokenToRepeater, callDuringTry=True) - rep.setName('(prev) ' + _ustr(expr)) - return rep - -def matchPreviousExpr(expr): - """Helper to define an expression that is indirectly defined from - the tokens matched in a previous expression, that is, it looks for - a 'repeat' of a previous expression. For example:: - - first = Word(nums) - second = matchPreviousExpr(first) - matchExpr = first + ":" + second - - will match ``"1:1"``, but not ``"1:2"``. Because this - matches by expressions, will *not* match the leading ``"1:1"`` - in ``"1:10"``; the expressions are evaluated first, and then - compared, so ``"1"`` is compared with ``"10"``. Do *not* use - with packrat parsing enabled. - """ - rep = Forward() - e2 = expr.copy() - rep <<= e2 - def copyTokenToRepeater(s,l,t): - matchTokens = _flatten(t.asList()) - def mustMatchTheseTokens(s,l,t): - theseTokens = _flatten(t.asList()) - if theseTokens != matchTokens: - raise ParseException("",0,"") - rep.setParseAction( mustMatchTheseTokens, callDuringTry=True ) - expr.addParseAction(copyTokenToRepeater, callDuringTry=True) - rep.setName('(prev) ' + _ustr(expr)) - return rep - -def _escapeRegexRangeChars(s): - #~ escape these chars: ^-] - for c in r"\^-]": - s = s.replace(c,_bslash+c) - s = s.replace("\n",r"\n") - s = s.replace("\t",r"\t") - return _ustr(s) - -def oneOf( strs, caseless=False, useRegex=True ): - """Helper to quickly define a set of alternative Literals, and makes - sure to do longest-first testing when there is a conflict, - regardless of the input order, but returns - a :class:`MatchFirst` for best performance. - - Parameters: - - - strs - a string of space-delimited literals, or a collection of - string literals - - caseless - (default= ``False``) - treat all literals as - caseless - - useRegex - (default= ``True``) - as an optimization, will - generate a Regex object; otherwise, will generate - a :class:`MatchFirst` object (if ``caseless=True``, or if - creating a :class:`Regex` raises an exception) - - Example:: - - comp_oper = oneOf("< = > <= >= !=") - var = Word(alphas) - number = Word(nums) - term = var | number - comparison_expr = term + comp_oper + term - print(comparison_expr.searchString("B = 12 AA=23 B<=AA AA>12")) - - prints:: - - [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']] - """ - if caseless: - isequal = ( lambda a,b: a.upper() == b.upper() ) - masks = ( lambda a,b: b.upper().startswith(a.upper()) ) - parseElementClass = CaselessLiteral - else: - isequal = ( lambda a,b: a == b ) - masks = ( lambda a,b: b.startswith(a) ) - parseElementClass = Literal - - symbols = [] - if isinstance(strs,basestring): - symbols = strs.split() - elif isinstance(strs, Iterable): - symbols = list(strs) - else: - warnings.warn("Invalid argument to oneOf, expected string or iterable", - SyntaxWarning, stacklevel=2) - if not symbols: - return NoMatch() - - i = 0 - while i < len(symbols)-1: - cur = symbols[i] - for j,other in enumerate(symbols[i+1:]): - if ( isequal(other, cur) ): - del symbols[i+j+1] - break - elif ( masks(cur, other) ): - del symbols[i+j+1] - symbols.insert(i,other) - cur = other - break - else: - i += 1 - - if not caseless and useRegex: - #~ print (strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] )) - try: - if len(symbols)==len("".join(symbols)): - return Regex( "[%s]" % "".join(_escapeRegexRangeChars(sym) for sym in symbols) ).setName(' | '.join(symbols)) - else: - return Regex( "|".join(re.escape(sym) for sym in symbols) ).setName(' | '.join(symbols)) - except Exception: - warnings.warn("Exception creating Regex for oneOf, building MatchFirst", - SyntaxWarning, stacklevel=2) - - - # last resort, just use MatchFirst - return MatchFirst(parseElementClass(sym) for sym in symbols).setName(' | '.join(symbols)) - -def dictOf( key, value ): - """Helper to easily and clearly define a dictionary by specifying - the respective patterns for the key and value. Takes care of - defining the :class:`Dict`, :class:`ZeroOrMore`, and - :class:`Group` tokens in the proper order. The key pattern - can include delimiting markers or punctuation, as long as they are - suppressed, thereby leaving the significant key text. The value - pattern can include named results, so that the :class:`Dict` results - can include named token fields. - - Example:: - - text = "shape: SQUARE posn: upper left color: light blue texture: burlap" - attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) - print(OneOrMore(attr_expr).parseString(text).dump()) - - attr_label = label - attr_value = Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join) - - # similar to Dict, but simpler call format - result = dictOf(attr_label, attr_value).parseString(text) - print(result.dump()) - print(result['shape']) - print(result.shape) # object attribute access works too - print(result.asDict()) - - prints:: - - [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] - - color: light blue - - posn: upper left - - shape: SQUARE - - texture: burlap - SQUARE - SQUARE - {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'} - """ - return Dict(OneOrMore(Group(key + value))) - -def originalTextFor(expr, asString=True): - """Helper to return the original, untokenized text for a given - expression. Useful to restore the parsed fields of an HTML start - tag into the raw tag text itself, or to revert separate tokens with - intervening whitespace back to the original matching input text. By - default, returns astring containing the original parsed text. - - If the optional ``asString`` argument is passed as - ``False``, then the return value is - a :class:`ParseResults` containing any results names that - were originally matched, and a single token containing the original - matched text from the input string. So if the expression passed to - :class:`originalTextFor` contains expressions with defined - results names, you must set ``asString`` to ``False`` if you - want to preserve those results name values. - - Example:: - - src = "this is test <b> bold <i>text</i> </b> normal text " - for tag in ("b","i"): - opener,closer = makeHTMLTags(tag) - patt = originalTextFor(opener + SkipTo(closer) + closer) - print(patt.searchString(src)[0]) - - prints:: - - ['<b> bold <i>text</i> </b>'] - ['<i>text</i>'] - """ - locMarker = Empty().setParseAction(lambda s,loc,t: loc) - endlocMarker = locMarker.copy() - endlocMarker.callPreparse = False - matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end") - if asString: - extractText = lambda s,l,t: s[t._original_start:t._original_end] - else: - def extractText(s,l,t): - t[:] = [s[t.pop('_original_start'):t.pop('_original_end')]] - matchExpr.setParseAction(extractText) - matchExpr.ignoreExprs = expr.ignoreExprs - return matchExpr - -def ungroup(expr): - """Helper to undo pyparsing's default grouping of And expressions, - even if all but one are non-empty. - """ - return TokenConverter(expr).addParseAction(lambda t:t[0]) - -def locatedExpr(expr): - """Helper to decorate a returned token with its starting and ending - locations in the input string. - - This helper adds the following results names: - - - locn_start = location where matched expression begins - - locn_end = location where matched expression ends - - value = the actual parsed results - - Be careful if the input text contains ``<TAB>`` characters, you - may want to call :class:`ParserElement.parseWithTabs` - - Example:: - - wd = Word(alphas) - for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"): - print(match) - - prints:: - - [[0, 'ljsdf', 5]] - [[8, 'lksdjjf', 15]] - [[18, 'lkkjj', 23]] - """ - locator = Empty().setParseAction(lambda s,l,t: l) - return Group(locator("locn_start") + expr("value") + locator.copy().leaveWhitespace()("locn_end")) - - -# convenience constants for positional expressions -empty = Empty().setName("empty") -lineStart = LineStart().setName("lineStart") -lineEnd = LineEnd().setName("lineEnd") -stringStart = StringStart().setName("stringStart") -stringEnd = StringEnd().setName("stringEnd") - -_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1]) -_escapedHexChar = Regex(r"\\0?[xX][0-9a-fA-F]+").setParseAction(lambda s,l,t:unichr(int(t[0].lstrip(r'\0x'),16))) -_escapedOctChar = Regex(r"\\0[0-7]+").setParseAction(lambda s,l,t:unichr(int(t[0][1:],8))) -_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | CharsNotIn(r'\]', exact=1) -_charRange = Group(_singleChar + Suppress("-") + _singleChar) -_reBracketExpr = Literal("[") + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]" - -def srange(s): - r"""Helper to easily define string ranges for use in Word - construction. Borrows syntax from regexp '[]' string range - definitions:: - - srange("[0-9]") -> "0123456789" - srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz" - srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_" - - The input string must be enclosed in []'s, and the returned string - is the expanded character set joined into a single string. The - values enclosed in the []'s may be: - - - a single character - - an escaped character with a leading backslash (such as ``\-`` - or ``\]``) - - an escaped hex character with a leading ``'\x'`` - (``\x21``, which is a ``'!'`` character) (``\0x##`` - is also supported for backwards compatibility) - - an escaped octal character with a leading ``'\0'`` - (``\041``, which is a ``'!'`` character) - - a range of any of the above, separated by a dash (``'a-z'``, - etc.) - - any combination of the above (``'aeiouy'``, - ``'a-zA-Z0-9_$'``, etc.) - """ - _expanded = lambda p: p if not isinstance(p,ParseResults) else ''.join(unichr(c) for c in range(ord(p[0]),ord(p[1])+1)) - try: - return "".join(_expanded(part) for part in _reBracketExpr.parseString(s).body) - except Exception: - return "" - -def matchOnlyAtCol(n): - """Helper method for defining parse actions that require matching at - a specific column in the input text. - """ - def verifyCol(strg,locn,toks): - if col(locn,strg) != n: - raise ParseException(strg,locn,"matched token not at column %d" % n) - return verifyCol - -def replaceWith(replStr): - """Helper method for common parse actions that simply return - a literal value. Especially useful when used with - :class:`transformString<ParserElement.transformString>` (). - - Example:: - - num = Word(nums).setParseAction(lambda toks: int(toks[0])) - na = oneOf("N/A NA").setParseAction(replaceWith(math.nan)) - term = na | num - - OneOrMore(term).parseString("324 234 N/A 234") # -> [324, 234, nan, 234] - """ - return lambda s,l,t: [replStr] - -def removeQuotes(s,l,t): - """Helper parse action for removing quotation marks from parsed - quoted strings. - - Example:: - - # by default, quotation marks are included in parsed results - quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"] - - # use removeQuotes to strip quotation marks from parsed results - quotedString.setParseAction(removeQuotes) - quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"] - """ - return t[0][1:-1] - -def tokenMap(func, *args): - """Helper to define a parse action by mapping a function to all - elements of a ParseResults list. If any additional args are passed, - they are forwarded to the given function as additional arguments - after the token, as in - ``hex_integer = Word(hexnums).setParseAction(tokenMap(int, 16))``, - which will convert the parsed data to an integer using base 16. - - Example (compare the last to example in :class:`ParserElement.transformString`:: - - hex_ints = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16)) - hex_ints.runTests(''' - 00 11 22 aa FF 0a 0d 1a - ''') - - upperword = Word(alphas).setParseAction(tokenMap(str.upper)) - OneOrMore(upperword).runTests(''' - my kingdom for a horse - ''') - - wd = Word(alphas).setParseAction(tokenMap(str.title)) - OneOrMore(wd).setParseAction(' '.join).runTests(''' - now is the winter of our discontent made glorious summer by this sun of york - ''') - - prints:: - - 00 11 22 aa FF 0a 0d 1a - [0, 17, 34, 170, 255, 10, 13, 26] - - my kingdom for a horse - ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE'] - - now is the winter of our discontent made glorious summer by this sun of york - ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York'] - """ - def pa(s,l,t): - return [func(tokn, *args) for tokn in t] - - try: - func_name = getattr(func, '__name__', - getattr(func, '__class__').__name__) - except Exception: - func_name = str(func) - pa.__name__ = func_name - - return pa - -upcaseTokens = tokenMap(lambda t: _ustr(t).upper()) -"""(Deprecated) Helper parse action to convert tokens to upper case. -Deprecated in favor of :class:`pyparsing_common.upcaseTokens`""" - -downcaseTokens = tokenMap(lambda t: _ustr(t).lower()) -"""(Deprecated) Helper parse action to convert tokens to lower case. -Deprecated in favor of :class:`pyparsing_common.downcaseTokens`""" - -def _makeTags(tagStr, xml, - suppress_LT=Suppress("<"), - suppress_GT=Suppress(">")): - """Internal helper to construct opening and closing tag expressions, given a tag name""" - if isinstance(tagStr,basestring): - resname = tagStr - tagStr = Keyword(tagStr, caseless=not xml) - else: - resname = tagStr.name - - tagAttrName = Word(alphas,alphanums+"_-:") - if (xml): - tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes ) - openTag = (suppress_LT - + tagStr("tag") - + Dict(ZeroOrMore(Group(tagAttrName + Suppress("=") + tagAttrValue ))) - + Optional("/", default=[False])("empty").setParseAction(lambda s,l,t:t[0]=='/') - + suppress_GT) - else: - tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printables, excludeChars=">") - openTag = (suppress_LT - + tagStr("tag") - + Dict(ZeroOrMore(Group(tagAttrName.setParseAction(downcaseTokens) - + Optional(Suppress("=") + tagAttrValue)))) - + Optional("/",default=[False])("empty").setParseAction(lambda s,l,t:t[0]=='/') - + suppress_GT) - closeTag = Combine(_L("</") + tagStr + ">", adjacent=False) - - openTag.setName("<%s>" % resname) - # add start<tagname> results name in parse action now that ungrouped names are not reported at two levels - openTag.addParseAction(lambda t: t.__setitem__("start"+"".join(resname.replace(":"," ").title().split()), t.copy())) - closeTag = closeTag("end"+"".join(resname.replace(":"," ").title().split())).setName("</%s>" % resname) - openTag.tag = resname - closeTag.tag = resname - openTag.tag_body = SkipTo(closeTag()) - return openTag, closeTag - -def makeHTMLTags(tagStr): - """Helper to construct opening and closing tag expressions for HTML, - given a tag name. Matches tags in either upper or lower case, - attributes with namespaces and with quoted or unquoted values. - - Example:: - - text = '<td>More info at the <a href="https://github.com/pyparsing/pyparsing/wiki">pyparsing</a> wiki page</td>' - # makeHTMLTags returns pyparsing expressions for the opening and - # closing tags as a 2-tuple - a,a_end = makeHTMLTags("A") - link_expr = a + SkipTo(a_end)("link_text") + a_end - - for link in link_expr.searchString(text): - # attributes in the <A> tag (like "href" shown here) are - # also accessible as named results - print(link.link_text, '->', link.href) - - prints:: - - pyparsing -> https://github.com/pyparsing/pyparsing/wiki - """ - return _makeTags( tagStr, False ) - -def makeXMLTags(tagStr): - """Helper to construct opening and closing tag expressions for XML, - given a tag name. Matches tags only in the given upper/lower case. - - Example: similar to :class:`makeHTMLTags` - """ - return _makeTags( tagStr, True ) - -def withAttribute(*args,**attrDict): - """Helper to create a validating parse action to be used with start - tags created with :class:`makeXMLTags` or - :class:`makeHTMLTags`. Use ``withAttribute`` to qualify - a starting tag with a required attribute value, to avoid false - matches on common tags such as ``<TD>`` or ``<DIV>``. - - Call ``withAttribute`` with a series of attribute names and - values. Specify the list of filter attributes names and values as: - - - keyword arguments, as in ``(align="right")``, or - - as an explicit dict with ``**`` operator, when an attribute - name is also a Python reserved word, as in ``**{"class":"Customer", "align":"right"}`` - - a list of name-value tuples, as in ``(("ns1:class", "Customer"), ("ns2:align","right"))`` - - For attribute names with a namespace prefix, you must use the second - form. Attribute names are matched insensitive to upper/lower case. - - If just testing for ``class`` (with or without a namespace), use - :class:`withClass`. - - To verify that the attribute exists, but without specifying a value, - pass ``withAttribute.ANY_VALUE`` as the value. - - Example:: - - html = ''' - <div> - Some text - <div type="grid">1 4 0 1 0</div> - <div type="graph">1,3 2,3 1,1</div> - <div>this has no type</div> - </div> - - ''' - div,div_end = makeHTMLTags("div") - - # only match div tag having a type attribute with value "grid" - div_grid = div().setParseAction(withAttribute(type="grid")) - grid_expr = div_grid + SkipTo(div | div_end)("body") - for grid_header in grid_expr.searchString(html): - print(grid_header.body) - - # construct a match with any div tag having a type attribute, regardless of the value - div_any_type = div().setParseAction(withAttribute(type=withAttribute.ANY_VALUE)) - div_expr = div_any_type + SkipTo(div | div_end)("body") - for div_header in div_expr.searchString(html): - print(div_header.body) - - prints:: - - 1 4 0 1 0 - - 1 4 0 1 0 - 1,3 2,3 1,1 - """ - if args: - attrs = args[:] - else: - attrs = attrDict.items() - attrs = [(k,v) for k,v in attrs] - def pa(s,l,tokens): - for attrName,attrValue in attrs: - if attrName not in tokens: - raise ParseException(s,l,"no matching attribute " + attrName) - if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: - raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" % - (attrName, tokens[attrName], attrValue)) - return pa -withAttribute.ANY_VALUE = object() - -def withClass(classname, namespace=''): - """Simplified version of :class:`withAttribute` when - matching on a div class - made difficult because ``class`` is - a reserved word in Python. - - Example:: - - html = ''' - <div> - Some text - <div class="grid">1 4 0 1 0</div> - <div class="graph">1,3 2,3 1,1</div> - <div>this <div> has no class</div> - </div> - - ''' - div,div_end = makeHTMLTags("div") - div_grid = div().setParseAction(withClass("grid")) - - grid_expr = div_grid + SkipTo(div | div_end)("body") - for grid_header in grid_expr.searchString(html): - print(grid_header.body) - - div_any_type = div().setParseAction(withClass(withAttribute.ANY_VALUE)) - div_expr = div_any_type + SkipTo(div | div_end)("body") - for div_header in div_expr.searchString(html): - print(div_header.body) - - prints:: - - 1 4 0 1 0 - - 1 4 0 1 0 - 1,3 2,3 1,1 - """ - classattr = "%s:class" % namespace if namespace else "class" - return withAttribute(**{classattr : classname}) - -opAssoc = SimpleNamespace() -opAssoc.LEFT = object() -opAssoc.RIGHT = object() - -def infixNotation( baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')') ): - """Helper method for constructing grammars of expressions made up of - operators working in a precedence hierarchy. Operators may be unary - or binary, left- or right-associative. Parse actions can also be - attached to operator expressions. The generated parser will also - recognize the use of parentheses to override operator precedences - (see example below). - - Note: if you define a deep operator list, you may see performance - issues when using infixNotation. See - :class:`ParserElement.enablePackrat` for a mechanism to potentially - improve your parser performance. - - Parameters: - - baseExpr - expression representing the most basic element for the - nested - - opList - list of tuples, one for each operator precedence level - in the expression grammar; each tuple is of the form ``(opExpr, - numTerms, rightLeftAssoc, parseAction)``, where: - - - opExpr is the pyparsing expression for the operator; may also - be a string, which will be converted to a Literal; if numTerms - is 3, opExpr is a tuple of two expressions, for the two - operators separating the 3 terms - - numTerms is the number of terms for this operator (must be 1, - 2, or 3) - - rightLeftAssoc is the indicator whether the operator is right - or left associative, using the pyparsing-defined constants - ``opAssoc.RIGHT`` and ``opAssoc.LEFT``. - - parseAction is the parse action to be associated with - expressions matching this operator expression (the parse action - tuple member may be omitted); if the parse action is passed - a tuple or list of functions, this is equivalent to calling - ``setParseAction(*fn)`` - (:class:`ParserElement.setParseAction`) - - lpar - expression for matching left-parentheses - (default= ``Suppress('(')``) - - rpar - expression for matching right-parentheses - (default= ``Suppress(')')``) - - Example:: - - # simple example of four-function arithmetic with ints and - # variable names - integer = pyparsing_common.signed_integer - varname = pyparsing_common.identifier - - arith_expr = infixNotation(integer | varname, - [ - ('-', 1, opAssoc.RIGHT), - (oneOf('* /'), 2, opAssoc.LEFT), - (oneOf('+ -'), 2, opAssoc.LEFT), - ]) - - arith_expr.runTests(''' - 5+3*6 - (5+3)*6 - -2--11 - ''', fullDump=False) - - prints:: - - 5+3*6 - [[5, '+', [3, '*', 6]]] - - (5+3)*6 - [[[5, '+', 3], '*', 6]] - - -2--11 - [[['-', 2], '-', ['-', 11]]] - """ - # captive version of FollowedBy that does not do parse actions or capture results names - class _FB(FollowedBy): - def parseImpl(self, instring, loc, doActions=True): - self.expr.tryParse(instring, loc) - return loc, [] - - ret = Forward() - lastExpr = baseExpr | ( lpar + ret + rpar ) - for i,operDef in enumerate(opList): - opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] - termName = "%s term" % opExpr if arity < 3 else "%s%s term" % opExpr - if arity == 3: - if opExpr is None or len(opExpr) != 2: - raise ValueError( - "if numterms=3, opExpr must be a tuple or list of two expressions") - opExpr1, opExpr2 = opExpr - thisExpr = Forward().setName(termName) - if rightLeftAssoc == opAssoc.LEFT: - if arity == 1: - matchExpr = _FB(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) ) - elif arity == 2: - if opExpr is not None: - matchExpr = _FB(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) - else: - matchExpr = _FB(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) ) - elif arity == 3: - matchExpr = _FB(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \ - Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr ) - else: - raise ValueError("operator must be unary (1), binary (2), or ternary (3)") - elif rightLeftAssoc == opAssoc.RIGHT: - if arity == 1: - # try to avoid LR with this extra test - if not isinstance(opExpr, Optional): - opExpr = Optional(opExpr) - matchExpr = _FB(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) - elif arity == 2: - if opExpr is not None: - matchExpr = _FB(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) - else: - matchExpr = _FB(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) ) - elif arity == 3: - matchExpr = _FB(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \ - Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr ) - else: - raise ValueError("operator must be unary (1), binary (2), or ternary (3)") - else: - raise ValueError("operator must indicate right or left associativity") - if pa: - if isinstance(pa, (tuple, list)): - matchExpr.setParseAction(*pa) - else: - matchExpr.setParseAction(pa) - thisExpr <<= ( matchExpr.setName(termName) | lastExpr ) - lastExpr = thisExpr - ret <<= lastExpr - return ret - -operatorPrecedence = infixNotation -"""(Deprecated) Former name of :class:`infixNotation`, will be -dropped in a future release.""" - -dblQuotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"').setName("string enclosed in double quotes") -sglQuotedString = Combine(Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("string enclosed in single quotes") -quotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"'| - Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("quotedString using single or double quotes") -unicodeString = Combine(_L('u') + quotedString.copy()).setName("unicode string literal") - -def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString.copy()): - """Helper method for defining nested lists enclosed in opening and - closing delimiters ("(" and ")" are the default). - - Parameters: - - opener - opening character for a nested list - (default= ``"("``); can also be a pyparsing expression - - closer - closing character for a nested list - (default= ``")"``); can also be a pyparsing expression - - content - expression for items within the nested lists - (default= ``None``) - - ignoreExpr - expression for ignoring opening and closing - delimiters (default= :class:`quotedString`) - - If an expression is not provided for the content argument, the - nested expression will capture all whitespace-delimited content - between delimiters as a list of separate values. - - Use the ``ignoreExpr`` argument to define expressions that may - contain opening or closing characters that should not be treated as - opening or closing characters for nesting, such as quotedString or - a comment expression. Specify multiple expressions using an - :class:`Or` or :class:`MatchFirst`. The default is - :class:`quotedString`, but if no expressions are to be ignored, then - pass ``None`` for this argument. - - Example:: - - data_type = oneOf("void int short long char float double") - decl_data_type = Combine(data_type + Optional(Word('*'))) - ident = Word(alphas+'_', alphanums+'_') - number = pyparsing_common.number - arg = Group(decl_data_type + ident) - LPAR,RPAR = map(Suppress, "()") - - code_body = nestedExpr('{', '}', ignoreExpr=(quotedString | cStyleComment)) - - c_function = (decl_data_type("type") - + ident("name") - + LPAR + Optional(delimitedList(arg), [])("args") + RPAR - + code_body("body")) - c_function.ignore(cStyleComment) - - source_code = ''' - int is_odd(int x) { - return (x%2); - } - - int dec_to_hex(char hchar) { - if (hchar >= '0' && hchar <= '9') { - return (ord(hchar)-ord('0')); - } else { - return (10+ord(hchar)-ord('A')); - } - } - ''' - for func in c_function.searchString(source_code): - print("%(name)s (%(type)s) args: %(args)s" % func) - - - prints:: - - is_odd (int) args: [['int', 'x']] - dec_to_hex (int) args: [['char', 'hchar']] - """ - if opener == closer: - raise ValueError("opening and closing strings cannot be the same") - if content is None: - if isinstance(opener,basestring) and isinstance(closer,basestring): - if len(opener) == 1 and len(closer)==1: - if ignoreExpr is not None: - content = (Combine(OneOrMore(~ignoreExpr + - CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS,exact=1)) - ).setParseAction(lambda t:t[0].strip())) - else: - content = (empty.copy()+CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS - ).setParseAction(lambda t:t[0].strip())) - else: - if ignoreExpr is not None: - content = (Combine(OneOrMore(~ignoreExpr + - ~Literal(opener) + ~Literal(closer) + - CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) - ).setParseAction(lambda t:t[0].strip())) - else: - content = (Combine(OneOrMore(~Literal(opener) + ~Literal(closer) + - CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) - ).setParseAction(lambda t:t[0].strip())) - else: - raise ValueError("opening and closing arguments must be strings if no content expression is given") - ret = Forward() - if ignoreExpr is not None: - ret <<= Group( Suppress(opener) + ZeroOrMore( ignoreExpr | ret | content ) + Suppress(closer) ) - else: - ret <<= Group( Suppress(opener) + ZeroOrMore( ret | content ) + Suppress(closer) ) - ret.setName('nested %s%s expression' % (opener,closer)) - return ret - -def indentedBlock(blockStatementExpr, indentStack, indent=True): - """Helper method for defining space-delimited indentation blocks, - such as those used to define block statements in Python source code. - - Parameters: - - - blockStatementExpr - expression defining syntax of statement that - is repeated within the indented block - - indentStack - list created by caller to manage indentation stack - (multiple statementWithIndentedBlock expressions within a single - grammar should share a common indentStack) - - indent - boolean indicating whether block must be indented beyond - the the current level; set to False for block of left-most - statements (default= ``True``) - - A valid block must contain at least one ``blockStatement``. - - Example:: - - data = ''' - def A(z): - A1 - B = 100 - G = A2 - A2 - A3 - B - def BB(a,b,c): - BB1 - def BBA(): - bba1 - bba2 - bba3 - C - D - def spam(x,y): - def eggs(z): - pass - ''' - - - indentStack = [1] - stmt = Forward() - - identifier = Word(alphas, alphanums) - funcDecl = ("def" + identifier + Group( "(" + Optional( delimitedList(identifier) ) + ")" ) + ":") - func_body = indentedBlock(stmt, indentStack) - funcDef = Group( funcDecl + func_body ) - - rvalue = Forward() - funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")") - rvalue << (funcCall | identifier | Word(nums)) - assignment = Group(identifier + "=" + rvalue) - stmt << ( funcDef | assignment | identifier ) - - module_body = OneOrMore(stmt) - - parseTree = module_body.parseString(data) - parseTree.pprint() - - prints:: - - [['def', - 'A', - ['(', 'z', ')'], - ':', - [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], - 'B', - ['def', - 'BB', - ['(', 'a', 'b', 'c', ')'], - ':', - [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], - 'C', - 'D', - ['def', - 'spam', - ['(', 'x', 'y', ')'], - ':', - [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] - """ - backup_stack = indentStack[:] - - def reset_stack(): - indentStack[:] = backup_stack - - def checkPeerIndent(s,l,t): - if l >= len(s): return - curCol = col(l,s) - if curCol != indentStack[-1]: - if curCol > indentStack[-1]: - raise ParseException(s,l,"illegal nesting") - raise ParseException(s,l,"not a peer entry") - - def checkSubIndent(s,l,t): - curCol = col(l,s) - if curCol > indentStack[-1]: - indentStack.append( curCol ) - else: - raise ParseException(s,l,"not a subentry") - - def checkUnindent(s,l,t): - if l >= len(s): return - curCol = col(l,s) - if not(indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]): - raise ParseException(s,l,"not an unindent") - indentStack.pop() - - NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress()) - INDENT = (Empty() + Empty().setParseAction(checkSubIndent)).setName('INDENT') - PEER = Empty().setParseAction(checkPeerIndent).setName('') - UNDENT = Empty().setParseAction(checkUnindent).setName('UNINDENT') - if indent: - smExpr = Group( Optional(NL) + - #~ FollowedBy(blockStatementExpr) + - INDENT + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) + UNDENT) - else: - smExpr = Group( Optional(NL) + - (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) ) - smExpr.setFailAction(lambda a, b, c, d: reset_stack()) - blockStatementExpr.ignore(_bslash + LineEnd()) - return smExpr.setName('indented block') - -alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]") -punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]") - -anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_:").setName('any tag')) -_htmlEntityMap = dict(zip("gt lt amp nbsp quot apos".split(),'><& "\'')) -commonHTMLEntity = Regex('&(?P<entity>' + '|'.join(_htmlEntityMap.keys()) +");").setName("common HTML entity") -def replaceHTMLEntity(t): - """Helper parser action to replace common HTML entities with their special characters""" - return _htmlEntityMap.get(t.entity) - -# it's easy to get these comment structures wrong - they're very common, so may as well make them available -cStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/').setName("C style comment") -"Comment of the form ``/* ... */``" - -htmlComment = Regex(r"<!--[\s\S]*?-->").setName("HTML comment") -"Comment of the form ``<!-- ... -->``" - -restOfLine = Regex(r".*").leaveWhitespace().setName("rest of line") -dblSlashComment = Regex(r"//(?:\\\n|[^\n])*").setName("// comment") -"Comment of the form ``// ... (to end of line)``" - -cppStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/'| dblSlashComment).setName("C++ style comment") -"Comment of either form :class:`cStyleComment` or :class:`dblSlashComment`" - -javaStyleComment = cppStyleComment -"Same as :class:`cppStyleComment`" - -pythonStyleComment = Regex(r"#.*").setName("Python style comment") -"Comment of the form ``# ... (to end of line)``" - -_commasepitem = Combine(OneOrMore(Word(printables, excludeChars=',') + - Optional( Word(" \t") + - ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem") -commaSeparatedList = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("commaSeparatedList") -"""(Deprecated) Predefined expression of 1 or more printable words or -quoted strings, separated by commas. - -This expression is deprecated in favor of :class:`pyparsing_common.comma_separated_list`. -""" - -# some other useful expressions - using lower-case class name since we are really using this as a namespace -class pyparsing_common: - """Here are some common low-level expressions that may be useful in - jump-starting parser development: - - - numeric forms (:class:`integers<integer>`, :class:`reals<real>`, - :class:`scientific notation<sci_real>`) - - common :class:`programming identifiers<identifier>` - - network addresses (:class:`MAC<mac_address>`, - :class:`IPv4<ipv4_address>`, :class:`IPv6<ipv6_address>`) - - ISO8601 :class:`dates<iso8601_date>` and - :class:`datetime<iso8601_datetime>` - - :class:`UUID<uuid>` - - :class:`comma-separated list<comma_separated_list>` - - Parse actions: - - - :class:`convertToInteger` - - :class:`convertToFloat` - - :class:`convertToDate` - - :class:`convertToDatetime` - - :class:`stripHTMLTags` - - :class:`upcaseTokens` - - :class:`downcaseTokens` - - Example:: - - pyparsing_common.number.runTests(''' - # any int or real number, returned as the appropriate type - 100 - -100 - +100 - 3.14159 - 6.02e23 - 1e-12 - ''') - - pyparsing_common.fnumber.runTests(''' - # any int or real number, returned as float - 100 - -100 - +100 - 3.14159 - 6.02e23 - 1e-12 - ''') - - pyparsing_common.hex_integer.runTests(''' - # hex numbers - 100 - FF - ''') - - pyparsing_common.fraction.runTests(''' - # fractions - 1/2 - -3/4 - ''') - - pyparsing_common.mixed_integer.runTests(''' - # mixed fractions - 1 - 1/2 - -3/4 - 1-3/4 - ''') - - import uuid - pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) - pyparsing_common.uuid.runTests(''' - # uuid - 12345678-1234-5678-1234-567812345678 - ''') - - prints:: - - # any int or real number, returned as the appropriate type - 100 - [100] - - -100 - [-100] - - +100 - [100] - - 3.14159 - [3.14159] - - 6.02e23 - [6.02e+23] - - 1e-12 - [1e-12] - - # any int or real number, returned as float - 100 - [100.0] - - -100 - [-100.0] - - +100 - [100.0] - - 3.14159 - [3.14159] - - 6.02e23 - [6.02e+23] - - 1e-12 - [1e-12] - - # hex numbers - 100 - [256] - - FF - [255] - - # fractions - 1/2 - [0.5] - - -3/4 - [-0.75] - - # mixed fractions - 1 - [1] - - 1/2 - [0.5] - - -3/4 - [-0.75] - - 1-3/4 - [1.75] - - # uuid - 12345678-1234-5678-1234-567812345678 - [UUID('12345678-1234-5678-1234-567812345678')] - """ - - convertToInteger = tokenMap(int) - """ - Parse action for converting parsed integers to Python int - """ - - convertToFloat = tokenMap(float) - """ - Parse action for converting parsed numbers to Python float - """ - - integer = Word(nums).setName("integer").setParseAction(convertToInteger) - """expression that parses an unsigned integer, returns an int""" - - hex_integer = Word(hexnums).setName("hex integer").setParseAction(tokenMap(int,16)) - """expression that parses a hexadecimal integer, returns an int""" - - signed_integer = Regex(r'[+-]?\d+').setName("signed integer").setParseAction(convertToInteger) - """expression that parses an integer with optional leading sign, returns an int""" - - fraction = (signed_integer().setParseAction(convertToFloat) + '/' + signed_integer().setParseAction(convertToFloat)).setName("fraction") - """fractional expression of an integer divided by an integer, returns a float""" - fraction.addParseAction(lambda t: t[0]/t[-1]) - - mixed_integer = (fraction | signed_integer + Optional(Optional('-').suppress() + fraction)).setName("fraction or mixed integer-fraction") - """mixed integer of the form 'integer - fraction', with optional leading integer, returns float""" - mixed_integer.addParseAction(sum) - - real = Regex(r'[+-]?\d+\.\d*').setName("real number").setParseAction(convertToFloat) - """expression that parses a floating point number and returns a float""" - - sci_real = Regex(r'[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)').setName("real number with scientific notation").setParseAction(convertToFloat) - """expression that parses a floating point number with optional - scientific notation and returns a float""" - - # streamlining this expression makes the docs nicer-looking - number = (sci_real | real | signed_integer).streamline() - """any numeric expression, returns the corresponding Python type""" - - fnumber = Regex(r'[+-]?\d+\.?\d*([eE][+-]?\d+)?').setName("fnumber").setParseAction(convertToFloat) - """any int or real number, returned as float""" - - identifier = Word(alphas+'_', alphanums+'_').setName("identifier") - """typical code identifier (leading alpha or '_', followed by 0 or more alphas, nums, or '_')""" - - ipv4_address = Regex(r'(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}').setName("IPv4 address") - "IPv4 address (``0.0.0.0 - 255.255.255.255``)" - - _ipv6_part = Regex(r'[0-9a-fA-F]{1,4}').setName("hex_integer") - _full_ipv6_address = (_ipv6_part + (':' + _ipv6_part)*7).setName("full IPv6 address") - _short_ipv6_address = (Optional(_ipv6_part + (':' + _ipv6_part)*(0,6)) + "::" + Optional(_ipv6_part + (':' + _ipv6_part)*(0,6))).setName("short IPv6 address") - _short_ipv6_address.addCondition(lambda t: sum(1 for tt in t if pyparsing_common._ipv6_part.matches(tt)) < 8) - _mixed_ipv6_address = ("::ffff:" + ipv4_address).setName("mixed IPv6 address") - ipv6_address = Combine((_full_ipv6_address | _mixed_ipv6_address | _short_ipv6_address).setName("IPv6 address")).setName("IPv6 address") - "IPv6 address (long, short, or mixed form)" - - mac_address = Regex(r'[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}').setName("MAC address") - "MAC address xx:xx:xx:xx:xx (may also have '-' or '.' delimiters)" - - @staticmethod - def convertToDate(fmt="%Y-%m-%d"): - """ - Helper to create a parse action for converting parsed date string to Python datetime.date - - Params - - - fmt - format to be passed to datetime.strptime (default= ``"%Y-%m-%d"``) - - Example:: - - date_expr = pyparsing_common.iso8601_date.copy() - date_expr.setParseAction(pyparsing_common.convertToDate()) - print(date_expr.parseString("1999-12-31")) - - prints:: - - [datetime.date(1999, 12, 31)] - """ - def cvt_fn(s,l,t): - try: - return datetime.strptime(t[0], fmt).date() - except ValueError as ve: - raise ParseException(s, l, str(ve)) - return cvt_fn - - @staticmethod - def convertToDatetime(fmt="%Y-%m-%dT%H:%M:%S.%f"): - """Helper to create a parse action for converting parsed - datetime string to Python datetime.datetime - - Params - - - fmt - format to be passed to datetime.strptime (default= ``"%Y-%m-%dT%H:%M:%S.%f"``) - - Example:: - - dt_expr = pyparsing_common.iso8601_datetime.copy() - dt_expr.setParseAction(pyparsing_common.convertToDatetime()) - print(dt_expr.parseString("1999-12-31T23:59:59.999")) - - prints:: - - [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] - """ - def cvt_fn(s,l,t): - try: - return datetime.strptime(t[0], fmt) - except ValueError as ve: - raise ParseException(s, l, str(ve)) - return cvt_fn - - iso8601_date = Regex(r'(?P<year>\d{4})(?:-(?P<month>\d\d)(?:-(?P<day>\d\d))?)?').setName("ISO8601 date") - "ISO8601 date (``yyyy-mm-dd``)" - - iso8601_datetime = Regex(r'(?P<year>\d{4})-(?P<month>\d\d)-(?P<day>\d\d)[T ](?P<hour>\d\d):(?P<minute>\d\d)(:(?P<second>\d\d(\.\d*)?)?)?(?P<tz>Z|[+-]\d\d:?\d\d)?').setName("ISO8601 datetime") - "ISO8601 datetime (``yyyy-mm-ddThh:mm:ss.s(Z|+-00:00)``) - trailing seconds, milliseconds, and timezone optional; accepts separating ``'T'`` or ``' '``" - - uuid = Regex(r'[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}').setName("UUID") - "UUID (``xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx``)" - - _html_stripper = anyOpenTag.suppress() | anyCloseTag.suppress() - @staticmethod - def stripHTMLTags(s, l, tokens): - """Parse action to remove HTML tags from web page HTML source - - Example:: - - # strip HTML links from normal text - text = '<td>More info at the <a href="https://github.com/pyparsing/pyparsing/wiki">pyparsing</a> wiki page</td>' - td,td_end = makeHTMLTags("TD") - table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end - print(table_text.parseString(text).body) - - Prints:: - - More info at the pyparsing wiki page - """ - return pyparsing_common._html_stripper.transformString(tokens[0]) - - _commasepitem = Combine(OneOrMore(~Literal(",") + ~LineEnd() + Word(printables, excludeChars=',') - + Optional( White(" \t") ) ) ).streamline().setName("commaItem") - comma_separated_list = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("comma separated list") - """Predefined expression of 1 or more printable words or quoted strings, separated by commas.""" - - upcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).upper())) - """Parse action to convert tokens to upper case.""" - - downcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).lower())) - """Parse action to convert tokens to lower case.""" - - -class _lazyclassproperty(object): - def __init__(self, fn): - self.fn = fn - self.__doc__ = fn.__doc__ - self.__name__ = fn.__name__ - - def __get__(self, obj, cls): - if cls is None: - cls = type(obj) - if not hasattr(cls, '_intern') or any(cls._intern is getattr(superclass, '_intern', []) for superclass in cls.__mro__[1:]): - cls._intern = {} - attrname = self.fn.__name__ - if attrname not in cls._intern: - cls._intern[attrname] = self.fn(cls) - return cls._intern[attrname] - - -class unicode_set(object): - """ - A set of Unicode characters, for language-specific strings for - ``alphas``, ``nums``, ``alphanums``, and ``printables``. - A unicode_set is defined by a list of ranges in the Unicode character - set, in a class attribute ``_ranges``, such as:: - - _ranges = [(0x0020, 0x007e), (0x00a0, 0x00ff),] - - A unicode set can also be defined using multiple inheritance of other unicode sets:: - - class CJK(Chinese, Japanese, Korean): - pass - """ - _ranges = [] - - @classmethod - def _get_chars_for_ranges(cls): - ret = [] - for cc in cls.__mro__: - if cc is unicode_set: - break - for rr in cc._ranges: - ret.extend(range(rr[0], rr[-1]+1)) - return [unichr(c) for c in sorted(set(ret))] - - @_lazyclassproperty - def printables(cls): - "all non-whitespace characters in this range" - return u''.join(filterfalse(unicode.isspace, cls._get_chars_for_ranges())) - - @_lazyclassproperty - def alphas(cls): - "all alphabetic characters in this range" - return u''.join(filter(unicode.isalpha, cls._get_chars_for_ranges())) - - @_lazyclassproperty - def nums(cls): - "all numeric digit characters in this range" - return u''.join(filter(unicode.isdigit, cls._get_chars_for_ranges())) - - @_lazyclassproperty - def alphanums(cls): - "all alphanumeric characters in this range" - return cls.alphas + cls.nums - - -class pyparsing_unicode(unicode_set): - """ - A namespace class for defining common language unicode_sets. - """ - _ranges = [(32, sys.maxunicode)] - - class Latin1(unicode_set): - "Unicode set for Latin-1 Unicode Character Range" - _ranges = [(0x0020, 0x007e), (0x00a0, 0x00ff),] - - class LatinA(unicode_set): - "Unicode set for Latin-A Unicode Character Range" - _ranges = [(0x0100, 0x017f),] - - class LatinB(unicode_set): - "Unicode set for Latin-B Unicode Character Range" - _ranges = [(0x0180, 0x024f),] - - class Greek(unicode_set): - "Unicode set for Greek Unicode Character Ranges" - _ranges = [ - (0x0370, 0x03ff), (0x1f00, 0x1f15), (0x1f18, 0x1f1d), (0x1f20, 0x1f45), (0x1f48, 0x1f4d), - (0x1f50, 0x1f57), (0x1f59,), (0x1f5b,), (0x1f5d,), (0x1f5f, 0x1f7d), (0x1f80, 0x1fb4), (0x1fb6, 0x1fc4), - (0x1fc6, 0x1fd3), (0x1fd6, 0x1fdb), (0x1fdd, 0x1fef), (0x1ff2, 0x1ff4), (0x1ff6, 0x1ffe), - ] - - class Cyrillic(unicode_set): - "Unicode set for Cyrillic Unicode Character Range" - _ranges = [(0x0400, 0x04ff)] - - class Chinese(unicode_set): - "Unicode set for Chinese Unicode Character Range" - _ranges = [(0x4e00, 0x9fff), (0x3000, 0x303f), ] - - class Japanese(unicode_set): - "Unicode set for Japanese Unicode Character Range, combining Kanji, Hiragana, and Katakana ranges" - _ranges = [ ] - - class Kanji(unicode_set): - "Unicode set for Kanji Unicode Character Range" - _ranges = [(0x4E00, 0x9Fbf), (0x3000, 0x303f), ] - - class Hiragana(unicode_set): - "Unicode set for Hiragana Unicode Character Range" - _ranges = [(0x3040, 0x309f), ] - - class Katakana(unicode_set): - "Unicode set for Katakana Unicode Character Range" - _ranges = [(0x30a0, 0x30ff), ] - - class Korean(unicode_set): - "Unicode set for Korean Unicode Character Range" - _ranges = [(0xac00, 0xd7af), (0x1100, 0x11ff), (0x3130, 0x318f), (0xa960, 0xa97f), (0xd7b0, 0xd7ff), (0x3000, 0x303f), ] - - class CJK(Chinese, Japanese, Korean): - "Unicode set for combined Chinese, Japanese, and Korean (CJK) Unicode Character Range" - pass - - class Thai(unicode_set): - "Unicode set for Thai Unicode Character Range" - _ranges = [(0x0e01, 0x0e3a), (0x0e3f, 0x0e5b), ] - - class Arabic(unicode_set): - "Unicode set for Arabic Unicode Character Range" - _ranges = [(0x0600, 0x061b), (0x061e, 0x06ff), (0x0700, 0x077f), ] - - class Hebrew(unicode_set): - "Unicode set for Hebrew Unicode Character Range" - _ranges = [(0x0590, 0x05ff), ] - - class Devanagari(unicode_set): - "Unicode set for Devanagari Unicode Character Range" - _ranges = [(0x0900, 0x097f), (0xa8e0, 0xa8ff)] - -pyparsing_unicode.Japanese._ranges = (pyparsing_unicode.Japanese.Kanji._ranges - + pyparsing_unicode.Japanese.Hiragana._ranges - + pyparsing_unicode.Japanese.Katakana._ranges) - -# define ranges in language character sets -if PY_3: - setattr(pyparsing_unicode, "العربية", pyparsing_unicode.Arabic) - setattr(pyparsing_unicode, "中文", pyparsing_unicode.Chinese) - setattr(pyparsing_unicode, "кириллица", pyparsing_unicode.Cyrillic) - setattr(pyparsing_unicode, "Ελληνικά", pyparsing_unicode.Greek) - setattr(pyparsing_unicode, "עִברִית", pyparsing_unicode.Hebrew) - setattr(pyparsing_unicode, "日本語", pyparsing_unicode.Japanese) - setattr(pyparsing_unicode.Japanese, "漢字", pyparsing_unicode.Japanese.Kanji) - setattr(pyparsing_unicode.Japanese, "カタカナ", pyparsing_unicode.Japanese.Katakana) - setattr(pyparsing_unicode.Japanese, "ひらがな", pyparsing_unicode.Japanese.Hiragana) - setattr(pyparsing_unicode, "한국어", pyparsing_unicode.Korean) - setattr(pyparsing_unicode, "ไทย", pyparsing_unicode.Thai) - setattr(pyparsing_unicode, "देवनागरी", pyparsing_unicode.Devanagari) - - -if __name__ == "__main__": - - selectToken = CaselessLiteral("select") - fromToken = CaselessLiteral("from") - - ident = Word(alphas, alphanums + "_$") - - columnName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) - columnNameList = Group(delimitedList(columnName)).setName("columns") - columnSpec = ('*' | columnNameList) - - tableName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) - tableNameList = Group(delimitedList(tableName)).setName("tables") - - simpleSQL = selectToken("command") + columnSpec("columns") + fromToken + tableNameList("tables") - - # demo runTests method, including embedded comments in test string - simpleSQL.runTests(""" - # '*' as column list and dotted table name - select * from SYS.XYZZY - - # caseless match on "SELECT", and casts back to "select" - SELECT * from XYZZY, ABC - - # list of column names, and mixed case SELECT keyword - Select AA,BB,CC from Sys.dual - - # multiple tables - Select A, B, C from Sys.dual, Table2 - - # invalid SELECT keyword - should fail - Xelect A, B, C from Sys.dual - - # incomplete command - should fail - Select - - # invalid column name - should fail - Select ^^^ frox Sys.dual - - """) - - pyparsing_common.number.runTests(""" - 100 - -100 - +100 - 3.14159 - 6.02e23 - 1e-12 - """) - - # any int or real number, returned as float - pyparsing_common.fnumber.runTests(""" - 100 - -100 - +100 - 3.14159 - 6.02e23 - 1e-12 - """) - - pyparsing_common.hex_integer.runTests(""" - 100 - FF - """) - - import uuid - pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) - pyparsing_common.uuid.runTests(""" - 12345678-1234-5678-1234-567812345678 - """) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/__init__.py deleted file mode 100644 index 8ed060f..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .core import TomlError -from .parser import load, loads -from .test import translate_to_test -from .writer import dump, dumps \ No newline at end of file diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/core.py b/venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/core.py deleted file mode 100644 index c182734..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/core.py +++ /dev/null @@ -1,13 +0,0 @@ -class TomlError(RuntimeError): - def __init__(self, message, line, col, filename): - RuntimeError.__init__(self, message, line, col, filename) - self.message = message - self.line = line - self.col = col - self.filename = filename - - def __str__(self): - return '{}({}, {}): {}'.format(self.filename, self.line, self.col, self.message) - - def __repr__(self): - return 'TomlError({!r}, {!r}, {!r}, {!r})'.format(self.message, self.line, self.col, self.filename) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/parser.py b/venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/parser.py deleted file mode 100644 index 3493aa6..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/parser.py +++ /dev/null @@ -1,341 +0,0 @@ -import string, re, sys, datetime -from .core import TomlError -from .utils import rfc3339_re, parse_rfc3339_re - -if sys.version_info[0] == 2: - _chr = unichr -else: - _chr = chr - -def load(fin, translate=lambda t, x, v: v, object_pairs_hook=dict): - return loads(fin.read(), translate=translate, object_pairs_hook=object_pairs_hook, filename=getattr(fin, 'name', repr(fin))) - -def loads(s, filename='<string>', translate=lambda t, x, v: v, object_pairs_hook=dict): - if isinstance(s, bytes): - s = s.decode('utf-8') - - s = s.replace('\r\n', '\n') - - root = object_pairs_hook() - tables = object_pairs_hook() - scope = root - - src = _Source(s, filename=filename) - ast = _p_toml(src, object_pairs_hook=object_pairs_hook) - - def error(msg): - raise TomlError(msg, pos[0], pos[1], filename) - - def process_value(v, object_pairs_hook): - kind, text, value, pos = v - if kind == 'str' and value.startswith('\n'): - value = value[1:] - if kind == 'array': - if value and any(k != value[0][0] for k, t, v, p in value[1:]): - error('array-type-mismatch') - value = [process_value(item, object_pairs_hook=object_pairs_hook) for item in value] - elif kind == 'table': - value = object_pairs_hook([(k, process_value(value[k], object_pairs_hook=object_pairs_hook)) for k in value]) - return translate(kind, text, value) - - for kind, value, pos in ast: - if kind == 'kv': - k, v = value - if k in scope: - error('duplicate_keys. Key "{0}" was used more than once.'.format(k)) - scope[k] = process_value(v, object_pairs_hook=object_pairs_hook) - else: - is_table_array = (kind == 'table_array') - cur = tables - for name in value[:-1]: - if isinstance(cur.get(name), list): - d, cur = cur[name][-1] - else: - d, cur = cur.setdefault(name, (None, object_pairs_hook())) - - scope = object_pairs_hook() - name = value[-1] - if name not in cur: - if is_table_array: - cur[name] = [(scope, object_pairs_hook())] - else: - cur[name] = (scope, object_pairs_hook()) - elif isinstance(cur[name], list): - if not is_table_array: - error('table_type_mismatch') - cur[name].append((scope, object_pairs_hook())) - else: - if is_table_array: - error('table_type_mismatch') - old_scope, next_table = cur[name] - if old_scope is not None: - error('duplicate_tables') - cur[name] = (scope, next_table) - - def merge_tables(scope, tables): - if scope is None: - scope = object_pairs_hook() - for k in tables: - if k in scope: - error('key_table_conflict') - v = tables[k] - if isinstance(v, list): - scope[k] = [merge_tables(sc, tbl) for sc, tbl in v] - else: - scope[k] = merge_tables(v[0], v[1]) - return scope - - return merge_tables(root, tables) - -class _Source: - def __init__(self, s, filename=None): - self.s = s - self._pos = (1, 1) - self._last = None - self._filename = filename - self.backtrack_stack = [] - - def last(self): - return self._last - - def pos(self): - return self._pos - - def fail(self): - return self._expect(None) - - def consume_dot(self): - if self.s: - self._last = self.s[0] - self.s = self[1:] - self._advance(self._last) - return self._last - return None - - def expect_dot(self): - return self._expect(self.consume_dot()) - - def consume_eof(self): - if not self.s: - self._last = '' - return True - return False - - def expect_eof(self): - return self._expect(self.consume_eof()) - - def consume(self, s): - if self.s.startswith(s): - self.s = self.s[len(s):] - self._last = s - self._advance(s) - return True - return False - - def expect(self, s): - return self._expect(self.consume(s)) - - def consume_re(self, re): - m = re.match(self.s) - if m: - self.s = self.s[len(m.group(0)):] - self._last = m - self._advance(m.group(0)) - return m - return None - - def expect_re(self, re): - return self._expect(self.consume_re(re)) - - def __enter__(self): - self.backtrack_stack.append((self.s, self._pos)) - - def __exit__(self, type, value, traceback): - if type is None: - self.backtrack_stack.pop() - else: - self.s, self._pos = self.backtrack_stack.pop() - return type == TomlError - - def commit(self): - self.backtrack_stack[-1] = (self.s, self._pos) - - def _expect(self, r): - if not r: - raise TomlError('msg', self._pos[0], self._pos[1], self._filename) - return r - - def _advance(self, s): - suffix_pos = s.rfind('\n') - if suffix_pos == -1: - self._pos = (self._pos[0], self._pos[1] + len(s)) - else: - self._pos = (self._pos[0] + s.count('\n'), len(s) - suffix_pos) - -_ews_re = re.compile(r'(?:[ \t]|#[^\n]*\n|#[^\n]*\Z|\n)*') -def _p_ews(s): - s.expect_re(_ews_re) - -_ws_re = re.compile(r'[ \t]*') -def _p_ws(s): - s.expect_re(_ws_re) - -_escapes = { 'b': '\b', 'n': '\n', 'r': '\r', 't': '\t', '"': '"', - '\\': '\\', 'f': '\f' } - -_basicstr_re = re.compile(r'[^"\\\000-\037]*') -_short_uni_re = re.compile(r'u([0-9a-fA-F]{4})') -_long_uni_re = re.compile(r'U([0-9a-fA-F]{8})') -_escapes_re = re.compile(r'[btnfr\"\\]') -_newline_esc_re = re.compile('\n[ \t\n]*') -def _p_basicstr_content(s, content=_basicstr_re): - res = [] - while True: - res.append(s.expect_re(content).group(0)) - if not s.consume('\\'): - break - if s.consume_re(_newline_esc_re): - pass - elif s.consume_re(_short_uni_re) or s.consume_re(_long_uni_re): - v = int(s.last().group(1), 16) - if 0xd800 <= v < 0xe000: - s.fail() - res.append(_chr(v)) - else: - s.expect_re(_escapes_re) - res.append(_escapes[s.last().group(0)]) - return ''.join(res) - -_key_re = re.compile(r'[0-9a-zA-Z-_]+') -def _p_key(s): - with s: - s.expect('"') - r = _p_basicstr_content(s, _basicstr_re) - s.expect('"') - return r - if s.consume('\''): - if s.consume('\'\''): - r = s.expect_re(_litstr_ml_re).group(0) - s.expect('\'\'\'') - else: - r = s.expect_re(_litstr_re).group(0) - s.expect('\'') - return r - return s.expect_re(_key_re).group(0) - -_float_re = re.compile(r'[+-]?(?:0|[1-9](?:_?\d)*)(?:\.\d(?:_?\d)*)?(?:[eE][+-]?(?:\d(?:_?\d)*))?') - -_basicstr_ml_re = re.compile(r'(?:""?(?!")|[^"\\\000-\011\013-\037])*') -_litstr_re = re.compile(r"[^'\000\010\012-\037]*") -_litstr_ml_re = re.compile(r"(?:(?:|'|'')(?:[^'\000-\010\013-\037]))*") -def _p_value(s, object_pairs_hook): - pos = s.pos() - - if s.consume('true'): - return 'bool', s.last(), True, pos - if s.consume('false'): - return 'bool', s.last(), False, pos - - if s.consume('"'): - if s.consume('""'): - r = _p_basicstr_content(s, _basicstr_ml_re) - s.expect('"""') - else: - r = _p_basicstr_content(s, _basicstr_re) - s.expect('"') - return 'str', r, r, pos - - if s.consume('\''): - if s.consume('\'\''): - r = s.expect_re(_litstr_ml_re).group(0) - s.expect('\'\'\'') - else: - r = s.expect_re(_litstr_re).group(0) - s.expect('\'') - return 'str', r, r, pos - - if s.consume_re(rfc3339_re): - m = s.last() - return 'datetime', m.group(0), parse_rfc3339_re(m), pos - - if s.consume_re(_float_re): - m = s.last().group(0) - r = m.replace('_','') - if '.' in m or 'e' in m or 'E' in m: - return 'float', m, float(r), pos - else: - return 'int', m, int(r, 10), pos - - if s.consume('['): - items = [] - with s: - while True: - _p_ews(s) - items.append(_p_value(s, object_pairs_hook=object_pairs_hook)) - s.commit() - _p_ews(s) - s.expect(',') - s.commit() - _p_ews(s) - s.expect(']') - return 'array', None, items, pos - - if s.consume('{'): - _p_ws(s) - items = object_pairs_hook() - if not s.consume('}'): - k = _p_key(s) - _p_ws(s) - s.expect('=') - _p_ws(s) - items[k] = _p_value(s, object_pairs_hook=object_pairs_hook) - _p_ws(s) - while s.consume(','): - _p_ws(s) - k = _p_key(s) - _p_ws(s) - s.expect('=') - _p_ws(s) - items[k] = _p_value(s, object_pairs_hook=object_pairs_hook) - _p_ws(s) - s.expect('}') - return 'table', None, items, pos - - s.fail() - -def _p_stmt(s, object_pairs_hook): - pos = s.pos() - if s.consume( '['): - is_array = s.consume('[') - _p_ws(s) - keys = [_p_key(s)] - _p_ws(s) - while s.consume('.'): - _p_ws(s) - keys.append(_p_key(s)) - _p_ws(s) - s.expect(']') - if is_array: - s.expect(']') - return 'table_array' if is_array else 'table', keys, pos - - key = _p_key(s) - _p_ws(s) - s.expect('=') - _p_ws(s) - value = _p_value(s, object_pairs_hook=object_pairs_hook) - return 'kv', (key, value), pos - -_stmtsep_re = re.compile(r'(?:[ \t]*(?:#[^\n]*)?\n)+[ \t]*') -def _p_toml(s, object_pairs_hook): - stmts = [] - _p_ews(s) - with s: - stmts.append(_p_stmt(s, object_pairs_hook=object_pairs_hook)) - while True: - s.commit() - s.expect_re(_stmtsep_re) - stmts.append(_p_stmt(s, object_pairs_hook=object_pairs_hook)) - _p_ews(s) - s.expect_eof() - return stmts diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/test.py b/venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/test.py deleted file mode 100644 index ec8abfc..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/test.py +++ /dev/null @@ -1,30 +0,0 @@ -import datetime -from .utils import format_rfc3339 - -try: - _string_types = (str, unicode) - _int_types = (int, long) -except NameError: - _string_types = str - _int_types = int - -def translate_to_test(v): - if isinstance(v, dict): - return { k: translate_to_test(v) for k, v in v.items() } - if isinstance(v, list): - a = [translate_to_test(x) for x in v] - if v and isinstance(v[0], dict): - return a - else: - return {'type': 'array', 'value': a} - if isinstance(v, datetime.datetime): - return {'type': 'datetime', 'value': format_rfc3339(v)} - if isinstance(v, bool): - return {'type': 'bool', 'value': 'true' if v else 'false'} - if isinstance(v, _int_types): - return {'type': 'integer', 'value': str(v)} - if isinstance(v, float): - return {'type': 'float', 'value': '{:.17}'.format(v)} - if isinstance(v, _string_types): - return {'type': 'string', 'value': v} - raise RuntimeError('unexpected value: {!r}'.format(v)) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/utils.py b/venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/utils.py deleted file mode 100644 index 636a680..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/utils.py +++ /dev/null @@ -1,67 +0,0 @@ -import datetime -import re - -rfc3339_re = re.compile(r'(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(\.\d+)?(?:Z|([+-]\d{2}):(\d{2}))') - -def parse_rfc3339(v): - m = rfc3339_re.match(v) - if not m or m.group(0) != v: - return None - return parse_rfc3339_re(m) - -def parse_rfc3339_re(m): - r = map(int, m.groups()[:6]) - if m.group(7): - micro = float(m.group(7)) - else: - micro = 0 - - if m.group(8): - g = int(m.group(8), 10) * 60 + int(m.group(9), 10) - tz = _TimeZone(datetime.timedelta(0, g * 60)) - else: - tz = _TimeZone(datetime.timedelta(0, 0)) - - y, m, d, H, M, S = r - return datetime.datetime(y, m, d, H, M, S, int(micro * 1000000), tz) - - -def format_rfc3339(v): - offs = v.utcoffset() - offs = int(offs.total_seconds()) // 60 if offs is not None else 0 - - if offs == 0: - suffix = 'Z' - else: - if offs > 0: - suffix = '+' - else: - suffix = '-' - offs = -offs - suffix = '{0}{1:02}:{2:02}'.format(suffix, offs // 60, offs % 60) - - if v.microsecond: - return v.strftime('%Y-%m-%dT%H:%M:%S.%f') + suffix - else: - return v.strftime('%Y-%m-%dT%H:%M:%S') + suffix - -class _TimeZone(datetime.tzinfo): - def __init__(self, offset): - self._offset = offset - - def utcoffset(self, dt): - return self._offset - - def dst(self, dt): - return None - - def tzname(self, dt): - m = self._offset.total_seconds() // 60 - if m < 0: - res = '-' - m = -m - else: - res = '+' - h = m // 60 - m = m - h * 60 - return '{}{:.02}{:.02}'.format(res, h, m) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/writer.py b/venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/writer.py deleted file mode 100644 index 73b5089..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/pytoml/writer.py +++ /dev/null @@ -1,106 +0,0 @@ -from __future__ import unicode_literals -import io, datetime, math, string, sys - -from .utils import format_rfc3339 - -if sys.version_info[0] == 3: - long = int - unicode = str - - -def dumps(obj, sort_keys=False): - fout = io.StringIO() - dump(obj, fout, sort_keys=sort_keys) - return fout.getvalue() - - -_escapes = {'\n': 'n', '\r': 'r', '\\': '\\', '\t': 't', '\b': 'b', '\f': 'f', '"': '"'} - - -def _escape_string(s): - res = [] - start = 0 - - def flush(): - if start != i: - res.append(s[start:i]) - return i + 1 - - i = 0 - while i < len(s): - c = s[i] - if c in '"\\\n\r\t\b\f': - start = flush() - res.append('\\' + _escapes[c]) - elif ord(c) < 0x20: - start = flush() - res.append('\\u%04x' % ord(c)) - i += 1 - - flush() - return '"' + ''.join(res) + '"' - - -_key_chars = string.digits + string.ascii_letters + '-_' -def _escape_id(s): - if any(c not in _key_chars for c in s): - return _escape_string(s) - return s - - -def _format_value(v): - if isinstance(v, bool): - return 'true' if v else 'false' - if isinstance(v, int) or isinstance(v, long): - return unicode(v) - if isinstance(v, float): - if math.isnan(v) or math.isinf(v): - raise ValueError("{0} is not a valid TOML value".format(v)) - else: - return repr(v) - elif isinstance(v, unicode) or isinstance(v, bytes): - return _escape_string(v) - elif isinstance(v, datetime.datetime): - return format_rfc3339(v) - elif isinstance(v, list): - return '[{0}]'.format(', '.join(_format_value(obj) for obj in v)) - elif isinstance(v, dict): - return '{{{0}}}'.format(', '.join('{} = {}'.format(_escape_id(k), _format_value(obj)) for k, obj in v.items())) - else: - raise RuntimeError(v) - - -def dump(obj, fout, sort_keys=False): - tables = [((), obj, False)] - - while tables: - name, table, is_array = tables.pop() - if name: - section_name = '.'.join(_escape_id(c) for c in name) - if is_array: - fout.write('[[{0}]]\n'.format(section_name)) - else: - fout.write('[{0}]\n'.format(section_name)) - - table_keys = sorted(table.keys()) if sort_keys else table.keys() - new_tables = [] - has_kv = False - for k in table_keys: - v = table[k] - if isinstance(v, dict): - new_tables.append((name + (k,), v, False)) - elif isinstance(v, list) and v and all(isinstance(o, dict) for o in v): - new_tables.extend((name + (k,), d, True) for d in v) - elif v is None: - # based on mojombo's comment: https://github.com/toml-lang/toml/issues/146#issuecomment-25019344 - fout.write( - '#{} = null # To use: uncomment and replace null with value\n'.format(_escape_id(k))) - has_kv = True - else: - fout.write('{0} = {1}\n'.format(_escape_id(k), _format_value(v))) - has_kv = True - - tables.extend(reversed(new_tables)) - - if (name or has_kv) and tables: - fout.write('\n') diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/requests/__init__.py deleted file mode 100644 index 80c4ce1..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/__init__.py +++ /dev/null @@ -1,133 +0,0 @@ -# -*- coding: utf-8 -*- - -# __ -# /__) _ _ _ _ _/ _ -# / ( (- (/ (/ (- _) / _) -# / - -""" -Requests HTTP Library -~~~~~~~~~~~~~~~~~~~~~ - -Requests is an HTTP library, written in Python, for human beings. Basic GET -usage: - - >>> import requests - >>> r = requests.get('https://www.python.org') - >>> r.status_code - 200 - >>> 'Python is a programming language' in r.content - True - -... or POST: - - >>> payload = dict(key1='value1', key2='value2') - >>> r = requests.post('https://httpbin.org/post', data=payload) - >>> print(r.text) - { - ... - "form": { - "key2": "value2", - "key1": "value1" - }, - ... - } - -The other HTTP methods are supported - see `requests.api`. Full documentation -is at <http://python-requests.org>. - -:copyright: (c) 2017 by Kenneth Reitz. -:license: Apache 2.0, see LICENSE for more details. -""" - -from pip._vendor import urllib3 -from pip._vendor import chardet -import warnings -from .exceptions import RequestsDependencyWarning - - -def check_compatibility(urllib3_version, chardet_version): - urllib3_version = urllib3_version.split('.') - assert urllib3_version != ['dev'] # Verify urllib3 isn't installed from git. - - # Sometimes, urllib3 only reports its version as 16.1. - if len(urllib3_version) == 2: - urllib3_version.append('0') - - # Check urllib3 for compatibility. - major, minor, patch = urllib3_version # noqa: F811 - major, minor, patch = int(major), int(minor), int(patch) - # urllib3 >= 1.21.1, <= 1.24 - assert major == 1 - assert minor >= 21 - assert minor <= 24 - - # Check chardet for compatibility. - major, minor, patch = chardet_version.split('.')[:3] - major, minor, patch = int(major), int(minor), int(patch) - # chardet >= 3.0.2, < 3.1.0 - assert major == 3 - assert minor < 1 - assert patch >= 2 - - -def _check_cryptography(cryptography_version): - # cryptography < 1.3.4 - try: - cryptography_version = list(map(int, cryptography_version.split('.'))) - except ValueError: - return - - if cryptography_version < [1, 3, 4]: - warning = 'Old version of cryptography ({}) may cause slowdown.'.format(cryptography_version) - warnings.warn(warning, RequestsDependencyWarning) - -# Check imported dependencies for compatibility. -try: - check_compatibility(urllib3.__version__, chardet.__version__) -except (AssertionError, ValueError): - warnings.warn("urllib3 ({}) or chardet ({}) doesn't match a supported " - "version!".format(urllib3.__version__, chardet.__version__), - RequestsDependencyWarning) - -# Attempt to enable urllib3's SNI support, if possible -from pip._internal.utils.compat import WINDOWS -if not WINDOWS: - try: - from pip._vendor.urllib3.contrib import pyopenssl - pyopenssl.inject_into_urllib3() - - # Check cryptography version - from cryptography import __version__ as cryptography_version - _check_cryptography(cryptography_version) - except ImportError: - pass - -# urllib3's DependencyWarnings should be silenced. -from pip._vendor.urllib3.exceptions import DependencyWarning -warnings.simplefilter('ignore', DependencyWarning) - -from .__version__ import __title__, __description__, __url__, __version__ -from .__version__ import __build__, __author__, __author_email__, __license__ -from .__version__ import __copyright__, __cake__ - -from . import utils -from . import packages -from .models import Request, Response, PreparedRequest -from .api import request, get, head, post, patch, put, delete, options -from .sessions import session, Session -from .status_codes import codes -from .exceptions import ( - RequestException, Timeout, URLRequired, - TooManyRedirects, HTTPError, ConnectionError, - FileModeWarning, ConnectTimeout, ReadTimeout -) - -# Set default logging handler to avoid "No handler found" warnings. -import logging -from logging import NullHandler - -logging.getLogger(__name__).addHandler(NullHandler()) - -# FileModeWarnings go off per the default. -warnings.simplefilter('default', FileModeWarning, append=True) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/__version__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/requests/__version__.py deleted file mode 100644 index f5b5d03..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/__version__.py +++ /dev/null @@ -1,14 +0,0 @@ -# .-. .-. .-. . . .-. .-. .-. .-. -# |( |- |.| | | |- `-. | `-. -# ' ' `-' `-`.`-' `-' `-' ' `-' - -__title__ = 'requests' -__description__ = 'Python HTTP for Humans.' -__url__ = 'http://python-requests.org' -__version__ = '2.21.0' -__build__ = 0x022100 -__author__ = 'Kenneth Reitz' -__author_email__ = 'me@kennethreitz.org' -__license__ = 'Apache 2.0' -__copyright__ = 'Copyright 2018 Kenneth Reitz' -__cake__ = u'\u2728 \U0001f370 \u2728' diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/_internal_utils.py b/venv2/lib/python2.7/site-packages/pip/_vendor/requests/_internal_utils.py deleted file mode 100644 index 759d9a5..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/_internal_utils.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -requests._internal_utils -~~~~~~~~~~~~~~ - -Provides utility functions that are consumed internally by Requests -which depend on extremely few external helpers (such as compat) -""" - -from .compat import is_py2, builtin_str, str - - -def to_native_string(string, encoding='ascii'): - """Given a string object, regardless of type, returns a representation of - that string in the native string type, encoding and decoding where - necessary. This assumes ASCII unless told otherwise. - """ - if isinstance(string, builtin_str): - out = string - else: - if is_py2: - out = string.encode(encoding) - else: - out = string.decode(encoding) - - return out - - -def unicode_is_ascii(u_string): - """Determine if unicode string only contains ASCII characters. - - :param str u_string: unicode string to check. Must be unicode - and not Python 2 `str`. - :rtype: bool - """ - assert isinstance(u_string, str) - try: - u_string.encode('ascii') - return True - except UnicodeEncodeError: - return False diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/adapters.py b/venv2/lib/python2.7/site-packages/pip/_vendor/requests/adapters.py deleted file mode 100644 index c30e7c9..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/adapters.py +++ /dev/null @@ -1,533 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -requests.adapters -~~~~~~~~~~~~~~~~~ - -This module contains the transport adapters that Requests uses to define -and maintain connections. -""" - -import os.path -import socket - -from pip._vendor.urllib3.poolmanager import PoolManager, proxy_from_url -from pip._vendor.urllib3.response import HTTPResponse -from pip._vendor.urllib3.util import parse_url -from pip._vendor.urllib3.util import Timeout as TimeoutSauce -from pip._vendor.urllib3.util.retry import Retry -from pip._vendor.urllib3.exceptions import ClosedPoolError -from pip._vendor.urllib3.exceptions import ConnectTimeoutError -from pip._vendor.urllib3.exceptions import HTTPError as _HTTPError -from pip._vendor.urllib3.exceptions import MaxRetryError -from pip._vendor.urllib3.exceptions import NewConnectionError -from pip._vendor.urllib3.exceptions import ProxyError as _ProxyError -from pip._vendor.urllib3.exceptions import ProtocolError -from pip._vendor.urllib3.exceptions import ReadTimeoutError -from pip._vendor.urllib3.exceptions import SSLError as _SSLError -from pip._vendor.urllib3.exceptions import ResponseError -from pip._vendor.urllib3.exceptions import LocationValueError - -from .models import Response -from .compat import urlparse, basestring -from .utils import (DEFAULT_CA_BUNDLE_PATH, extract_zipped_paths, - get_encoding_from_headers, prepend_scheme_if_needed, - get_auth_from_url, urldefragauth, select_proxy) -from .structures import CaseInsensitiveDict -from .cookies import extract_cookies_to_jar -from .exceptions import (ConnectionError, ConnectTimeout, ReadTimeout, SSLError, - ProxyError, RetryError, InvalidSchema, InvalidProxyURL, - InvalidURL) -from .auth import _basic_auth_str - -try: - from pip._vendor.urllib3.contrib.socks import SOCKSProxyManager -except ImportError: - def SOCKSProxyManager(*args, **kwargs): - raise InvalidSchema("Missing dependencies for SOCKS support.") - -DEFAULT_POOLBLOCK = False -DEFAULT_POOLSIZE = 10 -DEFAULT_RETRIES = 0 -DEFAULT_POOL_TIMEOUT = None - - -class BaseAdapter(object): - """The Base Transport Adapter""" - - def __init__(self): - super(BaseAdapter, self).__init__() - - def send(self, request, stream=False, timeout=None, verify=True, - cert=None, proxies=None): - """Sends PreparedRequest object. Returns Response object. - - :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. - :param stream: (optional) Whether to stream the request content. - :param timeout: (optional) How long to wait for the server to send - data before giving up, as a float, or a :ref:`(connect timeout, - read timeout) <timeouts>` tuple. - :type timeout: float or tuple - :param verify: (optional) Either a boolean, in which case it controls whether we verify - the server's TLS certificate, or a string, in which case it must be a path - to a CA bundle to use - :param cert: (optional) Any user-provided SSL certificate to be trusted. - :param proxies: (optional) The proxies dictionary to apply to the request. - """ - raise NotImplementedError - - def close(self): - """Cleans up adapter specific items.""" - raise NotImplementedError - - -class HTTPAdapter(BaseAdapter): - """The built-in HTTP Adapter for urllib3. - - Provides a general-case interface for Requests sessions to contact HTTP and - HTTPS urls by implementing the Transport Adapter interface. This class will - usually be created by the :class:`Session <Session>` class under the - covers. - - :param pool_connections: The number of urllib3 connection pools to cache. - :param pool_maxsize: The maximum number of connections to save in the pool. - :param max_retries: The maximum number of retries each connection - should attempt. Note, this applies only to failed DNS lookups, socket - connections and connection timeouts, never to requests where data has - made it to the server. By default, Requests does not retry failed - connections. If you need granular control over the conditions under - which we retry a request, import urllib3's ``Retry`` class and pass - that instead. - :param pool_block: Whether the connection pool should block for connections. - - Usage:: - - >>> import requests - >>> s = requests.Session() - >>> a = requests.adapters.HTTPAdapter(max_retries=3) - >>> s.mount('http://', a) - """ - __attrs__ = ['max_retries', 'config', '_pool_connections', '_pool_maxsize', - '_pool_block'] - - def __init__(self, pool_connections=DEFAULT_POOLSIZE, - pool_maxsize=DEFAULT_POOLSIZE, max_retries=DEFAULT_RETRIES, - pool_block=DEFAULT_POOLBLOCK): - if max_retries == DEFAULT_RETRIES: - self.max_retries = Retry(0, read=False) - else: - self.max_retries = Retry.from_int(max_retries) - self.config = {} - self.proxy_manager = {} - - super(HTTPAdapter, self).__init__() - - self._pool_connections = pool_connections - self._pool_maxsize = pool_maxsize - self._pool_block = pool_block - - self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block) - - def __getstate__(self): - return {attr: getattr(self, attr, None) for attr in self.__attrs__} - - def __setstate__(self, state): - # Can't handle by adding 'proxy_manager' to self.__attrs__ because - # self.poolmanager uses a lambda function, which isn't pickleable. - self.proxy_manager = {} - self.config = {} - - for attr, value in state.items(): - setattr(self, attr, value) - - self.init_poolmanager(self._pool_connections, self._pool_maxsize, - block=self._pool_block) - - def init_poolmanager(self, connections, maxsize, block=DEFAULT_POOLBLOCK, **pool_kwargs): - """Initializes a urllib3 PoolManager. - - This method should not be called from user code, and is only - exposed for use when subclassing the - :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. - - :param connections: The number of urllib3 connection pools to cache. - :param maxsize: The maximum number of connections to save in the pool. - :param block: Block when no free connections are available. - :param pool_kwargs: Extra keyword arguments used to initialize the Pool Manager. - """ - # save these values for pickling - self._pool_connections = connections - self._pool_maxsize = maxsize - self._pool_block = block - - self.poolmanager = PoolManager(num_pools=connections, maxsize=maxsize, - block=block, strict=True, **pool_kwargs) - - def proxy_manager_for(self, proxy, **proxy_kwargs): - """Return urllib3 ProxyManager for the given proxy. - - This method should not be called from user code, and is only - exposed for use when subclassing the - :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. - - :param proxy: The proxy to return a urllib3 ProxyManager for. - :param proxy_kwargs: Extra keyword arguments used to configure the Proxy Manager. - :returns: ProxyManager - :rtype: urllib3.ProxyManager - """ - if proxy in self.proxy_manager: - manager = self.proxy_manager[proxy] - elif proxy.lower().startswith('socks'): - username, password = get_auth_from_url(proxy) - manager = self.proxy_manager[proxy] = SOCKSProxyManager( - proxy, - username=username, - password=password, - num_pools=self._pool_connections, - maxsize=self._pool_maxsize, - block=self._pool_block, - **proxy_kwargs - ) - else: - proxy_headers = self.proxy_headers(proxy) - manager = self.proxy_manager[proxy] = proxy_from_url( - proxy, - proxy_headers=proxy_headers, - num_pools=self._pool_connections, - maxsize=self._pool_maxsize, - block=self._pool_block, - **proxy_kwargs) - - return manager - - def cert_verify(self, conn, url, verify, cert): - """Verify a SSL certificate. This method should not be called from user - code, and is only exposed for use when subclassing the - :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. - - :param conn: The urllib3 connection object associated with the cert. - :param url: The requested URL. - :param verify: Either a boolean, in which case it controls whether we verify - the server's TLS certificate, or a string, in which case it must be a path - to a CA bundle to use - :param cert: The SSL certificate to verify. - """ - if url.lower().startswith('https') and verify: - - cert_loc = None - - # Allow self-specified cert location. - if verify is not True: - cert_loc = verify - - if not cert_loc: - cert_loc = extract_zipped_paths(DEFAULT_CA_BUNDLE_PATH) - - if not cert_loc or not os.path.exists(cert_loc): - raise IOError("Could not find a suitable TLS CA certificate bundle, " - "invalid path: {}".format(cert_loc)) - - conn.cert_reqs = 'CERT_REQUIRED' - - if not os.path.isdir(cert_loc): - conn.ca_certs = cert_loc - else: - conn.ca_cert_dir = cert_loc - else: - conn.cert_reqs = 'CERT_NONE' - conn.ca_certs = None - conn.ca_cert_dir = None - - if cert: - if not isinstance(cert, basestring): - conn.cert_file = cert[0] - conn.key_file = cert[1] - else: - conn.cert_file = cert - conn.key_file = None - if conn.cert_file and not os.path.exists(conn.cert_file): - raise IOError("Could not find the TLS certificate file, " - "invalid path: {}".format(conn.cert_file)) - if conn.key_file and not os.path.exists(conn.key_file): - raise IOError("Could not find the TLS key file, " - "invalid path: {}".format(conn.key_file)) - - def build_response(self, req, resp): - """Builds a :class:`Response <requests.Response>` object from a urllib3 - response. This should not be called from user code, and is only exposed - for use when subclassing the - :class:`HTTPAdapter <requests.adapters.HTTPAdapter>` - - :param req: The :class:`PreparedRequest <PreparedRequest>` used to generate the response. - :param resp: The urllib3 response object. - :rtype: requests.Response - """ - response = Response() - - # Fallback to None if there's no status_code, for whatever reason. - response.status_code = getattr(resp, 'status', None) - - # Make headers case-insensitive. - response.headers = CaseInsensitiveDict(getattr(resp, 'headers', {})) - - # Set encoding. - response.encoding = get_encoding_from_headers(response.headers) - response.raw = resp - response.reason = response.raw.reason - - if isinstance(req.url, bytes): - response.url = req.url.decode('utf-8') - else: - response.url = req.url - - # Add new cookies from the server. - extract_cookies_to_jar(response.cookies, req, resp) - - # Give the Response some context. - response.request = req - response.connection = self - - return response - - def get_connection(self, url, proxies=None): - """Returns a urllib3 connection for the given URL. This should not be - called from user code, and is only exposed for use when subclassing the - :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. - - :param url: The URL to connect to. - :param proxies: (optional) A Requests-style dictionary of proxies used on this request. - :rtype: urllib3.ConnectionPool - """ - proxy = select_proxy(url, proxies) - - if proxy: - proxy = prepend_scheme_if_needed(proxy, 'http') - proxy_url = parse_url(proxy) - if not proxy_url.host: - raise InvalidProxyURL("Please check proxy URL. It is malformed" - " and could be missing the host.") - proxy_manager = self.proxy_manager_for(proxy) - conn = proxy_manager.connection_from_url(url) - else: - # Only scheme should be lower case - parsed = urlparse(url) - url = parsed.geturl() - conn = self.poolmanager.connection_from_url(url) - - return conn - - def close(self): - """Disposes of any internal state. - - Currently, this closes the PoolManager and any active ProxyManager, - which closes any pooled connections. - """ - self.poolmanager.clear() - for proxy in self.proxy_manager.values(): - proxy.clear() - - def request_url(self, request, proxies): - """Obtain the url to use when making the final request. - - If the message is being sent through a HTTP proxy, the full URL has to - be used. Otherwise, we should only use the path portion of the URL. - - This should not be called from user code, and is only exposed for use - when subclassing the - :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. - - :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. - :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs. - :rtype: str - """ - proxy = select_proxy(request.url, proxies) - scheme = urlparse(request.url).scheme - - is_proxied_http_request = (proxy and scheme != 'https') - using_socks_proxy = False - if proxy: - proxy_scheme = urlparse(proxy).scheme.lower() - using_socks_proxy = proxy_scheme.startswith('socks') - - url = request.path_url - if is_proxied_http_request and not using_socks_proxy: - url = urldefragauth(request.url) - - return url - - def add_headers(self, request, **kwargs): - """Add any headers needed by the connection. As of v2.0 this does - nothing by default, but is left for overriding by users that subclass - the :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. - - This should not be called from user code, and is only exposed for use - when subclassing the - :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. - - :param request: The :class:`PreparedRequest <PreparedRequest>` to add headers to. - :param kwargs: The keyword arguments from the call to send(). - """ - pass - - def proxy_headers(self, proxy): - """Returns a dictionary of the headers to add to any request sent - through a proxy. This works with urllib3 magic to ensure that they are - correctly sent to the proxy, rather than in a tunnelled request if - CONNECT is being used. - - This should not be called from user code, and is only exposed for use - when subclassing the - :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. - - :param proxy: The url of the proxy being used for this request. - :rtype: dict - """ - headers = {} - username, password = get_auth_from_url(proxy) - - if username: - headers['Proxy-Authorization'] = _basic_auth_str(username, - password) - - return headers - - def send(self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None): - """Sends PreparedRequest object. Returns Response object. - - :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. - :param stream: (optional) Whether to stream the request content. - :param timeout: (optional) How long to wait for the server to send - data before giving up, as a float, or a :ref:`(connect timeout, - read timeout) <timeouts>` tuple. - :type timeout: float or tuple or urllib3 Timeout object - :param verify: (optional) Either a boolean, in which case it controls whether - we verify the server's TLS certificate, or a string, in which case it - must be a path to a CA bundle to use - :param cert: (optional) Any user-provided SSL certificate to be trusted. - :param proxies: (optional) The proxies dictionary to apply to the request. - :rtype: requests.Response - """ - - try: - conn = self.get_connection(request.url, proxies) - except LocationValueError as e: - raise InvalidURL(e, request=request) - - self.cert_verify(conn, request.url, verify, cert) - url = self.request_url(request, proxies) - self.add_headers(request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies) - - chunked = not (request.body is None or 'Content-Length' in request.headers) - - if isinstance(timeout, tuple): - try: - connect, read = timeout - timeout = TimeoutSauce(connect=connect, read=read) - except ValueError as e: - # this may raise a string formatting error. - err = ("Invalid timeout {}. Pass a (connect, read) " - "timeout tuple, or a single float to set " - "both timeouts to the same value".format(timeout)) - raise ValueError(err) - elif isinstance(timeout, TimeoutSauce): - pass - else: - timeout = TimeoutSauce(connect=timeout, read=timeout) - - try: - if not chunked: - resp = conn.urlopen( - method=request.method, - url=url, - body=request.body, - headers=request.headers, - redirect=False, - assert_same_host=False, - preload_content=False, - decode_content=False, - retries=self.max_retries, - timeout=timeout - ) - - # Send the request. - else: - if hasattr(conn, 'proxy_pool'): - conn = conn.proxy_pool - - low_conn = conn._get_conn(timeout=DEFAULT_POOL_TIMEOUT) - - try: - low_conn.putrequest(request.method, - url, - skip_accept_encoding=True) - - for header, value in request.headers.items(): - low_conn.putheader(header, value) - - low_conn.endheaders() - - for i in request.body: - low_conn.send(hex(len(i))[2:].encode('utf-8')) - low_conn.send(b'\r\n') - low_conn.send(i) - low_conn.send(b'\r\n') - low_conn.send(b'0\r\n\r\n') - - # Receive the response from the server - try: - # For Python 2.7, use buffering of HTTP responses - r = low_conn.getresponse(buffering=True) - except TypeError: - # For compatibility with Python 3.3+ - r = low_conn.getresponse() - - resp = HTTPResponse.from_httplib( - r, - pool=conn, - connection=low_conn, - preload_content=False, - decode_content=False - ) - except: - # If we hit any problems here, clean up the connection. - # Then, reraise so that we can handle the actual exception. - low_conn.close() - raise - - except (ProtocolError, socket.error) as err: - raise ConnectionError(err, request=request) - - except MaxRetryError as e: - if isinstance(e.reason, ConnectTimeoutError): - # TODO: Remove this in 3.0.0: see #2811 - if not isinstance(e.reason, NewConnectionError): - raise ConnectTimeout(e, request=request) - - if isinstance(e.reason, ResponseError): - raise RetryError(e, request=request) - - if isinstance(e.reason, _ProxyError): - raise ProxyError(e, request=request) - - if isinstance(e.reason, _SSLError): - # This branch is for urllib3 v1.22 and later. - raise SSLError(e, request=request) - - raise ConnectionError(e, request=request) - - except ClosedPoolError as e: - raise ConnectionError(e, request=request) - - except _ProxyError as e: - raise ProxyError(e) - - except (_SSLError, _HTTPError) as e: - if isinstance(e, _SSLError): - # This branch is for urllib3 versions earlier than v1.22 - raise SSLError(e, request=request) - elif isinstance(e, ReadTimeoutError): - raise ReadTimeout(e, request=request) - else: - raise - - return self.build_response(request, resp) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/api.py b/venv2/lib/python2.7/site-packages/pip/_vendor/requests/api.py deleted file mode 100644 index abada96..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/api.py +++ /dev/null @@ -1,158 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -requests.api -~~~~~~~~~~~~ - -This module implements the Requests API. - -:copyright: (c) 2012 by Kenneth Reitz. -:license: Apache2, see LICENSE for more details. -""" - -from . import sessions - - -def request(method, url, **kwargs): - """Constructs and sends a :class:`Request <Request>`. - - :param method: method for the new :class:`Request` object. - :param url: URL for the new :class:`Request` object. - :param params: (optional) Dictionary, list of tuples or bytes to send - in the body of the :class:`Request`. - :param data: (optional) Dictionary, list of tuples, bytes, or file-like - object to send in the body of the :class:`Request`. - :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`. - :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`. - :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`. - :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload. - ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')`` - or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string - defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers - to add for the file. - :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth. - :param timeout: (optional) How many seconds to wait for the server to send data - before giving up, as a float, or a :ref:`(connect timeout, read - timeout) <timeouts>` tuple. - :type timeout: float or tuple - :param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``. - :type allow_redirects: bool - :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy. - :param verify: (optional) Either a boolean, in which case it controls whether we verify - the server's TLS certificate, or a string, in which case it must be a path - to a CA bundle to use. Defaults to ``True``. - :param stream: (optional) if ``False``, the response content will be immediately downloaded. - :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair. - :return: :class:`Response <Response>` object - :rtype: requests.Response - - Usage:: - - >>> import requests - >>> req = requests.request('GET', 'https://httpbin.org/get') - <Response [200]> - """ - - # By using the 'with' statement we are sure the session is closed, thus we - # avoid leaving sockets open which can trigger a ResourceWarning in some - # cases, and look like a memory leak in others. - with sessions.Session() as session: - return session.request(method=method, url=url, **kwargs) - - -def get(url, params=None, **kwargs): - r"""Sends a GET request. - - :param url: URL for the new :class:`Request` object. - :param params: (optional) Dictionary, list of tuples or bytes to send - in the body of the :class:`Request`. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :return: :class:`Response <Response>` object - :rtype: requests.Response - """ - - kwargs.setdefault('allow_redirects', True) - return request('get', url, params=params, **kwargs) - - -def options(url, **kwargs): - r"""Sends an OPTIONS request. - - :param url: URL for the new :class:`Request` object. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :return: :class:`Response <Response>` object - :rtype: requests.Response - """ - - kwargs.setdefault('allow_redirects', True) - return request('options', url, **kwargs) - - -def head(url, **kwargs): - r"""Sends a HEAD request. - - :param url: URL for the new :class:`Request` object. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :return: :class:`Response <Response>` object - :rtype: requests.Response - """ - - kwargs.setdefault('allow_redirects', False) - return request('head', url, **kwargs) - - -def post(url, data=None, json=None, **kwargs): - r"""Sends a POST request. - - :param url: URL for the new :class:`Request` object. - :param data: (optional) Dictionary, list of tuples, bytes, or file-like - object to send in the body of the :class:`Request`. - :param json: (optional) json data to send in the body of the :class:`Request`. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :return: :class:`Response <Response>` object - :rtype: requests.Response - """ - - return request('post', url, data=data, json=json, **kwargs) - - -def put(url, data=None, **kwargs): - r"""Sends a PUT request. - - :param url: URL for the new :class:`Request` object. - :param data: (optional) Dictionary, list of tuples, bytes, or file-like - object to send in the body of the :class:`Request`. - :param json: (optional) json data to send in the body of the :class:`Request`. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :return: :class:`Response <Response>` object - :rtype: requests.Response - """ - - return request('put', url, data=data, **kwargs) - - -def patch(url, data=None, **kwargs): - r"""Sends a PATCH request. - - :param url: URL for the new :class:`Request` object. - :param data: (optional) Dictionary, list of tuples, bytes, or file-like - object to send in the body of the :class:`Request`. - :param json: (optional) json data to send in the body of the :class:`Request`. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :return: :class:`Response <Response>` object - :rtype: requests.Response - """ - - return request('patch', url, data=data, **kwargs) - - -def delete(url, **kwargs): - r"""Sends a DELETE request. - - :param url: URL for the new :class:`Request` object. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :return: :class:`Response <Response>` object - :rtype: requests.Response - """ - - return request('delete', url, **kwargs) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/auth.py b/venv2/lib/python2.7/site-packages/pip/_vendor/requests/auth.py deleted file mode 100644 index bdde51c..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/auth.py +++ /dev/null @@ -1,305 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -requests.auth -~~~~~~~~~~~~~ - -This module contains the authentication handlers for Requests. -""" - -import os -import re -import time -import hashlib -import threading -import warnings - -from base64 import b64encode - -from .compat import urlparse, str, basestring -from .cookies import extract_cookies_to_jar -from ._internal_utils import to_native_string -from .utils import parse_dict_header - -CONTENT_TYPE_FORM_URLENCODED = 'application/x-www-form-urlencoded' -CONTENT_TYPE_MULTI_PART = 'multipart/form-data' - - -def _basic_auth_str(username, password): - """Returns a Basic Auth string.""" - - # "I want us to put a big-ol' comment on top of it that - # says that this behaviour is dumb but we need to preserve - # it because people are relying on it." - # - Lukasa - # - # These are here solely to maintain backwards compatibility - # for things like ints. This will be removed in 3.0.0. - if not isinstance(username, basestring): - warnings.warn( - "Non-string usernames will no longer be supported in Requests " - "3.0.0. Please convert the object you've passed in ({!r}) to " - "a string or bytes object in the near future to avoid " - "problems.".format(username), - category=DeprecationWarning, - ) - username = str(username) - - if not isinstance(password, basestring): - warnings.warn( - "Non-string passwords will no longer be supported in Requests " - "3.0.0. Please convert the object you've passed in ({!r}) to " - "a string or bytes object in the near future to avoid " - "problems.".format(password), - category=DeprecationWarning, - ) - password = str(password) - # -- End Removal -- - - if isinstance(username, str): - username = username.encode('latin1') - - if isinstance(password, str): - password = password.encode('latin1') - - authstr = 'Basic ' + to_native_string( - b64encode(b':'.join((username, password))).strip() - ) - - return authstr - - -class AuthBase(object): - """Base class that all auth implementations derive from""" - - def __call__(self, r): - raise NotImplementedError('Auth hooks must be callable.') - - -class HTTPBasicAuth(AuthBase): - """Attaches HTTP Basic Authentication to the given Request object.""" - - def __init__(self, username, password): - self.username = username - self.password = password - - def __eq__(self, other): - return all([ - self.username == getattr(other, 'username', None), - self.password == getattr(other, 'password', None) - ]) - - def __ne__(self, other): - return not self == other - - def __call__(self, r): - r.headers['Authorization'] = _basic_auth_str(self.username, self.password) - return r - - -class HTTPProxyAuth(HTTPBasicAuth): - """Attaches HTTP Proxy Authentication to a given Request object.""" - - def __call__(self, r): - r.headers['Proxy-Authorization'] = _basic_auth_str(self.username, self.password) - return r - - -class HTTPDigestAuth(AuthBase): - """Attaches HTTP Digest Authentication to the given Request object.""" - - def __init__(self, username, password): - self.username = username - self.password = password - # Keep state in per-thread local storage - self._thread_local = threading.local() - - def init_per_thread_state(self): - # Ensure state is initialized just once per-thread - if not hasattr(self._thread_local, 'init'): - self._thread_local.init = True - self._thread_local.last_nonce = '' - self._thread_local.nonce_count = 0 - self._thread_local.chal = {} - self._thread_local.pos = None - self._thread_local.num_401_calls = None - - def build_digest_header(self, method, url): - """ - :rtype: str - """ - - realm = self._thread_local.chal['realm'] - nonce = self._thread_local.chal['nonce'] - qop = self._thread_local.chal.get('qop') - algorithm = self._thread_local.chal.get('algorithm') - opaque = self._thread_local.chal.get('opaque') - hash_utf8 = None - - if algorithm is None: - _algorithm = 'MD5' - else: - _algorithm = algorithm.upper() - # lambdas assume digest modules are imported at the top level - if _algorithm == 'MD5' or _algorithm == 'MD5-SESS': - def md5_utf8(x): - if isinstance(x, str): - x = x.encode('utf-8') - return hashlib.md5(x).hexdigest() - hash_utf8 = md5_utf8 - elif _algorithm == 'SHA': - def sha_utf8(x): - if isinstance(x, str): - x = x.encode('utf-8') - return hashlib.sha1(x).hexdigest() - hash_utf8 = sha_utf8 - elif _algorithm == 'SHA-256': - def sha256_utf8(x): - if isinstance(x, str): - x = x.encode('utf-8') - return hashlib.sha256(x).hexdigest() - hash_utf8 = sha256_utf8 - elif _algorithm == 'SHA-512': - def sha512_utf8(x): - if isinstance(x, str): - x = x.encode('utf-8') - return hashlib.sha512(x).hexdigest() - hash_utf8 = sha512_utf8 - - KD = lambda s, d: hash_utf8("%s:%s" % (s, d)) - - if hash_utf8 is None: - return None - - # XXX not implemented yet - entdig = None - p_parsed = urlparse(url) - #: path is request-uri defined in RFC 2616 which should not be empty - path = p_parsed.path or "/" - if p_parsed.query: - path += '?' + p_parsed.query - - A1 = '%s:%s:%s' % (self.username, realm, self.password) - A2 = '%s:%s' % (method, path) - - HA1 = hash_utf8(A1) - HA2 = hash_utf8(A2) - - if nonce == self._thread_local.last_nonce: - self._thread_local.nonce_count += 1 - else: - self._thread_local.nonce_count = 1 - ncvalue = '%08x' % self._thread_local.nonce_count - s = str(self._thread_local.nonce_count).encode('utf-8') - s += nonce.encode('utf-8') - s += time.ctime().encode('utf-8') - s += os.urandom(8) - - cnonce = (hashlib.sha1(s).hexdigest()[:16]) - if _algorithm == 'MD5-SESS': - HA1 = hash_utf8('%s:%s:%s' % (HA1, nonce, cnonce)) - - if not qop: - respdig = KD(HA1, "%s:%s" % (nonce, HA2)) - elif qop == 'auth' or 'auth' in qop.split(','): - noncebit = "%s:%s:%s:%s:%s" % ( - nonce, ncvalue, cnonce, 'auth', HA2 - ) - respdig = KD(HA1, noncebit) - else: - # XXX handle auth-int. - return None - - self._thread_local.last_nonce = nonce - - # XXX should the partial digests be encoded too? - base = 'username="%s", realm="%s", nonce="%s", uri="%s", ' \ - 'response="%s"' % (self.username, realm, nonce, path, respdig) - if opaque: - base += ', opaque="%s"' % opaque - if algorithm: - base += ', algorithm="%s"' % algorithm - if entdig: - base += ', digest="%s"' % entdig - if qop: - base += ', qop="auth", nc=%s, cnonce="%s"' % (ncvalue, cnonce) - - return 'Digest %s' % (base) - - def handle_redirect(self, r, **kwargs): - """Reset num_401_calls counter on redirects.""" - if r.is_redirect: - self._thread_local.num_401_calls = 1 - - def handle_401(self, r, **kwargs): - """ - Takes the given response and tries digest-auth, if needed. - - :rtype: requests.Response - """ - - # If response is not 4xx, do not auth - # See https://github.com/requests/requests/issues/3772 - if not 400 <= r.status_code < 500: - self._thread_local.num_401_calls = 1 - return r - - if self._thread_local.pos is not None: - # Rewind the file position indicator of the body to where - # it was to resend the request. - r.request.body.seek(self._thread_local.pos) - s_auth = r.headers.get('www-authenticate', '') - - if 'digest' in s_auth.lower() and self._thread_local.num_401_calls < 2: - - self._thread_local.num_401_calls += 1 - pat = re.compile(r'digest ', flags=re.IGNORECASE) - self._thread_local.chal = parse_dict_header(pat.sub('', s_auth, count=1)) - - # Consume content and release the original connection - # to allow our new request to reuse the same one. - r.content - r.close() - prep = r.request.copy() - extract_cookies_to_jar(prep._cookies, r.request, r.raw) - prep.prepare_cookies(prep._cookies) - - prep.headers['Authorization'] = self.build_digest_header( - prep.method, prep.url) - _r = r.connection.send(prep, **kwargs) - _r.history.append(r) - _r.request = prep - - return _r - - self._thread_local.num_401_calls = 1 - return r - - def __call__(self, r): - # Initialize per-thread state, if needed - self.init_per_thread_state() - # If we have a saved nonce, skip the 401 - if self._thread_local.last_nonce: - r.headers['Authorization'] = self.build_digest_header(r.method, r.url) - try: - self._thread_local.pos = r.body.tell() - except AttributeError: - # In the case of HTTPDigestAuth being reused and the body of - # the previous request was a file-like object, pos has the - # file position of the previous body. Ensure it's set to - # None. - self._thread_local.pos = None - r.register_hook('response', self.handle_401) - r.register_hook('response', self.handle_redirect) - self._thread_local.num_401_calls = 1 - - return r - - def __eq__(self, other): - return all([ - self.username == getattr(other, 'username', None), - self.password == getattr(other, 'password', None) - ]) - - def __ne__(self, other): - return not self == other diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/certs.py b/venv2/lib/python2.7/site-packages/pip/_vendor/requests/certs.py deleted file mode 100644 index 06a594e..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/certs.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -""" -requests.certs -~~~~~~~~~~~~~~ - -This module returns the preferred default CA certificate bundle. There is -only one — the one from the certifi package. - -If you are packaging Requests, e.g., for a Linux distribution or a managed -environment, you can change the definition of where() to return a separately -packaged CA bundle. -""" -from pip._vendor.certifi import where - -if __name__ == '__main__': - print(where()) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/compat.py b/venv2/lib/python2.7/site-packages/pip/_vendor/requests/compat.py deleted file mode 100644 index 6a86893..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/compat.py +++ /dev/null @@ -1,74 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -requests.compat -~~~~~~~~~~~~~~~ - -This module handles import compatibility issues between Python 2 and -Python 3. -""" - -from pip._vendor import chardet - -import sys - -# ------- -# Pythons -# ------- - -# Syntax sugar. -_ver = sys.version_info - -#: Python 2.x? -is_py2 = (_ver[0] == 2) - -#: Python 3.x? -is_py3 = (_ver[0] == 3) - -# Note: We've patched out simplejson support in pip because it prevents -# upgrading simplejson on Windows. -# try: -# import simplejson as json -# except (ImportError, SyntaxError): -# # simplejson does not support Python 3.2, it throws a SyntaxError -# # because of u'...' Unicode literals. -import json - -# --------- -# Specifics -# --------- - -if is_py2: - from urllib import ( - quote, unquote, quote_plus, unquote_plus, urlencode, getproxies, - proxy_bypass, proxy_bypass_environment, getproxies_environment) - from urlparse import urlparse, urlunparse, urljoin, urlsplit, urldefrag - from urllib2 import parse_http_list - import cookielib - from Cookie import Morsel - from StringIO import StringIO - from collections import Callable, Mapping, MutableMapping, OrderedDict - - - builtin_str = str - bytes = str - str = unicode - basestring = basestring - numeric_types = (int, long, float) - integer_types = (int, long) - -elif is_py3: - from urllib.parse import urlparse, urlunparse, urljoin, urlsplit, urlencode, quote, unquote, quote_plus, unquote_plus, urldefrag - from urllib.request import parse_http_list, getproxies, proxy_bypass, proxy_bypass_environment, getproxies_environment - from http import cookiejar as cookielib - from http.cookies import Morsel - from io import StringIO - from collections import OrderedDict - from collections.abc import Callable, Mapping, MutableMapping - - builtin_str = str - str = str - bytes = bytes - basestring = (str, bytes) - numeric_types = (int, float) - integer_types = (int,) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/cookies.py b/venv2/lib/python2.7/site-packages/pip/_vendor/requests/cookies.py deleted file mode 100644 index 56fccd9..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/cookies.py +++ /dev/null @@ -1,549 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -requests.cookies -~~~~~~~~~~~~~~~~ - -Compatibility code to be able to use `cookielib.CookieJar` with requests. - -requests.utils imports from here, so be careful with imports. -""" - -import copy -import time -import calendar - -from ._internal_utils import to_native_string -from .compat import cookielib, urlparse, urlunparse, Morsel, MutableMapping - -try: - import threading -except ImportError: - import dummy_threading as threading - - -class MockRequest(object): - """Wraps a `requests.Request` to mimic a `urllib2.Request`. - - The code in `cookielib.CookieJar` expects this interface in order to correctly - manage cookie policies, i.e., determine whether a cookie can be set, given the - domains of the request and the cookie. - - The original request object is read-only. The client is responsible for collecting - the new headers via `get_new_headers()` and interpreting them appropriately. You - probably want `get_cookie_header`, defined below. - """ - - def __init__(self, request): - self._r = request - self._new_headers = {} - self.type = urlparse(self._r.url).scheme - - def get_type(self): - return self.type - - def get_host(self): - return urlparse(self._r.url).netloc - - def get_origin_req_host(self): - return self.get_host() - - def get_full_url(self): - # Only return the response's URL if the user hadn't set the Host - # header - if not self._r.headers.get('Host'): - return self._r.url - # If they did set it, retrieve it and reconstruct the expected domain - host = to_native_string(self._r.headers['Host'], encoding='utf-8') - parsed = urlparse(self._r.url) - # Reconstruct the URL as we expect it - return urlunparse([ - parsed.scheme, host, parsed.path, parsed.params, parsed.query, - parsed.fragment - ]) - - def is_unverifiable(self): - return True - - def has_header(self, name): - return name in self._r.headers or name in self._new_headers - - def get_header(self, name, default=None): - return self._r.headers.get(name, self._new_headers.get(name, default)) - - def add_header(self, key, val): - """cookielib has no legitimate use for this method; add it back if you find one.""" - raise NotImplementedError("Cookie headers should be added with add_unredirected_header()") - - def add_unredirected_header(self, name, value): - self._new_headers[name] = value - - def get_new_headers(self): - return self._new_headers - - @property - def unverifiable(self): - return self.is_unverifiable() - - @property - def origin_req_host(self): - return self.get_origin_req_host() - - @property - def host(self): - return self.get_host() - - -class MockResponse(object): - """Wraps a `httplib.HTTPMessage` to mimic a `urllib.addinfourl`. - - ...what? Basically, expose the parsed HTTP headers from the server response - the way `cookielib` expects to see them. - """ - - def __init__(self, headers): - """Make a MockResponse for `cookielib` to read. - - :param headers: a httplib.HTTPMessage or analogous carrying the headers - """ - self._headers = headers - - def info(self): - return self._headers - - def getheaders(self, name): - self._headers.getheaders(name) - - -def extract_cookies_to_jar(jar, request, response): - """Extract the cookies from the response into a CookieJar. - - :param jar: cookielib.CookieJar (not necessarily a RequestsCookieJar) - :param request: our own requests.Request object - :param response: urllib3.HTTPResponse object - """ - if not (hasattr(response, '_original_response') and - response._original_response): - return - # the _original_response field is the wrapped httplib.HTTPResponse object, - req = MockRequest(request) - # pull out the HTTPMessage with the headers and put it in the mock: - res = MockResponse(response._original_response.msg) - jar.extract_cookies(res, req) - - -def get_cookie_header(jar, request): - """ - Produce an appropriate Cookie header string to be sent with `request`, or None. - - :rtype: str - """ - r = MockRequest(request) - jar.add_cookie_header(r) - return r.get_new_headers().get('Cookie') - - -def remove_cookie_by_name(cookiejar, name, domain=None, path=None): - """Unsets a cookie by name, by default over all domains and paths. - - Wraps CookieJar.clear(), is O(n). - """ - clearables = [] - for cookie in cookiejar: - if cookie.name != name: - continue - if domain is not None and domain != cookie.domain: - continue - if path is not None and path != cookie.path: - continue - clearables.append((cookie.domain, cookie.path, cookie.name)) - - for domain, path, name in clearables: - cookiejar.clear(domain, path, name) - - -class CookieConflictError(RuntimeError): - """There are two cookies that meet the criteria specified in the cookie jar. - Use .get and .set and include domain and path args in order to be more specific. - """ - - -class RequestsCookieJar(cookielib.CookieJar, MutableMapping): - """Compatibility class; is a cookielib.CookieJar, but exposes a dict - interface. - - This is the CookieJar we create by default for requests and sessions that - don't specify one, since some clients may expect response.cookies and - session.cookies to support dict operations. - - Requests does not use the dict interface internally; it's just for - compatibility with external client code. All requests code should work - out of the box with externally provided instances of ``CookieJar``, e.g. - ``LWPCookieJar`` and ``FileCookieJar``. - - Unlike a regular CookieJar, this class is pickleable. - - .. warning:: dictionary operations that are normally O(1) may be O(n). - """ - - def get(self, name, default=None, domain=None, path=None): - """Dict-like get() that also supports optional domain and path args in - order to resolve naming collisions from using one cookie jar over - multiple domains. - - .. warning:: operation is O(n), not O(1). - """ - try: - return self._find_no_duplicates(name, domain, path) - except KeyError: - return default - - def set(self, name, value, **kwargs): - """Dict-like set() that also supports optional domain and path args in - order to resolve naming collisions from using one cookie jar over - multiple domains. - """ - # support client code that unsets cookies by assignment of a None value: - if value is None: - remove_cookie_by_name(self, name, domain=kwargs.get('domain'), path=kwargs.get('path')) - return - - if isinstance(value, Morsel): - c = morsel_to_cookie(value) - else: - c = create_cookie(name, value, **kwargs) - self.set_cookie(c) - return c - - def iterkeys(self): - """Dict-like iterkeys() that returns an iterator of names of cookies - from the jar. - - .. seealso:: itervalues() and iteritems(). - """ - for cookie in iter(self): - yield cookie.name - - def keys(self): - """Dict-like keys() that returns a list of names of cookies from the - jar. - - .. seealso:: values() and items(). - """ - return list(self.iterkeys()) - - def itervalues(self): - """Dict-like itervalues() that returns an iterator of values of cookies - from the jar. - - .. seealso:: iterkeys() and iteritems(). - """ - for cookie in iter(self): - yield cookie.value - - def values(self): - """Dict-like values() that returns a list of values of cookies from the - jar. - - .. seealso:: keys() and items(). - """ - return list(self.itervalues()) - - def iteritems(self): - """Dict-like iteritems() that returns an iterator of name-value tuples - from the jar. - - .. seealso:: iterkeys() and itervalues(). - """ - for cookie in iter(self): - yield cookie.name, cookie.value - - def items(self): - """Dict-like items() that returns a list of name-value tuples from the - jar. Allows client-code to call ``dict(RequestsCookieJar)`` and get a - vanilla python dict of key value pairs. - - .. seealso:: keys() and values(). - """ - return list(self.iteritems()) - - def list_domains(self): - """Utility method to list all the domains in the jar.""" - domains = [] - for cookie in iter(self): - if cookie.domain not in domains: - domains.append(cookie.domain) - return domains - - def list_paths(self): - """Utility method to list all the paths in the jar.""" - paths = [] - for cookie in iter(self): - if cookie.path not in paths: - paths.append(cookie.path) - return paths - - def multiple_domains(self): - """Returns True if there are multiple domains in the jar. - Returns False otherwise. - - :rtype: bool - """ - domains = [] - for cookie in iter(self): - if cookie.domain is not None and cookie.domain in domains: - return True - domains.append(cookie.domain) - return False # there is only one domain in jar - - def get_dict(self, domain=None, path=None): - """Takes as an argument an optional domain and path and returns a plain - old Python dict of name-value pairs of cookies that meet the - requirements. - - :rtype: dict - """ - dictionary = {} - for cookie in iter(self): - if ( - (domain is None or cookie.domain == domain) and - (path is None or cookie.path == path) - ): - dictionary[cookie.name] = cookie.value - return dictionary - - def __contains__(self, name): - try: - return super(RequestsCookieJar, self).__contains__(name) - except CookieConflictError: - return True - - def __getitem__(self, name): - """Dict-like __getitem__() for compatibility with client code. Throws - exception if there are more than one cookie with name. In that case, - use the more explicit get() method instead. - - .. warning:: operation is O(n), not O(1). - """ - return self._find_no_duplicates(name) - - def __setitem__(self, name, value): - """Dict-like __setitem__ for compatibility with client code. Throws - exception if there is already a cookie of that name in the jar. In that - case, use the more explicit set() method instead. - """ - self.set(name, value) - - def __delitem__(self, name): - """Deletes a cookie given a name. Wraps ``cookielib.CookieJar``'s - ``remove_cookie_by_name()``. - """ - remove_cookie_by_name(self, name) - - def set_cookie(self, cookie, *args, **kwargs): - if hasattr(cookie.value, 'startswith') and cookie.value.startswith('"') and cookie.value.endswith('"'): - cookie.value = cookie.value.replace('\\"', '') - return super(RequestsCookieJar, self).set_cookie(cookie, *args, **kwargs) - - def update(self, other): - """Updates this jar with cookies from another CookieJar or dict-like""" - if isinstance(other, cookielib.CookieJar): - for cookie in other: - self.set_cookie(copy.copy(cookie)) - else: - super(RequestsCookieJar, self).update(other) - - def _find(self, name, domain=None, path=None): - """Requests uses this method internally to get cookie values. - - If there are conflicting cookies, _find arbitrarily chooses one. - See _find_no_duplicates if you want an exception thrown if there are - conflicting cookies. - - :param name: a string containing name of cookie - :param domain: (optional) string containing domain of cookie - :param path: (optional) string containing path of cookie - :return: cookie.value - """ - for cookie in iter(self): - if cookie.name == name: - if domain is None or cookie.domain == domain: - if path is None or cookie.path == path: - return cookie.value - - raise KeyError('name=%r, domain=%r, path=%r' % (name, domain, path)) - - def _find_no_duplicates(self, name, domain=None, path=None): - """Both ``__get_item__`` and ``get`` call this function: it's never - used elsewhere in Requests. - - :param name: a string containing name of cookie - :param domain: (optional) string containing domain of cookie - :param path: (optional) string containing path of cookie - :raises KeyError: if cookie is not found - :raises CookieConflictError: if there are multiple cookies - that match name and optionally domain and path - :return: cookie.value - """ - toReturn = None - for cookie in iter(self): - if cookie.name == name: - if domain is None or cookie.domain == domain: - if path is None or cookie.path == path: - if toReturn is not None: # if there are multiple cookies that meet passed in criteria - raise CookieConflictError('There are multiple cookies with name, %r' % (name)) - toReturn = cookie.value # we will eventually return this as long as no cookie conflict - - if toReturn: - return toReturn - raise KeyError('name=%r, domain=%r, path=%r' % (name, domain, path)) - - def __getstate__(self): - """Unlike a normal CookieJar, this class is pickleable.""" - state = self.__dict__.copy() - # remove the unpickleable RLock object - state.pop('_cookies_lock') - return state - - def __setstate__(self, state): - """Unlike a normal CookieJar, this class is pickleable.""" - self.__dict__.update(state) - if '_cookies_lock' not in self.__dict__: - self._cookies_lock = threading.RLock() - - def copy(self): - """Return a copy of this RequestsCookieJar.""" - new_cj = RequestsCookieJar() - new_cj.set_policy(self.get_policy()) - new_cj.update(self) - return new_cj - - def get_policy(self): - """Return the CookiePolicy instance used.""" - return self._policy - - -def _copy_cookie_jar(jar): - if jar is None: - return None - - if hasattr(jar, 'copy'): - # We're dealing with an instance of RequestsCookieJar - return jar.copy() - # We're dealing with a generic CookieJar instance - new_jar = copy.copy(jar) - new_jar.clear() - for cookie in jar: - new_jar.set_cookie(copy.copy(cookie)) - return new_jar - - -def create_cookie(name, value, **kwargs): - """Make a cookie from underspecified parameters. - - By default, the pair of `name` and `value` will be set for the domain '' - and sent on every request (this is sometimes called a "supercookie"). - """ - result = { - 'version': 0, - 'name': name, - 'value': value, - 'port': None, - 'domain': '', - 'path': '/', - 'secure': False, - 'expires': None, - 'discard': True, - 'comment': None, - 'comment_url': None, - 'rest': {'HttpOnly': None}, - 'rfc2109': False, - } - - badargs = set(kwargs) - set(result) - if badargs: - err = 'create_cookie() got unexpected keyword arguments: %s' - raise TypeError(err % list(badargs)) - - result.update(kwargs) - result['port_specified'] = bool(result['port']) - result['domain_specified'] = bool(result['domain']) - result['domain_initial_dot'] = result['domain'].startswith('.') - result['path_specified'] = bool(result['path']) - - return cookielib.Cookie(**result) - - -def morsel_to_cookie(morsel): - """Convert a Morsel object into a Cookie containing the one k/v pair.""" - - expires = None - if morsel['max-age']: - try: - expires = int(time.time() + int(morsel['max-age'])) - except ValueError: - raise TypeError('max-age: %s must be integer' % morsel['max-age']) - elif morsel['expires']: - time_template = '%a, %d-%b-%Y %H:%M:%S GMT' - expires = calendar.timegm( - time.strptime(morsel['expires'], time_template) - ) - return create_cookie( - comment=morsel['comment'], - comment_url=bool(morsel['comment']), - discard=False, - domain=morsel['domain'], - expires=expires, - name=morsel.key, - path=morsel['path'], - port=None, - rest={'HttpOnly': morsel['httponly']}, - rfc2109=False, - secure=bool(morsel['secure']), - value=morsel.value, - version=morsel['version'] or 0, - ) - - -def cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True): - """Returns a CookieJar from a key/value dictionary. - - :param cookie_dict: Dict of key/values to insert into CookieJar. - :param cookiejar: (optional) A cookiejar to add the cookies to. - :param overwrite: (optional) If False, will not replace cookies - already in the jar with new ones. - :rtype: CookieJar - """ - if cookiejar is None: - cookiejar = RequestsCookieJar() - - if cookie_dict is not None: - names_from_jar = [cookie.name for cookie in cookiejar] - for name in cookie_dict: - if overwrite or (name not in names_from_jar): - cookiejar.set_cookie(create_cookie(name, cookie_dict[name])) - - return cookiejar - - -def merge_cookies(cookiejar, cookies): - """Add cookies to cookiejar and returns a merged CookieJar. - - :param cookiejar: CookieJar object to add the cookies to. - :param cookies: Dictionary or CookieJar object to be added. - :rtype: CookieJar - """ - if not isinstance(cookiejar, cookielib.CookieJar): - raise ValueError('You can only merge into CookieJar') - - if isinstance(cookies, dict): - cookiejar = cookiejar_from_dict( - cookies, cookiejar=cookiejar, overwrite=False) - elif isinstance(cookies, cookielib.CookieJar): - try: - cookiejar.update(cookies) - except AttributeError: - for cookie_in_jar in cookies: - cookiejar.set_cookie(cookie_in_jar) - - return cookiejar diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/exceptions.py b/venv2/lib/python2.7/site-packages/pip/_vendor/requests/exceptions.py deleted file mode 100644 index a91e1fd..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/exceptions.py +++ /dev/null @@ -1,126 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -requests.exceptions -~~~~~~~~~~~~~~~~~~~ - -This module contains the set of Requests' exceptions. -""" -from pip._vendor.urllib3.exceptions import HTTPError as BaseHTTPError - - -class RequestException(IOError): - """There was an ambiguous exception that occurred while handling your - request. - """ - - def __init__(self, *args, **kwargs): - """Initialize RequestException with `request` and `response` objects.""" - response = kwargs.pop('response', None) - self.response = response - self.request = kwargs.pop('request', None) - if (response is not None and not self.request and - hasattr(response, 'request')): - self.request = self.response.request - super(RequestException, self).__init__(*args, **kwargs) - - -class HTTPError(RequestException): - """An HTTP error occurred.""" - - -class ConnectionError(RequestException): - """A Connection error occurred.""" - - -class ProxyError(ConnectionError): - """A proxy error occurred.""" - - -class SSLError(ConnectionError): - """An SSL error occurred.""" - - -class Timeout(RequestException): - """The request timed out. - - Catching this error will catch both - :exc:`~requests.exceptions.ConnectTimeout` and - :exc:`~requests.exceptions.ReadTimeout` errors. - """ - - -class ConnectTimeout(ConnectionError, Timeout): - """The request timed out while trying to connect to the remote server. - - Requests that produced this error are safe to retry. - """ - - -class ReadTimeout(Timeout): - """The server did not send any data in the allotted amount of time.""" - - -class URLRequired(RequestException): - """A valid URL is required to make a request.""" - - -class TooManyRedirects(RequestException): - """Too many redirects.""" - - -class MissingSchema(RequestException, ValueError): - """The URL schema (e.g. http or https) is missing.""" - - -class InvalidSchema(RequestException, ValueError): - """See defaults.py for valid schemas.""" - - -class InvalidURL(RequestException, ValueError): - """The URL provided was somehow invalid.""" - - -class InvalidHeader(RequestException, ValueError): - """The header value provided was somehow invalid.""" - - -class InvalidProxyURL(InvalidURL): - """The proxy URL provided is invalid.""" - - -class ChunkedEncodingError(RequestException): - """The server declared chunked encoding but sent an invalid chunk.""" - - -class ContentDecodingError(RequestException, BaseHTTPError): - """Failed to decode response content""" - - -class StreamConsumedError(RequestException, TypeError): - """The content for this response was already consumed""" - - -class RetryError(RequestException): - """Custom retries logic failed""" - - -class UnrewindableBodyError(RequestException): - """Requests encountered an error when trying to rewind a body""" - -# Warnings - - -class RequestsWarning(Warning): - """Base warning for Requests.""" - pass - - -class FileModeWarning(RequestsWarning, DeprecationWarning): - """A file was opened in text mode, but Requests determined its binary length.""" - pass - - -class RequestsDependencyWarning(RequestsWarning): - """An imported dependency doesn't match the expected version range.""" - pass diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/help.py b/venv2/lib/python2.7/site-packages/pip/_vendor/requests/help.py deleted file mode 100644 index 3c3072b..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/help.py +++ /dev/null @@ -1,119 +0,0 @@ -"""Module containing bug report helper(s).""" -from __future__ import print_function - -import json -import platform -import sys -import ssl - -from pip._vendor import idna -from pip._vendor import urllib3 -from pip._vendor import chardet - -from . import __version__ as requests_version - -try: - from pip._vendor.urllib3.contrib import pyopenssl -except ImportError: - pyopenssl = None - OpenSSL = None - cryptography = None -else: - import OpenSSL - import cryptography - - -def _implementation(): - """Return a dict with the Python implementation and version. - - Provide both the name and the version of the Python implementation - currently running. For example, on CPython 2.7.5 it will return - {'name': 'CPython', 'version': '2.7.5'}. - - This function works best on CPython and PyPy: in particular, it probably - doesn't work for Jython or IronPython. Future investigation should be done - to work out the correct shape of the code for those platforms. - """ - implementation = platform.python_implementation() - - if implementation == 'CPython': - implementation_version = platform.python_version() - elif implementation == 'PyPy': - implementation_version = '%s.%s.%s' % (sys.pypy_version_info.major, - sys.pypy_version_info.minor, - sys.pypy_version_info.micro) - if sys.pypy_version_info.releaselevel != 'final': - implementation_version = ''.join([ - implementation_version, sys.pypy_version_info.releaselevel - ]) - elif implementation == 'Jython': - implementation_version = platform.python_version() # Complete Guess - elif implementation == 'IronPython': - implementation_version = platform.python_version() # Complete Guess - else: - implementation_version = 'Unknown' - - return {'name': implementation, 'version': implementation_version} - - -def info(): - """Generate information for a bug report.""" - try: - platform_info = { - 'system': platform.system(), - 'release': platform.release(), - } - except IOError: - platform_info = { - 'system': 'Unknown', - 'release': 'Unknown', - } - - implementation_info = _implementation() - urllib3_info = {'version': urllib3.__version__} - chardet_info = {'version': chardet.__version__} - - pyopenssl_info = { - 'version': None, - 'openssl_version': '', - } - if OpenSSL: - pyopenssl_info = { - 'version': OpenSSL.__version__, - 'openssl_version': '%x' % OpenSSL.SSL.OPENSSL_VERSION_NUMBER, - } - cryptography_info = { - 'version': getattr(cryptography, '__version__', ''), - } - idna_info = { - 'version': getattr(idna, '__version__', ''), - } - - system_ssl = ssl.OPENSSL_VERSION_NUMBER - system_ssl_info = { - 'version': '%x' % system_ssl if system_ssl is not None else '' - } - - return { - 'platform': platform_info, - 'implementation': implementation_info, - 'system_ssl': system_ssl_info, - 'using_pyopenssl': pyopenssl is not None, - 'pyOpenSSL': pyopenssl_info, - 'urllib3': urllib3_info, - 'chardet': chardet_info, - 'cryptography': cryptography_info, - 'idna': idna_info, - 'requests': { - 'version': requests_version, - }, - } - - -def main(): - """Pretty-print the bug information as JSON.""" - print(json.dumps(info(), sort_keys=True, indent=2)) - - -if __name__ == '__main__': - main() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/hooks.py b/venv2/lib/python2.7/site-packages/pip/_vendor/requests/hooks.py deleted file mode 100644 index 7a51f21..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/hooks.py +++ /dev/null @@ -1,34 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -requests.hooks -~~~~~~~~~~~~~~ - -This module provides the capabilities for the Requests hooks system. - -Available hooks: - -``response``: - The response generated from a Request. -""" -HOOKS = ['response'] - - -def default_hooks(): - return {event: [] for event in HOOKS} - -# TODO: response is the only one - - -def dispatch_hook(key, hooks, hook_data, **kwargs): - """Dispatches a hook dictionary on a given piece of data.""" - hooks = hooks or {} - hooks = hooks.get(key) - if hooks: - if hasattr(hooks, '__call__'): - hooks = [hooks] - for hook in hooks: - _hook_data = hook(hook_data, **kwargs) - if _hook_data is not None: - hook_data = _hook_data - return hook_data diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/models.py b/venv2/lib/python2.7/site-packages/pip/_vendor/requests/models.py deleted file mode 100644 index 0839957..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/models.py +++ /dev/null @@ -1,953 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -requests.models -~~~~~~~~~~~~~~~ - -This module contains the primary objects that power Requests. -""" - -import datetime -import sys - -# Import encoding now, to avoid implicit import later. -# Implicit import within threads may cause LookupError when standard library is in a ZIP, -# such as in Embedded Python. See https://github.com/requests/requests/issues/3578. -import encodings.idna - -from pip._vendor.urllib3.fields import RequestField -from pip._vendor.urllib3.filepost import encode_multipart_formdata -from pip._vendor.urllib3.util import parse_url -from pip._vendor.urllib3.exceptions import ( - DecodeError, ReadTimeoutError, ProtocolError, LocationParseError) - -from io import UnsupportedOperation -from .hooks import default_hooks -from .structures import CaseInsensitiveDict - -from .auth import HTTPBasicAuth -from .cookies import cookiejar_from_dict, get_cookie_header, _copy_cookie_jar -from .exceptions import ( - HTTPError, MissingSchema, InvalidURL, ChunkedEncodingError, - ContentDecodingError, ConnectionError, StreamConsumedError) -from ._internal_utils import to_native_string, unicode_is_ascii -from .utils import ( - guess_filename, get_auth_from_url, requote_uri, - stream_decode_response_unicode, to_key_val_list, parse_header_links, - iter_slices, guess_json_utf, super_len, check_header_validity) -from .compat import ( - Callable, Mapping, - cookielib, urlunparse, urlsplit, urlencode, str, bytes, - is_py2, chardet, builtin_str, basestring) -from .compat import json as complexjson -from .status_codes import codes - -#: The set of HTTP status codes that indicate an automatically -#: processable redirect. -REDIRECT_STATI = ( - codes.moved, # 301 - codes.found, # 302 - codes.other, # 303 - codes.temporary_redirect, # 307 - codes.permanent_redirect, # 308 -) - -DEFAULT_REDIRECT_LIMIT = 30 -CONTENT_CHUNK_SIZE = 10 * 1024 -ITER_CHUNK_SIZE = 512 - - -class RequestEncodingMixin(object): - @property - def path_url(self): - """Build the path URL to use.""" - - url = [] - - p = urlsplit(self.url) - - path = p.path - if not path: - path = '/' - - url.append(path) - - query = p.query - if query: - url.append('?') - url.append(query) - - return ''.join(url) - - @staticmethod - def _encode_params(data): - """Encode parameters in a piece of data. - - Will successfully encode parameters when passed as a dict or a list of - 2-tuples. Order is retained if data is a list of 2-tuples but arbitrary - if parameters are supplied as a dict. - """ - - if isinstance(data, (str, bytes)): - return data - elif hasattr(data, 'read'): - return data - elif hasattr(data, '__iter__'): - result = [] - for k, vs in to_key_val_list(data): - if isinstance(vs, basestring) or not hasattr(vs, '__iter__'): - vs = [vs] - for v in vs: - if v is not None: - result.append( - (k.encode('utf-8') if isinstance(k, str) else k, - v.encode('utf-8') if isinstance(v, str) else v)) - return urlencode(result, doseq=True) - else: - return data - - @staticmethod - def _encode_files(files, data): - """Build the body for a multipart/form-data request. - - Will successfully encode files when passed as a dict or a list of - tuples. Order is retained if data is a list of tuples but arbitrary - if parameters are supplied as a dict. - The tuples may be 2-tuples (filename, fileobj), 3-tuples (filename, fileobj, contentype) - or 4-tuples (filename, fileobj, contentype, custom_headers). - """ - if (not files): - raise ValueError("Files must be provided.") - elif isinstance(data, basestring): - raise ValueError("Data must not be a string.") - - new_fields = [] - fields = to_key_val_list(data or {}) - files = to_key_val_list(files or {}) - - for field, val in fields: - if isinstance(val, basestring) or not hasattr(val, '__iter__'): - val = [val] - for v in val: - if v is not None: - # Don't call str() on bytestrings: in Py3 it all goes wrong. - if not isinstance(v, bytes): - v = str(v) - - new_fields.append( - (field.decode('utf-8') if isinstance(field, bytes) else field, - v.encode('utf-8') if isinstance(v, str) else v)) - - for (k, v) in files: - # support for explicit filename - ft = None - fh = None - if isinstance(v, (tuple, list)): - if len(v) == 2: - fn, fp = v - elif len(v) == 3: - fn, fp, ft = v - else: - fn, fp, ft, fh = v - else: - fn = guess_filename(v) or k - fp = v - - if isinstance(fp, (str, bytes, bytearray)): - fdata = fp - elif hasattr(fp, 'read'): - fdata = fp.read() - elif fp is None: - continue - else: - fdata = fp - - rf = RequestField(name=k, data=fdata, filename=fn, headers=fh) - rf.make_multipart(content_type=ft) - new_fields.append(rf) - - body, content_type = encode_multipart_formdata(new_fields) - - return body, content_type - - -class RequestHooksMixin(object): - def register_hook(self, event, hook): - """Properly register a hook.""" - - if event not in self.hooks: - raise ValueError('Unsupported event specified, with event name "%s"' % (event)) - - if isinstance(hook, Callable): - self.hooks[event].append(hook) - elif hasattr(hook, '__iter__'): - self.hooks[event].extend(h for h in hook if isinstance(h, Callable)) - - def deregister_hook(self, event, hook): - """Deregister a previously registered hook. - Returns True if the hook existed, False if not. - """ - - try: - self.hooks[event].remove(hook) - return True - except ValueError: - return False - - -class Request(RequestHooksMixin): - """A user-created :class:`Request <Request>` object. - - Used to prepare a :class:`PreparedRequest <PreparedRequest>`, which is sent to the server. - - :param method: HTTP method to use. - :param url: URL to send. - :param headers: dictionary of headers to send. - :param files: dictionary of {filename: fileobject} files to multipart upload. - :param data: the body to attach to the request. If a dictionary or - list of tuples ``[(key, value)]`` is provided, form-encoding will - take place. - :param json: json for the body to attach to the request (if files or data is not specified). - :param params: URL parameters to append to the URL. If a dictionary or - list of tuples ``[(key, value)]`` is provided, form-encoding will - take place. - :param auth: Auth handler or (user, pass) tuple. - :param cookies: dictionary or CookieJar of cookies to attach to this request. - :param hooks: dictionary of callback hooks, for internal usage. - - Usage:: - - >>> import requests - >>> req = requests.Request('GET', 'https://httpbin.org/get') - >>> req.prepare() - <PreparedRequest [GET]> - """ - - def __init__(self, - method=None, url=None, headers=None, files=None, data=None, - params=None, auth=None, cookies=None, hooks=None, json=None): - - # Default empty dicts for dict params. - data = [] if data is None else data - files = [] if files is None else files - headers = {} if headers is None else headers - params = {} if params is None else params - hooks = {} if hooks is None else hooks - - self.hooks = default_hooks() - for (k, v) in list(hooks.items()): - self.register_hook(event=k, hook=v) - - self.method = method - self.url = url - self.headers = headers - self.files = files - self.data = data - self.json = json - self.params = params - self.auth = auth - self.cookies = cookies - - def __repr__(self): - return '<Request [%s]>' % (self.method) - - def prepare(self): - """Constructs a :class:`PreparedRequest <PreparedRequest>` for transmission and returns it.""" - p = PreparedRequest() - p.prepare( - method=self.method, - url=self.url, - headers=self.headers, - files=self.files, - data=self.data, - json=self.json, - params=self.params, - auth=self.auth, - cookies=self.cookies, - hooks=self.hooks, - ) - return p - - -class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): - """The fully mutable :class:`PreparedRequest <PreparedRequest>` object, - containing the exact bytes that will be sent to the server. - - Generated from either a :class:`Request <Request>` object or manually. - - Usage:: - - >>> import requests - >>> req = requests.Request('GET', 'https://httpbin.org/get') - >>> r = req.prepare() - <PreparedRequest [GET]> - - >>> s = requests.Session() - >>> s.send(r) - <Response [200]> - """ - - def __init__(self): - #: HTTP verb to send to the server. - self.method = None - #: HTTP URL to send the request to. - self.url = None - #: dictionary of HTTP headers. - self.headers = None - # The `CookieJar` used to create the Cookie header will be stored here - # after prepare_cookies is called - self._cookies = None - #: request body to send to the server. - self.body = None - #: dictionary of callback hooks, for internal usage. - self.hooks = default_hooks() - #: integer denoting starting position of a readable file-like body. - self._body_position = None - - def prepare(self, - method=None, url=None, headers=None, files=None, data=None, - params=None, auth=None, cookies=None, hooks=None, json=None): - """Prepares the entire request with the given parameters.""" - - self.prepare_method(method) - self.prepare_url(url, params) - self.prepare_headers(headers) - self.prepare_cookies(cookies) - self.prepare_body(data, files, json) - self.prepare_auth(auth, url) - - # Note that prepare_auth must be last to enable authentication schemes - # such as OAuth to work on a fully prepared request. - - # This MUST go after prepare_auth. Authenticators could add a hook - self.prepare_hooks(hooks) - - def __repr__(self): - return '<PreparedRequest [%s]>' % (self.method) - - def copy(self): - p = PreparedRequest() - p.method = self.method - p.url = self.url - p.headers = self.headers.copy() if self.headers is not None else None - p._cookies = _copy_cookie_jar(self._cookies) - p.body = self.body - p.hooks = self.hooks - p._body_position = self._body_position - return p - - def prepare_method(self, method): - """Prepares the given HTTP method.""" - self.method = method - if self.method is not None: - self.method = to_native_string(self.method.upper()) - - @staticmethod - def _get_idna_encoded_host(host): - from pip._vendor import idna - - try: - host = idna.encode(host, uts46=True).decode('utf-8') - except idna.IDNAError: - raise UnicodeError - return host - - def prepare_url(self, url, params): - """Prepares the given HTTP URL.""" - #: Accept objects that have string representations. - #: We're unable to blindly call unicode/str functions - #: as this will include the bytestring indicator (b'') - #: on python 3.x. - #: https://github.com/requests/requests/pull/2238 - if isinstance(url, bytes): - url = url.decode('utf8') - else: - url = unicode(url) if is_py2 else str(url) - - # Remove leading whitespaces from url - url = url.lstrip() - - # Don't do any URL preparation for non-HTTP schemes like `mailto`, - # `data` etc to work around exceptions from `url_parse`, which - # handles RFC 3986 only. - if ':' in url and not url.lower().startswith('http'): - self.url = url - return - - # Support for unicode domain names and paths. - try: - scheme, auth, host, port, path, query, fragment = parse_url(url) - except LocationParseError as e: - raise InvalidURL(*e.args) - - if not scheme: - error = ("Invalid URL {0!r}: No schema supplied. Perhaps you meant http://{0}?") - error = error.format(to_native_string(url, 'utf8')) - - raise MissingSchema(error) - - if not host: - raise InvalidURL("Invalid URL %r: No host supplied" % url) - - # In general, we want to try IDNA encoding the hostname if the string contains - # non-ASCII characters. This allows users to automatically get the correct IDNA - # behaviour. For strings containing only ASCII characters, we need to also verify - # it doesn't start with a wildcard (*), before allowing the unencoded hostname. - if not unicode_is_ascii(host): - try: - host = self._get_idna_encoded_host(host) - except UnicodeError: - raise InvalidURL('URL has an invalid label.') - elif host.startswith(u'*'): - raise InvalidURL('URL has an invalid label.') - - # Carefully reconstruct the network location - netloc = auth or '' - if netloc: - netloc += '@' - netloc += host - if port: - netloc += ':' + str(port) - - # Bare domains aren't valid URLs. - if not path: - path = '/' - - if is_py2: - if isinstance(scheme, str): - scheme = scheme.encode('utf-8') - if isinstance(netloc, str): - netloc = netloc.encode('utf-8') - if isinstance(path, str): - path = path.encode('utf-8') - if isinstance(query, str): - query = query.encode('utf-8') - if isinstance(fragment, str): - fragment = fragment.encode('utf-8') - - if isinstance(params, (str, bytes)): - params = to_native_string(params) - - enc_params = self._encode_params(params) - if enc_params: - if query: - query = '%s&%s' % (query, enc_params) - else: - query = enc_params - - url = requote_uri(urlunparse([scheme, netloc, path, None, query, fragment])) - self.url = url - - def prepare_headers(self, headers): - """Prepares the given HTTP headers.""" - - self.headers = CaseInsensitiveDict() - if headers: - for header in headers.items(): - # Raise exception on invalid header value. - check_header_validity(header) - name, value = header - self.headers[to_native_string(name)] = value - - def prepare_body(self, data, files, json=None): - """Prepares the given HTTP body data.""" - - # Check if file, fo, generator, iterator. - # If not, run through normal process. - - # Nottin' on you. - body = None - content_type = None - - if not data and json is not None: - # urllib3 requires a bytes-like body. Python 2's json.dumps - # provides this natively, but Python 3 gives a Unicode string. - content_type = 'application/json' - body = complexjson.dumps(json) - if not isinstance(body, bytes): - body = body.encode('utf-8') - - is_stream = all([ - hasattr(data, '__iter__'), - not isinstance(data, (basestring, list, tuple, Mapping)) - ]) - - try: - length = super_len(data) - except (TypeError, AttributeError, UnsupportedOperation): - length = None - - if is_stream: - body = data - - if getattr(body, 'tell', None) is not None: - # Record the current file position before reading. - # This will allow us to rewind a file in the event - # of a redirect. - try: - self._body_position = body.tell() - except (IOError, OSError): - # This differentiates from None, allowing us to catch - # a failed `tell()` later when trying to rewind the body - self._body_position = object() - - if files: - raise NotImplementedError('Streamed bodies and files are mutually exclusive.') - - if length: - self.headers['Content-Length'] = builtin_str(length) - else: - self.headers['Transfer-Encoding'] = 'chunked' - else: - # Multi-part file uploads. - if files: - (body, content_type) = self._encode_files(files, data) - else: - if data: - body = self._encode_params(data) - if isinstance(data, basestring) or hasattr(data, 'read'): - content_type = None - else: - content_type = 'application/x-www-form-urlencoded' - - self.prepare_content_length(body) - - # Add content-type if it wasn't explicitly provided. - if content_type and ('content-type' not in self.headers): - self.headers['Content-Type'] = content_type - - self.body = body - - def prepare_content_length(self, body): - """Prepare Content-Length header based on request method and body""" - if body is not None: - length = super_len(body) - if length: - # If length exists, set it. Otherwise, we fallback - # to Transfer-Encoding: chunked. - self.headers['Content-Length'] = builtin_str(length) - elif self.method not in ('GET', 'HEAD') and self.headers.get('Content-Length') is None: - # Set Content-Length to 0 for methods that can have a body - # but don't provide one. (i.e. not GET or HEAD) - self.headers['Content-Length'] = '0' - - def prepare_auth(self, auth, url=''): - """Prepares the given HTTP auth data.""" - - # If no Auth is explicitly provided, extract it from the URL first. - if auth is None: - url_auth = get_auth_from_url(self.url) - auth = url_auth if any(url_auth) else None - - if auth: - if isinstance(auth, tuple) and len(auth) == 2: - # special-case basic HTTP auth - auth = HTTPBasicAuth(*auth) - - # Allow auth to make its changes. - r = auth(self) - - # Update self to reflect the auth changes. - self.__dict__.update(r.__dict__) - - # Recompute Content-Length - self.prepare_content_length(self.body) - - def prepare_cookies(self, cookies): - """Prepares the given HTTP cookie data. - - This function eventually generates a ``Cookie`` header from the - given cookies using cookielib. Due to cookielib's design, the header - will not be regenerated if it already exists, meaning this function - can only be called once for the life of the - :class:`PreparedRequest <PreparedRequest>` object. Any subsequent calls - to ``prepare_cookies`` will have no actual effect, unless the "Cookie" - header is removed beforehand. - """ - if isinstance(cookies, cookielib.CookieJar): - self._cookies = cookies - else: - self._cookies = cookiejar_from_dict(cookies) - - cookie_header = get_cookie_header(self._cookies, self) - if cookie_header is not None: - self.headers['Cookie'] = cookie_header - - def prepare_hooks(self, hooks): - """Prepares the given hooks.""" - # hooks can be passed as None to the prepare method and to this - # method. To prevent iterating over None, simply use an empty list - # if hooks is False-y - hooks = hooks or [] - for event in hooks: - self.register_hook(event, hooks[event]) - - -class Response(object): - """The :class:`Response <Response>` object, which contains a - server's response to an HTTP request. - """ - - __attrs__ = [ - '_content', 'status_code', 'headers', 'url', 'history', - 'encoding', 'reason', 'cookies', 'elapsed', 'request' - ] - - def __init__(self): - self._content = False - self._content_consumed = False - self._next = None - - #: Integer Code of responded HTTP Status, e.g. 404 or 200. - self.status_code = None - - #: Case-insensitive Dictionary of Response Headers. - #: For example, ``headers['content-encoding']`` will return the - #: value of a ``'Content-Encoding'`` response header. - self.headers = CaseInsensitiveDict() - - #: File-like object representation of response (for advanced usage). - #: Use of ``raw`` requires that ``stream=True`` be set on the request. - # This requirement does not apply for use internally to Requests. - self.raw = None - - #: Final URL location of Response. - self.url = None - - #: Encoding to decode with when accessing r.text. - self.encoding = None - - #: A list of :class:`Response <Response>` objects from - #: the history of the Request. Any redirect responses will end - #: up here. The list is sorted from the oldest to the most recent request. - self.history = [] - - #: Textual reason of responded HTTP Status, e.g. "Not Found" or "OK". - self.reason = None - - #: A CookieJar of Cookies the server sent back. - self.cookies = cookiejar_from_dict({}) - - #: The amount of time elapsed between sending the request - #: and the arrival of the response (as a timedelta). - #: This property specifically measures the time taken between sending - #: the first byte of the request and finishing parsing the headers. It - #: is therefore unaffected by consuming the response content or the - #: value of the ``stream`` keyword argument. - self.elapsed = datetime.timedelta(0) - - #: The :class:`PreparedRequest <PreparedRequest>` object to which this - #: is a response. - self.request = None - - def __enter__(self): - return self - - def __exit__(self, *args): - self.close() - - def __getstate__(self): - # Consume everything; accessing the content attribute makes - # sure the content has been fully read. - if not self._content_consumed: - self.content - - return {attr: getattr(self, attr, None) for attr in self.__attrs__} - - def __setstate__(self, state): - for name, value in state.items(): - setattr(self, name, value) - - # pickled objects do not have .raw - setattr(self, '_content_consumed', True) - setattr(self, 'raw', None) - - def __repr__(self): - return '<Response [%s]>' % (self.status_code) - - def __bool__(self): - """Returns True if :attr:`status_code` is less than 400. - - This attribute checks if the status code of the response is between - 400 and 600 to see if there was a client error or a server error. If - the status code, is between 200 and 400, this will return True. This - is **not** a check to see if the response code is ``200 OK``. - """ - return self.ok - - def __nonzero__(self): - """Returns True if :attr:`status_code` is less than 400. - - This attribute checks if the status code of the response is between - 400 and 600 to see if there was a client error or a server error. If - the status code, is between 200 and 400, this will return True. This - is **not** a check to see if the response code is ``200 OK``. - """ - return self.ok - - def __iter__(self): - """Allows you to use a response as an iterator.""" - return self.iter_content(128) - - @property - def ok(self): - """Returns True if :attr:`status_code` is less than 400, False if not. - - This attribute checks if the status code of the response is between - 400 and 600 to see if there was a client error or a server error. If - the status code is between 200 and 400, this will return True. This - is **not** a check to see if the response code is ``200 OK``. - """ - try: - self.raise_for_status() - except HTTPError: - return False - return True - - @property - def is_redirect(self): - """True if this Response is a well-formed HTTP redirect that could have - been processed automatically (by :meth:`Session.resolve_redirects`). - """ - return ('location' in self.headers and self.status_code in REDIRECT_STATI) - - @property - def is_permanent_redirect(self): - """True if this Response one of the permanent versions of redirect.""" - return ('location' in self.headers and self.status_code in (codes.moved_permanently, codes.permanent_redirect)) - - @property - def next(self): - """Returns a PreparedRequest for the next request in a redirect chain, if there is one.""" - return self._next - - @property - def apparent_encoding(self): - """The apparent encoding, provided by the chardet library.""" - return chardet.detect(self.content)['encoding'] - - def iter_content(self, chunk_size=1, decode_unicode=False): - """Iterates over the response data. When stream=True is set on the - request, this avoids reading the content at once into memory for - large responses. The chunk size is the number of bytes it should - read into memory. This is not necessarily the length of each item - returned as decoding can take place. - - chunk_size must be of type int or None. A value of None will - function differently depending on the value of `stream`. - stream=True will read data as it arrives in whatever size the - chunks are received. If stream=False, data is returned as - a single chunk. - - If decode_unicode is True, content will be decoded using the best - available encoding based on the response. - """ - - def generate(): - # Special case for urllib3. - if hasattr(self.raw, 'stream'): - try: - for chunk in self.raw.stream(chunk_size, decode_content=True): - yield chunk - except ProtocolError as e: - raise ChunkedEncodingError(e) - except DecodeError as e: - raise ContentDecodingError(e) - except ReadTimeoutError as e: - raise ConnectionError(e) - else: - # Standard file-like object. - while True: - chunk = self.raw.read(chunk_size) - if not chunk: - break - yield chunk - - self._content_consumed = True - - if self._content_consumed and isinstance(self._content, bool): - raise StreamConsumedError() - elif chunk_size is not None and not isinstance(chunk_size, int): - raise TypeError("chunk_size must be an int, it is instead a %s." % type(chunk_size)) - # simulate reading small chunks of the content - reused_chunks = iter_slices(self._content, chunk_size) - - stream_chunks = generate() - - chunks = reused_chunks if self._content_consumed else stream_chunks - - if decode_unicode: - chunks = stream_decode_response_unicode(chunks, self) - - return chunks - - def iter_lines(self, chunk_size=ITER_CHUNK_SIZE, decode_unicode=False, delimiter=None): - """Iterates over the response data, one line at a time. When - stream=True is set on the request, this avoids reading the - content at once into memory for large responses. - - .. note:: This method is not reentrant safe. - """ - - pending = None - - for chunk in self.iter_content(chunk_size=chunk_size, decode_unicode=decode_unicode): - - if pending is not None: - chunk = pending + chunk - - if delimiter: - lines = chunk.split(delimiter) - else: - lines = chunk.splitlines() - - if lines and lines[-1] and chunk and lines[-1][-1] == chunk[-1]: - pending = lines.pop() - else: - pending = None - - for line in lines: - yield line - - if pending is not None: - yield pending - - @property - def content(self): - """Content of the response, in bytes.""" - - if self._content is False: - # Read the contents. - if self._content_consumed: - raise RuntimeError( - 'The content for this response was already consumed') - - if self.status_code == 0 or self.raw is None: - self._content = None - else: - self._content = b''.join(self.iter_content(CONTENT_CHUNK_SIZE)) or b'' - - self._content_consumed = True - # don't need to release the connection; that's been handled by urllib3 - # since we exhausted the data. - return self._content - - @property - def text(self): - """Content of the response, in unicode. - - If Response.encoding is None, encoding will be guessed using - ``chardet``. - - The encoding of the response content is determined based solely on HTTP - headers, following RFC 2616 to the letter. If you can take advantage of - non-HTTP knowledge to make a better guess at the encoding, you should - set ``r.encoding`` appropriately before accessing this property. - """ - - # Try charset from content-type - content = None - encoding = self.encoding - - if not self.content: - return str('') - - # Fallback to auto-detected encoding. - if self.encoding is None: - encoding = self.apparent_encoding - - # Decode unicode from given encoding. - try: - content = str(self.content, encoding, errors='replace') - except (LookupError, TypeError): - # A LookupError is raised if the encoding was not found which could - # indicate a misspelling or similar mistake. - # - # A TypeError can be raised if encoding is None - # - # So we try blindly encoding. - content = str(self.content, errors='replace') - - return content - - def json(self, **kwargs): - r"""Returns the json-encoded content of a response, if any. - - :param \*\*kwargs: Optional arguments that ``json.loads`` takes. - :raises ValueError: If the response body does not contain valid json. - """ - - if not self.encoding and self.content and len(self.content) > 3: - # No encoding set. JSON RFC 4627 section 3 states we should expect - # UTF-8, -16 or -32. Detect which one to use; If the detection or - # decoding fails, fall back to `self.text` (using chardet to make - # a best guess). - encoding = guess_json_utf(self.content) - if encoding is not None: - try: - return complexjson.loads( - self.content.decode(encoding), **kwargs - ) - except UnicodeDecodeError: - # Wrong UTF codec detected; usually because it's not UTF-8 - # but some other 8-bit codec. This is an RFC violation, - # and the server didn't bother to tell us what codec *was* - # used. - pass - return complexjson.loads(self.text, **kwargs) - - @property - def links(self): - """Returns the parsed header links of the response, if any.""" - - header = self.headers.get('link') - - # l = MultiDict() - l = {} - - if header: - links = parse_header_links(header) - - for link in links: - key = link.get('rel') or link.get('url') - l[key] = link - - return l - - def raise_for_status(self): - """Raises stored :class:`HTTPError`, if one occurred.""" - - http_error_msg = '' - if isinstance(self.reason, bytes): - # We attempt to decode utf-8 first because some servers - # choose to localize their reason strings. If the string - # isn't utf-8, we fall back to iso-8859-1 for all other - # encodings. (See PR #3538) - try: - reason = self.reason.decode('utf-8') - except UnicodeDecodeError: - reason = self.reason.decode('iso-8859-1') - else: - reason = self.reason - - if 400 <= self.status_code < 500: - http_error_msg = u'%s Client Error: %s for url: %s' % (self.status_code, reason, self.url) - - elif 500 <= self.status_code < 600: - http_error_msg = u'%s Server Error: %s for url: %s' % (self.status_code, reason, self.url) - - if http_error_msg: - raise HTTPError(http_error_msg, response=self) - - def close(self): - """Releases the connection back to the pool. Once this method has been - called the underlying ``raw`` object must not be accessed again. - - *Note: Should not normally need to be called explicitly.* - """ - if not self._content_consumed: - self.raw.close() - - release_conn = getattr(self.raw, 'release_conn', None) - if release_conn is not None: - release_conn() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/packages.py b/venv2/lib/python2.7/site-packages/pip/_vendor/requests/packages.py deleted file mode 100644 index 9582fa7..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/packages.py +++ /dev/null @@ -1,16 +0,0 @@ -import sys - -# This code exists for backwards compatibility reasons. -# I don't like it either. Just look the other way. :) - -for package in ('urllib3', 'idna', 'chardet'): - vendored_package = "pip._vendor." + package - locals()[package] = __import__(vendored_package) - # This traversal is apparently necessary such that the identities are - # preserved (requests.packages.urllib3.* is urllib3.*) - for mod in list(sys.modules): - if mod == vendored_package or mod.startswith(vendored_package + '.'): - unprefixed_mod = mod[len("pip._vendor."):] - sys.modules['pip._vendor.requests.packages.' + unprefixed_mod] = sys.modules[mod] - -# Kinda cool, though, right? diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/sessions.py b/venv2/lib/python2.7/site-packages/pip/_vendor/requests/sessions.py deleted file mode 100644 index d73d700..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/sessions.py +++ /dev/null @@ -1,770 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -requests.session -~~~~~~~~~~~~~~~~ - -This module provides a Session object to manage and persist settings across -requests (cookies, auth, proxies). -""" -import os -import sys -import time -from datetime import timedelta - -from .auth import _basic_auth_str -from .compat import cookielib, is_py3, OrderedDict, urljoin, urlparse, Mapping -from .cookies import ( - cookiejar_from_dict, extract_cookies_to_jar, RequestsCookieJar, merge_cookies) -from .models import Request, PreparedRequest, DEFAULT_REDIRECT_LIMIT -from .hooks import default_hooks, dispatch_hook -from ._internal_utils import to_native_string -from .utils import to_key_val_list, default_headers, DEFAULT_PORTS -from .exceptions import ( - TooManyRedirects, InvalidSchema, ChunkedEncodingError, ContentDecodingError) - -from .structures import CaseInsensitiveDict -from .adapters import HTTPAdapter - -from .utils import ( - requote_uri, get_environ_proxies, get_netrc_auth, should_bypass_proxies, - get_auth_from_url, rewind_body -) - -from .status_codes import codes - -# formerly defined here, reexposed here for backward compatibility -from .models import REDIRECT_STATI - -# Preferred clock, based on which one is more accurate on a given system. -if sys.platform == 'win32': - try: # Python 3.4+ - preferred_clock = time.perf_counter - except AttributeError: # Earlier than Python 3. - preferred_clock = time.clock -else: - preferred_clock = time.time - - -def merge_setting(request_setting, session_setting, dict_class=OrderedDict): - """Determines appropriate setting for a given request, taking into account - the explicit setting on that request, and the setting in the session. If a - setting is a dictionary, they will be merged together using `dict_class` - """ - - if session_setting is None: - return request_setting - - if request_setting is None: - return session_setting - - # Bypass if not a dictionary (e.g. verify) - if not ( - isinstance(session_setting, Mapping) and - isinstance(request_setting, Mapping) - ): - return request_setting - - merged_setting = dict_class(to_key_val_list(session_setting)) - merged_setting.update(to_key_val_list(request_setting)) - - # Remove keys that are set to None. Extract keys first to avoid altering - # the dictionary during iteration. - none_keys = [k for (k, v) in merged_setting.items() if v is None] - for key in none_keys: - del merged_setting[key] - - return merged_setting - - -def merge_hooks(request_hooks, session_hooks, dict_class=OrderedDict): - """Properly merges both requests and session hooks. - - This is necessary because when request_hooks == {'response': []}, the - merge breaks Session hooks entirely. - """ - if session_hooks is None or session_hooks.get('response') == []: - return request_hooks - - if request_hooks is None or request_hooks.get('response') == []: - return session_hooks - - return merge_setting(request_hooks, session_hooks, dict_class) - - -class SessionRedirectMixin(object): - - def get_redirect_target(self, resp): - """Receives a Response. Returns a redirect URI or ``None``""" - # Due to the nature of how requests processes redirects this method will - # be called at least once upon the original response and at least twice - # on each subsequent redirect response (if any). - # If a custom mixin is used to handle this logic, it may be advantageous - # to cache the redirect location onto the response object as a private - # attribute. - if resp.is_redirect: - location = resp.headers['location'] - # Currently the underlying http module on py3 decode headers - # in latin1, but empirical evidence suggests that latin1 is very - # rarely used with non-ASCII characters in HTTP headers. - # It is more likely to get UTF8 header rather than latin1. - # This causes incorrect handling of UTF8 encoded location headers. - # To solve this, we re-encode the location in latin1. - if is_py3: - location = location.encode('latin1') - return to_native_string(location, 'utf8') - return None - - def should_strip_auth(self, old_url, new_url): - """Decide whether Authorization header should be removed when redirecting""" - old_parsed = urlparse(old_url) - new_parsed = urlparse(new_url) - if old_parsed.hostname != new_parsed.hostname: - return True - # Special case: allow http -> https redirect when using the standard - # ports. This isn't specified by RFC 7235, but is kept to avoid - # breaking backwards compatibility with older versions of requests - # that allowed any redirects on the same host. - if (old_parsed.scheme == 'http' and old_parsed.port in (80, None) - and new_parsed.scheme == 'https' and new_parsed.port in (443, None)): - return False - - # Handle default port usage corresponding to scheme. - changed_port = old_parsed.port != new_parsed.port - changed_scheme = old_parsed.scheme != new_parsed.scheme - default_port = (DEFAULT_PORTS.get(old_parsed.scheme, None), None) - if (not changed_scheme and old_parsed.port in default_port - and new_parsed.port in default_port): - return False - - # Standard case: root URI must match - return changed_port or changed_scheme - - def resolve_redirects(self, resp, req, stream=False, timeout=None, - verify=True, cert=None, proxies=None, yield_requests=False, **adapter_kwargs): - """Receives a Response. Returns a generator of Responses or Requests.""" - - hist = [] # keep track of history - - url = self.get_redirect_target(resp) - previous_fragment = urlparse(req.url).fragment - while url: - prepared_request = req.copy() - - # Update history and keep track of redirects. - # resp.history must ignore the original request in this loop - hist.append(resp) - resp.history = hist[1:] - - try: - resp.content # Consume socket so it can be released - except (ChunkedEncodingError, ContentDecodingError, RuntimeError): - resp.raw.read(decode_content=False) - - if len(resp.history) >= self.max_redirects: - raise TooManyRedirects('Exceeded %s redirects.' % self.max_redirects, response=resp) - - # Release the connection back into the pool. - resp.close() - - # Handle redirection without scheme (see: RFC 1808 Section 4) - if url.startswith('//'): - parsed_rurl = urlparse(resp.url) - url = '%s:%s' % (to_native_string(parsed_rurl.scheme), url) - - # Normalize url case and attach previous fragment if needed (RFC 7231 7.1.2) - parsed = urlparse(url) - if parsed.fragment == '' and previous_fragment: - parsed = parsed._replace(fragment=previous_fragment) - elif parsed.fragment: - previous_fragment = parsed.fragment - url = parsed.geturl() - - # Facilitate relative 'location' headers, as allowed by RFC 7231. - # (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/resource') - # Compliant with RFC3986, we percent encode the url. - if not parsed.netloc: - url = urljoin(resp.url, requote_uri(url)) - else: - url = requote_uri(url) - - prepared_request.url = to_native_string(url) - - self.rebuild_method(prepared_request, resp) - - # https://github.com/requests/requests/issues/1084 - if resp.status_code not in (codes.temporary_redirect, codes.permanent_redirect): - # https://github.com/requests/requests/issues/3490 - purged_headers = ('Content-Length', 'Content-Type', 'Transfer-Encoding') - for header in purged_headers: - prepared_request.headers.pop(header, None) - prepared_request.body = None - - headers = prepared_request.headers - try: - del headers['Cookie'] - except KeyError: - pass - - # Extract any cookies sent on the response to the cookiejar - # in the new request. Because we've mutated our copied prepared - # request, use the old one that we haven't yet touched. - extract_cookies_to_jar(prepared_request._cookies, req, resp.raw) - merge_cookies(prepared_request._cookies, self.cookies) - prepared_request.prepare_cookies(prepared_request._cookies) - - # Rebuild auth and proxy information. - proxies = self.rebuild_proxies(prepared_request, proxies) - self.rebuild_auth(prepared_request, resp) - - # A failed tell() sets `_body_position` to `object()`. This non-None - # value ensures `rewindable` will be True, allowing us to raise an - # UnrewindableBodyError, instead of hanging the connection. - rewindable = ( - prepared_request._body_position is not None and - ('Content-Length' in headers or 'Transfer-Encoding' in headers) - ) - - # Attempt to rewind consumed file-like object. - if rewindable: - rewind_body(prepared_request) - - # Override the original request. - req = prepared_request - - if yield_requests: - yield req - else: - - resp = self.send( - req, - stream=stream, - timeout=timeout, - verify=verify, - cert=cert, - proxies=proxies, - allow_redirects=False, - **adapter_kwargs - ) - - extract_cookies_to_jar(self.cookies, prepared_request, resp.raw) - - # extract redirect url, if any, for the next loop - url = self.get_redirect_target(resp) - yield resp - - def rebuild_auth(self, prepared_request, response): - """When being redirected we may want to strip authentication from the - request to avoid leaking credentials. This method intelligently removes - and reapplies authentication where possible to avoid credential loss. - """ - headers = prepared_request.headers - url = prepared_request.url - - if 'Authorization' in headers and self.should_strip_auth(response.request.url, url): - # If we get redirected to a new host, we should strip out any - # authentication headers. - del headers['Authorization'] - - # .netrc might have more auth for us on our new host. - new_auth = get_netrc_auth(url) if self.trust_env else None - if new_auth is not None: - prepared_request.prepare_auth(new_auth) - - return - - def rebuild_proxies(self, prepared_request, proxies): - """This method re-evaluates the proxy configuration by considering the - environment variables. If we are redirected to a URL covered by - NO_PROXY, we strip the proxy configuration. Otherwise, we set missing - proxy keys for this URL (in case they were stripped by a previous - redirect). - - This method also replaces the Proxy-Authorization header where - necessary. - - :rtype: dict - """ - proxies = proxies if proxies is not None else {} - headers = prepared_request.headers - url = prepared_request.url - scheme = urlparse(url).scheme - new_proxies = proxies.copy() - no_proxy = proxies.get('no_proxy') - - bypass_proxy = should_bypass_proxies(url, no_proxy=no_proxy) - if self.trust_env and not bypass_proxy: - environ_proxies = get_environ_proxies(url, no_proxy=no_proxy) - - proxy = environ_proxies.get(scheme, environ_proxies.get('all')) - - if proxy: - new_proxies.setdefault(scheme, proxy) - - if 'Proxy-Authorization' in headers: - del headers['Proxy-Authorization'] - - try: - username, password = get_auth_from_url(new_proxies[scheme]) - except KeyError: - username, password = None, None - - if username and password: - headers['Proxy-Authorization'] = _basic_auth_str(username, password) - - return new_proxies - - def rebuild_method(self, prepared_request, response): - """When being redirected we may want to change the method of the request - based on certain specs or browser behavior. - """ - method = prepared_request.method - - # https://tools.ietf.org/html/rfc7231#section-6.4.4 - if response.status_code == codes.see_other and method != 'HEAD': - method = 'GET' - - # Do what the browsers do, despite standards... - # First, turn 302s into GETs. - if response.status_code == codes.found and method != 'HEAD': - method = 'GET' - - # Second, if a POST is responded to with a 301, turn it into a GET. - # This bizarre behaviour is explained in Issue 1704. - if response.status_code == codes.moved and method == 'POST': - method = 'GET' - - prepared_request.method = method - - -class Session(SessionRedirectMixin): - """A Requests session. - - Provides cookie persistence, connection-pooling, and configuration. - - Basic Usage:: - - >>> import requests - >>> s = requests.Session() - >>> s.get('https://httpbin.org/get') - <Response [200]> - - Or as a context manager:: - - >>> with requests.Session() as s: - >>> s.get('https://httpbin.org/get') - <Response [200]> - """ - - __attrs__ = [ - 'headers', 'cookies', 'auth', 'proxies', 'hooks', 'params', 'verify', - 'cert', 'prefetch', 'adapters', 'stream', 'trust_env', - 'max_redirects', - ] - - def __init__(self): - - #: A case-insensitive dictionary of headers to be sent on each - #: :class:`Request <Request>` sent from this - #: :class:`Session <Session>`. - self.headers = default_headers() - - #: Default Authentication tuple or object to attach to - #: :class:`Request <Request>`. - self.auth = None - - #: Dictionary mapping protocol or protocol and host to the URL of the proxy - #: (e.g. {'http': 'foo.bar:3128', 'http://host.name': 'foo.bar:4012'}) to - #: be used on each :class:`Request <Request>`. - self.proxies = {} - - #: Event-handling hooks. - self.hooks = default_hooks() - - #: Dictionary of querystring data to attach to each - #: :class:`Request <Request>`. The dictionary values may be lists for - #: representing multivalued query parameters. - self.params = {} - - #: Stream response content default. - self.stream = False - - #: SSL Verification default. - self.verify = True - - #: SSL client certificate default, if String, path to ssl client - #: cert file (.pem). If Tuple, ('cert', 'key') pair. - self.cert = None - - #: Maximum number of redirects allowed. If the request exceeds this - #: limit, a :class:`TooManyRedirects` exception is raised. - #: This defaults to requests.models.DEFAULT_REDIRECT_LIMIT, which is - #: 30. - self.max_redirects = DEFAULT_REDIRECT_LIMIT - - #: Trust environment settings for proxy configuration, default - #: authentication and similar. - self.trust_env = True - - #: A CookieJar containing all currently outstanding cookies set on this - #: session. By default it is a - #: :class:`RequestsCookieJar <requests.cookies.RequestsCookieJar>`, but - #: may be any other ``cookielib.CookieJar`` compatible object. - self.cookies = cookiejar_from_dict({}) - - # Default connection adapters. - self.adapters = OrderedDict() - self.mount('https://', HTTPAdapter()) - self.mount('http://', HTTPAdapter()) - - def __enter__(self): - return self - - def __exit__(self, *args): - self.close() - - def prepare_request(self, request): - """Constructs a :class:`PreparedRequest <PreparedRequest>` for - transmission and returns it. The :class:`PreparedRequest` has settings - merged from the :class:`Request <Request>` instance and those of the - :class:`Session`. - - :param request: :class:`Request` instance to prepare with this - session's settings. - :rtype: requests.PreparedRequest - """ - cookies = request.cookies or {} - - # Bootstrap CookieJar. - if not isinstance(cookies, cookielib.CookieJar): - cookies = cookiejar_from_dict(cookies) - - # Merge with session cookies - merged_cookies = merge_cookies( - merge_cookies(RequestsCookieJar(), self.cookies), cookies) - - # Set environment's basic authentication if not explicitly set. - auth = request.auth - if self.trust_env and not auth and not self.auth: - auth = get_netrc_auth(request.url) - - p = PreparedRequest() - p.prepare( - method=request.method.upper(), - url=request.url, - files=request.files, - data=request.data, - json=request.json, - headers=merge_setting(request.headers, self.headers, dict_class=CaseInsensitiveDict), - params=merge_setting(request.params, self.params), - auth=merge_setting(auth, self.auth), - cookies=merged_cookies, - hooks=merge_hooks(request.hooks, self.hooks), - ) - return p - - def request(self, method, url, - params=None, data=None, headers=None, cookies=None, files=None, - auth=None, timeout=None, allow_redirects=True, proxies=None, - hooks=None, stream=None, verify=None, cert=None, json=None): - """Constructs a :class:`Request <Request>`, prepares it and sends it. - Returns :class:`Response <Response>` object. - - :param method: method for the new :class:`Request` object. - :param url: URL for the new :class:`Request` object. - :param params: (optional) Dictionary or bytes to be sent in the query - string for the :class:`Request`. - :param data: (optional) Dictionary, list of tuples, bytes, or file-like - object to send in the body of the :class:`Request`. - :param json: (optional) json to send in the body of the - :class:`Request`. - :param headers: (optional) Dictionary of HTTP Headers to send with the - :class:`Request`. - :param cookies: (optional) Dict or CookieJar object to send with the - :class:`Request`. - :param files: (optional) Dictionary of ``'filename': file-like-objects`` - for multipart encoding upload. - :param auth: (optional) Auth tuple or callable to enable - Basic/Digest/Custom HTTP Auth. - :param timeout: (optional) How long to wait for the server to send - data before giving up, as a float, or a :ref:`(connect timeout, - read timeout) <timeouts>` tuple. - :type timeout: float or tuple - :param allow_redirects: (optional) Set to True by default. - :type allow_redirects: bool - :param proxies: (optional) Dictionary mapping protocol or protocol and - hostname to the URL of the proxy. - :param stream: (optional) whether to immediately download the response - content. Defaults to ``False``. - :param verify: (optional) Either a boolean, in which case it controls whether we verify - the server's TLS certificate, or a string, in which case it must be a path - to a CA bundle to use. Defaults to ``True``. - :param cert: (optional) if String, path to ssl client cert file (.pem). - If Tuple, ('cert', 'key') pair. - :rtype: requests.Response - """ - # Create the Request. - req = Request( - method=method.upper(), - url=url, - headers=headers, - files=files, - data=data or {}, - json=json, - params=params or {}, - auth=auth, - cookies=cookies, - hooks=hooks, - ) - prep = self.prepare_request(req) - - proxies = proxies or {} - - settings = self.merge_environment_settings( - prep.url, proxies, stream, verify, cert - ) - - # Send the request. - send_kwargs = { - 'timeout': timeout, - 'allow_redirects': allow_redirects, - } - send_kwargs.update(settings) - resp = self.send(prep, **send_kwargs) - - return resp - - def get(self, url, **kwargs): - r"""Sends a GET request. Returns :class:`Response` object. - - :param url: URL for the new :class:`Request` object. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :rtype: requests.Response - """ - - kwargs.setdefault('allow_redirects', True) - return self.request('GET', url, **kwargs) - - def options(self, url, **kwargs): - r"""Sends a OPTIONS request. Returns :class:`Response` object. - - :param url: URL for the new :class:`Request` object. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :rtype: requests.Response - """ - - kwargs.setdefault('allow_redirects', True) - return self.request('OPTIONS', url, **kwargs) - - def head(self, url, **kwargs): - r"""Sends a HEAD request. Returns :class:`Response` object. - - :param url: URL for the new :class:`Request` object. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :rtype: requests.Response - """ - - kwargs.setdefault('allow_redirects', False) - return self.request('HEAD', url, **kwargs) - - def post(self, url, data=None, json=None, **kwargs): - r"""Sends a POST request. Returns :class:`Response` object. - - :param url: URL for the new :class:`Request` object. - :param data: (optional) Dictionary, list of tuples, bytes, or file-like - object to send in the body of the :class:`Request`. - :param json: (optional) json to send in the body of the :class:`Request`. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :rtype: requests.Response - """ - - return self.request('POST', url, data=data, json=json, **kwargs) - - def put(self, url, data=None, **kwargs): - r"""Sends a PUT request. Returns :class:`Response` object. - - :param url: URL for the new :class:`Request` object. - :param data: (optional) Dictionary, list of tuples, bytes, or file-like - object to send in the body of the :class:`Request`. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :rtype: requests.Response - """ - - return self.request('PUT', url, data=data, **kwargs) - - def patch(self, url, data=None, **kwargs): - r"""Sends a PATCH request. Returns :class:`Response` object. - - :param url: URL for the new :class:`Request` object. - :param data: (optional) Dictionary, list of tuples, bytes, or file-like - object to send in the body of the :class:`Request`. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :rtype: requests.Response - """ - - return self.request('PATCH', url, data=data, **kwargs) - - def delete(self, url, **kwargs): - r"""Sends a DELETE request. Returns :class:`Response` object. - - :param url: URL for the new :class:`Request` object. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :rtype: requests.Response - """ - - return self.request('DELETE', url, **kwargs) - - def send(self, request, **kwargs): - """Send a given PreparedRequest. - - :rtype: requests.Response - """ - # Set defaults that the hooks can utilize to ensure they always have - # the correct parameters to reproduce the previous request. - kwargs.setdefault('stream', self.stream) - kwargs.setdefault('verify', self.verify) - kwargs.setdefault('cert', self.cert) - kwargs.setdefault('proxies', self.proxies) - - # It's possible that users might accidentally send a Request object. - # Guard against that specific failure case. - if isinstance(request, Request): - raise ValueError('You can only send PreparedRequests.') - - # Set up variables needed for resolve_redirects and dispatching of hooks - allow_redirects = kwargs.pop('allow_redirects', True) - stream = kwargs.get('stream') - hooks = request.hooks - - # Get the appropriate adapter to use - adapter = self.get_adapter(url=request.url) - - # Start time (approximately) of the request - start = preferred_clock() - - # Send the request - r = adapter.send(request, **kwargs) - - # Total elapsed time of the request (approximately) - elapsed = preferred_clock() - start - r.elapsed = timedelta(seconds=elapsed) - - # Response manipulation hooks - r = dispatch_hook('response', hooks, r, **kwargs) - - # Persist cookies - if r.history: - - # If the hooks create history then we want those cookies too - for resp in r.history: - extract_cookies_to_jar(self.cookies, resp.request, resp.raw) - - extract_cookies_to_jar(self.cookies, request, r.raw) - - # Redirect resolving generator. - gen = self.resolve_redirects(r, request, **kwargs) - - # Resolve redirects if allowed. - history = [resp for resp in gen] if allow_redirects else [] - - # Shuffle things around if there's history. - if history: - # Insert the first (original) request at the start - history.insert(0, r) - # Get the last request made - r = history.pop() - r.history = history - - # If redirects aren't being followed, store the response on the Request for Response.next(). - if not allow_redirects: - try: - r._next = next(self.resolve_redirects(r, request, yield_requests=True, **kwargs)) - except StopIteration: - pass - - if not stream: - r.content - - return r - - def merge_environment_settings(self, url, proxies, stream, verify, cert): - """ - Check the environment and merge it with some settings. - - :rtype: dict - """ - # Gather clues from the surrounding environment. - if self.trust_env: - # Set environment's proxies. - no_proxy = proxies.get('no_proxy') if proxies is not None else None - env_proxies = get_environ_proxies(url, no_proxy=no_proxy) - for (k, v) in env_proxies.items(): - proxies.setdefault(k, v) - - # Look for requests environment configuration and be compatible - # with cURL. - if verify is True or verify is None: - verify = (os.environ.get('REQUESTS_CA_BUNDLE') or - os.environ.get('CURL_CA_BUNDLE')) - - # Merge all the kwargs. - proxies = merge_setting(proxies, self.proxies) - stream = merge_setting(stream, self.stream) - verify = merge_setting(verify, self.verify) - cert = merge_setting(cert, self.cert) - - return {'verify': verify, 'proxies': proxies, 'stream': stream, - 'cert': cert} - - def get_adapter(self, url): - """ - Returns the appropriate connection adapter for the given URL. - - :rtype: requests.adapters.BaseAdapter - """ - for (prefix, adapter) in self.adapters.items(): - - if url.lower().startswith(prefix.lower()): - return adapter - - # Nothing matches :-/ - raise InvalidSchema("No connection adapters were found for '%s'" % url) - - def close(self): - """Closes all adapters and as such the session""" - for v in self.adapters.values(): - v.close() - - def mount(self, prefix, adapter): - """Registers a connection adapter to a prefix. - - Adapters are sorted in descending order by prefix length. - """ - self.adapters[prefix] = adapter - keys_to_move = [k for k in self.adapters if len(k) < len(prefix)] - - for key in keys_to_move: - self.adapters[key] = self.adapters.pop(key) - - def __getstate__(self): - state = {attr: getattr(self, attr, None) for attr in self.__attrs__} - return state - - def __setstate__(self, state): - for attr, value in state.items(): - setattr(self, attr, value) - - -def session(): - """ - Returns a :class:`Session` for context-management. - - .. deprecated:: 1.0.0 - - This method has been deprecated since version 1.0.0 and is only kept for - backwards compatibility. New code should use :class:`~requests.sessions.Session` - to create a session. This may be removed at a future date. - - :rtype: Session - """ - return Session() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/status_codes.py b/venv2/lib/python2.7/site-packages/pip/_vendor/requests/status_codes.py deleted file mode 100644 index 813e8c4..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/status_codes.py +++ /dev/null @@ -1,120 +0,0 @@ -# -*- coding: utf-8 -*- - -r""" -The ``codes`` object defines a mapping from common names for HTTP statuses -to their numerical codes, accessible either as attributes or as dictionary -items. - ->>> requests.codes['temporary_redirect'] -307 ->>> requests.codes.teapot -418 ->>> requests.codes['\o/'] -200 - -Some codes have multiple names, and both upper- and lower-case versions of -the names are allowed. For example, ``codes.ok``, ``codes.OK``, and -``codes.okay`` all correspond to the HTTP status code 200. -""" - -from .structures import LookupDict - -_codes = { - - # Informational. - 100: ('continue',), - 101: ('switching_protocols',), - 102: ('processing',), - 103: ('checkpoint',), - 122: ('uri_too_long', 'request_uri_too_long'), - 200: ('ok', 'okay', 'all_ok', 'all_okay', 'all_good', '\\o/', '✓'), - 201: ('created',), - 202: ('accepted',), - 203: ('non_authoritative_info', 'non_authoritative_information'), - 204: ('no_content',), - 205: ('reset_content', 'reset'), - 206: ('partial_content', 'partial'), - 207: ('multi_status', 'multiple_status', 'multi_stati', 'multiple_stati'), - 208: ('already_reported',), - 226: ('im_used',), - - # Redirection. - 300: ('multiple_choices',), - 301: ('moved_permanently', 'moved', '\\o-'), - 302: ('found',), - 303: ('see_other', 'other'), - 304: ('not_modified',), - 305: ('use_proxy',), - 306: ('switch_proxy',), - 307: ('temporary_redirect', 'temporary_moved', 'temporary'), - 308: ('permanent_redirect', - 'resume_incomplete', 'resume',), # These 2 to be removed in 3.0 - - # Client Error. - 400: ('bad_request', 'bad'), - 401: ('unauthorized',), - 402: ('payment_required', 'payment'), - 403: ('forbidden',), - 404: ('not_found', '-o-'), - 405: ('method_not_allowed', 'not_allowed'), - 406: ('not_acceptable',), - 407: ('proxy_authentication_required', 'proxy_auth', 'proxy_authentication'), - 408: ('request_timeout', 'timeout'), - 409: ('conflict',), - 410: ('gone',), - 411: ('length_required',), - 412: ('precondition_failed', 'precondition'), - 413: ('request_entity_too_large',), - 414: ('request_uri_too_large',), - 415: ('unsupported_media_type', 'unsupported_media', 'media_type'), - 416: ('requested_range_not_satisfiable', 'requested_range', 'range_not_satisfiable'), - 417: ('expectation_failed',), - 418: ('im_a_teapot', 'teapot', 'i_am_a_teapot'), - 421: ('misdirected_request',), - 422: ('unprocessable_entity', 'unprocessable'), - 423: ('locked',), - 424: ('failed_dependency', 'dependency'), - 425: ('unordered_collection', 'unordered'), - 426: ('upgrade_required', 'upgrade'), - 428: ('precondition_required', 'precondition'), - 429: ('too_many_requests', 'too_many'), - 431: ('header_fields_too_large', 'fields_too_large'), - 444: ('no_response', 'none'), - 449: ('retry_with', 'retry'), - 450: ('blocked_by_windows_parental_controls', 'parental_controls'), - 451: ('unavailable_for_legal_reasons', 'legal_reasons'), - 499: ('client_closed_request',), - - # Server Error. - 500: ('internal_server_error', 'server_error', '/o\\', '✗'), - 501: ('not_implemented',), - 502: ('bad_gateway',), - 503: ('service_unavailable', 'unavailable'), - 504: ('gateway_timeout',), - 505: ('http_version_not_supported', 'http_version'), - 506: ('variant_also_negotiates',), - 507: ('insufficient_storage',), - 509: ('bandwidth_limit_exceeded', 'bandwidth'), - 510: ('not_extended',), - 511: ('network_authentication_required', 'network_auth', 'network_authentication'), -} - -codes = LookupDict(name='status_codes') - -def _init(): - for code, titles in _codes.items(): - for title in titles: - setattr(codes, title, code) - if not title.startswith(('\\', '/')): - setattr(codes, title.upper(), code) - - def doc(code): - names = ', '.join('``%s``' % n for n in _codes[code]) - return '* %d: %s' % (code, names) - - global __doc__ - __doc__ = (__doc__ + '\n' + - '\n'.join(doc(code) for code in sorted(_codes)) - if __doc__ is not None else None) - -_init() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/structures.py b/venv2/lib/python2.7/site-packages/pip/_vendor/requests/structures.py deleted file mode 100644 index da930e2..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/structures.py +++ /dev/null @@ -1,103 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -requests.structures -~~~~~~~~~~~~~~~~~~~ - -Data structures that power Requests. -""" - -from .compat import OrderedDict, Mapping, MutableMapping - - -class CaseInsensitiveDict(MutableMapping): - """A case-insensitive ``dict``-like object. - - Implements all methods and operations of - ``MutableMapping`` as well as dict's ``copy``. Also - provides ``lower_items``. - - All keys are expected to be strings. The structure remembers the - case of the last key to be set, and ``iter(instance)``, - ``keys()``, ``items()``, ``iterkeys()``, and ``iteritems()`` - will contain case-sensitive keys. However, querying and contains - testing is case insensitive:: - - cid = CaseInsensitiveDict() - cid['Accept'] = 'application/json' - cid['aCCEPT'] == 'application/json' # True - list(cid) == ['Accept'] # True - - For example, ``headers['content-encoding']`` will return the - value of a ``'Content-Encoding'`` response header, regardless - of how the header name was originally stored. - - If the constructor, ``.update``, or equality comparison - operations are given keys that have equal ``.lower()``s, the - behavior is undefined. - """ - - def __init__(self, data=None, **kwargs): - self._store = OrderedDict() - if data is None: - data = {} - self.update(data, **kwargs) - - def __setitem__(self, key, value): - # Use the lowercased key for lookups, but store the actual - # key alongside the value. - self._store[key.lower()] = (key, value) - - def __getitem__(self, key): - return self._store[key.lower()][1] - - def __delitem__(self, key): - del self._store[key.lower()] - - def __iter__(self): - return (casedkey for casedkey, mappedvalue in self._store.values()) - - def __len__(self): - return len(self._store) - - def lower_items(self): - """Like iteritems(), but with all lowercase keys.""" - return ( - (lowerkey, keyval[1]) - for (lowerkey, keyval) - in self._store.items() - ) - - def __eq__(self, other): - if isinstance(other, Mapping): - other = CaseInsensitiveDict(other) - else: - return NotImplemented - # Compare insensitively - return dict(self.lower_items()) == dict(other.lower_items()) - - # Copy is required - def copy(self): - return CaseInsensitiveDict(self._store.values()) - - def __repr__(self): - return str(dict(self.items())) - - -class LookupDict(dict): - """Dictionary lookup object.""" - - def __init__(self, name=None): - self.name = name - super(LookupDict, self).__init__() - - def __repr__(self): - return '<lookup \'%s\'>' % (self.name) - - def __getitem__(self, key): - # We allow fall-through here, so values default to None - - return self.__dict__.get(key, None) - - def get(self, key, default=None): - return self.__dict__.get(key, default) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/utils.py b/venv2/lib/python2.7/site-packages/pip/_vendor/requests/utils.py deleted file mode 100644 index 8170a8d..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/requests/utils.py +++ /dev/null @@ -1,977 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -requests.utils -~~~~~~~~~~~~~~ - -This module provides utility functions that are used within Requests -that are also useful for external consumption. -""" - -import codecs -import contextlib -import io -import os -import re -import socket -import struct -import sys -import tempfile -import warnings -import zipfile - -from .__version__ import __version__ -from . import certs -# to_native_string is unused here, but imported here for backwards compatibility -from ._internal_utils import to_native_string -from .compat import parse_http_list as _parse_list_header -from .compat import ( - quote, urlparse, bytes, str, OrderedDict, unquote, getproxies, - proxy_bypass, urlunparse, basestring, integer_types, is_py3, - proxy_bypass_environment, getproxies_environment, Mapping) -from .cookies import cookiejar_from_dict -from .structures import CaseInsensitiveDict -from .exceptions import ( - InvalidURL, InvalidHeader, FileModeWarning, UnrewindableBodyError) - -NETRC_FILES = ('.netrc', '_netrc') - -DEFAULT_CA_BUNDLE_PATH = certs.where() - -DEFAULT_PORTS = {'http': 80, 'https': 443} - - -if sys.platform == 'win32': - # provide a proxy_bypass version on Windows without DNS lookups - - def proxy_bypass_registry(host): - try: - if is_py3: - import winreg - else: - import _winreg as winreg - except ImportError: - return False - - try: - internetSettings = winreg.OpenKey(winreg.HKEY_CURRENT_USER, - r'Software\Microsoft\Windows\CurrentVersion\Internet Settings') - # ProxyEnable could be REG_SZ or REG_DWORD, normalizing it - proxyEnable = int(winreg.QueryValueEx(internetSettings, - 'ProxyEnable')[0]) - # ProxyOverride is almost always a string - proxyOverride = winreg.QueryValueEx(internetSettings, - 'ProxyOverride')[0] - except OSError: - return False - if not proxyEnable or not proxyOverride: - return False - - # make a check value list from the registry entry: replace the - # '<local>' string by the localhost entry and the corresponding - # canonical entry. - proxyOverride = proxyOverride.split(';') - # now check if we match one of the registry values. - for test in proxyOverride: - if test == '<local>': - if '.' not in host: - return True - test = test.replace(".", r"\.") # mask dots - test = test.replace("*", r".*") # change glob sequence - test = test.replace("?", r".") # change glob char - if re.match(test, host, re.I): - return True - return False - - def proxy_bypass(host): # noqa - """Return True, if the host should be bypassed. - - Checks proxy settings gathered from the environment, if specified, - or the registry. - """ - if getproxies_environment(): - return proxy_bypass_environment(host) - else: - return proxy_bypass_registry(host) - - -def dict_to_sequence(d): - """Returns an internal sequence dictionary update.""" - - if hasattr(d, 'items'): - d = d.items() - - return d - - -def super_len(o): - total_length = None - current_position = 0 - - if hasattr(o, '__len__'): - total_length = len(o) - - elif hasattr(o, 'len'): - total_length = o.len - - elif hasattr(o, 'fileno'): - try: - fileno = o.fileno() - except io.UnsupportedOperation: - pass - else: - total_length = os.fstat(fileno).st_size - - # Having used fstat to determine the file length, we need to - # confirm that this file was opened up in binary mode. - if 'b' not in o.mode: - warnings.warn(( - "Requests has determined the content-length for this " - "request using the binary size of the file: however, the " - "file has been opened in text mode (i.e. without the 'b' " - "flag in the mode). This may lead to an incorrect " - "content-length. In Requests 3.0, support will be removed " - "for files in text mode."), - FileModeWarning - ) - - if hasattr(o, 'tell'): - try: - current_position = o.tell() - except (OSError, IOError): - # This can happen in some weird situations, such as when the file - # is actually a special file descriptor like stdin. In this - # instance, we don't know what the length is, so set it to zero and - # let requests chunk it instead. - if total_length is not None: - current_position = total_length - else: - if hasattr(o, 'seek') and total_length is None: - # StringIO and BytesIO have seek but no useable fileno - try: - # seek to end of file - o.seek(0, 2) - total_length = o.tell() - - # seek back to current position to support - # partially read file-like objects - o.seek(current_position or 0) - except (OSError, IOError): - total_length = 0 - - if total_length is None: - total_length = 0 - - return max(0, total_length - current_position) - - -def get_netrc_auth(url, raise_errors=False): - """Returns the Requests tuple auth for a given url from netrc.""" - - try: - from netrc import netrc, NetrcParseError - - netrc_path = None - - for f in NETRC_FILES: - try: - loc = os.path.expanduser('~/{}'.format(f)) - except KeyError: - # os.path.expanduser can fail when $HOME is undefined and - # getpwuid fails. See https://bugs.python.org/issue20164 & - # https://github.com/requests/requests/issues/1846 - return - - if os.path.exists(loc): - netrc_path = loc - break - - # Abort early if there isn't one. - if netrc_path is None: - return - - ri = urlparse(url) - - # Strip port numbers from netloc. This weird `if...encode`` dance is - # used for Python 3.2, which doesn't support unicode literals. - splitstr = b':' - if isinstance(url, str): - splitstr = splitstr.decode('ascii') - host = ri.netloc.split(splitstr)[0] - - try: - _netrc = netrc(netrc_path).authenticators(host) - if _netrc: - # Return with login / password - login_i = (0 if _netrc[0] else 1) - return (_netrc[login_i], _netrc[2]) - except (NetrcParseError, IOError): - # If there was a parsing error or a permissions issue reading the file, - # we'll just skip netrc auth unless explicitly asked to raise errors. - if raise_errors: - raise - - # AppEngine hackiness. - except (ImportError, AttributeError): - pass - - -def guess_filename(obj): - """Tries to guess the filename of the given object.""" - name = getattr(obj, 'name', None) - if (name and isinstance(name, basestring) and name[0] != '<' and - name[-1] != '>'): - return os.path.basename(name) - - -def extract_zipped_paths(path): - """Replace nonexistent paths that look like they refer to a member of a zip - archive with the location of an extracted copy of the target, or else - just return the provided path unchanged. - """ - if os.path.exists(path): - # this is already a valid path, no need to do anything further - return path - - # find the first valid part of the provided path and treat that as a zip archive - # assume the rest of the path is the name of a member in the archive - archive, member = os.path.split(path) - while archive and not os.path.exists(archive): - archive, prefix = os.path.split(archive) - member = '/'.join([prefix, member]) - - if not zipfile.is_zipfile(archive): - return path - - zip_file = zipfile.ZipFile(archive) - if member not in zip_file.namelist(): - return path - - # we have a valid zip archive and a valid member of that archive - tmp = tempfile.gettempdir() - extracted_path = os.path.join(tmp, *member.split('/')) - if not os.path.exists(extracted_path): - extracted_path = zip_file.extract(member, path=tmp) - - return extracted_path - - -def from_key_val_list(value): - """Take an object and test to see if it can be represented as a - dictionary. Unless it can not be represented as such, return an - OrderedDict, e.g., - - :: - - >>> from_key_val_list([('key', 'val')]) - OrderedDict([('key', 'val')]) - >>> from_key_val_list('string') - ValueError: cannot encode objects that are not 2-tuples - >>> from_key_val_list({'key': 'val'}) - OrderedDict([('key', 'val')]) - - :rtype: OrderedDict - """ - if value is None: - return None - - if isinstance(value, (str, bytes, bool, int)): - raise ValueError('cannot encode objects that are not 2-tuples') - - return OrderedDict(value) - - -def to_key_val_list(value): - """Take an object and test to see if it can be represented as a - dictionary. If it can be, return a list of tuples, e.g., - - :: - - >>> to_key_val_list([('key', 'val')]) - [('key', 'val')] - >>> to_key_val_list({'key': 'val'}) - [('key', 'val')] - >>> to_key_val_list('string') - ValueError: cannot encode objects that are not 2-tuples. - - :rtype: list - """ - if value is None: - return None - - if isinstance(value, (str, bytes, bool, int)): - raise ValueError('cannot encode objects that are not 2-tuples') - - if isinstance(value, Mapping): - value = value.items() - - return list(value) - - -# From mitsuhiko/werkzeug (used with permission). -def parse_list_header(value): - """Parse lists as described by RFC 2068 Section 2. - - In particular, parse comma-separated lists where the elements of - the list may include quoted-strings. A quoted-string could - contain a comma. A non-quoted string could have quotes in the - middle. Quotes are removed automatically after parsing. - - It basically works like :func:`parse_set_header` just that items - may appear multiple times and case sensitivity is preserved. - - The return value is a standard :class:`list`: - - >>> parse_list_header('token, "quoted value"') - ['token', 'quoted value'] - - To create a header from the :class:`list` again, use the - :func:`dump_header` function. - - :param value: a string with a list header. - :return: :class:`list` - :rtype: list - """ - result = [] - for item in _parse_list_header(value): - if item[:1] == item[-1:] == '"': - item = unquote_header_value(item[1:-1]) - result.append(item) - return result - - -# From mitsuhiko/werkzeug (used with permission). -def parse_dict_header(value): - """Parse lists of key, value pairs as described by RFC 2068 Section 2 and - convert them into a python dict: - - >>> d = parse_dict_header('foo="is a fish", bar="as well"') - >>> type(d) is dict - True - >>> sorted(d.items()) - [('bar', 'as well'), ('foo', 'is a fish')] - - If there is no value for a key it will be `None`: - - >>> parse_dict_header('key_without_value') - {'key_without_value': None} - - To create a header from the :class:`dict` again, use the - :func:`dump_header` function. - - :param value: a string with a dict header. - :return: :class:`dict` - :rtype: dict - """ - result = {} - for item in _parse_list_header(value): - if '=' not in item: - result[item] = None - continue - name, value = item.split('=', 1) - if value[:1] == value[-1:] == '"': - value = unquote_header_value(value[1:-1]) - result[name] = value - return result - - -# From mitsuhiko/werkzeug (used with permission). -def unquote_header_value(value, is_filename=False): - r"""Unquotes a header value. (Reversal of :func:`quote_header_value`). - This does not use the real unquoting but what browsers are actually - using for quoting. - - :param value: the header value to unquote. - :rtype: str - """ - if value and value[0] == value[-1] == '"': - # this is not the real unquoting, but fixing this so that the - # RFC is met will result in bugs with internet explorer and - # probably some other browsers as well. IE for example is - # uploading files with "C:\foo\bar.txt" as filename - value = value[1:-1] - - # if this is a filename and the starting characters look like - # a UNC path, then just return the value without quotes. Using the - # replace sequence below on a UNC path has the effect of turning - # the leading double slash into a single slash and then - # _fix_ie_filename() doesn't work correctly. See #458. - if not is_filename or value[:2] != '\\\\': - return value.replace('\\\\', '\\').replace('\\"', '"') - return value - - -def dict_from_cookiejar(cj): - """Returns a key/value dictionary from a CookieJar. - - :param cj: CookieJar object to extract cookies from. - :rtype: dict - """ - - cookie_dict = {} - - for cookie in cj: - cookie_dict[cookie.name] = cookie.value - - return cookie_dict - - -def add_dict_to_cookiejar(cj, cookie_dict): - """Returns a CookieJar from a key/value dictionary. - - :param cj: CookieJar to insert cookies into. - :param cookie_dict: Dict of key/values to insert into CookieJar. - :rtype: CookieJar - """ - - return cookiejar_from_dict(cookie_dict, cj) - - -def get_encodings_from_content(content): - """Returns encodings from given content string. - - :param content: bytestring to extract encodings from. - """ - warnings.warn(( - 'In requests 3.0, get_encodings_from_content will be removed. For ' - 'more information, please see the discussion on issue #2266. (This' - ' warning should only appear once.)'), - DeprecationWarning) - - charset_re = re.compile(r'<meta.*?charset=["\']*(.+?)["\'>]', flags=re.I) - pragma_re = re.compile(r'<meta.*?content=["\']*;?charset=(.+?)["\'>]', flags=re.I) - xml_re = re.compile(r'^<\?xml.*?encoding=["\']*(.+?)["\'>]') - - return (charset_re.findall(content) + - pragma_re.findall(content) + - xml_re.findall(content)) - - -def _parse_content_type_header(header): - """Returns content type and parameters from given header - - :param header: string - :return: tuple containing content type and dictionary of - parameters - """ - - tokens = header.split(';') - content_type, params = tokens[0].strip(), tokens[1:] - params_dict = {} - items_to_strip = "\"' " - - for param in params: - param = param.strip() - if param: - key, value = param, True - index_of_equals = param.find("=") - if index_of_equals != -1: - key = param[:index_of_equals].strip(items_to_strip) - value = param[index_of_equals + 1:].strip(items_to_strip) - params_dict[key.lower()] = value - return content_type, params_dict - - -def get_encoding_from_headers(headers): - """Returns encodings from given HTTP Header Dict. - - :param headers: dictionary to extract encoding from. - :rtype: str - """ - - content_type = headers.get('content-type') - - if not content_type: - return None - - content_type, params = _parse_content_type_header(content_type) - - if 'charset' in params: - return params['charset'].strip("'\"") - - if 'text' in content_type: - return 'ISO-8859-1' - - -def stream_decode_response_unicode(iterator, r): - """Stream decodes a iterator.""" - - if r.encoding is None: - for item in iterator: - yield item - return - - decoder = codecs.getincrementaldecoder(r.encoding)(errors='replace') - for chunk in iterator: - rv = decoder.decode(chunk) - if rv: - yield rv - rv = decoder.decode(b'', final=True) - if rv: - yield rv - - -def iter_slices(string, slice_length): - """Iterate over slices of a string.""" - pos = 0 - if slice_length is None or slice_length <= 0: - slice_length = len(string) - while pos < len(string): - yield string[pos:pos + slice_length] - pos += slice_length - - -def get_unicode_from_response(r): - """Returns the requested content back in unicode. - - :param r: Response object to get unicode content from. - - Tried: - - 1. charset from content-type - 2. fall back and replace all unicode characters - - :rtype: str - """ - warnings.warn(( - 'In requests 3.0, get_unicode_from_response will be removed. For ' - 'more information, please see the discussion on issue #2266. (This' - ' warning should only appear once.)'), - DeprecationWarning) - - tried_encodings = [] - - # Try charset from content-type - encoding = get_encoding_from_headers(r.headers) - - if encoding: - try: - return str(r.content, encoding) - except UnicodeError: - tried_encodings.append(encoding) - - # Fall back: - try: - return str(r.content, encoding, errors='replace') - except TypeError: - return r.content - - -# The unreserved URI characters (RFC 3986) -UNRESERVED_SET = frozenset( - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789-._~") - - -def unquote_unreserved(uri): - """Un-escape any percent-escape sequences in a URI that are unreserved - characters. This leaves all reserved, illegal and non-ASCII bytes encoded. - - :rtype: str - """ - parts = uri.split('%') - for i in range(1, len(parts)): - h = parts[i][0:2] - if len(h) == 2 and h.isalnum(): - try: - c = chr(int(h, 16)) - except ValueError: - raise InvalidURL("Invalid percent-escape sequence: '%s'" % h) - - if c in UNRESERVED_SET: - parts[i] = c + parts[i][2:] - else: - parts[i] = '%' + parts[i] - else: - parts[i] = '%' + parts[i] - return ''.join(parts) - - -def requote_uri(uri): - """Re-quote the given URI. - - This function passes the given URI through an unquote/quote cycle to - ensure that it is fully and consistently quoted. - - :rtype: str - """ - safe_with_percent = "!#$%&'()*+,/:;=?@[]~" - safe_without_percent = "!#$&'()*+,/:;=?@[]~" - try: - # Unquote only the unreserved characters - # Then quote only illegal characters (do not quote reserved, - # unreserved, or '%') - return quote(unquote_unreserved(uri), safe=safe_with_percent) - except InvalidURL: - # We couldn't unquote the given URI, so let's try quoting it, but - # there may be unquoted '%'s in the URI. We need to make sure they're - # properly quoted so they do not cause issues elsewhere. - return quote(uri, safe=safe_without_percent) - - -def address_in_network(ip, net): - """This function allows you to check if an IP belongs to a network subnet - - Example: returns True if ip = 192.168.1.1 and net = 192.168.1.0/24 - returns False if ip = 192.168.1.1 and net = 192.168.100.0/24 - - :rtype: bool - """ - ipaddr = struct.unpack('=L', socket.inet_aton(ip))[0] - netaddr, bits = net.split('/') - netmask = struct.unpack('=L', socket.inet_aton(dotted_netmask(int(bits))))[0] - network = struct.unpack('=L', socket.inet_aton(netaddr))[0] & netmask - return (ipaddr & netmask) == (network & netmask) - - -def dotted_netmask(mask): - """Converts mask from /xx format to xxx.xxx.xxx.xxx - - Example: if mask is 24 function returns 255.255.255.0 - - :rtype: str - """ - bits = 0xffffffff ^ (1 << 32 - mask) - 1 - return socket.inet_ntoa(struct.pack('>I', bits)) - - -def is_ipv4_address(string_ip): - """ - :rtype: bool - """ - try: - socket.inet_aton(string_ip) - except socket.error: - return False - return True - - -def is_valid_cidr(string_network): - """ - Very simple check of the cidr format in no_proxy variable. - - :rtype: bool - """ - if string_network.count('/') == 1: - try: - mask = int(string_network.split('/')[1]) - except ValueError: - return False - - if mask < 1 or mask > 32: - return False - - try: - socket.inet_aton(string_network.split('/')[0]) - except socket.error: - return False - else: - return False - return True - - -@contextlib.contextmanager -def set_environ(env_name, value): - """Set the environment variable 'env_name' to 'value' - - Save previous value, yield, and then restore the previous value stored in - the environment variable 'env_name'. - - If 'value' is None, do nothing""" - value_changed = value is not None - if value_changed: - old_value = os.environ.get(env_name) - os.environ[env_name] = value - try: - yield - finally: - if value_changed: - if old_value is None: - del os.environ[env_name] - else: - os.environ[env_name] = old_value - - -def should_bypass_proxies(url, no_proxy): - """ - Returns whether we should bypass proxies or not. - - :rtype: bool - """ - # Prioritize lowercase environment variables over uppercase - # to keep a consistent behaviour with other http projects (curl, wget). - get_proxy = lambda k: os.environ.get(k) or os.environ.get(k.upper()) - - # First check whether no_proxy is defined. If it is, check that the URL - # we're getting isn't in the no_proxy list. - no_proxy_arg = no_proxy - if no_proxy is None: - no_proxy = get_proxy('no_proxy') - parsed = urlparse(url) - - if parsed.hostname is None: - # URLs don't always have hostnames, e.g. file:/// urls. - return True - - if no_proxy: - # We need to check whether we match here. We need to see if we match - # the end of the hostname, both with and without the port. - no_proxy = ( - host for host in no_proxy.replace(' ', '').split(',') if host - ) - - if is_ipv4_address(parsed.hostname): - for proxy_ip in no_proxy: - if is_valid_cidr(proxy_ip): - if address_in_network(parsed.hostname, proxy_ip): - return True - elif parsed.hostname == proxy_ip: - # If no_proxy ip was defined in plain IP notation instead of cidr notation & - # matches the IP of the index - return True - else: - host_with_port = parsed.hostname - if parsed.port: - host_with_port += ':{}'.format(parsed.port) - - for host in no_proxy: - if parsed.hostname.endswith(host) or host_with_port.endswith(host): - # The URL does match something in no_proxy, so we don't want - # to apply the proxies on this URL. - return True - - with set_environ('no_proxy', no_proxy_arg): - # parsed.hostname can be `None` in cases such as a file URI. - try: - bypass = proxy_bypass(parsed.hostname) - except (TypeError, socket.gaierror): - bypass = False - - if bypass: - return True - - return False - - -def get_environ_proxies(url, no_proxy=None): - """ - Return a dict of environment proxies. - - :rtype: dict - """ - if should_bypass_proxies(url, no_proxy=no_proxy): - return {} - else: - return getproxies() - - -def select_proxy(url, proxies): - """Select a proxy for the url, if applicable. - - :param url: The url being for the request - :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs - """ - proxies = proxies or {} - urlparts = urlparse(url) - if urlparts.hostname is None: - return proxies.get(urlparts.scheme, proxies.get('all')) - - proxy_keys = [ - urlparts.scheme + '://' + urlparts.hostname, - urlparts.scheme, - 'all://' + urlparts.hostname, - 'all', - ] - proxy = None - for proxy_key in proxy_keys: - if proxy_key in proxies: - proxy = proxies[proxy_key] - break - - return proxy - - -def default_user_agent(name="python-requests"): - """ - Return a string representing the default user agent. - - :rtype: str - """ - return '%s/%s' % (name, __version__) - - -def default_headers(): - """ - :rtype: requests.structures.CaseInsensitiveDict - """ - return CaseInsensitiveDict({ - 'User-Agent': default_user_agent(), - 'Accept-Encoding': ', '.join(('gzip', 'deflate')), - 'Accept': '*/*', - 'Connection': 'keep-alive', - }) - - -def parse_header_links(value): - """Return a list of parsed link headers proxies. - - i.e. Link: <http:/.../front.jpeg>; rel=front; type="image/jpeg",<http://.../back.jpeg>; rel=back;type="image/jpeg" - - :rtype: list - """ - - links = [] - - replace_chars = ' \'"' - - value = value.strip(replace_chars) - if not value: - return links - - for val in re.split(', *<', value): - try: - url, params = val.split(';', 1) - except ValueError: - url, params = val, '' - - link = {'url': url.strip('<> \'"')} - - for param in params.split(';'): - try: - key, value = param.split('=') - except ValueError: - break - - link[key.strip(replace_chars)] = value.strip(replace_chars) - - links.append(link) - - return links - - -# Null bytes; no need to recreate these on each call to guess_json_utf -_null = '\x00'.encode('ascii') # encoding to ASCII for Python 3 -_null2 = _null * 2 -_null3 = _null * 3 - - -def guess_json_utf(data): - """ - :rtype: str - """ - # JSON always starts with two ASCII characters, so detection is as - # easy as counting the nulls and from their location and count - # determine the encoding. Also detect a BOM, if present. - sample = data[:4] - if sample in (codecs.BOM_UTF32_LE, codecs.BOM_UTF32_BE): - return 'utf-32' # BOM included - if sample[:3] == codecs.BOM_UTF8: - return 'utf-8-sig' # BOM included, MS style (discouraged) - if sample[:2] in (codecs.BOM_UTF16_LE, codecs.BOM_UTF16_BE): - return 'utf-16' # BOM included - nullcount = sample.count(_null) - if nullcount == 0: - return 'utf-8' - if nullcount == 2: - if sample[::2] == _null2: # 1st and 3rd are null - return 'utf-16-be' - if sample[1::2] == _null2: # 2nd and 4th are null - return 'utf-16-le' - # Did not detect 2 valid UTF-16 ascii-range characters - if nullcount == 3: - if sample[:3] == _null3: - return 'utf-32-be' - if sample[1:] == _null3: - return 'utf-32-le' - # Did not detect a valid UTF-32 ascii-range character - return None - - -def prepend_scheme_if_needed(url, new_scheme): - """Given a URL that may or may not have a scheme, prepend the given scheme. - Does not replace a present scheme with the one provided as an argument. - - :rtype: str - """ - scheme, netloc, path, params, query, fragment = urlparse(url, new_scheme) - - # urlparse is a finicky beast, and sometimes decides that there isn't a - # netloc present. Assume that it's being over-cautious, and switch netloc - # and path if urlparse decided there was no netloc. - if not netloc: - netloc, path = path, netloc - - return urlunparse((scheme, netloc, path, params, query, fragment)) - - -def get_auth_from_url(url): - """Given a url with authentication components, extract them into a tuple of - username,password. - - :rtype: (str,str) - """ - parsed = urlparse(url) - - try: - auth = (unquote(parsed.username), unquote(parsed.password)) - except (AttributeError, TypeError): - auth = ('', '') - - return auth - - -# Moved outside of function to avoid recompile every call -_CLEAN_HEADER_REGEX_BYTE = re.compile(b'^\\S[^\\r\\n]*$|^$') -_CLEAN_HEADER_REGEX_STR = re.compile(r'^\S[^\r\n]*$|^$') - - -def check_header_validity(header): - """Verifies that header value is a string which doesn't contain - leading whitespace or return characters. This prevents unintended - header injection. - - :param header: tuple, in the format (name, value). - """ - name, value = header - - if isinstance(value, bytes): - pat = _CLEAN_HEADER_REGEX_BYTE - else: - pat = _CLEAN_HEADER_REGEX_STR - try: - if not pat.match(value): - raise InvalidHeader("Invalid return character or leading space in header: %s" % name) - except TypeError: - raise InvalidHeader("Value for header {%s: %s} must be of type str or " - "bytes, not %s" % (name, value, type(value))) - - -def urldefragauth(url): - """ - Given a url remove the fragment and the authentication part. - - :rtype: str - """ - scheme, netloc, path, params, query, fragment = urlparse(url) - - # see func:`prepend_scheme_if_needed` - if not netloc: - netloc, path = path, netloc - - netloc = netloc.rsplit('@', 1)[-1] - - return urlunparse((scheme, netloc, path, params, query, '')) - - -def rewind_body(prepared_request): - """Move file pointer back to its recorded starting position - so it can be read again on redirect. - """ - body_seek = getattr(prepared_request.body, 'seek', None) - if body_seek is not None and isinstance(prepared_request._body_position, integer_types): - try: - body_seek(prepared_request._body_position) - except (IOError, OSError): - raise UnrewindableBodyError("An error occurred when rewinding request " - "body for redirect.") - else: - raise UnrewindableBodyError("Unable to rewind request body for redirect.") diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/retrying.py b/venv2/lib/python2.7/site-packages/pip/_vendor/retrying.py deleted file mode 100644 index 6d1e627..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/retrying.py +++ /dev/null @@ -1,267 +0,0 @@ -## Copyright 2013-2014 Ray Holder -## -## Licensed under the Apache License, Version 2.0 (the "License"); -## you may not use this file except in compliance with the License. -## You may obtain a copy of the License at -## -## http://www.apache.org/licenses/LICENSE-2.0 -## -## Unless required by applicable law or agreed to in writing, software -## distributed under the License is distributed on an "AS IS" BASIS, -## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -## See the License for the specific language governing permissions and -## limitations under the License. - -import random -from pip._vendor import six -import sys -import time -import traceback - - -# sys.maxint / 2, since Python 3.2 doesn't have a sys.maxint... -MAX_WAIT = 1073741823 - - -def retry(*dargs, **dkw): - """ - Decorator function that instantiates the Retrying object - @param *dargs: positional arguments passed to Retrying object - @param **dkw: keyword arguments passed to the Retrying object - """ - # support both @retry and @retry() as valid syntax - if len(dargs) == 1 and callable(dargs[0]): - def wrap_simple(f): - - @six.wraps(f) - def wrapped_f(*args, **kw): - return Retrying().call(f, *args, **kw) - - return wrapped_f - - return wrap_simple(dargs[0]) - - else: - def wrap(f): - - @six.wraps(f) - def wrapped_f(*args, **kw): - return Retrying(*dargs, **dkw).call(f, *args, **kw) - - return wrapped_f - - return wrap - - -class Retrying(object): - - def __init__(self, - stop=None, wait=None, - stop_max_attempt_number=None, - stop_max_delay=None, - wait_fixed=None, - wait_random_min=None, wait_random_max=None, - wait_incrementing_start=None, wait_incrementing_increment=None, - wait_exponential_multiplier=None, wait_exponential_max=None, - retry_on_exception=None, - retry_on_result=None, - wrap_exception=False, - stop_func=None, - wait_func=None, - wait_jitter_max=None): - - self._stop_max_attempt_number = 5 if stop_max_attempt_number is None else stop_max_attempt_number - self._stop_max_delay = 100 if stop_max_delay is None else stop_max_delay - self._wait_fixed = 1000 if wait_fixed is None else wait_fixed - self._wait_random_min = 0 if wait_random_min is None else wait_random_min - self._wait_random_max = 1000 if wait_random_max is None else wait_random_max - self._wait_incrementing_start = 0 if wait_incrementing_start is None else wait_incrementing_start - self._wait_incrementing_increment = 100 if wait_incrementing_increment is None else wait_incrementing_increment - self._wait_exponential_multiplier = 1 if wait_exponential_multiplier is None else wait_exponential_multiplier - self._wait_exponential_max = MAX_WAIT if wait_exponential_max is None else wait_exponential_max - self._wait_jitter_max = 0 if wait_jitter_max is None else wait_jitter_max - - # TODO add chaining of stop behaviors - # stop behavior - stop_funcs = [] - if stop_max_attempt_number is not None: - stop_funcs.append(self.stop_after_attempt) - - if stop_max_delay is not None: - stop_funcs.append(self.stop_after_delay) - - if stop_func is not None: - self.stop = stop_func - - elif stop is None: - self.stop = lambda attempts, delay: any(f(attempts, delay) for f in stop_funcs) - - else: - self.stop = getattr(self, stop) - - # TODO add chaining of wait behaviors - # wait behavior - wait_funcs = [lambda *args, **kwargs: 0] - if wait_fixed is not None: - wait_funcs.append(self.fixed_sleep) - - if wait_random_min is not None or wait_random_max is not None: - wait_funcs.append(self.random_sleep) - - if wait_incrementing_start is not None or wait_incrementing_increment is not None: - wait_funcs.append(self.incrementing_sleep) - - if wait_exponential_multiplier is not None or wait_exponential_max is not None: - wait_funcs.append(self.exponential_sleep) - - if wait_func is not None: - self.wait = wait_func - - elif wait is None: - self.wait = lambda attempts, delay: max(f(attempts, delay) for f in wait_funcs) - - else: - self.wait = getattr(self, wait) - - # retry on exception filter - if retry_on_exception is None: - self._retry_on_exception = self.always_reject - else: - self._retry_on_exception = retry_on_exception - - # TODO simplify retrying by Exception types - # retry on result filter - if retry_on_result is None: - self._retry_on_result = self.never_reject - else: - self._retry_on_result = retry_on_result - - self._wrap_exception = wrap_exception - - def stop_after_attempt(self, previous_attempt_number, delay_since_first_attempt_ms): - """Stop after the previous attempt >= stop_max_attempt_number.""" - return previous_attempt_number >= self._stop_max_attempt_number - - def stop_after_delay(self, previous_attempt_number, delay_since_first_attempt_ms): - """Stop after the time from the first attempt >= stop_max_delay.""" - return delay_since_first_attempt_ms >= self._stop_max_delay - - def no_sleep(self, previous_attempt_number, delay_since_first_attempt_ms): - """Don't sleep at all before retrying.""" - return 0 - - def fixed_sleep(self, previous_attempt_number, delay_since_first_attempt_ms): - """Sleep a fixed amount of time between each retry.""" - return self._wait_fixed - - def random_sleep(self, previous_attempt_number, delay_since_first_attempt_ms): - """Sleep a random amount of time between wait_random_min and wait_random_max""" - return random.randint(self._wait_random_min, self._wait_random_max) - - def incrementing_sleep(self, previous_attempt_number, delay_since_first_attempt_ms): - """ - Sleep an incremental amount of time after each attempt, starting at - wait_incrementing_start and incrementing by wait_incrementing_increment - """ - result = self._wait_incrementing_start + (self._wait_incrementing_increment * (previous_attempt_number - 1)) - if result < 0: - result = 0 - return result - - def exponential_sleep(self, previous_attempt_number, delay_since_first_attempt_ms): - exp = 2 ** previous_attempt_number - result = self._wait_exponential_multiplier * exp - if result > self._wait_exponential_max: - result = self._wait_exponential_max - if result < 0: - result = 0 - return result - - def never_reject(self, result): - return False - - def always_reject(self, result): - return True - - def should_reject(self, attempt): - reject = False - if attempt.has_exception: - reject |= self._retry_on_exception(attempt.value[1]) - else: - reject |= self._retry_on_result(attempt.value) - - return reject - - def call(self, fn, *args, **kwargs): - start_time = int(round(time.time() * 1000)) - attempt_number = 1 - while True: - try: - attempt = Attempt(fn(*args, **kwargs), attempt_number, False) - except: - tb = sys.exc_info() - attempt = Attempt(tb, attempt_number, True) - - if not self.should_reject(attempt): - return attempt.get(self._wrap_exception) - - delay_since_first_attempt_ms = int(round(time.time() * 1000)) - start_time - if self.stop(attempt_number, delay_since_first_attempt_ms): - if not self._wrap_exception and attempt.has_exception: - # get() on an attempt with an exception should cause it to be raised, but raise just in case - raise attempt.get() - else: - raise RetryError(attempt) - else: - sleep = self.wait(attempt_number, delay_since_first_attempt_ms) - if self._wait_jitter_max: - jitter = random.random() * self._wait_jitter_max - sleep = sleep + max(0, jitter) - time.sleep(sleep / 1000.0) - - attempt_number += 1 - - -class Attempt(object): - """ - An Attempt encapsulates a call to a target function that may end as a - normal return value from the function or an Exception depending on what - occurred during the execution. - """ - - def __init__(self, value, attempt_number, has_exception): - self.value = value - self.attempt_number = attempt_number - self.has_exception = has_exception - - def get(self, wrap_exception=False): - """ - Return the return value of this Attempt instance or raise an Exception. - If wrap_exception is true, this Attempt is wrapped inside of a - RetryError before being raised. - """ - if self.has_exception: - if wrap_exception: - raise RetryError(self) - else: - six.reraise(self.value[0], self.value[1], self.value[2]) - else: - return self.value - - def __repr__(self): - if self.has_exception: - return "Attempts: {0}, Error:\n{1}".format(self.attempt_number, "".join(traceback.format_tb(self.value[2]))) - else: - return "Attempts: {0}, Value: {1}".format(self.attempt_number, self.value) - - -class RetryError(Exception): - """ - A RetryError encapsulates the last Attempt instance right before giving up. - """ - - def __init__(self, last_attempt): - self.last_attempt = last_attempt - - def __str__(self): - return "RetryError[{0}]".format(self.last_attempt) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/six.py b/venv2/lib/python2.7/site-packages/pip/_vendor/six.py deleted file mode 100644 index 89b2188..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/six.py +++ /dev/null @@ -1,952 +0,0 @@ -# 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 <benjamin@python.org>" -__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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/__init__.py deleted file mode 100644 index 148a9c3..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/__init__.py +++ /dev/null @@ -1,92 +0,0 @@ -""" -urllib3 - Thread-safe connection pooling and re-using. -""" - -from __future__ import absolute_import -import warnings - -from .connectionpool import ( - HTTPConnectionPool, - HTTPSConnectionPool, - connection_from_url -) - -from . import exceptions -from .filepost import encode_multipart_formdata -from .poolmanager import PoolManager, ProxyManager, proxy_from_url -from .response import HTTPResponse -from .util.request import make_headers -from .util.url import get_host -from .util.timeout import Timeout -from .util.retry import Retry - - -# Set default logging handler to avoid "No handler found" warnings. -import logging -from logging import NullHandler - -__author__ = 'Andrey Petrov (andrey.petrov@shazow.net)' -__license__ = 'MIT' -__version__ = '1.24.1' - -__all__ = ( - 'HTTPConnectionPool', - 'HTTPSConnectionPool', - 'PoolManager', - 'ProxyManager', - 'HTTPResponse', - 'Retry', - 'Timeout', - 'add_stderr_logger', - 'connection_from_url', - 'disable_warnings', - 'encode_multipart_formdata', - 'get_host', - 'make_headers', - 'proxy_from_url', -) - -logging.getLogger(__name__).addHandler(NullHandler()) - - -def add_stderr_logger(level=logging.DEBUG): - """ - Helper for quickly adding a StreamHandler to the logger. Useful for - debugging. - - Returns the handler after adding it. - """ - # This method needs to be in this __init__.py to get the __name__ correct - # even if urllib3 is vendored within another package. - logger = logging.getLogger(__name__) - handler = logging.StreamHandler() - handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s')) - logger.addHandler(handler) - logger.setLevel(level) - logger.debug('Added a stderr logging handler to logger: %s', __name__) - return handler - - -# ... Clean up. -del NullHandler - - -# All warning filters *must* be appended unless you're really certain that they -# shouldn't be: otherwise, it's very hard for users to use most Python -# mechanisms to silence them. -# SecurityWarning's always go off by default. -warnings.simplefilter('always', exceptions.SecurityWarning, append=True) -# SubjectAltNameWarning's should go off once per host -warnings.simplefilter('default', exceptions.SubjectAltNameWarning, append=True) -# InsecurePlatformWarning's don't vary between requests, so we keep it default. -warnings.simplefilter('default', exceptions.InsecurePlatformWarning, - append=True) -# SNIMissingWarnings should go off only once. -warnings.simplefilter('default', exceptions.SNIMissingWarning, append=True) - - -def disable_warnings(category=exceptions.HTTPWarning): - """ - Helper for quickly disabling all urllib3 warnings. - """ - warnings.simplefilter('ignore', category) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/_collections.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/_collections.py deleted file mode 100644 index 34f2381..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/_collections.py +++ /dev/null @@ -1,329 +0,0 @@ -from __future__ import absolute_import -try: - from collections.abc import Mapping, MutableMapping -except ImportError: - from collections import Mapping, MutableMapping -try: - from threading import RLock -except ImportError: # Platform-specific: No threads available - class RLock: - def __enter__(self): - pass - - def __exit__(self, exc_type, exc_value, traceback): - pass - - -from collections import OrderedDict -from .exceptions import InvalidHeader -from .packages.six import iterkeys, itervalues, PY3 - - -__all__ = ['RecentlyUsedContainer', 'HTTPHeaderDict'] - - -_Null = object() - - -class RecentlyUsedContainer(MutableMapping): - """ - Provides a thread-safe dict-like container which maintains up to - ``maxsize`` keys while throwing away the least-recently-used keys beyond - ``maxsize``. - - :param maxsize: - Maximum number of recent elements to retain. - - :param dispose_func: - Every time an item is evicted from the container, - ``dispose_func(value)`` is called. Callback which will get called - """ - - ContainerCls = OrderedDict - - def __init__(self, maxsize=10, dispose_func=None): - self._maxsize = maxsize - self.dispose_func = dispose_func - - self._container = self.ContainerCls() - self.lock = RLock() - - def __getitem__(self, key): - # Re-insert the item, moving it to the end of the eviction line. - with self.lock: - item = self._container.pop(key) - self._container[key] = item - return item - - def __setitem__(self, key, value): - evicted_value = _Null - with self.lock: - # Possibly evict the existing value of 'key' - evicted_value = self._container.get(key, _Null) - self._container[key] = value - - # If we didn't evict an existing value, we might have to evict the - # least recently used item from the beginning of the container. - if len(self._container) > self._maxsize: - _key, evicted_value = self._container.popitem(last=False) - - if self.dispose_func and evicted_value is not _Null: - self.dispose_func(evicted_value) - - def __delitem__(self, key): - with self.lock: - value = self._container.pop(key) - - if self.dispose_func: - self.dispose_func(value) - - def __len__(self): - with self.lock: - return len(self._container) - - def __iter__(self): - raise NotImplementedError('Iteration over this class is unlikely to be threadsafe.') - - def clear(self): - with self.lock: - # Copy pointers to all values, then wipe the mapping - values = list(itervalues(self._container)) - self._container.clear() - - if self.dispose_func: - for value in values: - self.dispose_func(value) - - def keys(self): - with self.lock: - return list(iterkeys(self._container)) - - -class HTTPHeaderDict(MutableMapping): - """ - :param headers: - An iterable of field-value pairs. Must not contain multiple field names - when compared case-insensitively. - - :param kwargs: - Additional field-value pairs to pass in to ``dict.update``. - - A ``dict`` like container for storing HTTP Headers. - - Field names are stored and compared case-insensitively in compliance with - RFC 7230. Iteration provides the first case-sensitive key seen for each - case-insensitive pair. - - Using ``__setitem__`` syntax overwrites fields that compare equal - case-insensitively in order to maintain ``dict``'s api. For fields that - compare equal, instead create a new ``HTTPHeaderDict`` and use ``.add`` - in a loop. - - If multiple fields that are equal case-insensitively are passed to the - constructor or ``.update``, the behavior is undefined and some will be - lost. - - >>> headers = HTTPHeaderDict() - >>> headers.add('Set-Cookie', 'foo=bar') - >>> headers.add('set-cookie', 'baz=quxx') - >>> headers['content-length'] = '7' - >>> headers['SET-cookie'] - 'foo=bar, baz=quxx' - >>> headers['Content-Length'] - '7' - """ - - def __init__(self, headers=None, **kwargs): - super(HTTPHeaderDict, self).__init__() - self._container = OrderedDict() - if headers is not None: - if isinstance(headers, HTTPHeaderDict): - self._copy_from(headers) - else: - self.extend(headers) - if kwargs: - self.extend(kwargs) - - def __setitem__(self, key, val): - self._container[key.lower()] = [key, val] - return self._container[key.lower()] - - def __getitem__(self, key): - val = self._container[key.lower()] - return ', '.join(val[1:]) - - def __delitem__(self, key): - del self._container[key.lower()] - - def __contains__(self, key): - return key.lower() in self._container - - def __eq__(self, other): - if not isinstance(other, Mapping) and not hasattr(other, 'keys'): - return False - if not isinstance(other, type(self)): - other = type(self)(other) - return (dict((k.lower(), v) for k, v in self.itermerged()) == - dict((k.lower(), v) for k, v in other.itermerged())) - - def __ne__(self, other): - return not self.__eq__(other) - - if not PY3: # Python 2 - iterkeys = MutableMapping.iterkeys - itervalues = MutableMapping.itervalues - - __marker = object() - - def __len__(self): - return len(self._container) - - def __iter__(self): - # Only provide the originally cased names - for vals in self._container.values(): - yield vals[0] - - def pop(self, key, default=__marker): - '''D.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. - ''' - # Using the MutableMapping function directly fails due to the private marker. - # Using ordinary dict.pop would expose the internal structures. - # So let's reinvent the wheel. - try: - value = self[key] - except KeyError: - if default is self.__marker: - raise - return default - else: - del self[key] - return value - - def discard(self, key): - try: - del self[key] - except KeyError: - pass - - def add(self, key, val): - """Adds a (name, value) pair, doesn't overwrite the value if it already - exists. - - >>> headers = HTTPHeaderDict(foo='bar') - >>> headers.add('Foo', 'baz') - >>> headers['foo'] - 'bar, baz' - """ - key_lower = key.lower() - new_vals = [key, val] - # Keep the common case aka no item present as fast as possible - vals = self._container.setdefault(key_lower, new_vals) - if new_vals is not vals: - vals.append(val) - - def extend(self, *args, **kwargs): - """Generic import function for any type of header-like object. - Adapted version of MutableMapping.update in order to insert items - with self.add instead of self.__setitem__ - """ - if len(args) > 1: - raise TypeError("extend() takes at most 1 positional " - "arguments ({0} given)".format(len(args))) - other = args[0] if len(args) >= 1 else () - - if isinstance(other, HTTPHeaderDict): - for key, val in other.iteritems(): - self.add(key, val) - elif isinstance(other, Mapping): - for key in other: - self.add(key, other[key]) - elif hasattr(other, "keys"): - for key in other.keys(): - self.add(key, other[key]) - else: - for key, value in other: - self.add(key, value) - - for key, value in kwargs.items(): - self.add(key, value) - - def getlist(self, key, default=__marker): - """Returns a list of all the values for the named field. Returns an - empty list if the key doesn't exist.""" - try: - vals = self._container[key.lower()] - except KeyError: - if default is self.__marker: - return [] - return default - else: - return vals[1:] - - # Backwards compatibility for httplib - getheaders = getlist - getallmatchingheaders = getlist - iget = getlist - - # Backwards compatibility for http.cookiejar - get_all = getlist - - def __repr__(self): - return "%s(%s)" % (type(self).__name__, dict(self.itermerged())) - - def _copy_from(self, other): - for key in other: - val = other.getlist(key) - if isinstance(val, list): - # Don't need to convert tuples - val = list(val) - self._container[key.lower()] = [key] + val - - def copy(self): - clone = type(self)() - clone._copy_from(self) - return clone - - def iteritems(self): - """Iterate over all header lines, including duplicate ones.""" - for key in self: - vals = self._container[key.lower()] - for val in vals[1:]: - yield vals[0], val - - def itermerged(self): - """Iterate over all headers, merging duplicate ones together.""" - for key in self: - val = self._container[key.lower()] - yield val[0], ', '.join(val[1:]) - - def items(self): - return list(self.iteritems()) - - @classmethod - def from_httplib(cls, message): # Python 2 - """Read headers from a Python 2 httplib message object.""" - # python2.7 does not expose a proper API for exporting multiheaders - # efficiently. This function re-reads raw lines from the message - # object and extracts the multiheaders properly. - obs_fold_continued_leaders = (' ', '\t') - headers = [] - - for line in message.headers: - if line.startswith(obs_fold_continued_leaders): - if not headers: - # We received a header line that starts with OWS as described - # in RFC-7230 S3.2.4. This indicates a multiline header, but - # there exists no previous header to which we can attach it. - raise InvalidHeader( - 'Header continuation with no previous header: %s' % line - ) - else: - key, value = headers[-1] - headers[-1] = (key, value + ' ' + line.strip()) - continue - - key, value = line.split(':', 1) - headers.append((key, value.strip())) - - return cls(headers) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/connection.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/connection.py deleted file mode 100644 index 02b3665..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/connection.py +++ /dev/null @@ -1,391 +0,0 @@ -from __future__ import absolute_import -import datetime -import logging -import os -import socket -from socket import error as SocketError, timeout as SocketTimeout -import warnings -from .packages import six -from .packages.six.moves.http_client import HTTPConnection as _HTTPConnection -from .packages.six.moves.http_client import HTTPException # noqa: F401 - -try: # Compiled with SSL? - import ssl - BaseSSLError = ssl.SSLError -except (ImportError, AttributeError): # Platform-specific: No SSL. - ssl = None - - class BaseSSLError(BaseException): - pass - - -try: # Python 3: - # Not a no-op, we're adding this to the namespace so it can be imported. - ConnectionError = ConnectionError -except NameError: # Python 2: - class ConnectionError(Exception): - pass - - -from .exceptions import ( - NewConnectionError, - ConnectTimeoutError, - SubjectAltNameWarning, - SystemTimeWarning, -) -from .packages.ssl_match_hostname import match_hostname, CertificateError - -from .util.ssl_ import ( - resolve_cert_reqs, - resolve_ssl_version, - assert_fingerprint, - create_urllib3_context, - ssl_wrap_socket -) - - -from .util import connection - -from ._collections import HTTPHeaderDict - -log = logging.getLogger(__name__) - -port_by_scheme = { - 'http': 80, - 'https': 443, -} - -# When updating RECENT_DATE, move it to within two years of the current date, -# and not less than 6 months ago. -# Example: if Today is 2018-01-01, then RECENT_DATE should be any date on or -# after 2016-01-01 (today - 2 years) AND before 2017-07-01 (today - 6 months) -RECENT_DATE = datetime.date(2017, 6, 30) - - -class DummyConnection(object): - """Used to detect a failed ConnectionCls import.""" - pass - - -class HTTPConnection(_HTTPConnection, object): - """ - Based on httplib.HTTPConnection but provides an extra constructor - backwards-compatibility layer between older and newer Pythons. - - Additional keyword parameters are used to configure attributes of the connection. - Accepted parameters include: - - - ``strict``: See the documentation on :class:`urllib3.connectionpool.HTTPConnectionPool` - - ``source_address``: Set the source address for the current connection. - - ``socket_options``: Set specific options on the underlying socket. If not specified, then - defaults are loaded from ``HTTPConnection.default_socket_options`` which includes disabling - Nagle's algorithm (sets TCP_NODELAY to 1) unless the connection is behind a proxy. - - For example, if you wish to enable TCP Keep Alive in addition to the defaults, - you might pass:: - - HTTPConnection.default_socket_options + [ - (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1), - ] - - Or you may want to disable the defaults by passing an empty list (e.g., ``[]``). - """ - - default_port = port_by_scheme['http'] - - #: Disable Nagle's algorithm by default. - #: ``[(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)]`` - default_socket_options = [(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)] - - #: Whether this connection verifies the host's certificate. - is_verified = False - - def __init__(self, *args, **kw): - if six.PY3: # Python 3 - kw.pop('strict', None) - - # Pre-set source_address. - self.source_address = kw.get('source_address') - - #: The socket options provided by the user. If no options are - #: provided, we use the default options. - self.socket_options = kw.pop('socket_options', self.default_socket_options) - - _HTTPConnection.__init__(self, *args, **kw) - - @property - def host(self): - """ - Getter method to remove any trailing dots that indicate the hostname is an FQDN. - - In general, SSL certificates don't include the trailing dot indicating a - fully-qualified domain name, and thus, they don't validate properly when - checked against a domain name that includes the dot. In addition, some - servers may not expect to receive the trailing dot when provided. - - However, the hostname with trailing dot is critical to DNS resolution; doing a - lookup with the trailing dot will properly only resolve the appropriate FQDN, - whereas a lookup without a trailing dot will search the system's search domain - list. Thus, it's important to keep the original host around for use only in - those cases where it's appropriate (i.e., when doing DNS lookup to establish the - actual TCP connection across which we're going to send HTTP requests). - """ - return self._dns_host.rstrip('.') - - @host.setter - def host(self, value): - """ - Setter for the `host` property. - - We assume that only urllib3 uses the _dns_host attribute; httplib itself - only uses `host`, and it seems reasonable that other libraries follow suit. - """ - self._dns_host = value - - def _new_conn(self): - """ Establish a socket connection and set nodelay settings on it. - - :return: New socket connection. - """ - extra_kw = {} - if self.source_address: - extra_kw['source_address'] = self.source_address - - if self.socket_options: - extra_kw['socket_options'] = self.socket_options - - try: - conn = connection.create_connection( - (self._dns_host, self.port), self.timeout, **extra_kw) - - except SocketTimeout as e: - raise ConnectTimeoutError( - self, "Connection to %s timed out. (connect timeout=%s)" % - (self.host, self.timeout)) - - except SocketError as e: - raise NewConnectionError( - self, "Failed to establish a new connection: %s" % e) - - return conn - - def _prepare_conn(self, conn): - self.sock = conn - if self._tunnel_host: - # TODO: Fix tunnel so it doesn't depend on self.sock state. - self._tunnel() - # Mark this connection as not reusable - self.auto_open = 0 - - def connect(self): - conn = self._new_conn() - self._prepare_conn(conn) - - def request_chunked(self, method, url, body=None, headers=None): - """ - Alternative to the common request method, which sends the - body with chunked encoding and not as one block - """ - headers = HTTPHeaderDict(headers if headers is not None else {}) - skip_accept_encoding = 'accept-encoding' in headers - skip_host = 'host' in headers - self.putrequest( - method, - url, - skip_accept_encoding=skip_accept_encoding, - skip_host=skip_host - ) - for header, value in headers.items(): - self.putheader(header, value) - if 'transfer-encoding' not in headers: - self.putheader('Transfer-Encoding', 'chunked') - self.endheaders() - - if body is not None: - stringish_types = six.string_types + (bytes,) - if isinstance(body, stringish_types): - body = (body,) - for chunk in body: - if not chunk: - continue - if not isinstance(chunk, bytes): - chunk = chunk.encode('utf8') - len_str = hex(len(chunk))[2:] - self.send(len_str.encode('utf-8')) - self.send(b'\r\n') - self.send(chunk) - self.send(b'\r\n') - - # After the if clause, to always have a closed body - self.send(b'0\r\n\r\n') - - -class HTTPSConnection(HTTPConnection): - default_port = port_by_scheme['https'] - - ssl_version = None - - def __init__(self, host, port=None, key_file=None, cert_file=None, - strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, - ssl_context=None, server_hostname=None, **kw): - - HTTPConnection.__init__(self, host, port, strict=strict, - timeout=timeout, **kw) - - self.key_file = key_file - self.cert_file = cert_file - self.ssl_context = ssl_context - self.server_hostname = server_hostname - - # Required property for Google AppEngine 1.9.0 which otherwise causes - # HTTPS requests to go out as HTTP. (See Issue #356) - self._protocol = 'https' - - def connect(self): - conn = self._new_conn() - self._prepare_conn(conn) - - if self.ssl_context is None: - self.ssl_context = create_urllib3_context( - ssl_version=resolve_ssl_version(None), - cert_reqs=resolve_cert_reqs(None), - ) - - self.sock = ssl_wrap_socket( - sock=conn, - keyfile=self.key_file, - certfile=self.cert_file, - ssl_context=self.ssl_context, - server_hostname=self.server_hostname - ) - - -class VerifiedHTTPSConnection(HTTPSConnection): - """ - Based on httplib.HTTPSConnection but wraps the socket with - SSL certification. - """ - cert_reqs = None - ca_certs = None - ca_cert_dir = None - ssl_version = None - assert_fingerprint = None - - def set_cert(self, key_file=None, cert_file=None, - cert_reqs=None, ca_certs=None, - assert_hostname=None, assert_fingerprint=None, - ca_cert_dir=None): - """ - This method should only be called once, before the connection is used. - """ - # If cert_reqs is not provided, we can try to guess. If the user gave - # us a cert database, we assume they want to use it: otherwise, if - # they gave us an SSL Context object we should use whatever is set for - # it. - if cert_reqs is None: - if ca_certs or ca_cert_dir: - cert_reqs = 'CERT_REQUIRED' - elif self.ssl_context is not None: - cert_reqs = self.ssl_context.verify_mode - - self.key_file = key_file - self.cert_file = cert_file - self.cert_reqs = cert_reqs - self.assert_hostname = assert_hostname - self.assert_fingerprint = assert_fingerprint - self.ca_certs = ca_certs and os.path.expanduser(ca_certs) - self.ca_cert_dir = ca_cert_dir and os.path.expanduser(ca_cert_dir) - - def connect(self): - # Add certificate verification - conn = self._new_conn() - hostname = self.host - - if self._tunnel_host: - self.sock = conn - # Calls self._set_hostport(), so self.host is - # self._tunnel_host below. - self._tunnel() - # Mark this connection as not reusable - self.auto_open = 0 - - # Override the host with the one we're requesting data from. - hostname = self._tunnel_host - - server_hostname = hostname - if self.server_hostname is not None: - server_hostname = self.server_hostname - - is_time_off = datetime.date.today() < RECENT_DATE - if is_time_off: - warnings.warn(( - 'System time is way off (before {0}). This will probably ' - 'lead to SSL verification errors').format(RECENT_DATE), - SystemTimeWarning - ) - - # Wrap socket using verification with the root certs in - # trusted_root_certs - if self.ssl_context is None: - self.ssl_context = create_urllib3_context( - ssl_version=resolve_ssl_version(self.ssl_version), - cert_reqs=resolve_cert_reqs(self.cert_reqs), - ) - - context = self.ssl_context - context.verify_mode = resolve_cert_reqs(self.cert_reqs) - self.sock = ssl_wrap_socket( - sock=conn, - keyfile=self.key_file, - certfile=self.cert_file, - ca_certs=self.ca_certs, - ca_cert_dir=self.ca_cert_dir, - server_hostname=server_hostname, - ssl_context=context) - - if self.assert_fingerprint: - assert_fingerprint(self.sock.getpeercert(binary_form=True), - self.assert_fingerprint) - elif context.verify_mode != ssl.CERT_NONE \ - and not getattr(context, 'check_hostname', False) \ - and self.assert_hostname is not False: - # While urllib3 attempts to always turn off hostname matching from - # the TLS library, this cannot always be done. So we check whether - # the TLS Library still thinks it's matching hostnames. - cert = self.sock.getpeercert() - if not cert.get('subjectAltName', ()): - warnings.warn(( - 'Certificate for {0} has no `subjectAltName`, falling back to check for a ' - '`commonName` for now. This feature is being removed by major browsers and ' - 'deprecated by RFC 2818. (See https://github.com/shazow/urllib3/issues/497 ' - 'for details.)'.format(hostname)), - SubjectAltNameWarning - ) - _match_hostname(cert, self.assert_hostname or server_hostname) - - self.is_verified = ( - context.verify_mode == ssl.CERT_REQUIRED or - self.assert_fingerprint is not None - ) - - -def _match_hostname(cert, asserted_hostname): - try: - match_hostname(cert, asserted_hostname) - except CertificateError as e: - log.error( - 'Certificate did not match expected hostname: %s. ' - 'Certificate: %s', asserted_hostname, cert - ) - # Add cert to exception and reraise so client code can inspect - # the cert when catching the exception, if they want to - e._peer_cert = cert - raise - - -if ssl: - # Make a copy for testing. - UnverifiedHTTPSConnection = HTTPSConnection - HTTPSConnection = VerifiedHTTPSConnection -else: - HTTPSConnection = DummyConnection diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/connectionpool.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/connectionpool.py deleted file mode 100644 index f7a8f19..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/connectionpool.py +++ /dev/null @@ -1,896 +0,0 @@ -from __future__ import absolute_import -import errno -import logging -import sys -import warnings - -from socket import error as SocketError, timeout as SocketTimeout -import socket - - -from .exceptions import ( - ClosedPoolError, - ProtocolError, - EmptyPoolError, - HeaderParsingError, - HostChangedError, - LocationValueError, - MaxRetryError, - ProxyError, - ReadTimeoutError, - SSLError, - TimeoutError, - InsecureRequestWarning, - NewConnectionError, -) -from .packages.ssl_match_hostname import CertificateError -from .packages import six -from .packages.six.moves import queue -from .connection import ( - port_by_scheme, - DummyConnection, - HTTPConnection, HTTPSConnection, VerifiedHTTPSConnection, - HTTPException, BaseSSLError, -) -from .request import RequestMethods -from .response import HTTPResponse - -from .util.connection import is_connection_dropped -from .util.request import set_file_position -from .util.response import assert_header_parsing -from .util.retry import Retry -from .util.timeout import Timeout -from .util.url import get_host, Url, NORMALIZABLE_SCHEMES -from .util.queue import LifoQueue - - -xrange = six.moves.xrange - -log = logging.getLogger(__name__) - -_Default = object() - - -# Pool objects -class ConnectionPool(object): - """ - Base class for all connection pools, such as - :class:`.HTTPConnectionPool` and :class:`.HTTPSConnectionPool`. - """ - - scheme = None - QueueCls = LifoQueue - - def __init__(self, host, port=None): - if not host: - raise LocationValueError("No host specified.") - - self.host = _ipv6_host(host, self.scheme) - self._proxy_host = host.lower() - self.port = port - - def __str__(self): - return '%s(host=%r, port=%r)' % (type(self).__name__, - self.host, self.port) - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self.close() - # Return False to re-raise any potential exceptions - return False - - def close(self): - """ - Close all pooled connections and disable the pool. - """ - pass - - -# This is taken from http://hg.python.org/cpython/file/7aaba721ebc0/Lib/socket.py#l252 -_blocking_errnos = {errno.EAGAIN, errno.EWOULDBLOCK} - - -class HTTPConnectionPool(ConnectionPool, RequestMethods): - """ - Thread-safe connection pool for one host. - - :param host: - Host used for this HTTP Connection (e.g. "localhost"), passed into - :class:`httplib.HTTPConnection`. - - :param port: - Port used for this HTTP Connection (None is equivalent to 80), passed - into :class:`httplib.HTTPConnection`. - - :param strict: - Causes BadStatusLine to be raised if the status line can't be parsed - as a valid HTTP/1.0 or 1.1 status line, passed into - :class:`httplib.HTTPConnection`. - - .. note:: - Only works in Python 2. This parameter is ignored in Python 3. - - :param timeout: - Socket timeout in seconds for each individual connection. This can - be a float or integer, which sets the timeout for the HTTP request, - or an instance of :class:`urllib3.util.Timeout` which gives you more - fine-grained control over request timeouts. After the constructor has - been parsed, this is always a `urllib3.util.Timeout` object. - - :param maxsize: - Number of connections to save that can be reused. More than 1 is useful - in multithreaded situations. If ``block`` is set to False, more - connections will be created but they will not be saved once they've - been used. - - :param block: - If set to True, no more than ``maxsize`` connections will be used at - a time. When no free connections are available, the call will block - until a connection has been released. This is a useful side effect for - particular multithreaded situations where one does not want to use more - than maxsize connections per host to prevent flooding. - - :param headers: - Headers to include with all requests, unless other headers are given - explicitly. - - :param retries: - Retry configuration to use by default with requests in this pool. - - :param _proxy: - Parsed proxy URL, should not be used directly, instead, see - :class:`urllib3.connectionpool.ProxyManager`" - - :param _proxy_headers: - A dictionary with proxy headers, should not be used directly, - instead, see :class:`urllib3.connectionpool.ProxyManager`" - - :param \\**conn_kw: - Additional parameters are used to create fresh :class:`urllib3.connection.HTTPConnection`, - :class:`urllib3.connection.HTTPSConnection` instances. - """ - - scheme = 'http' - ConnectionCls = HTTPConnection - ResponseCls = HTTPResponse - - def __init__(self, host, port=None, strict=False, - timeout=Timeout.DEFAULT_TIMEOUT, maxsize=1, block=False, - headers=None, retries=None, - _proxy=None, _proxy_headers=None, - **conn_kw): - ConnectionPool.__init__(self, host, port) - RequestMethods.__init__(self, headers) - - self.strict = strict - - if not isinstance(timeout, Timeout): - timeout = Timeout.from_float(timeout) - - if retries is None: - retries = Retry.DEFAULT - - self.timeout = timeout - self.retries = retries - - self.pool = self.QueueCls(maxsize) - self.block = block - - self.proxy = _proxy - self.proxy_headers = _proxy_headers or {} - - # Fill the queue up so that doing get() on it will block properly - for _ in xrange(maxsize): - self.pool.put(None) - - # These are mostly for testing and debugging purposes. - self.num_connections = 0 - self.num_requests = 0 - self.conn_kw = conn_kw - - if self.proxy: - # Enable Nagle's algorithm for proxies, to avoid packet fragmentation. - # We cannot know if the user has added default socket options, so we cannot replace the - # list. - self.conn_kw.setdefault('socket_options', []) - - def _new_conn(self): - """ - Return a fresh :class:`HTTPConnection`. - """ - self.num_connections += 1 - log.debug("Starting new HTTP connection (%d): %s:%s", - self.num_connections, self.host, self.port or "80") - - conn = self.ConnectionCls(host=self.host, port=self.port, - timeout=self.timeout.connect_timeout, - strict=self.strict, **self.conn_kw) - return conn - - def _get_conn(self, timeout=None): - """ - Get a connection. Will return a pooled connection if one is available. - - If no connections are available and :prop:`.block` is ``False``, then a - fresh connection is returned. - - :param timeout: - Seconds to wait before giving up and raising - :class:`urllib3.exceptions.EmptyPoolError` if the pool is empty and - :prop:`.block` is ``True``. - """ - conn = None - try: - conn = self.pool.get(block=self.block, timeout=timeout) - - except AttributeError: # self.pool is None - raise ClosedPoolError(self, "Pool is closed.") - - except queue.Empty: - if self.block: - raise EmptyPoolError(self, - "Pool reached maximum size and no more " - "connections are allowed.") - pass # Oh well, we'll create a new connection then - - # If this is a persistent connection, check if it got disconnected - if conn and is_connection_dropped(conn): - log.debug("Resetting dropped connection: %s", self.host) - conn.close() - if getattr(conn, 'auto_open', 1) == 0: - # This is a proxied connection that has been mutated by - # httplib._tunnel() and cannot be reused (since it would - # attempt to bypass the proxy) - conn = None - - return conn or self._new_conn() - - def _put_conn(self, conn): - """ - Put a connection back into the pool. - - :param conn: - Connection object for the current host and port as returned by - :meth:`._new_conn` or :meth:`._get_conn`. - - If the pool is already full, the connection is closed and discarded - because we exceeded maxsize. If connections are discarded frequently, - then maxsize should be increased. - - If the pool is closed, then the connection will be closed and discarded. - """ - try: - self.pool.put(conn, block=False) - return # Everything is dandy, done. - except AttributeError: - # self.pool is None. - pass - except queue.Full: - # This should never happen if self.block == True - log.warning( - "Connection pool is full, discarding connection: %s", - self.host) - - # Connection never got put back into the pool, close it. - if conn: - conn.close() - - def _validate_conn(self, conn): - """ - Called right before a request is made, after the socket is created. - """ - pass - - def _prepare_proxy(self, conn): - # Nothing to do for HTTP connections. - pass - - def _get_timeout(self, timeout): - """ Helper that always returns a :class:`urllib3.util.Timeout` """ - if timeout is _Default: - return self.timeout.clone() - - if isinstance(timeout, Timeout): - return timeout.clone() - else: - # User passed us an int/float. This is for backwards compatibility, - # can be removed later - return Timeout.from_float(timeout) - - def _raise_timeout(self, err, url, timeout_value): - """Is the error actually a timeout? Will raise a ReadTimeout or pass""" - - if isinstance(err, SocketTimeout): - raise ReadTimeoutError(self, url, "Read timed out. (read timeout=%s)" % timeout_value) - - # See the above comment about EAGAIN in Python 3. In Python 2 we have - # to specifically catch it and throw the timeout error - if hasattr(err, 'errno') and err.errno in _blocking_errnos: - raise ReadTimeoutError(self, url, "Read timed out. (read timeout=%s)" % timeout_value) - - # Catch possible read timeouts thrown as SSL errors. If not the - # case, rethrow the original. We need to do this because of: - # http://bugs.python.org/issue10272 - if 'timed out' in str(err) or 'did not complete (read)' in str(err): # Python < 2.7.4 - raise ReadTimeoutError(self, url, "Read timed out. (read timeout=%s)" % timeout_value) - - def _make_request(self, conn, method, url, timeout=_Default, chunked=False, - **httplib_request_kw): - """ - Perform a request on a given urllib connection object taken from our - pool. - - :param conn: - a connection from one of our connection pools - - :param timeout: - Socket timeout in seconds for the request. This can be a - float or integer, which will set the same timeout value for - the socket connect and the socket read, or an instance of - :class:`urllib3.util.Timeout`, which gives you more fine-grained - control over your timeouts. - """ - self.num_requests += 1 - - timeout_obj = self._get_timeout(timeout) - timeout_obj.start_connect() - conn.timeout = timeout_obj.connect_timeout - - # Trigger any extra validation we need to do. - try: - self._validate_conn(conn) - except (SocketTimeout, BaseSSLError) as e: - # Py2 raises this as a BaseSSLError, Py3 raises it as socket timeout. - self._raise_timeout(err=e, url=url, timeout_value=conn.timeout) - raise - - # conn.request() calls httplib.*.request, not the method in - # urllib3.request. It also calls makefile (recv) on the socket. - if chunked: - conn.request_chunked(method, url, **httplib_request_kw) - else: - conn.request(method, url, **httplib_request_kw) - - # Reset the timeout for the recv() on the socket - read_timeout = timeout_obj.read_timeout - - # App Engine doesn't have a sock attr - if getattr(conn, 'sock', None): - # In Python 3 socket.py will catch EAGAIN and return None when you - # try and read into the file pointer created by http.client, which - # instead raises a BadStatusLine exception. Instead of catching - # the exception and assuming all BadStatusLine exceptions are read - # timeouts, check for a zero timeout before making the request. - if read_timeout == 0: - raise ReadTimeoutError( - self, url, "Read timed out. (read timeout=%s)" % read_timeout) - if read_timeout is Timeout.DEFAULT_TIMEOUT: - conn.sock.settimeout(socket.getdefaulttimeout()) - else: # None or a value - conn.sock.settimeout(read_timeout) - - # Receive the response from the server - try: - try: # Python 2.7, use buffering of HTTP responses - httplib_response = conn.getresponse(buffering=True) - except TypeError: # Python 3 - try: - httplib_response = conn.getresponse() - except Exception as e: - # Remove the TypeError from the exception chain in Python 3; - # otherwise it looks like a programming error was the cause. - six.raise_from(e, None) - except (SocketTimeout, BaseSSLError, SocketError) as e: - self._raise_timeout(err=e, url=url, timeout_value=read_timeout) - raise - - # AppEngine doesn't have a version attr. - http_version = getattr(conn, '_http_vsn_str', 'HTTP/?') - log.debug("%s://%s:%s \"%s %s %s\" %s %s", self.scheme, self.host, self.port, - method, url, http_version, httplib_response.status, - httplib_response.length) - - try: - assert_header_parsing(httplib_response.msg) - except (HeaderParsingError, TypeError) as hpe: # Platform-specific: Python 3 - log.warning( - 'Failed to parse headers (url=%s): %s', - self._absolute_url(url), hpe, exc_info=True) - - return httplib_response - - def _absolute_url(self, path): - return Url(scheme=self.scheme, host=self.host, port=self.port, path=path).url - - def close(self): - """ - Close all pooled connections and disable the pool. - """ - if self.pool is None: - return - # Disable access to the pool - old_pool, self.pool = self.pool, None - - try: - while True: - conn = old_pool.get(block=False) - if conn: - conn.close() - - except queue.Empty: - pass # Done. - - def is_same_host(self, url): - """ - Check if the given ``url`` is a member of the same host as this - connection pool. - """ - if url.startswith('/'): - return True - - # TODO: Add optional support for socket.gethostbyname checking. - scheme, host, port = get_host(url) - - host = _ipv6_host(host, self.scheme) - - # Use explicit default port for comparison when none is given - if self.port and not port: - port = port_by_scheme.get(scheme) - elif not self.port and port == port_by_scheme.get(scheme): - port = None - - return (scheme, host, port) == (self.scheme, self.host, self.port) - - def urlopen(self, method, url, body=None, headers=None, retries=None, - redirect=True, assert_same_host=True, timeout=_Default, - pool_timeout=None, release_conn=None, chunked=False, - body_pos=None, **response_kw): - """ - Get a connection from the pool and perform an HTTP request. This is the - lowest level call for making a request, so you'll need to specify all - the raw details. - - .. note:: - - More commonly, it's appropriate to use a convenience method provided - by :class:`.RequestMethods`, such as :meth:`request`. - - .. note:: - - `release_conn` will only behave as expected if - `preload_content=False` because we want to make - `preload_content=False` the default behaviour someday soon without - breaking backwards compatibility. - - :param method: - HTTP request method (such as GET, POST, PUT, etc.) - - :param body: - Data to send in the request body (useful for creating - POST requests, see HTTPConnectionPool.post_url for - more convenience). - - :param headers: - Dictionary of custom headers to send, such as User-Agent, - If-None-Match, etc. If None, pool headers are used. If provided, - these headers completely replace any pool-specific headers. - - :param retries: - Configure the number of retries to allow before raising a - :class:`~urllib3.exceptions.MaxRetryError` exception. - - Pass ``None`` to retry until you receive a response. Pass a - :class:`~urllib3.util.retry.Retry` object for fine-grained control - over different types of retries. - Pass an integer number to retry connection errors that many times, - but no other types of errors. Pass zero to never retry. - - If ``False``, then retries are disabled and any exception is raised - immediately. Also, instead of raising a MaxRetryError on redirects, - the redirect response will be returned. - - :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. - - :param redirect: - If True, automatically handle redirects (status codes 301, 302, - 303, 307, 308). Each redirect counts as a retry. Disabling retries - will disable redirect, too. - - :param assert_same_host: - If ``True``, will make sure that the host of the pool requests is - consistent else will raise HostChangedError. When False, you can - use the pool on an HTTP proxy and request foreign hosts. - - :param timeout: - If specified, overrides the default timeout for this one - request. It may be a float (in seconds) or an instance of - :class:`urllib3.util.Timeout`. - - :param pool_timeout: - If set and the pool is set to block=True, then this method will - block for ``pool_timeout`` seconds and raise EmptyPoolError if no - connection is available within the time period. - - :param release_conn: - If False, then the urlopen call will not release the connection - back into the pool once a response is received (but will release if - you read the entire contents of the response such as when - `preload_content=True`). This is useful if you're not preloading - the response's content immediately. You will need to call - ``r.release_conn()`` on the response ``r`` to return the connection - back into the pool. If None, it takes the value of - ``response_kw.get('preload_content', True)``. - - :param chunked: - If True, urllib3 will send the body using chunked transfer - encoding. Otherwise, urllib3 will send the body using the standard - content-length form. Defaults to False. - - :param int body_pos: - Position to seek to in file-like body in the event of a retry or - redirect. Typically this won't need to be set because urllib3 will - auto-populate the value when needed. - - :param \\**response_kw: - Additional parameters are passed to - :meth:`urllib3.response.HTTPResponse.from_httplib` - """ - if headers is None: - headers = self.headers - - if not isinstance(retries, Retry): - retries = Retry.from_int(retries, redirect=redirect, default=self.retries) - - if release_conn is None: - release_conn = response_kw.get('preload_content', True) - - # Check host - if assert_same_host and not self.is_same_host(url): - raise HostChangedError(self, url, retries) - - conn = None - - # Track whether `conn` needs to be released before - # returning/raising/recursing. Update this variable if necessary, and - # leave `release_conn` constant throughout the function. That way, if - # the function recurses, the original value of `release_conn` will be - # passed down into the recursive call, and its value will be respected. - # - # See issue #651 [1] for details. - # - # [1] <https://github.com/shazow/urllib3/issues/651> - release_this_conn = release_conn - - # Merge the proxy headers. Only do this in HTTP. We have to copy the - # headers dict so we can safely change it without those changes being - # reflected in anyone else's copy. - if self.scheme == 'http': - headers = headers.copy() - headers.update(self.proxy_headers) - - # Must keep the exception bound to a separate variable or else Python 3 - # complains about UnboundLocalError. - err = None - - # Keep track of whether we cleanly exited the except block. This - # ensures we do proper cleanup in finally. - clean_exit = False - - # Rewind body position, if needed. Record current position - # for future rewinds in the event of a redirect/retry. - body_pos = set_file_position(body, body_pos) - - try: - # Request a connection from the queue. - timeout_obj = self._get_timeout(timeout) - conn = self._get_conn(timeout=pool_timeout) - - conn.timeout = timeout_obj.connect_timeout - - is_new_proxy_conn = self.proxy is not None and not getattr(conn, 'sock', None) - if is_new_proxy_conn: - self._prepare_proxy(conn) - - # Make the request on the httplib connection object. - httplib_response = self._make_request(conn, method, url, - timeout=timeout_obj, - body=body, headers=headers, - chunked=chunked) - - # If we're going to release the connection in ``finally:``, then - # the response doesn't need to know about the connection. Otherwise - # it will also try to release it and we'll have a double-release - # mess. - response_conn = conn if not release_conn else None - - # Pass method to Response for length checking - response_kw['request_method'] = method - - # Import httplib's response into our own wrapper object - response = self.ResponseCls.from_httplib(httplib_response, - pool=self, - connection=response_conn, - retries=retries, - **response_kw) - - # Everything went great! - clean_exit = True - - except queue.Empty: - # Timed out by queue. - raise EmptyPoolError(self, "No pool connections are available.") - - except (TimeoutError, HTTPException, SocketError, ProtocolError, - BaseSSLError, SSLError, CertificateError) as e: - # Discard the connection for these exceptions. It will be - # replaced during the next _get_conn() call. - clean_exit = False - if isinstance(e, (BaseSSLError, CertificateError)): - e = SSLError(e) - elif isinstance(e, (SocketError, NewConnectionError)) and self.proxy: - e = ProxyError('Cannot connect to proxy.', e) - elif isinstance(e, (SocketError, HTTPException)): - e = ProtocolError('Connection aborted.', e) - - retries = retries.increment(method, url, error=e, _pool=self, - _stacktrace=sys.exc_info()[2]) - retries.sleep() - - # Keep track of the error for the retry warning. - err = e - - finally: - if not clean_exit: - # We hit some kind of exception, handled or otherwise. We need - # to throw the connection away unless explicitly told not to. - # Close the connection, set the variable to None, and make sure - # we put the None back in the pool to avoid leaking it. - conn = conn and conn.close() - release_this_conn = True - - if release_this_conn: - # Put the connection back to be reused. If the connection is - # expired then it will be None, which will get replaced with a - # fresh connection during _get_conn. - self._put_conn(conn) - - if not conn: - # Try again - log.warning("Retrying (%r) after connection " - "broken by '%r': %s", retries, err, url) - return self.urlopen(method, url, body, headers, retries, - redirect, assert_same_host, - timeout=timeout, pool_timeout=pool_timeout, - release_conn=release_conn, body_pos=body_pos, - **response_kw) - - def drain_and_release_conn(response): - try: - # discard any remaining response body, the connection will be - # released back to the pool once the entire response is read - response.read() - except (TimeoutError, HTTPException, SocketError, ProtocolError, - BaseSSLError, SSLError) as e: - pass - - # Handle redirect? - redirect_location = redirect and response.get_redirect_location() - if redirect_location: - if response.status == 303: - method = 'GET' - - try: - retries = retries.increment(method, url, response=response, _pool=self) - except MaxRetryError: - if retries.raise_on_redirect: - # Drain and release the connection for this response, since - # we're not returning it to be released manually. - drain_and_release_conn(response) - raise - return response - - # drain and return the connection to the pool before recursing - drain_and_release_conn(response) - - retries.sleep_for_retry(response) - log.debug("Redirecting %s -> %s", url, redirect_location) - return self.urlopen( - method, redirect_location, body, headers, - retries=retries, redirect=redirect, - assert_same_host=assert_same_host, - timeout=timeout, pool_timeout=pool_timeout, - release_conn=release_conn, body_pos=body_pos, - **response_kw) - - # Check if we should retry the HTTP response. - has_retry_after = bool(response.getheader('Retry-After')) - if retries.is_retry(method, response.status, has_retry_after): - try: - retries = retries.increment(method, url, response=response, _pool=self) - except MaxRetryError: - if retries.raise_on_status: - # Drain and release the connection for this response, since - # we're not returning it to be released manually. - drain_and_release_conn(response) - raise - return response - - # drain and return the connection to the pool before recursing - drain_and_release_conn(response) - - retries.sleep(response) - log.debug("Retry: %s", url) - return self.urlopen( - method, url, body, headers, - retries=retries, redirect=redirect, - assert_same_host=assert_same_host, - timeout=timeout, pool_timeout=pool_timeout, - release_conn=release_conn, - body_pos=body_pos, **response_kw) - - return response - - -class HTTPSConnectionPool(HTTPConnectionPool): - """ - Same as :class:`.HTTPConnectionPool`, but HTTPS. - - When Python is compiled with the :mod:`ssl` module, then - :class:`.VerifiedHTTPSConnection` is used, which *can* verify certificates, - instead of :class:`.HTTPSConnection`. - - :class:`.VerifiedHTTPSConnection` uses one of ``assert_fingerprint``, - ``assert_hostname`` and ``host`` in this order to verify connections. - If ``assert_hostname`` is False, no verification is done. - - The ``key_file``, ``cert_file``, ``cert_reqs``, ``ca_certs``, - ``ca_cert_dir``, and ``ssl_version`` are only used if :mod:`ssl` is - available and are fed into :meth:`urllib3.util.ssl_wrap_socket` to upgrade - the connection socket into an SSL socket. - """ - - scheme = 'https' - ConnectionCls = HTTPSConnection - - def __init__(self, host, port=None, - strict=False, timeout=Timeout.DEFAULT_TIMEOUT, maxsize=1, - block=False, headers=None, retries=None, - _proxy=None, _proxy_headers=None, - key_file=None, cert_file=None, cert_reqs=None, - ca_certs=None, ssl_version=None, - assert_hostname=None, assert_fingerprint=None, - ca_cert_dir=None, **conn_kw): - - HTTPConnectionPool.__init__(self, host, port, strict, timeout, maxsize, - block, headers, retries, _proxy, _proxy_headers, - **conn_kw) - - if ca_certs and cert_reqs is None: - cert_reqs = 'CERT_REQUIRED' - - self.key_file = key_file - self.cert_file = cert_file - self.cert_reqs = cert_reqs - self.ca_certs = ca_certs - self.ca_cert_dir = ca_cert_dir - self.ssl_version = ssl_version - self.assert_hostname = assert_hostname - self.assert_fingerprint = assert_fingerprint - - def _prepare_conn(self, conn): - """ - Prepare the ``connection`` for :meth:`urllib3.util.ssl_wrap_socket` - and establish the tunnel if proxy is used. - """ - - if isinstance(conn, VerifiedHTTPSConnection): - conn.set_cert(key_file=self.key_file, - cert_file=self.cert_file, - cert_reqs=self.cert_reqs, - ca_certs=self.ca_certs, - ca_cert_dir=self.ca_cert_dir, - assert_hostname=self.assert_hostname, - assert_fingerprint=self.assert_fingerprint) - conn.ssl_version = self.ssl_version - return conn - - def _prepare_proxy(self, conn): - """ - Establish tunnel connection early, because otherwise httplib - would improperly set Host: header to proxy's IP:port. - """ - conn.set_tunnel(self._proxy_host, self.port, self.proxy_headers) - conn.connect() - - def _new_conn(self): - """ - Return a fresh :class:`httplib.HTTPSConnection`. - """ - self.num_connections += 1 - log.debug("Starting new HTTPS connection (%d): %s:%s", - self.num_connections, self.host, self.port or "443") - - if not self.ConnectionCls or self.ConnectionCls is DummyConnection: - raise SSLError("Can't connect to HTTPS URL because the SSL " - "module is not available.") - - actual_host = self.host - actual_port = self.port - if self.proxy is not None: - actual_host = self.proxy.host - actual_port = self.proxy.port - - conn = self.ConnectionCls(host=actual_host, port=actual_port, - timeout=self.timeout.connect_timeout, - strict=self.strict, **self.conn_kw) - - return self._prepare_conn(conn) - - def _validate_conn(self, conn): - """ - Called right before a request is made, after the socket is created. - """ - super(HTTPSConnectionPool, self)._validate_conn(conn) - - # Force connect early to allow us to validate the connection. - if not getattr(conn, 'sock', None): # AppEngine might not have `.sock` - conn.connect() - - if not conn.is_verified: - warnings.warn(( - 'Unverified HTTPS request is being made. ' - 'Adding certificate verification is strongly advised. See: ' - 'https://urllib3.readthedocs.io/en/latest/advanced-usage.html' - '#ssl-warnings'), - InsecureRequestWarning) - - -def connection_from_url(url, **kw): - """ - Given a url, return an :class:`.ConnectionPool` instance of its host. - - This is a shortcut for not having to parse out the scheme, host, and port - of the url before creating an :class:`.ConnectionPool` instance. - - :param url: - Absolute URL string that must include the scheme. Port is optional. - - :param \\**kw: - Passes additional parameters to the constructor of the appropriate - :class:`.ConnectionPool`. Useful for specifying things like - timeout, maxsize, headers, etc. - - Example:: - - >>> conn = connection_from_url('http://google.com/') - >>> r = conn.request('GET', '/') - """ - scheme, host, port = get_host(url) - port = port or port_by_scheme.get(scheme, 80) - if scheme == 'https': - return HTTPSConnectionPool(host, port=port, **kw) - else: - return HTTPConnectionPool(host, port=port, **kw) - - -def _ipv6_host(host, scheme): - """ - Process IPv6 address literals - """ - - # httplib doesn't like it when we include brackets in IPv6 addresses - # Specifically, if we include brackets but also pass the port then - # httplib crazily doubles up the square brackets on the Host header. - # Instead, we need to make sure we never pass ``None`` as the port. - # However, for backward compatibility reasons we can't actually - # *assert* that. See http://bugs.python.org/issue28539 - # - # Also if an IPv6 address literal has a zone identifier, the - # percent sign might be URIencoded, convert it back into ASCII - if host.startswith('[') and host.endswith(']'): - host = host.replace('%25', '%').strip('[]') - if scheme in NORMALIZABLE_SCHEMES: - host = host.lower() - return host diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py deleted file mode 100644 index f3e0094..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -This module provides means to detect the App Engine environment. -""" - -import os - - -def is_appengine(): - return (is_local_appengine() or - is_prod_appengine() or - is_prod_appengine_mvms()) - - -def is_appengine_sandbox(): - return is_appengine() and not is_prod_appengine_mvms() - - -def is_local_appengine(): - return ('APPENGINE_RUNTIME' in os.environ and - 'Development/' in os.environ['SERVER_SOFTWARE']) - - -def is_prod_appengine(): - return ('APPENGINE_RUNTIME' in os.environ and - 'Google App Engine/' in os.environ['SERVER_SOFTWARE'] and - not is_prod_appengine_mvms()) - - -def is_prod_appengine_mvms(): - return os.environ.get('GAE_VM', False) == 'true' diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py deleted file mode 100644 index bcf41c0..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py +++ /dev/null @@ -1,593 +0,0 @@ -""" -This module uses ctypes to bind a whole bunch of functions and constants from -SecureTransport. The goal here is to provide the low-level API to -SecureTransport. These are essentially the C-level functions and constants, and -they're pretty gross to work with. - -This code is a bastardised version of the code found in Will Bond's oscrypto -library. An enormous debt is owed to him for blazing this trail for us. For -that reason, this code should be considered to be covered both by urllib3's -license and by oscrypto's: - - Copyright (c) 2015-2016 Will Bond <will@wbond.net> - - 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. -""" -from __future__ import absolute_import - -import platform -from ctypes.util import find_library -from ctypes import ( - c_void_p, c_int32, c_char_p, c_size_t, c_byte, c_uint32, c_ulong, c_long, - c_bool -) -from ctypes import CDLL, POINTER, CFUNCTYPE - - -security_path = find_library('Security') -if not security_path: - raise ImportError('The library Security could not be found') - - -core_foundation_path = find_library('CoreFoundation') -if not core_foundation_path: - raise ImportError('The library CoreFoundation could not be found') - - -version = platform.mac_ver()[0] -version_info = tuple(map(int, version.split('.'))) -if version_info < (10, 8): - raise OSError( - 'Only OS X 10.8 and newer are supported, not %s.%s' % ( - version_info[0], version_info[1] - ) - ) - -Security = CDLL(security_path, use_errno=True) -CoreFoundation = CDLL(core_foundation_path, use_errno=True) - -Boolean = c_bool -CFIndex = c_long -CFStringEncoding = c_uint32 -CFData = c_void_p -CFString = c_void_p -CFArray = c_void_p -CFMutableArray = c_void_p -CFDictionary = c_void_p -CFError = c_void_p -CFType = c_void_p -CFTypeID = c_ulong - -CFTypeRef = POINTER(CFType) -CFAllocatorRef = c_void_p - -OSStatus = c_int32 - -CFDataRef = POINTER(CFData) -CFStringRef = POINTER(CFString) -CFArrayRef = POINTER(CFArray) -CFMutableArrayRef = POINTER(CFMutableArray) -CFDictionaryRef = POINTER(CFDictionary) -CFArrayCallBacks = c_void_p -CFDictionaryKeyCallBacks = c_void_p -CFDictionaryValueCallBacks = c_void_p - -SecCertificateRef = POINTER(c_void_p) -SecExternalFormat = c_uint32 -SecExternalItemType = c_uint32 -SecIdentityRef = POINTER(c_void_p) -SecItemImportExportFlags = c_uint32 -SecItemImportExportKeyParameters = c_void_p -SecKeychainRef = POINTER(c_void_p) -SSLProtocol = c_uint32 -SSLCipherSuite = c_uint32 -SSLContextRef = POINTER(c_void_p) -SecTrustRef = POINTER(c_void_p) -SSLConnectionRef = c_uint32 -SecTrustResultType = c_uint32 -SecTrustOptionFlags = c_uint32 -SSLProtocolSide = c_uint32 -SSLConnectionType = c_uint32 -SSLSessionOption = c_uint32 - - -try: - Security.SecItemImport.argtypes = [ - CFDataRef, - CFStringRef, - POINTER(SecExternalFormat), - POINTER(SecExternalItemType), - SecItemImportExportFlags, - POINTER(SecItemImportExportKeyParameters), - SecKeychainRef, - POINTER(CFArrayRef), - ] - Security.SecItemImport.restype = OSStatus - - Security.SecCertificateGetTypeID.argtypes = [] - Security.SecCertificateGetTypeID.restype = CFTypeID - - Security.SecIdentityGetTypeID.argtypes = [] - Security.SecIdentityGetTypeID.restype = CFTypeID - - Security.SecKeyGetTypeID.argtypes = [] - Security.SecKeyGetTypeID.restype = CFTypeID - - Security.SecCertificateCreateWithData.argtypes = [ - CFAllocatorRef, - CFDataRef - ] - Security.SecCertificateCreateWithData.restype = SecCertificateRef - - Security.SecCertificateCopyData.argtypes = [ - SecCertificateRef - ] - Security.SecCertificateCopyData.restype = CFDataRef - - Security.SecCopyErrorMessageString.argtypes = [ - OSStatus, - c_void_p - ] - Security.SecCopyErrorMessageString.restype = CFStringRef - - Security.SecIdentityCreateWithCertificate.argtypes = [ - CFTypeRef, - SecCertificateRef, - POINTER(SecIdentityRef) - ] - Security.SecIdentityCreateWithCertificate.restype = OSStatus - - Security.SecKeychainCreate.argtypes = [ - c_char_p, - c_uint32, - c_void_p, - Boolean, - c_void_p, - POINTER(SecKeychainRef) - ] - Security.SecKeychainCreate.restype = OSStatus - - Security.SecKeychainDelete.argtypes = [ - SecKeychainRef - ] - Security.SecKeychainDelete.restype = OSStatus - - Security.SecPKCS12Import.argtypes = [ - CFDataRef, - CFDictionaryRef, - POINTER(CFArrayRef) - ] - Security.SecPKCS12Import.restype = OSStatus - - SSLReadFunc = CFUNCTYPE(OSStatus, SSLConnectionRef, c_void_p, POINTER(c_size_t)) - SSLWriteFunc = CFUNCTYPE(OSStatus, SSLConnectionRef, POINTER(c_byte), POINTER(c_size_t)) - - Security.SSLSetIOFuncs.argtypes = [ - SSLContextRef, - SSLReadFunc, - SSLWriteFunc - ] - Security.SSLSetIOFuncs.restype = OSStatus - - Security.SSLSetPeerID.argtypes = [ - SSLContextRef, - c_char_p, - c_size_t - ] - Security.SSLSetPeerID.restype = OSStatus - - Security.SSLSetCertificate.argtypes = [ - SSLContextRef, - CFArrayRef - ] - Security.SSLSetCertificate.restype = OSStatus - - Security.SSLSetCertificateAuthorities.argtypes = [ - SSLContextRef, - CFTypeRef, - Boolean - ] - Security.SSLSetCertificateAuthorities.restype = OSStatus - - Security.SSLSetConnection.argtypes = [ - SSLContextRef, - SSLConnectionRef - ] - Security.SSLSetConnection.restype = OSStatus - - Security.SSLSetPeerDomainName.argtypes = [ - SSLContextRef, - c_char_p, - c_size_t - ] - Security.SSLSetPeerDomainName.restype = OSStatus - - Security.SSLHandshake.argtypes = [ - SSLContextRef - ] - Security.SSLHandshake.restype = OSStatus - - Security.SSLRead.argtypes = [ - SSLContextRef, - c_char_p, - c_size_t, - POINTER(c_size_t) - ] - Security.SSLRead.restype = OSStatus - - Security.SSLWrite.argtypes = [ - SSLContextRef, - c_char_p, - c_size_t, - POINTER(c_size_t) - ] - Security.SSLWrite.restype = OSStatus - - Security.SSLClose.argtypes = [ - SSLContextRef - ] - Security.SSLClose.restype = OSStatus - - Security.SSLGetNumberSupportedCiphers.argtypes = [ - SSLContextRef, - POINTER(c_size_t) - ] - Security.SSLGetNumberSupportedCiphers.restype = OSStatus - - Security.SSLGetSupportedCiphers.argtypes = [ - SSLContextRef, - POINTER(SSLCipherSuite), - POINTER(c_size_t) - ] - Security.SSLGetSupportedCiphers.restype = OSStatus - - Security.SSLSetEnabledCiphers.argtypes = [ - SSLContextRef, - POINTER(SSLCipherSuite), - c_size_t - ] - Security.SSLSetEnabledCiphers.restype = OSStatus - - Security.SSLGetNumberEnabledCiphers.argtype = [ - SSLContextRef, - POINTER(c_size_t) - ] - Security.SSLGetNumberEnabledCiphers.restype = OSStatus - - Security.SSLGetEnabledCiphers.argtypes = [ - SSLContextRef, - POINTER(SSLCipherSuite), - POINTER(c_size_t) - ] - Security.SSLGetEnabledCiphers.restype = OSStatus - - Security.SSLGetNegotiatedCipher.argtypes = [ - SSLContextRef, - POINTER(SSLCipherSuite) - ] - Security.SSLGetNegotiatedCipher.restype = OSStatus - - Security.SSLGetNegotiatedProtocolVersion.argtypes = [ - SSLContextRef, - POINTER(SSLProtocol) - ] - Security.SSLGetNegotiatedProtocolVersion.restype = OSStatus - - Security.SSLCopyPeerTrust.argtypes = [ - SSLContextRef, - POINTER(SecTrustRef) - ] - Security.SSLCopyPeerTrust.restype = OSStatus - - Security.SecTrustSetAnchorCertificates.argtypes = [ - SecTrustRef, - CFArrayRef - ] - Security.SecTrustSetAnchorCertificates.restype = OSStatus - - Security.SecTrustSetAnchorCertificatesOnly.argstypes = [ - SecTrustRef, - Boolean - ] - Security.SecTrustSetAnchorCertificatesOnly.restype = OSStatus - - Security.SecTrustEvaluate.argtypes = [ - SecTrustRef, - POINTER(SecTrustResultType) - ] - Security.SecTrustEvaluate.restype = OSStatus - - Security.SecTrustGetCertificateCount.argtypes = [ - SecTrustRef - ] - Security.SecTrustGetCertificateCount.restype = CFIndex - - Security.SecTrustGetCertificateAtIndex.argtypes = [ - SecTrustRef, - CFIndex - ] - Security.SecTrustGetCertificateAtIndex.restype = SecCertificateRef - - Security.SSLCreateContext.argtypes = [ - CFAllocatorRef, - SSLProtocolSide, - SSLConnectionType - ] - Security.SSLCreateContext.restype = SSLContextRef - - Security.SSLSetSessionOption.argtypes = [ - SSLContextRef, - SSLSessionOption, - Boolean - ] - Security.SSLSetSessionOption.restype = OSStatus - - Security.SSLSetProtocolVersionMin.argtypes = [ - SSLContextRef, - SSLProtocol - ] - Security.SSLSetProtocolVersionMin.restype = OSStatus - - Security.SSLSetProtocolVersionMax.argtypes = [ - SSLContextRef, - SSLProtocol - ] - Security.SSLSetProtocolVersionMax.restype = OSStatus - - Security.SecCopyErrorMessageString.argtypes = [ - OSStatus, - c_void_p - ] - Security.SecCopyErrorMessageString.restype = CFStringRef - - Security.SSLReadFunc = SSLReadFunc - Security.SSLWriteFunc = SSLWriteFunc - Security.SSLContextRef = SSLContextRef - Security.SSLProtocol = SSLProtocol - Security.SSLCipherSuite = SSLCipherSuite - Security.SecIdentityRef = SecIdentityRef - Security.SecKeychainRef = SecKeychainRef - Security.SecTrustRef = SecTrustRef - Security.SecTrustResultType = SecTrustResultType - Security.SecExternalFormat = SecExternalFormat - Security.OSStatus = OSStatus - - Security.kSecImportExportPassphrase = CFStringRef.in_dll( - Security, 'kSecImportExportPassphrase' - ) - Security.kSecImportItemIdentity = CFStringRef.in_dll( - Security, 'kSecImportItemIdentity' - ) - - # CoreFoundation time! - CoreFoundation.CFRetain.argtypes = [ - CFTypeRef - ] - CoreFoundation.CFRetain.restype = CFTypeRef - - CoreFoundation.CFRelease.argtypes = [ - CFTypeRef - ] - CoreFoundation.CFRelease.restype = None - - CoreFoundation.CFGetTypeID.argtypes = [ - CFTypeRef - ] - CoreFoundation.CFGetTypeID.restype = CFTypeID - - CoreFoundation.CFStringCreateWithCString.argtypes = [ - CFAllocatorRef, - c_char_p, - CFStringEncoding - ] - CoreFoundation.CFStringCreateWithCString.restype = CFStringRef - - CoreFoundation.CFStringGetCStringPtr.argtypes = [ - CFStringRef, - CFStringEncoding - ] - CoreFoundation.CFStringGetCStringPtr.restype = c_char_p - - CoreFoundation.CFStringGetCString.argtypes = [ - CFStringRef, - c_char_p, - CFIndex, - CFStringEncoding - ] - CoreFoundation.CFStringGetCString.restype = c_bool - - CoreFoundation.CFDataCreate.argtypes = [ - CFAllocatorRef, - c_char_p, - CFIndex - ] - CoreFoundation.CFDataCreate.restype = CFDataRef - - CoreFoundation.CFDataGetLength.argtypes = [ - CFDataRef - ] - CoreFoundation.CFDataGetLength.restype = CFIndex - - CoreFoundation.CFDataGetBytePtr.argtypes = [ - CFDataRef - ] - CoreFoundation.CFDataGetBytePtr.restype = c_void_p - - CoreFoundation.CFDictionaryCreate.argtypes = [ - CFAllocatorRef, - POINTER(CFTypeRef), - POINTER(CFTypeRef), - CFIndex, - CFDictionaryKeyCallBacks, - CFDictionaryValueCallBacks - ] - CoreFoundation.CFDictionaryCreate.restype = CFDictionaryRef - - CoreFoundation.CFDictionaryGetValue.argtypes = [ - CFDictionaryRef, - CFTypeRef - ] - CoreFoundation.CFDictionaryGetValue.restype = CFTypeRef - - CoreFoundation.CFArrayCreate.argtypes = [ - CFAllocatorRef, - POINTER(CFTypeRef), - CFIndex, - CFArrayCallBacks, - ] - CoreFoundation.CFArrayCreate.restype = CFArrayRef - - CoreFoundation.CFArrayCreateMutable.argtypes = [ - CFAllocatorRef, - CFIndex, - CFArrayCallBacks - ] - CoreFoundation.CFArrayCreateMutable.restype = CFMutableArrayRef - - CoreFoundation.CFArrayAppendValue.argtypes = [ - CFMutableArrayRef, - c_void_p - ] - CoreFoundation.CFArrayAppendValue.restype = None - - CoreFoundation.CFArrayGetCount.argtypes = [ - CFArrayRef - ] - CoreFoundation.CFArrayGetCount.restype = CFIndex - - CoreFoundation.CFArrayGetValueAtIndex.argtypes = [ - CFArrayRef, - CFIndex - ] - CoreFoundation.CFArrayGetValueAtIndex.restype = c_void_p - - CoreFoundation.kCFAllocatorDefault = CFAllocatorRef.in_dll( - CoreFoundation, 'kCFAllocatorDefault' - ) - CoreFoundation.kCFTypeArrayCallBacks = c_void_p.in_dll(CoreFoundation, 'kCFTypeArrayCallBacks') - CoreFoundation.kCFTypeDictionaryKeyCallBacks = c_void_p.in_dll( - CoreFoundation, 'kCFTypeDictionaryKeyCallBacks' - ) - CoreFoundation.kCFTypeDictionaryValueCallBacks = c_void_p.in_dll( - CoreFoundation, 'kCFTypeDictionaryValueCallBacks' - ) - - CoreFoundation.CFTypeRef = CFTypeRef - CoreFoundation.CFArrayRef = CFArrayRef - CoreFoundation.CFStringRef = CFStringRef - CoreFoundation.CFDictionaryRef = CFDictionaryRef - -except (AttributeError): - raise ImportError('Error initializing ctypes') - - -class CFConst(object): - """ - A class object that acts as essentially a namespace for CoreFoundation - constants. - """ - kCFStringEncodingUTF8 = CFStringEncoding(0x08000100) - - -class SecurityConst(object): - """ - A class object that acts as essentially a namespace for Security constants. - """ - kSSLSessionOptionBreakOnServerAuth = 0 - - kSSLProtocol2 = 1 - kSSLProtocol3 = 2 - kTLSProtocol1 = 4 - kTLSProtocol11 = 7 - kTLSProtocol12 = 8 - - kSSLClientSide = 1 - kSSLStreamType = 0 - - kSecFormatPEMSequence = 10 - - kSecTrustResultInvalid = 0 - kSecTrustResultProceed = 1 - # This gap is present on purpose: this was kSecTrustResultConfirm, which - # is deprecated. - kSecTrustResultDeny = 3 - kSecTrustResultUnspecified = 4 - kSecTrustResultRecoverableTrustFailure = 5 - kSecTrustResultFatalTrustFailure = 6 - kSecTrustResultOtherError = 7 - - errSSLProtocol = -9800 - errSSLWouldBlock = -9803 - errSSLClosedGraceful = -9805 - errSSLClosedNoNotify = -9816 - errSSLClosedAbort = -9806 - - errSSLXCertChainInvalid = -9807 - errSSLCrypto = -9809 - errSSLInternal = -9810 - errSSLCertExpired = -9814 - errSSLCertNotYetValid = -9815 - errSSLUnknownRootCert = -9812 - errSSLNoRootCert = -9813 - errSSLHostNameMismatch = -9843 - errSSLPeerHandshakeFail = -9824 - errSSLPeerUserCancelled = -9839 - errSSLWeakPeerEphemeralDHKey = -9850 - errSSLServerAuthCompleted = -9841 - errSSLRecordOverflow = -9847 - - errSecVerifyFailed = -67808 - errSecNoTrustSettings = -25263 - errSecItemNotFound = -25300 - errSecInvalidTrustSettings = -25262 - - # Cipher suites. We only pick the ones our default cipher string allows. - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030 - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F - TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3 - TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F - TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2 - TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024 - TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028 - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A - TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014 - TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B - TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A - TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039 - TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038 - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023 - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027 - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009 - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013 - TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067 - TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040 - TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033 - TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032 - TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D - TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C - TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D - TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C - TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035 - TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F - TLS_AES_128_GCM_SHA256 = 0x1301 - TLS_AES_256_GCM_SHA384 = 0x1302 - TLS_CHACHA20_POLY1305_SHA256 = 0x1303 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py deleted file mode 100644 index b13cd9e..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py +++ /dev/null @@ -1,346 +0,0 @@ -""" -Low-level helpers for the SecureTransport bindings. - -These are Python functions that are not directly related to the high-level APIs -but are necessary to get them to work. They include a whole bunch of low-level -CoreFoundation messing about and memory management. The concerns in this module -are almost entirely about trying to avoid memory leaks and providing -appropriate and useful assistance to the higher-level code. -""" -import base64 -import ctypes -import itertools -import re -import os -import ssl -import tempfile - -from .bindings import Security, CoreFoundation, CFConst - - -# This regular expression is used to grab PEM data out of a PEM bundle. -_PEM_CERTS_RE = re.compile( - b"-----BEGIN CERTIFICATE-----\n(.*?)\n-----END CERTIFICATE-----", re.DOTALL -) - - -def _cf_data_from_bytes(bytestring): - """ - Given a bytestring, create a CFData object from it. This CFData object must - be CFReleased by the caller. - """ - return CoreFoundation.CFDataCreate( - CoreFoundation.kCFAllocatorDefault, bytestring, len(bytestring) - ) - - -def _cf_dictionary_from_tuples(tuples): - """ - Given a list of Python tuples, create an associated CFDictionary. - """ - dictionary_size = len(tuples) - - # We need to get the dictionary keys and values out in the same order. - keys = (t[0] for t in tuples) - values = (t[1] for t in tuples) - cf_keys = (CoreFoundation.CFTypeRef * dictionary_size)(*keys) - cf_values = (CoreFoundation.CFTypeRef * dictionary_size)(*values) - - return CoreFoundation.CFDictionaryCreate( - CoreFoundation.kCFAllocatorDefault, - cf_keys, - cf_values, - dictionary_size, - CoreFoundation.kCFTypeDictionaryKeyCallBacks, - CoreFoundation.kCFTypeDictionaryValueCallBacks, - ) - - -def _cf_string_to_unicode(value): - """ - Creates a Unicode string from a CFString object. Used entirely for error - reporting. - - Yes, it annoys me quite a lot that this function is this complex. - """ - value_as_void_p = ctypes.cast(value, ctypes.POINTER(ctypes.c_void_p)) - - string = CoreFoundation.CFStringGetCStringPtr( - value_as_void_p, - CFConst.kCFStringEncodingUTF8 - ) - if string is None: - buffer = ctypes.create_string_buffer(1024) - result = CoreFoundation.CFStringGetCString( - value_as_void_p, - buffer, - 1024, - CFConst.kCFStringEncodingUTF8 - ) - if not result: - raise OSError('Error copying C string from CFStringRef') - string = buffer.value - if string is not None: - string = string.decode('utf-8') - return string - - -def _assert_no_error(error, exception_class=None): - """ - Checks the return code and throws an exception if there is an error to - report - """ - if error == 0: - return - - cf_error_string = Security.SecCopyErrorMessageString(error, None) - output = _cf_string_to_unicode(cf_error_string) - CoreFoundation.CFRelease(cf_error_string) - - if output is None or output == u'': - output = u'OSStatus %s' % error - - if exception_class is None: - exception_class = ssl.SSLError - - raise exception_class(output) - - -def _cert_array_from_pem(pem_bundle): - """ - Given a bundle of certs in PEM format, turns them into a CFArray of certs - that can be used to validate a cert chain. - """ - # Normalize the PEM bundle's line endings. - pem_bundle = pem_bundle.replace(b"\r\n", b"\n") - - der_certs = [ - base64.b64decode(match.group(1)) - for match in _PEM_CERTS_RE.finditer(pem_bundle) - ] - if not der_certs: - raise ssl.SSLError("No root certificates specified") - - cert_array = CoreFoundation.CFArrayCreateMutable( - CoreFoundation.kCFAllocatorDefault, - 0, - ctypes.byref(CoreFoundation.kCFTypeArrayCallBacks) - ) - if not cert_array: - raise ssl.SSLError("Unable to allocate memory!") - - try: - for der_bytes in der_certs: - certdata = _cf_data_from_bytes(der_bytes) - if not certdata: - raise ssl.SSLError("Unable to allocate memory!") - cert = Security.SecCertificateCreateWithData( - CoreFoundation.kCFAllocatorDefault, certdata - ) - CoreFoundation.CFRelease(certdata) - if not cert: - raise ssl.SSLError("Unable to build cert object!") - - CoreFoundation.CFArrayAppendValue(cert_array, cert) - CoreFoundation.CFRelease(cert) - except Exception: - # We need to free the array before the exception bubbles further. - # We only want to do that if an error occurs: otherwise, the caller - # should free. - CoreFoundation.CFRelease(cert_array) - - return cert_array - - -def _is_cert(item): - """ - Returns True if a given CFTypeRef is a certificate. - """ - expected = Security.SecCertificateGetTypeID() - return CoreFoundation.CFGetTypeID(item) == expected - - -def _is_identity(item): - """ - Returns True if a given CFTypeRef is an identity. - """ - expected = Security.SecIdentityGetTypeID() - return CoreFoundation.CFGetTypeID(item) == expected - - -def _temporary_keychain(): - """ - This function creates a temporary Mac keychain that we can use to work with - credentials. This keychain uses a one-time password and a temporary file to - store the data. We expect to have one keychain per socket. The returned - SecKeychainRef must be freed by the caller, including calling - SecKeychainDelete. - - Returns a tuple of the SecKeychainRef and the path to the temporary - directory that contains it. - """ - # Unfortunately, SecKeychainCreate requires a path to a keychain. This - # means we cannot use mkstemp to use a generic temporary file. Instead, - # we're going to create a temporary directory and a filename to use there. - # This filename will be 8 random bytes expanded into base64. We also need - # some random bytes to password-protect the keychain we're creating, so we - # ask for 40 random bytes. - random_bytes = os.urandom(40) - filename = base64.b16encode(random_bytes[:8]).decode('utf-8') - password = base64.b16encode(random_bytes[8:]) # Must be valid UTF-8 - tempdirectory = tempfile.mkdtemp() - - keychain_path = os.path.join(tempdirectory, filename).encode('utf-8') - - # We now want to create the keychain itself. - keychain = Security.SecKeychainRef() - status = Security.SecKeychainCreate( - keychain_path, - len(password), - password, - False, - None, - ctypes.byref(keychain) - ) - _assert_no_error(status) - - # Having created the keychain, we want to pass it off to the caller. - return keychain, tempdirectory - - -def _load_items_from_file(keychain, path): - """ - Given a single file, loads all the trust objects from it into arrays and - the keychain. - Returns a tuple of lists: the first list is a list of identities, the - second a list of certs. - """ - certificates = [] - identities = [] - result_array = None - - with open(path, 'rb') as f: - raw_filedata = f.read() - - try: - filedata = CoreFoundation.CFDataCreate( - CoreFoundation.kCFAllocatorDefault, - raw_filedata, - len(raw_filedata) - ) - result_array = CoreFoundation.CFArrayRef() - result = Security.SecItemImport( - filedata, # cert data - None, # Filename, leaving it out for now - None, # What the type of the file is, we don't care - None, # what's in the file, we don't care - 0, # import flags - None, # key params, can include passphrase in the future - keychain, # The keychain to insert into - ctypes.byref(result_array) # Results - ) - _assert_no_error(result) - - # A CFArray is not very useful to us as an intermediary - # representation, so we are going to extract the objects we want - # and then free the array. We don't need to keep hold of keys: the - # keychain already has them! - result_count = CoreFoundation.CFArrayGetCount(result_array) - for index in range(result_count): - item = CoreFoundation.CFArrayGetValueAtIndex( - result_array, index - ) - item = ctypes.cast(item, CoreFoundation.CFTypeRef) - - if _is_cert(item): - CoreFoundation.CFRetain(item) - certificates.append(item) - elif _is_identity(item): - CoreFoundation.CFRetain(item) - identities.append(item) - finally: - if result_array: - CoreFoundation.CFRelease(result_array) - - CoreFoundation.CFRelease(filedata) - - return (identities, certificates) - - -def _load_client_cert_chain(keychain, *paths): - """ - Load certificates and maybe keys from a number of files. Has the end goal - of returning a CFArray containing one SecIdentityRef, and then zero or more - SecCertificateRef objects, suitable for use as a client certificate trust - chain. - """ - # Ok, the strategy. - # - # This relies on knowing that macOS will not give you a SecIdentityRef - # unless you have imported a key into a keychain. This is a somewhat - # artificial limitation of macOS (for example, it doesn't necessarily - # affect iOS), but there is nothing inside Security.framework that lets you - # get a SecIdentityRef without having a key in a keychain. - # - # So the policy here is we take all the files and iterate them in order. - # Each one will use SecItemImport to have one or more objects loaded from - # it. We will also point at a keychain that macOS can use to work with the - # private key. - # - # Once we have all the objects, we'll check what we actually have. If we - # already have a SecIdentityRef in hand, fab: we'll use that. Otherwise, - # we'll take the first certificate (which we assume to be our leaf) and - # ask the keychain to give us a SecIdentityRef with that cert's associated - # key. - # - # We'll then return a CFArray containing the trust chain: one - # SecIdentityRef and then zero-or-more SecCertificateRef objects. The - # responsibility for freeing this CFArray will be with the caller. This - # CFArray must remain alive for the entire connection, so in practice it - # will be stored with a single SSLSocket, along with the reference to the - # keychain. - certificates = [] - identities = [] - - # Filter out bad paths. - paths = (path for path in paths if path) - - try: - for file_path in paths: - new_identities, new_certs = _load_items_from_file( - keychain, file_path - ) - identities.extend(new_identities) - certificates.extend(new_certs) - - # Ok, we have everything. The question is: do we have an identity? If - # not, we want to grab one from the first cert we have. - if not identities: - new_identity = Security.SecIdentityRef() - status = Security.SecIdentityCreateWithCertificate( - keychain, - certificates[0], - ctypes.byref(new_identity) - ) - _assert_no_error(status) - identities.append(new_identity) - - # We now want to release the original certificate, as we no longer - # need it. - CoreFoundation.CFRelease(certificates.pop(0)) - - # We now need to build a new CFArray that holds the trust chain. - trust_chain = CoreFoundation.CFArrayCreateMutable( - CoreFoundation.kCFAllocatorDefault, - 0, - ctypes.byref(CoreFoundation.kCFTypeArrayCallBacks), - ) - for item in itertools.chain(identities, certificates): - # ArrayAppendValue does a CFRetain on the item. That's fine, - # because the finally block will release our other refs to them. - CoreFoundation.CFArrayAppendValue(trust_chain, item) - - return trust_chain - finally: - for obj in itertools.chain(identities, certificates): - CoreFoundation.CFRelease(obj) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/appengine.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/appengine.py deleted file mode 100644 index 9b42952..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/appengine.py +++ /dev/null @@ -1,289 +0,0 @@ -""" -This module provides a pool manager that uses Google App Engine's -`URLFetch Service <https://cloud.google.com/appengine/docs/python/urlfetch>`_. - -Example usage:: - - from pip._vendor.urllib3 import PoolManager - from pip._vendor.urllib3.contrib.appengine import AppEngineManager, is_appengine_sandbox - - if is_appengine_sandbox(): - # AppEngineManager uses AppEngine's URLFetch API behind the scenes - http = AppEngineManager() - else: - # PoolManager uses a socket-level API behind the scenes - http = PoolManager() - - r = http.request('GET', 'https://google.com/') - -There are `limitations <https://cloud.google.com/appengine/docs/python/\ -urlfetch/#Python_Quotas_and_limits>`_ to the URLFetch service and it may not be -the best choice for your application. There are three options for using -urllib3 on Google App Engine: - -1. You can use :class:`AppEngineManager` with URLFetch. URLFetch is - cost-effective in many circumstances as long as your usage is within the - limitations. -2. You can use a normal :class:`~urllib3.PoolManager` by enabling sockets. - Sockets also have `limitations and restrictions - <https://cloud.google.com/appengine/docs/python/sockets/\ - #limitations-and-restrictions>`_ and have a lower free quota than URLFetch. - To use sockets, be sure to specify the following in your ``app.yaml``:: - - env_variables: - GAE_USE_SOCKETS_HTTPLIB : 'true' - -3. If you are using `App Engine Flexible -<https://cloud.google.com/appengine/docs/flexible/>`_, you can use the standard -:class:`PoolManager` without any configuration or special environment variables. -""" - -from __future__ import absolute_import -import io -import logging -import warnings -from ..packages.six.moves.urllib.parse import urljoin - -from ..exceptions import ( - HTTPError, - HTTPWarning, - MaxRetryError, - ProtocolError, - TimeoutError, - SSLError -) - -from ..request import RequestMethods -from ..response import HTTPResponse -from ..util.timeout import Timeout -from ..util.retry import Retry -from . import _appengine_environ - -try: - from google.appengine.api import urlfetch -except ImportError: - urlfetch = None - - -log = logging.getLogger(__name__) - - -class AppEnginePlatformWarning(HTTPWarning): - pass - - -class AppEnginePlatformError(HTTPError): - pass - - -class AppEngineManager(RequestMethods): - """ - Connection manager for Google App Engine sandbox applications. - - This manager uses the URLFetch service directly instead of using the - emulated httplib, and is subject to URLFetch limitations as described in - the App Engine documentation `here - <https://cloud.google.com/appengine/docs/python/urlfetch>`_. - - Notably it will raise an :class:`AppEnginePlatformError` if: - * URLFetch is not available. - * If you attempt to use this on App Engine Flexible, as full socket - support is available. - * If a request size is more than 10 megabytes. - * If a response size is more than 32 megabtyes. - * If you use an unsupported request method such as OPTIONS. - - Beyond those cases, it will raise normal urllib3 errors. - """ - - def __init__(self, headers=None, retries=None, validate_certificate=True, - urlfetch_retries=True): - if not urlfetch: - raise AppEnginePlatformError( - "URLFetch is not available in this environment.") - - if is_prod_appengine_mvms(): - raise AppEnginePlatformError( - "Use normal urllib3.PoolManager instead of AppEngineManager" - "on Managed VMs, as using URLFetch is not necessary in " - "this environment.") - - warnings.warn( - "urllib3 is using URLFetch on Google App Engine sandbox instead " - "of sockets. To use sockets directly instead of URLFetch see " - "https://urllib3.readthedocs.io/en/latest/reference/urllib3.contrib.html.", - AppEnginePlatformWarning) - - RequestMethods.__init__(self, headers) - self.validate_certificate = validate_certificate - self.urlfetch_retries = urlfetch_retries - - self.retries = retries or Retry.DEFAULT - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - # Return False to re-raise any potential exceptions - return False - - def urlopen(self, method, url, body=None, headers=None, - retries=None, redirect=True, timeout=Timeout.DEFAULT_TIMEOUT, - **response_kw): - - retries = self._get_retries(retries, redirect) - - try: - follow_redirects = ( - redirect and - retries.redirect != 0 and - retries.total) - response = urlfetch.fetch( - url, - payload=body, - method=method, - headers=headers or {}, - allow_truncated=False, - follow_redirects=self.urlfetch_retries and follow_redirects, - deadline=self._get_absolute_timeout(timeout), - validate_certificate=self.validate_certificate, - ) - except urlfetch.DeadlineExceededError as e: - raise TimeoutError(self, e) - - except urlfetch.InvalidURLError as e: - if 'too large' in str(e): - raise AppEnginePlatformError( - "URLFetch request too large, URLFetch only " - "supports requests up to 10mb in size.", e) - raise ProtocolError(e) - - except urlfetch.DownloadError as e: - if 'Too many redirects' in str(e): - raise MaxRetryError(self, url, reason=e) - raise ProtocolError(e) - - except urlfetch.ResponseTooLargeError as e: - raise AppEnginePlatformError( - "URLFetch response too large, URLFetch only supports" - "responses up to 32mb in size.", e) - - except urlfetch.SSLCertificateError as e: - raise SSLError(e) - - except urlfetch.InvalidMethodError as e: - raise AppEnginePlatformError( - "URLFetch does not support method: %s" % method, e) - - http_response = self._urlfetch_response_to_http_response( - response, retries=retries, **response_kw) - - # Handle redirect? - redirect_location = redirect and http_response.get_redirect_location() - if redirect_location: - # Check for redirect response - if (self.urlfetch_retries and retries.raise_on_redirect): - raise MaxRetryError(self, url, "too many redirects") - else: - if http_response.status == 303: - method = 'GET' - - try: - retries = retries.increment(method, url, response=http_response, _pool=self) - except MaxRetryError: - if retries.raise_on_redirect: - raise MaxRetryError(self, url, "too many redirects") - return http_response - - retries.sleep_for_retry(http_response) - log.debug("Redirecting %s -> %s", url, redirect_location) - redirect_url = urljoin(url, redirect_location) - return self.urlopen( - method, redirect_url, body, headers, - retries=retries, redirect=redirect, - timeout=timeout, **response_kw) - - # Check if we should retry the HTTP response. - has_retry_after = bool(http_response.getheader('Retry-After')) - if retries.is_retry(method, http_response.status, has_retry_after): - retries = retries.increment( - method, url, response=http_response, _pool=self) - log.debug("Retry: %s", url) - retries.sleep(http_response) - return self.urlopen( - method, url, - body=body, headers=headers, - retries=retries, redirect=redirect, - timeout=timeout, **response_kw) - - return http_response - - def _urlfetch_response_to_http_response(self, urlfetch_resp, **response_kw): - - if is_prod_appengine(): - # Production GAE handles deflate encoding automatically, but does - # not remove the encoding header. - content_encoding = urlfetch_resp.headers.get('content-encoding') - - if content_encoding == 'deflate': - del urlfetch_resp.headers['content-encoding'] - - transfer_encoding = urlfetch_resp.headers.get('transfer-encoding') - # We have a full response's content, - # so let's make sure we don't report ourselves as chunked data. - if transfer_encoding == 'chunked': - encodings = transfer_encoding.split(",") - encodings.remove('chunked') - urlfetch_resp.headers['transfer-encoding'] = ','.join(encodings) - - original_response = HTTPResponse( - # In order for decoding to work, we must present the content as - # a file-like object. - body=io.BytesIO(urlfetch_resp.content), - msg=urlfetch_resp.header_msg, - headers=urlfetch_resp.headers, - status=urlfetch_resp.status_code, - **response_kw - ) - - return HTTPResponse( - body=io.BytesIO(urlfetch_resp.content), - headers=urlfetch_resp.headers, - status=urlfetch_resp.status_code, - original_response=original_response, - **response_kw - ) - - def _get_absolute_timeout(self, timeout): - if timeout is Timeout.DEFAULT_TIMEOUT: - return None # Defer to URLFetch's default. - if isinstance(timeout, Timeout): - if timeout._read is not None or timeout._connect is not None: - warnings.warn( - "URLFetch does not support granular timeout settings, " - "reverting to total or default URLFetch timeout.", - AppEnginePlatformWarning) - return timeout.total - return timeout - - def _get_retries(self, retries, redirect): - if not isinstance(retries, Retry): - retries = Retry.from_int( - retries, redirect=redirect, default=self.retries) - - if retries.connect or retries.read or retries.redirect: - warnings.warn( - "URLFetch only supports total retries and does not " - "recognize connect, read, or redirect retry parameters.", - AppEnginePlatformWarning) - - return retries - - -# Alias methods from _appengine_environ to maintain public API interface. - -is_appengine = _appengine_environ.is_appengine -is_appengine_sandbox = _appengine_environ.is_appengine_sandbox -is_local_appengine = _appengine_environ.is_local_appengine -is_prod_appengine = _appengine_environ.is_prod_appengine -is_prod_appengine_mvms = _appengine_environ.is_prod_appengine_mvms diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py deleted file mode 100644 index 8ea127c..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py +++ /dev/null @@ -1,111 +0,0 @@ -""" -NTLM authenticating pool, contributed by erikcederstran - -Issue #10, see: http://code.google.com/p/urllib3/issues/detail?id=10 -""" -from __future__ import absolute_import - -from logging import getLogger -from ntlm import ntlm - -from .. import HTTPSConnectionPool -from ..packages.six.moves.http_client import HTTPSConnection - - -log = getLogger(__name__) - - -class NTLMConnectionPool(HTTPSConnectionPool): - """ - Implements an NTLM authentication version of an urllib3 connection pool - """ - - scheme = 'https' - - def __init__(self, user, pw, authurl, *args, **kwargs): - """ - authurl is a random URL on the server that is protected by NTLM. - user is the Windows user, probably in the DOMAIN\\username format. - pw is the password for the user. - """ - super(NTLMConnectionPool, self).__init__(*args, **kwargs) - self.authurl = authurl - self.rawuser = user - user_parts = user.split('\\', 1) - self.domain = user_parts[0].upper() - self.user = user_parts[1] - self.pw = pw - - def _new_conn(self): - # Performs the NTLM handshake that secures the connection. The socket - # must be kept open while requests are performed. - self.num_connections += 1 - log.debug('Starting NTLM HTTPS connection no. %d: https://%s%s', - self.num_connections, self.host, self.authurl) - - headers = {'Connection': 'Keep-Alive'} - req_header = 'Authorization' - resp_header = 'www-authenticate' - - conn = HTTPSConnection(host=self.host, port=self.port) - - # Send negotiation message - headers[req_header] = ( - 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(self.rawuser)) - log.debug('Request headers: %s', headers) - conn.request('GET', self.authurl, None, headers) - res = conn.getresponse() - reshdr = dict(res.getheaders()) - log.debug('Response status: %s %s', res.status, res.reason) - log.debug('Response headers: %s', reshdr) - log.debug('Response data: %s [...]', res.read(100)) - - # Remove the reference to the socket, so that it can not be closed by - # the response object (we want to keep the socket open) - res.fp = None - - # Server should respond with a challenge message - auth_header_values = reshdr[resp_header].split(', ') - auth_header_value = None - for s in auth_header_values: - if s[:5] == 'NTLM ': - auth_header_value = s[5:] - if auth_header_value is None: - raise Exception('Unexpected %s response header: %s' % - (resp_header, reshdr[resp_header])) - - # Send authentication message - ServerChallenge, NegotiateFlags = \ - ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value) - auth_msg = ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, - self.user, - self.domain, - self.pw, - NegotiateFlags) - headers[req_header] = 'NTLM %s' % auth_msg - log.debug('Request headers: %s', headers) - conn.request('GET', self.authurl, None, headers) - res = conn.getresponse() - log.debug('Response status: %s %s', res.status, res.reason) - log.debug('Response headers: %s', dict(res.getheaders())) - log.debug('Response data: %s [...]', res.read()[:100]) - if res.status != 200: - if res.status == 401: - raise Exception('Server rejected request: wrong ' - 'username or password') - raise Exception('Wrong server response: %s %s' % - (res.status, res.reason)) - - res.fp = None - log.debug('Connection established') - return conn - - def urlopen(self, method, url, body=None, headers=None, retries=3, - redirect=True, assert_same_host=True): - if headers is None: - headers = {} - headers['Connection'] = 'Keep-Alive' - return super(NTLMConnectionPool, self).urlopen(method, url, body, - headers, retries, - redirect, - assert_same_host) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py deleted file mode 100644 index 363667c..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py +++ /dev/null @@ -1,466 +0,0 @@ -""" -SSL with SNI_-support for Python 2. Follow these instructions if you would -like to verify SSL certificates in Python 2. Note, the default libraries do -*not* do certificate checking; you need to do additional work to validate -certificates yourself. - -This needs the following packages installed: - -* pyOpenSSL (tested with 16.0.0) -* cryptography (minimum 1.3.4, from pyopenssl) -* idna (minimum 2.0, from cryptography) - -However, pyopenssl depends on cryptography, which depends on idna, so while we -use all three directly here we end up having relatively few packages required. - -You can install them with the following command: - - pip install pyopenssl cryptography idna - -To activate certificate checking, call -:func:`~urllib3.contrib.pyopenssl.inject_into_urllib3` from your Python code -before you begin making HTTP requests. This can be done in a ``sitecustomize`` -module, or at any other time before your application begins using ``urllib3``, -like this:: - - try: - import urllib3.contrib.pyopenssl - urllib3.contrib.pyopenssl.inject_into_urllib3() - except ImportError: - pass - -Now you can use :mod:`urllib3` as you normally would, and it will support SNI -when the required modules are installed. - -Activating this module also has the positive side effect of disabling SSL/TLS -compression in Python 2 (see `CRIME attack`_). - -If you want to configure the default list of supported cipher suites, you can -set the ``urllib3.contrib.pyopenssl.DEFAULT_SSL_CIPHER_LIST`` variable. - -.. _sni: https://en.wikipedia.org/wiki/Server_Name_Indication -.. _crime attack: https://en.wikipedia.org/wiki/CRIME_(security_exploit) -""" -from __future__ import absolute_import - -import OpenSSL.SSL -from cryptography import x509 -from cryptography.hazmat.backends.openssl import backend as openssl_backend -from cryptography.hazmat.backends.openssl.x509 import _Certificate -try: - from cryptography.x509 import UnsupportedExtension -except ImportError: - # UnsupportedExtension is gone in cryptography >= 2.1.0 - class UnsupportedExtension(Exception): - pass - -from socket import timeout, error as SocketError -from io import BytesIO - -try: # Platform-specific: Python 2 - from socket import _fileobject -except ImportError: # Platform-specific: Python 3 - _fileobject = None - from ..packages.backports.makefile import backport_makefile - -import logging -import ssl -from ..packages import six -import sys - -from .. import util - -__all__ = ['inject_into_urllib3', 'extract_from_urllib3'] - -# SNI always works. -HAS_SNI = True - -# Map from urllib3 to PyOpenSSL compatible parameter-values. -_openssl_versions = { - ssl.PROTOCOL_SSLv23: OpenSSL.SSL.SSLv23_METHOD, - ssl.PROTOCOL_TLSv1: OpenSSL.SSL.TLSv1_METHOD, -} - -if hasattr(ssl, 'PROTOCOL_TLSv1_1') and hasattr(OpenSSL.SSL, 'TLSv1_1_METHOD'): - _openssl_versions[ssl.PROTOCOL_TLSv1_1] = OpenSSL.SSL.TLSv1_1_METHOD - -if hasattr(ssl, 'PROTOCOL_TLSv1_2') and hasattr(OpenSSL.SSL, 'TLSv1_2_METHOD'): - _openssl_versions[ssl.PROTOCOL_TLSv1_2] = OpenSSL.SSL.TLSv1_2_METHOD - -try: - _openssl_versions.update({ssl.PROTOCOL_SSLv3: OpenSSL.SSL.SSLv3_METHOD}) -except AttributeError: - pass - -_stdlib_to_openssl_verify = { - ssl.CERT_NONE: OpenSSL.SSL.VERIFY_NONE, - ssl.CERT_OPTIONAL: OpenSSL.SSL.VERIFY_PEER, - ssl.CERT_REQUIRED: - OpenSSL.SSL.VERIFY_PEER + OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT, -} -_openssl_to_stdlib_verify = dict( - (v, k) for k, v in _stdlib_to_openssl_verify.items() -) - -# OpenSSL will only write 16K at a time -SSL_WRITE_BLOCKSIZE = 16384 - -orig_util_HAS_SNI = util.HAS_SNI -orig_util_SSLContext = util.ssl_.SSLContext - - -log = logging.getLogger(__name__) - - -def inject_into_urllib3(): - 'Monkey-patch urllib3 with PyOpenSSL-backed SSL-support.' - - _validate_dependencies_met() - - util.ssl_.SSLContext = PyOpenSSLContext - util.HAS_SNI = HAS_SNI - util.ssl_.HAS_SNI = HAS_SNI - util.IS_PYOPENSSL = True - util.ssl_.IS_PYOPENSSL = True - - -def extract_from_urllib3(): - 'Undo monkey-patching by :func:`inject_into_urllib3`.' - - util.ssl_.SSLContext = orig_util_SSLContext - util.HAS_SNI = orig_util_HAS_SNI - util.ssl_.HAS_SNI = orig_util_HAS_SNI - util.IS_PYOPENSSL = False - util.ssl_.IS_PYOPENSSL = False - - -def _validate_dependencies_met(): - """ - Verifies that PyOpenSSL's package-level dependencies have been met. - Throws `ImportError` if they are not met. - """ - # Method added in `cryptography==1.1`; not available in older versions - from cryptography.x509.extensions import Extensions - if getattr(Extensions, "get_extension_for_class", None) is None: - raise ImportError("'cryptography' module missing required functionality. " - "Try upgrading to v1.3.4 or newer.") - - # pyOpenSSL 0.14 and above use cryptography for OpenSSL bindings. The _x509 - # attribute is only present on those versions. - from OpenSSL.crypto import X509 - x509 = X509() - if getattr(x509, "_x509", None) is None: - raise ImportError("'pyOpenSSL' module missing required functionality. " - "Try upgrading to v0.14 or newer.") - - -def _dnsname_to_stdlib(name): - """ - Converts a dNSName SubjectAlternativeName field to the form used by the - standard library on the given Python version. - - Cryptography produces a dNSName as a unicode string that was idna-decoded - from ASCII bytes. We need to idna-encode that string to get it back, and - then on Python 3 we also need to convert to unicode via UTF-8 (the stdlib - uses PyUnicode_FromStringAndSize on it, which decodes via UTF-8). - - If the name cannot be idna-encoded then we return None signalling that - the name given should be skipped. - """ - def idna_encode(name): - """ - Borrowed wholesale from the Python Cryptography Project. It turns out - that we can't just safely call `idna.encode`: it can explode for - wildcard names. This avoids that problem. - """ - from pip._vendor import idna - - try: - for prefix in [u'*.', u'.']: - if name.startswith(prefix): - name = name[len(prefix):] - return prefix.encode('ascii') + idna.encode(name) - return idna.encode(name) - except idna.core.IDNAError: - return None - - name = idna_encode(name) - if name is None: - return None - elif sys.version_info >= (3, 0): - name = name.decode('utf-8') - return name - - -def get_subj_alt_name(peer_cert): - """ - Given an PyOpenSSL certificate, provides all the subject alternative names. - """ - # Pass the cert to cryptography, which has much better APIs for this. - if hasattr(peer_cert, "to_cryptography"): - cert = peer_cert.to_cryptography() - else: - # This is technically using private APIs, but should work across all - # relevant versions before PyOpenSSL got a proper API for this. - cert = _Certificate(openssl_backend, peer_cert._x509) - - # We want to find the SAN extension. Ask Cryptography to locate it (it's - # faster than looping in Python) - try: - ext = cert.extensions.get_extension_for_class( - x509.SubjectAlternativeName - ).value - except x509.ExtensionNotFound: - # No such extension, return the empty list. - return [] - except (x509.DuplicateExtension, UnsupportedExtension, - x509.UnsupportedGeneralNameType, UnicodeError) as e: - # A problem has been found with the quality of the certificate. Assume - # no SAN field is present. - log.warning( - "A problem was encountered with the certificate that prevented " - "urllib3 from finding the SubjectAlternativeName field. This can " - "affect certificate validation. The error was %s", - e, - ) - return [] - - # We want to return dNSName and iPAddress fields. We need to cast the IPs - # back to strings because the match_hostname function wants them as - # strings. - # Sadly the DNS names need to be idna encoded and then, on Python 3, UTF-8 - # decoded. This is pretty frustrating, but that's what the standard library - # does with certificates, and so we need to attempt to do the same. - # We also want to skip over names which cannot be idna encoded. - names = [ - ('DNS', name) for name in map(_dnsname_to_stdlib, ext.get_values_for_type(x509.DNSName)) - if name is not None - ] - names.extend( - ('IP Address', str(name)) - for name in ext.get_values_for_type(x509.IPAddress) - ) - - return names - - -class WrappedSocket(object): - '''API-compatibility wrapper for Python OpenSSL's Connection-class. - - Note: _makefile_refs, _drop() and _reuse() are needed for the garbage - collector of pypy. - ''' - - def __init__(self, connection, socket, suppress_ragged_eofs=True): - self.connection = connection - self.socket = socket - self.suppress_ragged_eofs = suppress_ragged_eofs - self._makefile_refs = 0 - self._closed = False - - def fileno(self): - return self.socket.fileno() - - # Copy-pasted from Python 3.5 source code - def _decref_socketios(self): - if self._makefile_refs > 0: - self._makefile_refs -= 1 - if self._closed: - self.close() - - def recv(self, *args, **kwargs): - try: - data = self.connection.recv(*args, **kwargs) - except OpenSSL.SSL.SysCallError as e: - if self.suppress_ragged_eofs and e.args == (-1, 'Unexpected EOF'): - return b'' - else: - raise SocketError(str(e)) - except OpenSSL.SSL.ZeroReturnError as e: - if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN: - return b'' - else: - raise - except OpenSSL.SSL.WantReadError: - if not util.wait_for_read(self.socket, self.socket.gettimeout()): - raise timeout('The read operation timed out') - else: - return self.recv(*args, **kwargs) - else: - return data - - def recv_into(self, *args, **kwargs): - try: - return self.connection.recv_into(*args, **kwargs) - except OpenSSL.SSL.SysCallError as e: - if self.suppress_ragged_eofs and e.args == (-1, 'Unexpected EOF'): - return 0 - else: - raise SocketError(str(e)) - except OpenSSL.SSL.ZeroReturnError as e: - if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN: - return 0 - else: - raise - except OpenSSL.SSL.WantReadError: - if not util.wait_for_read(self.socket, self.socket.gettimeout()): - raise timeout('The read operation timed out') - else: - return self.recv_into(*args, **kwargs) - - def settimeout(self, timeout): - return self.socket.settimeout(timeout) - - def _send_until_done(self, data): - while True: - try: - return self.connection.send(data) - except OpenSSL.SSL.WantWriteError: - if not util.wait_for_write(self.socket, self.socket.gettimeout()): - raise timeout() - continue - except OpenSSL.SSL.SysCallError as e: - raise SocketError(str(e)) - - def sendall(self, data): - total_sent = 0 - while total_sent < len(data): - sent = self._send_until_done(data[total_sent:total_sent + SSL_WRITE_BLOCKSIZE]) - total_sent += sent - - def shutdown(self): - # FIXME rethrow compatible exceptions should we ever use this - self.connection.shutdown() - - def close(self): - if self._makefile_refs < 1: - try: - self._closed = True - return self.connection.close() - except OpenSSL.SSL.Error: - return - else: - self._makefile_refs -= 1 - - def getpeercert(self, binary_form=False): - x509 = self.connection.get_peer_certificate() - - if not x509: - return x509 - - if binary_form: - return OpenSSL.crypto.dump_certificate( - OpenSSL.crypto.FILETYPE_ASN1, - x509) - - return { - 'subject': ( - (('commonName', x509.get_subject().CN),), - ), - 'subjectAltName': get_subj_alt_name(x509) - } - - def _reuse(self): - self._makefile_refs += 1 - - def _drop(self): - if self._makefile_refs < 1: - self.close() - else: - self._makefile_refs -= 1 - - -if _fileobject: # Platform-specific: Python 2 - def makefile(self, mode, bufsize=-1): - self._makefile_refs += 1 - return _fileobject(self, mode, bufsize, close=True) -else: # Platform-specific: Python 3 - makefile = backport_makefile - -WrappedSocket.makefile = makefile - - -class PyOpenSSLContext(object): - """ - I am a wrapper class for the PyOpenSSL ``Context`` object. I am responsible - for translating the interface of the standard library ``SSLContext`` object - to calls into PyOpenSSL. - """ - def __init__(self, protocol): - self.protocol = _openssl_versions[protocol] - self._ctx = OpenSSL.SSL.Context(self.protocol) - self._options = 0 - self.check_hostname = False - - @property - def options(self): - return self._options - - @options.setter - def options(self, value): - self._options = value - self._ctx.set_options(value) - - @property - def verify_mode(self): - return _openssl_to_stdlib_verify[self._ctx.get_verify_mode()] - - @verify_mode.setter - def verify_mode(self, value): - self._ctx.set_verify( - _stdlib_to_openssl_verify[value], - _verify_callback - ) - - def set_default_verify_paths(self): - self._ctx.set_default_verify_paths() - - def set_ciphers(self, ciphers): - if isinstance(ciphers, six.text_type): - ciphers = ciphers.encode('utf-8') - self._ctx.set_cipher_list(ciphers) - - def load_verify_locations(self, cafile=None, capath=None, cadata=None): - if cafile is not None: - cafile = cafile.encode('utf-8') - if capath is not None: - capath = capath.encode('utf-8') - self._ctx.load_verify_locations(cafile, capath) - if cadata is not None: - self._ctx.load_verify_locations(BytesIO(cadata)) - - def load_cert_chain(self, certfile, keyfile=None, password=None): - self._ctx.use_certificate_chain_file(certfile) - if password is not None: - self._ctx.set_passwd_cb(lambda max_length, prompt_twice, userdata: password) - self._ctx.use_privatekey_file(keyfile or certfile) - - def wrap_socket(self, sock, server_side=False, - do_handshake_on_connect=True, suppress_ragged_eofs=True, - server_hostname=None): - cnx = OpenSSL.SSL.Connection(self._ctx, sock) - - if isinstance(server_hostname, six.text_type): # Platform-specific: Python 3 - server_hostname = server_hostname.encode('utf-8') - - if server_hostname is not None: - cnx.set_tlsext_host_name(server_hostname) - - cnx.set_connect_state() - - while True: - try: - cnx.do_handshake() - except OpenSSL.SSL.WantReadError: - if not util.wait_for_read(sock, sock.gettimeout()): - raise timeout('select timed out') - continue - except OpenSSL.SSL.Error as e: - raise ssl.SSLError('bad handshake: %r' % e) - break - - return WrappedSocket(cnx, sock) - - -def _verify_callback(cnx, x509, err_no, err_depth, return_code): - return err_no == 0 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/securetransport.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/securetransport.py deleted file mode 100644 index 77cb59e..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/securetransport.py +++ /dev/null @@ -1,804 +0,0 @@ -""" -SecureTranport support for urllib3 via ctypes. - -This makes platform-native TLS available to urllib3 users on macOS without the -use of a compiler. This is an important feature because the Python Package -Index is moving to become a TLSv1.2-or-higher server, and the default OpenSSL -that ships with macOS is not capable of doing TLSv1.2. The only way to resolve -this is to give macOS users an alternative solution to the problem, and that -solution is to use SecureTransport. - -We use ctypes here because this solution must not require a compiler. That's -because pip is not allowed to require a compiler either. - -This is not intended to be a seriously long-term solution to this problem. -The hope is that PEP 543 will eventually solve this issue for us, at which -point we can retire this contrib module. But in the short term, we need to -solve the impending tire fire that is Python on Mac without this kind of -contrib module. So...here we are. - -To use this module, simply import and inject it:: - - import urllib3.contrib.securetransport - urllib3.contrib.securetransport.inject_into_urllib3() - -Happy TLSing! -""" -from __future__ import absolute_import - -import contextlib -import ctypes -import errno -import os.path -import shutil -import socket -import ssl -import threading -import weakref - -from .. import util -from ._securetransport.bindings import ( - Security, SecurityConst, CoreFoundation -) -from ._securetransport.low_level import ( - _assert_no_error, _cert_array_from_pem, _temporary_keychain, - _load_client_cert_chain -) - -try: # Platform-specific: Python 2 - from socket import _fileobject -except ImportError: # Platform-specific: Python 3 - _fileobject = None - from ..packages.backports.makefile import backport_makefile - -__all__ = ['inject_into_urllib3', 'extract_from_urllib3'] - -# SNI always works -HAS_SNI = True - -orig_util_HAS_SNI = util.HAS_SNI -orig_util_SSLContext = util.ssl_.SSLContext - -# This dictionary is used by the read callback to obtain a handle to the -# calling wrapped socket. This is a pretty silly approach, but for now it'll -# do. I feel like I should be able to smuggle a handle to the wrapped socket -# directly in the SSLConnectionRef, but for now this approach will work I -# guess. -# -# We need to lock around this structure for inserts, but we don't do it for -# reads/writes in the callbacks. The reasoning here goes as follows: -# -# 1. It is not possible to call into the callbacks before the dictionary is -# populated, so once in the callback the id must be in the dictionary. -# 2. The callbacks don't mutate the dictionary, they only read from it, and -# so cannot conflict with any of the insertions. -# -# This is good: if we had to lock in the callbacks we'd drastically slow down -# the performance of this code. -_connection_refs = weakref.WeakValueDictionary() -_connection_ref_lock = threading.Lock() - -# Limit writes to 16kB. This is OpenSSL's limit, but we'll cargo-cult it over -# for no better reason than we need *a* limit, and this one is right there. -SSL_WRITE_BLOCKSIZE = 16384 - -# This is our equivalent of util.ssl_.DEFAULT_CIPHERS, but expanded out to -# individual cipher suites. We need to do this because this is how -# SecureTransport wants them. -CIPHER_SUITES = [ - SecurityConst.TLS_AES_256_GCM_SHA384, - SecurityConst.TLS_CHACHA20_POLY1305_SHA256, - SecurityConst.TLS_AES_128_GCM_SHA256, - SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - SecurityConst.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, - SecurityConst.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, - SecurityConst.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, - SecurityConst.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, - SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, - SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, - SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, - SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - SecurityConst.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, - SecurityConst.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, - SecurityConst.TLS_DHE_RSA_WITH_AES_256_CBC_SHA, - SecurityConst.TLS_DHE_DSS_WITH_AES_256_CBC_SHA, - SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, - SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, - SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, - SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, - SecurityConst.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, - SecurityConst.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, - SecurityConst.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, - SecurityConst.TLS_DHE_DSS_WITH_AES_128_CBC_SHA, - SecurityConst.TLS_RSA_WITH_AES_256_GCM_SHA384, - SecurityConst.TLS_RSA_WITH_AES_128_GCM_SHA256, - SecurityConst.TLS_RSA_WITH_AES_256_CBC_SHA256, - SecurityConst.TLS_RSA_WITH_AES_128_CBC_SHA256, - SecurityConst.TLS_RSA_WITH_AES_256_CBC_SHA, - SecurityConst.TLS_RSA_WITH_AES_128_CBC_SHA, -] - -# Basically this is simple: for PROTOCOL_SSLv23 we turn it into a low of -# TLSv1 and a high of TLSv1.2. For everything else, we pin to that version. -_protocol_to_min_max = { - ssl.PROTOCOL_SSLv23: (SecurityConst.kTLSProtocol1, SecurityConst.kTLSProtocol12), -} - -if hasattr(ssl, "PROTOCOL_SSLv2"): - _protocol_to_min_max[ssl.PROTOCOL_SSLv2] = ( - SecurityConst.kSSLProtocol2, SecurityConst.kSSLProtocol2 - ) -if hasattr(ssl, "PROTOCOL_SSLv3"): - _protocol_to_min_max[ssl.PROTOCOL_SSLv3] = ( - SecurityConst.kSSLProtocol3, SecurityConst.kSSLProtocol3 - ) -if hasattr(ssl, "PROTOCOL_TLSv1"): - _protocol_to_min_max[ssl.PROTOCOL_TLSv1] = ( - SecurityConst.kTLSProtocol1, SecurityConst.kTLSProtocol1 - ) -if hasattr(ssl, "PROTOCOL_TLSv1_1"): - _protocol_to_min_max[ssl.PROTOCOL_TLSv1_1] = ( - SecurityConst.kTLSProtocol11, SecurityConst.kTLSProtocol11 - ) -if hasattr(ssl, "PROTOCOL_TLSv1_2"): - _protocol_to_min_max[ssl.PROTOCOL_TLSv1_2] = ( - SecurityConst.kTLSProtocol12, SecurityConst.kTLSProtocol12 - ) -if hasattr(ssl, "PROTOCOL_TLS"): - _protocol_to_min_max[ssl.PROTOCOL_TLS] = _protocol_to_min_max[ssl.PROTOCOL_SSLv23] - - -def inject_into_urllib3(): - """ - Monkey-patch urllib3 with SecureTransport-backed SSL-support. - """ - util.ssl_.SSLContext = SecureTransportContext - util.HAS_SNI = HAS_SNI - util.ssl_.HAS_SNI = HAS_SNI - util.IS_SECURETRANSPORT = True - util.ssl_.IS_SECURETRANSPORT = True - - -def extract_from_urllib3(): - """ - Undo monkey-patching by :func:`inject_into_urllib3`. - """ - util.ssl_.SSLContext = orig_util_SSLContext - util.HAS_SNI = orig_util_HAS_SNI - util.ssl_.HAS_SNI = orig_util_HAS_SNI - util.IS_SECURETRANSPORT = False - util.ssl_.IS_SECURETRANSPORT = False - - -def _read_callback(connection_id, data_buffer, data_length_pointer): - """ - SecureTransport read callback. This is called by ST to request that data - be returned from the socket. - """ - wrapped_socket = None - try: - wrapped_socket = _connection_refs.get(connection_id) - if wrapped_socket is None: - return SecurityConst.errSSLInternal - base_socket = wrapped_socket.socket - - requested_length = data_length_pointer[0] - - timeout = wrapped_socket.gettimeout() - error = None - read_count = 0 - - try: - while read_count < requested_length: - if timeout is None or timeout >= 0: - if not util.wait_for_read(base_socket, timeout): - raise socket.error(errno.EAGAIN, 'timed out') - - remaining = requested_length - read_count - buffer = (ctypes.c_char * remaining).from_address( - data_buffer + read_count - ) - chunk_size = base_socket.recv_into(buffer, remaining) - read_count += chunk_size - if not chunk_size: - if not read_count: - return SecurityConst.errSSLClosedGraceful - break - except (socket.error) as e: - error = e.errno - - if error is not None and error != errno.EAGAIN: - data_length_pointer[0] = read_count - if error == errno.ECONNRESET or error == errno.EPIPE: - return SecurityConst.errSSLClosedAbort - raise - - data_length_pointer[0] = read_count - - if read_count != requested_length: - return SecurityConst.errSSLWouldBlock - - return 0 - except Exception as e: - if wrapped_socket is not None: - wrapped_socket._exception = e - return SecurityConst.errSSLInternal - - -def _write_callback(connection_id, data_buffer, data_length_pointer): - """ - SecureTransport write callback. This is called by ST to request that data - actually be sent on the network. - """ - wrapped_socket = None - try: - wrapped_socket = _connection_refs.get(connection_id) - if wrapped_socket is None: - return SecurityConst.errSSLInternal - base_socket = wrapped_socket.socket - - bytes_to_write = data_length_pointer[0] - data = ctypes.string_at(data_buffer, bytes_to_write) - - timeout = wrapped_socket.gettimeout() - error = None - sent = 0 - - try: - while sent < bytes_to_write: - if timeout is None or timeout >= 0: - if not util.wait_for_write(base_socket, timeout): - raise socket.error(errno.EAGAIN, 'timed out') - chunk_sent = base_socket.send(data) - sent += chunk_sent - - # This has some needless copying here, but I'm not sure there's - # much value in optimising this data path. - data = data[chunk_sent:] - except (socket.error) as e: - error = e.errno - - if error is not None and error != errno.EAGAIN: - data_length_pointer[0] = sent - if error == errno.ECONNRESET or error == errno.EPIPE: - return SecurityConst.errSSLClosedAbort - raise - - data_length_pointer[0] = sent - - if sent != bytes_to_write: - return SecurityConst.errSSLWouldBlock - - return 0 - except Exception as e: - if wrapped_socket is not None: - wrapped_socket._exception = e - return SecurityConst.errSSLInternal - - -# We need to keep these two objects references alive: if they get GC'd while -# in use then SecureTransport could attempt to call a function that is in freed -# memory. That would be...uh...bad. Yeah, that's the word. Bad. -_read_callback_pointer = Security.SSLReadFunc(_read_callback) -_write_callback_pointer = Security.SSLWriteFunc(_write_callback) - - -class WrappedSocket(object): - """ - API-compatibility wrapper for Python's OpenSSL wrapped socket object. - - Note: _makefile_refs, _drop(), and _reuse() are needed for the garbage - collector of PyPy. - """ - def __init__(self, socket): - self.socket = socket - self.context = None - self._makefile_refs = 0 - self._closed = False - self._exception = None - self._keychain = None - self._keychain_dir = None - self._client_cert_chain = None - - # We save off the previously-configured timeout and then set it to - # zero. This is done because we use select and friends to handle the - # timeouts, but if we leave the timeout set on the lower socket then - # Python will "kindly" call select on that socket again for us. Avoid - # that by forcing the timeout to zero. - self._timeout = self.socket.gettimeout() - self.socket.settimeout(0) - - @contextlib.contextmanager - def _raise_on_error(self): - """ - A context manager that can be used to wrap calls that do I/O from - SecureTransport. If any of the I/O callbacks hit an exception, this - context manager will correctly propagate the exception after the fact. - This avoids silently swallowing those exceptions. - - It also correctly forces the socket closed. - """ - self._exception = None - - # We explicitly don't catch around this yield because in the unlikely - # event that an exception was hit in the block we don't want to swallow - # it. - yield - if self._exception is not None: - exception, self._exception = self._exception, None - self.close() - raise exception - - def _set_ciphers(self): - """ - Sets up the allowed ciphers. By default this matches the set in - util.ssl_.DEFAULT_CIPHERS, at least as supported by macOS. This is done - custom and doesn't allow changing at this time, mostly because parsing - OpenSSL cipher strings is going to be a freaking nightmare. - """ - ciphers = (Security.SSLCipherSuite * len(CIPHER_SUITES))(*CIPHER_SUITES) - result = Security.SSLSetEnabledCiphers( - self.context, ciphers, len(CIPHER_SUITES) - ) - _assert_no_error(result) - - def _custom_validate(self, verify, trust_bundle): - """ - Called when we have set custom validation. We do this in two cases: - first, when cert validation is entirely disabled; and second, when - using a custom trust DB. - """ - # If we disabled cert validation, just say: cool. - if not verify: - return - - # We want data in memory, so load it up. - if os.path.isfile(trust_bundle): - with open(trust_bundle, 'rb') as f: - trust_bundle = f.read() - - cert_array = None - trust = Security.SecTrustRef() - - try: - # Get a CFArray that contains the certs we want. - cert_array = _cert_array_from_pem(trust_bundle) - - # Ok, now the hard part. We want to get the SecTrustRef that ST has - # created for this connection, shove our CAs into it, tell ST to - # ignore everything else it knows, and then ask if it can build a - # chain. This is a buuuunch of code. - result = Security.SSLCopyPeerTrust( - self.context, ctypes.byref(trust) - ) - _assert_no_error(result) - if not trust: - raise ssl.SSLError("Failed to copy trust reference") - - result = Security.SecTrustSetAnchorCertificates(trust, cert_array) - _assert_no_error(result) - - result = Security.SecTrustSetAnchorCertificatesOnly(trust, True) - _assert_no_error(result) - - trust_result = Security.SecTrustResultType() - result = Security.SecTrustEvaluate( - trust, ctypes.byref(trust_result) - ) - _assert_no_error(result) - finally: - if trust: - CoreFoundation.CFRelease(trust) - - if cert_array is not None: - CoreFoundation.CFRelease(cert_array) - - # Ok, now we can look at what the result was. - successes = ( - SecurityConst.kSecTrustResultUnspecified, - SecurityConst.kSecTrustResultProceed - ) - if trust_result.value not in successes: - raise ssl.SSLError( - "certificate verify failed, error code: %d" % - trust_result.value - ) - - def handshake(self, - server_hostname, - verify, - trust_bundle, - min_version, - max_version, - client_cert, - client_key, - client_key_passphrase): - """ - Actually performs the TLS handshake. This is run automatically by - wrapped socket, and shouldn't be needed in user code. - """ - # First, we do the initial bits of connection setup. We need to create - # a context, set its I/O funcs, and set the connection reference. - self.context = Security.SSLCreateContext( - None, SecurityConst.kSSLClientSide, SecurityConst.kSSLStreamType - ) - result = Security.SSLSetIOFuncs( - self.context, _read_callback_pointer, _write_callback_pointer - ) - _assert_no_error(result) - - # Here we need to compute the handle to use. We do this by taking the - # id of self modulo 2**31 - 1. If this is already in the dictionary, we - # just keep incrementing by one until we find a free space. - with _connection_ref_lock: - handle = id(self) % 2147483647 - while handle in _connection_refs: - handle = (handle + 1) % 2147483647 - _connection_refs[handle] = self - - result = Security.SSLSetConnection(self.context, handle) - _assert_no_error(result) - - # If we have a server hostname, we should set that too. - if server_hostname: - if not isinstance(server_hostname, bytes): - server_hostname = server_hostname.encode('utf-8') - - result = Security.SSLSetPeerDomainName( - self.context, server_hostname, len(server_hostname) - ) - _assert_no_error(result) - - # Setup the ciphers. - self._set_ciphers() - - # Set the minimum and maximum TLS versions. - result = Security.SSLSetProtocolVersionMin(self.context, min_version) - _assert_no_error(result) - result = Security.SSLSetProtocolVersionMax(self.context, max_version) - _assert_no_error(result) - - # If there's a trust DB, we need to use it. We do that by telling - # SecureTransport to break on server auth. We also do that if we don't - # want to validate the certs at all: we just won't actually do any - # authing in that case. - if not verify or trust_bundle is not None: - result = Security.SSLSetSessionOption( - self.context, - SecurityConst.kSSLSessionOptionBreakOnServerAuth, - True - ) - _assert_no_error(result) - - # If there's a client cert, we need to use it. - if client_cert: - self._keychain, self._keychain_dir = _temporary_keychain() - self._client_cert_chain = _load_client_cert_chain( - self._keychain, client_cert, client_key - ) - result = Security.SSLSetCertificate( - self.context, self._client_cert_chain - ) - _assert_no_error(result) - - while True: - with self._raise_on_error(): - result = Security.SSLHandshake(self.context) - - if result == SecurityConst.errSSLWouldBlock: - raise socket.timeout("handshake timed out") - elif result == SecurityConst.errSSLServerAuthCompleted: - self._custom_validate(verify, trust_bundle) - continue - else: - _assert_no_error(result) - break - - def fileno(self): - return self.socket.fileno() - - # Copy-pasted from Python 3.5 source code - def _decref_socketios(self): - if self._makefile_refs > 0: - self._makefile_refs -= 1 - if self._closed: - self.close() - - def recv(self, bufsiz): - buffer = ctypes.create_string_buffer(bufsiz) - bytes_read = self.recv_into(buffer, bufsiz) - data = buffer[:bytes_read] - return data - - def recv_into(self, buffer, nbytes=None): - # Read short on EOF. - if self._closed: - return 0 - - if nbytes is None: - nbytes = len(buffer) - - buffer = (ctypes.c_char * nbytes).from_buffer(buffer) - processed_bytes = ctypes.c_size_t(0) - - with self._raise_on_error(): - result = Security.SSLRead( - self.context, buffer, nbytes, ctypes.byref(processed_bytes) - ) - - # There are some result codes that we want to treat as "not always - # errors". Specifically, those are errSSLWouldBlock, - # errSSLClosedGraceful, and errSSLClosedNoNotify. - if (result == SecurityConst.errSSLWouldBlock): - # If we didn't process any bytes, then this was just a time out. - # However, we can get errSSLWouldBlock in situations when we *did* - # read some data, and in those cases we should just read "short" - # and return. - if processed_bytes.value == 0: - # Timed out, no data read. - raise socket.timeout("recv timed out") - elif result in (SecurityConst.errSSLClosedGraceful, SecurityConst.errSSLClosedNoNotify): - # The remote peer has closed this connection. We should do so as - # well. Note that we don't actually return here because in - # principle this could actually be fired along with return data. - # It's unlikely though. - self.close() - else: - _assert_no_error(result) - - # Ok, we read and probably succeeded. We should return whatever data - # was actually read. - return processed_bytes.value - - def settimeout(self, timeout): - self._timeout = timeout - - def gettimeout(self): - return self._timeout - - def send(self, data): - processed_bytes = ctypes.c_size_t(0) - - with self._raise_on_error(): - result = Security.SSLWrite( - self.context, data, len(data), ctypes.byref(processed_bytes) - ) - - if result == SecurityConst.errSSLWouldBlock and processed_bytes.value == 0: - # Timed out - raise socket.timeout("send timed out") - else: - _assert_no_error(result) - - # We sent, and probably succeeded. Tell them how much we sent. - return processed_bytes.value - - def sendall(self, data): - total_sent = 0 - while total_sent < len(data): - sent = self.send(data[total_sent:total_sent + SSL_WRITE_BLOCKSIZE]) - total_sent += sent - - def shutdown(self): - with self._raise_on_error(): - Security.SSLClose(self.context) - - def close(self): - # TODO: should I do clean shutdown here? Do I have to? - if self._makefile_refs < 1: - self._closed = True - if self.context: - CoreFoundation.CFRelease(self.context) - self.context = None - if self._client_cert_chain: - CoreFoundation.CFRelease(self._client_cert_chain) - self._client_cert_chain = None - if self._keychain: - Security.SecKeychainDelete(self._keychain) - CoreFoundation.CFRelease(self._keychain) - shutil.rmtree(self._keychain_dir) - self._keychain = self._keychain_dir = None - return self.socket.close() - else: - self._makefile_refs -= 1 - - def getpeercert(self, binary_form=False): - # Urgh, annoying. - # - # Here's how we do this: - # - # 1. Call SSLCopyPeerTrust to get hold of the trust object for this - # connection. - # 2. Call SecTrustGetCertificateAtIndex for index 0 to get the leaf. - # 3. To get the CN, call SecCertificateCopyCommonName and process that - # string so that it's of the appropriate type. - # 4. To get the SAN, we need to do something a bit more complex: - # a. Call SecCertificateCopyValues to get the data, requesting - # kSecOIDSubjectAltName. - # b. Mess about with this dictionary to try to get the SANs out. - # - # This is gross. Really gross. It's going to be a few hundred LoC extra - # just to repeat something that SecureTransport can *already do*. So my - # operating assumption at this time is that what we want to do is - # instead to just flag to urllib3 that it shouldn't do its own hostname - # validation when using SecureTransport. - if not binary_form: - raise ValueError( - "SecureTransport only supports dumping binary certs" - ) - trust = Security.SecTrustRef() - certdata = None - der_bytes = None - - try: - # Grab the trust store. - result = Security.SSLCopyPeerTrust( - self.context, ctypes.byref(trust) - ) - _assert_no_error(result) - if not trust: - # Probably we haven't done the handshake yet. No biggie. - return None - - cert_count = Security.SecTrustGetCertificateCount(trust) - if not cert_count: - # Also a case that might happen if we haven't handshaked. - # Handshook? Handshaken? - return None - - leaf = Security.SecTrustGetCertificateAtIndex(trust, 0) - assert leaf - - # Ok, now we want the DER bytes. - certdata = Security.SecCertificateCopyData(leaf) - assert certdata - - data_length = CoreFoundation.CFDataGetLength(certdata) - data_buffer = CoreFoundation.CFDataGetBytePtr(certdata) - der_bytes = ctypes.string_at(data_buffer, data_length) - finally: - if certdata: - CoreFoundation.CFRelease(certdata) - if trust: - CoreFoundation.CFRelease(trust) - - return der_bytes - - def _reuse(self): - self._makefile_refs += 1 - - def _drop(self): - if self._makefile_refs < 1: - self.close() - else: - self._makefile_refs -= 1 - - -if _fileobject: # Platform-specific: Python 2 - def makefile(self, mode, bufsize=-1): - self._makefile_refs += 1 - return _fileobject(self, mode, bufsize, close=True) -else: # Platform-specific: Python 3 - def makefile(self, mode="r", buffering=None, *args, **kwargs): - # We disable buffering with SecureTransport because it conflicts with - # the buffering that ST does internally (see issue #1153 for more). - buffering = 0 - return backport_makefile(self, mode, buffering, *args, **kwargs) - -WrappedSocket.makefile = makefile - - -class SecureTransportContext(object): - """ - I am a wrapper class for the SecureTransport library, to translate the - interface of the standard library ``SSLContext`` object to calls into - SecureTransport. - """ - def __init__(self, protocol): - self._min_version, self._max_version = _protocol_to_min_max[protocol] - self._options = 0 - self._verify = False - self._trust_bundle = None - self._client_cert = None - self._client_key = None - self._client_key_passphrase = None - - @property - def check_hostname(self): - """ - SecureTransport cannot have its hostname checking disabled. For more, - see the comment on getpeercert() in this file. - """ - return True - - @check_hostname.setter - def check_hostname(self, value): - """ - SecureTransport cannot have its hostname checking disabled. For more, - see the comment on getpeercert() in this file. - """ - pass - - @property - def options(self): - # TODO: Well, crap. - # - # So this is the bit of the code that is the most likely to cause us - # trouble. Essentially we need to enumerate all of the SSL options that - # users might want to use and try to see if we can sensibly translate - # them, or whether we should just ignore them. - return self._options - - @options.setter - def options(self, value): - # TODO: Update in line with above. - self._options = value - - @property - def verify_mode(self): - return ssl.CERT_REQUIRED if self._verify else ssl.CERT_NONE - - @verify_mode.setter - def verify_mode(self, value): - self._verify = True if value == ssl.CERT_REQUIRED else False - - def set_default_verify_paths(self): - # So, this has to do something a bit weird. Specifically, what it does - # is nothing. - # - # This means that, if we had previously had load_verify_locations - # called, this does not undo that. We need to do that because it turns - # out that the rest of the urllib3 code will attempt to load the - # default verify paths if it hasn't been told about any paths, even if - # the context itself was sometime earlier. We resolve that by just - # ignoring it. - pass - - def load_default_certs(self): - return self.set_default_verify_paths() - - def set_ciphers(self, ciphers): - # For now, we just require the default cipher string. - if ciphers != util.ssl_.DEFAULT_CIPHERS: - raise ValueError( - "SecureTransport doesn't support custom cipher strings" - ) - - def load_verify_locations(self, cafile=None, capath=None, cadata=None): - # OK, we only really support cadata and cafile. - if capath is not None: - raise ValueError( - "SecureTransport does not support cert directories" - ) - - self._trust_bundle = cafile or cadata - - def load_cert_chain(self, certfile, keyfile=None, password=None): - self._client_cert = certfile - self._client_key = keyfile - self._client_cert_passphrase = password - - def wrap_socket(self, sock, server_side=False, - do_handshake_on_connect=True, suppress_ragged_eofs=True, - server_hostname=None): - # So, what do we do here? Firstly, we assert some properties. This is a - # stripped down shim, so there is some functionality we don't support. - # See PEP 543 for the real deal. - assert not server_side - assert do_handshake_on_connect - assert suppress_ragged_eofs - - # Ok, we're good to go. Now we want to create the wrapped socket object - # and store it in the appropriate place. - wrapped_socket = WrappedSocket(sock) - - # Now we can handshake - wrapped_socket.handshake( - server_hostname, self._verify, self._trust_bundle, - self._min_version, self._max_version, self._client_cert, - self._client_key, self._client_key_passphrase - ) - return wrapped_socket diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/socks.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/socks.py deleted file mode 100644 index 811e312..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/contrib/socks.py +++ /dev/null @@ -1,192 +0,0 @@ -# -*- coding: utf-8 -*- -""" -This module contains provisional support for SOCKS proxies from within -urllib3. This module supports SOCKS4 (specifically the SOCKS4A variant) and -SOCKS5. To enable its functionality, either install PySocks or install this -module with the ``socks`` extra. - -The SOCKS implementation supports the full range of urllib3 features. It also -supports the following SOCKS features: - -- SOCKS4 -- SOCKS4a -- SOCKS5 -- Usernames and passwords for the SOCKS proxy - -Known Limitations: - -- Currently PySocks does not support contacting remote websites via literal - IPv6 addresses. Any such connection attempt will fail. You must use a domain - name. -- Currently PySocks does not support IPv6 connections to the SOCKS proxy. Any - such connection attempt will fail. -""" -from __future__ import absolute_import - -try: - import socks -except ImportError: - import warnings - from ..exceptions import DependencyWarning - - warnings.warn(( - 'SOCKS support in urllib3 requires the installation of optional ' - 'dependencies: specifically, PySocks. For more information, see ' - 'https://urllib3.readthedocs.io/en/latest/contrib.html#socks-proxies' - ), - DependencyWarning - ) - raise - -from socket import error as SocketError, timeout as SocketTimeout - -from ..connection import ( - HTTPConnection, HTTPSConnection -) -from ..connectionpool import ( - HTTPConnectionPool, HTTPSConnectionPool -) -from ..exceptions import ConnectTimeoutError, NewConnectionError -from ..poolmanager import PoolManager -from ..util.url import parse_url - -try: - import ssl -except ImportError: - ssl = None - - -class SOCKSConnection(HTTPConnection): - """ - A plain-text HTTP connection that connects via a SOCKS proxy. - """ - def __init__(self, *args, **kwargs): - self._socks_options = kwargs.pop('_socks_options') - super(SOCKSConnection, self).__init__(*args, **kwargs) - - def _new_conn(self): - """ - Establish a new connection via the SOCKS proxy. - """ - extra_kw = {} - if self.source_address: - extra_kw['source_address'] = self.source_address - - if self.socket_options: - extra_kw['socket_options'] = self.socket_options - - try: - conn = socks.create_connection( - (self.host, self.port), - proxy_type=self._socks_options['socks_version'], - proxy_addr=self._socks_options['proxy_host'], - proxy_port=self._socks_options['proxy_port'], - proxy_username=self._socks_options['username'], - proxy_password=self._socks_options['password'], - proxy_rdns=self._socks_options['rdns'], - timeout=self.timeout, - **extra_kw - ) - - except SocketTimeout as e: - raise ConnectTimeoutError( - self, "Connection to %s timed out. (connect timeout=%s)" % - (self.host, self.timeout)) - - except socks.ProxyError as e: - # This is fragile as hell, but it seems to be the only way to raise - # useful errors here. - if e.socket_err: - error = e.socket_err - if isinstance(error, SocketTimeout): - raise ConnectTimeoutError( - self, - "Connection to %s timed out. (connect timeout=%s)" % - (self.host, self.timeout) - ) - else: - raise NewConnectionError( - self, - "Failed to establish a new connection: %s" % error - ) - else: - raise NewConnectionError( - self, - "Failed to establish a new connection: %s" % e - ) - - except SocketError as e: # Defensive: PySocks should catch all these. - raise NewConnectionError( - self, "Failed to establish a new connection: %s" % e) - - return conn - - -# We don't need to duplicate the Verified/Unverified distinction from -# urllib3/connection.py here because the HTTPSConnection will already have been -# correctly set to either the Verified or Unverified form by that module. This -# means the SOCKSHTTPSConnection will automatically be the correct type. -class SOCKSHTTPSConnection(SOCKSConnection, HTTPSConnection): - pass - - -class SOCKSHTTPConnectionPool(HTTPConnectionPool): - ConnectionCls = SOCKSConnection - - -class SOCKSHTTPSConnectionPool(HTTPSConnectionPool): - ConnectionCls = SOCKSHTTPSConnection - - -class SOCKSProxyManager(PoolManager): - """ - A version of the urllib3 ProxyManager that routes connections via the - defined SOCKS proxy. - """ - pool_classes_by_scheme = { - 'http': SOCKSHTTPConnectionPool, - 'https': SOCKSHTTPSConnectionPool, - } - - def __init__(self, proxy_url, username=None, password=None, - num_pools=10, headers=None, **connection_pool_kw): - parsed = parse_url(proxy_url) - - if username is None and password is None and parsed.auth is not None: - split = parsed.auth.split(':') - if len(split) == 2: - username, password = split - if parsed.scheme == 'socks5': - socks_version = socks.PROXY_TYPE_SOCKS5 - rdns = False - elif parsed.scheme == 'socks5h': - socks_version = socks.PROXY_TYPE_SOCKS5 - rdns = True - elif parsed.scheme == 'socks4': - socks_version = socks.PROXY_TYPE_SOCKS4 - rdns = False - elif parsed.scheme == 'socks4a': - socks_version = socks.PROXY_TYPE_SOCKS4 - rdns = True - else: - raise ValueError( - "Unable to determine SOCKS version from %s" % proxy_url - ) - - self.proxy_url = proxy_url - - socks_options = { - 'socks_version': socks_version, - 'proxy_host': parsed.host, - 'proxy_port': parsed.port, - 'username': username, - 'password': password, - 'rdns': rdns - } - connection_pool_kw['_socks_options'] = socks_options - - super(SOCKSProxyManager, self).__init__( - num_pools, headers, **connection_pool_kw - ) - - self.pool_classes_by_scheme = SOCKSProxyManager.pool_classes_by_scheme diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/exceptions.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/exceptions.py deleted file mode 100644 index 7bbaa98..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/exceptions.py +++ /dev/null @@ -1,246 +0,0 @@ -from __future__ import absolute_import -from .packages.six.moves.http_client import ( - IncompleteRead as httplib_IncompleteRead -) -# Base Exceptions - - -class HTTPError(Exception): - "Base exception used by this module." - pass - - -class HTTPWarning(Warning): - "Base warning used by this module." - pass - - -class PoolError(HTTPError): - "Base exception for errors caused within a pool." - def __init__(self, pool, message): - self.pool = pool - HTTPError.__init__(self, "%s: %s" % (pool, message)) - - def __reduce__(self): - # For pickling purposes. - return self.__class__, (None, None) - - -class RequestError(PoolError): - "Base exception for PoolErrors that have associated URLs." - def __init__(self, pool, url, message): - self.url = url - PoolError.__init__(self, pool, message) - - def __reduce__(self): - # For pickling purposes. - return self.__class__, (None, self.url, None) - - -class SSLError(HTTPError): - "Raised when SSL certificate fails in an HTTPS connection." - pass - - -class ProxyError(HTTPError): - "Raised when the connection to a proxy fails." - pass - - -class DecodeError(HTTPError): - "Raised when automatic decoding based on Content-Type fails." - pass - - -class ProtocolError(HTTPError): - "Raised when something unexpected happens mid-request/response." - pass - - -#: Renamed to ProtocolError but aliased for backwards compatibility. -ConnectionError = ProtocolError - - -# Leaf Exceptions - -class MaxRetryError(RequestError): - """Raised when the maximum number of retries is exceeded. - - :param pool: The connection pool - :type pool: :class:`~urllib3.connectionpool.HTTPConnectionPool` - :param string url: The requested Url - :param exceptions.Exception reason: The underlying error - - """ - - def __init__(self, pool, url, reason=None): - self.reason = reason - - message = "Max retries exceeded with url: %s (Caused by %r)" % ( - url, reason) - - RequestError.__init__(self, pool, url, message) - - -class HostChangedError(RequestError): - "Raised when an existing pool gets a request for a foreign host." - - def __init__(self, pool, url, retries=3): - message = "Tried to open a foreign host with url: %s" % url - RequestError.__init__(self, pool, url, message) - self.retries = retries - - -class TimeoutStateError(HTTPError): - """ Raised when passing an invalid state to a timeout """ - pass - - -class TimeoutError(HTTPError): - """ Raised when a socket timeout error occurs. - - Catching this error will catch both :exc:`ReadTimeoutErrors - <ReadTimeoutError>` and :exc:`ConnectTimeoutErrors <ConnectTimeoutError>`. - """ - pass - - -class ReadTimeoutError(TimeoutError, RequestError): - "Raised when a socket timeout occurs while receiving data from a server" - pass - - -# This timeout error does not have a URL attached and needs to inherit from the -# base HTTPError -class ConnectTimeoutError(TimeoutError): - "Raised when a socket timeout occurs while connecting to a server" - pass - - -class NewConnectionError(ConnectTimeoutError, PoolError): - "Raised when we fail to establish a new connection. Usually ECONNREFUSED." - pass - - -class EmptyPoolError(PoolError): - "Raised when a pool runs out of connections and no more are allowed." - pass - - -class ClosedPoolError(PoolError): - "Raised when a request enters a pool after the pool has been closed." - pass - - -class LocationValueError(ValueError, HTTPError): - "Raised when there is something wrong with a given URL input." - pass - - -class LocationParseError(LocationValueError): - "Raised when get_host or similar fails to parse the URL input." - - def __init__(self, location): - message = "Failed to parse: %s" % location - HTTPError.__init__(self, message) - - self.location = location - - -class ResponseError(HTTPError): - "Used as a container for an error reason supplied in a MaxRetryError." - GENERIC_ERROR = 'too many error responses' - SPECIFIC_ERROR = 'too many {status_code} error responses' - - -class SecurityWarning(HTTPWarning): - "Warned when performing security reducing actions" - pass - - -class SubjectAltNameWarning(SecurityWarning): - "Warned when connecting to a host with a certificate missing a SAN." - pass - - -class InsecureRequestWarning(SecurityWarning): - "Warned when making an unverified HTTPS request." - pass - - -class SystemTimeWarning(SecurityWarning): - "Warned when system time is suspected to be wrong" - pass - - -class InsecurePlatformWarning(SecurityWarning): - "Warned when certain SSL configuration is not available on a platform." - pass - - -class SNIMissingWarning(HTTPWarning): - "Warned when making a HTTPS request without SNI available." - pass - - -class DependencyWarning(HTTPWarning): - """ - Warned when an attempt is made to import a module with missing optional - dependencies. - """ - pass - - -class ResponseNotChunked(ProtocolError, ValueError): - "Response needs to be chunked in order to read it as chunks." - pass - - -class BodyNotHttplibCompatible(HTTPError): - """ - Body should be httplib.HTTPResponse like (have an fp attribute which - returns raw chunks) for read_chunked(). - """ - pass - - -class IncompleteRead(HTTPError, httplib_IncompleteRead): - """ - Response length doesn't match expected Content-Length - - Subclass of http_client.IncompleteRead to allow int value - for `partial` to avoid creating large objects on streamed - reads. - """ - def __init__(self, partial, expected): - super(IncompleteRead, self).__init__(partial, expected) - - def __repr__(self): - return ('IncompleteRead(%i bytes read, ' - '%i more expected)' % (self.partial, self.expected)) - - -class InvalidHeader(HTTPError): - "The header provided was somehow invalid." - pass - - -class ProxySchemeUnknown(AssertionError, ValueError): - "ProxyManager does not support the supplied scheme" - # TODO(t-8ch): Stop inheriting from AssertionError in v2.0. - - def __init__(self, scheme): - message = "Not supported proxy scheme %s" % scheme - super(ProxySchemeUnknown, self).__init__(message) - - -class HeaderParsingError(HTTPError): - "Raised by assert_header_parsing, but we convert it to a log.warning statement." - def __init__(self, defects, unparsed_data): - message = '%s, unparsed data: %r' % (defects or 'Unknown', unparsed_data) - super(HeaderParsingError, self).__init__(message) - - -class UnrewindableBodyError(HTTPError): - "urllib3 encountered an error when trying to rewind a body" - pass diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/fields.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/fields.py deleted file mode 100644 index 37fe64a..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/fields.py +++ /dev/null @@ -1,178 +0,0 @@ -from __future__ import absolute_import -import email.utils -import mimetypes - -from .packages import six - - -def guess_content_type(filename, default='application/octet-stream'): - """ - Guess the "Content-Type" of a file. - - :param filename: - The filename to guess the "Content-Type" of using :mod:`mimetypes`. - :param default: - If no "Content-Type" can be guessed, default to `default`. - """ - if filename: - return mimetypes.guess_type(filename)[0] or default - return default - - -def format_header_param(name, value): - """ - Helper function to format and quote a single header parameter. - - Particularly useful for header parameters which might contain - non-ASCII values, like file names. This follows RFC 2231, as - suggested by RFC 2388 Section 4.4. - - :param name: - The name of the parameter, a string expected to be ASCII only. - :param value: - The value of the parameter, provided as a unicode string. - """ - if not any(ch in value for ch in '"\\\r\n'): - result = '%s="%s"' % (name, value) - try: - result.encode('ascii') - except (UnicodeEncodeError, UnicodeDecodeError): - pass - else: - return result - if not six.PY3 and isinstance(value, six.text_type): # Python 2: - value = value.encode('utf-8') - value = email.utils.encode_rfc2231(value, 'utf-8') - value = '%s*=%s' % (name, value) - return value - - -class RequestField(object): - """ - A data container for request body parameters. - - :param name: - The name of this request field. - :param data: - The data/value body. - :param filename: - An optional filename of the request field. - :param headers: - An optional dict-like object of headers to initially use for the field. - """ - def __init__(self, name, data, filename=None, headers=None): - self._name = name - self._filename = filename - self.data = data - self.headers = {} - if headers: - self.headers = dict(headers) - - @classmethod - def from_tuples(cls, fieldname, value): - """ - A :class:`~urllib3.fields.RequestField` factory from old-style tuple parameters. - - Supports constructing :class:`~urllib3.fields.RequestField` from - parameter of key/value strings AND key/filetuple. A filetuple is a - (filename, data, MIME type) tuple where the MIME type is optional. - For example:: - - 'foo': 'bar', - 'fakefile': ('foofile.txt', 'contents of foofile'), - 'realfile': ('barfile.txt', open('realfile').read()), - 'typedfile': ('bazfile.bin', open('bazfile').read(), 'image/jpeg'), - 'nonamefile': 'contents of nonamefile field', - - Field names and filenames must be unicode. - """ - if isinstance(value, tuple): - if len(value) == 3: - filename, data, content_type = value - else: - filename, data = value - content_type = guess_content_type(filename) - else: - filename = None - content_type = None - data = value - - request_param = cls(fieldname, data, filename=filename) - request_param.make_multipart(content_type=content_type) - - return request_param - - def _render_part(self, name, value): - """ - Overridable helper function to format a single header parameter. - - :param name: - The name of the parameter, a string expected to be ASCII only. - :param value: - The value of the parameter, provided as a unicode string. - """ - return format_header_param(name, value) - - def _render_parts(self, header_parts): - """ - Helper function to format and quote a single header. - - Useful for single headers that are composed of multiple items. E.g., - 'Content-Disposition' fields. - - :param header_parts: - A sequence of (k, v) tuples or a :class:`dict` of (k, v) to format - as `k1="v1"; k2="v2"; ...`. - """ - parts = [] - iterable = header_parts - if isinstance(header_parts, dict): - iterable = header_parts.items() - - for name, value in iterable: - if value is not None: - parts.append(self._render_part(name, value)) - - return '; '.join(parts) - - def render_headers(self): - """ - Renders the headers for this request field. - """ - lines = [] - - sort_keys = ['Content-Disposition', 'Content-Type', 'Content-Location'] - for sort_key in sort_keys: - if self.headers.get(sort_key, False): - lines.append('%s: %s' % (sort_key, self.headers[sort_key])) - - for header_name, header_value in self.headers.items(): - if header_name not in sort_keys: - if header_value: - lines.append('%s: %s' % (header_name, header_value)) - - lines.append('\r\n') - return '\r\n'.join(lines) - - def make_multipart(self, content_disposition=None, content_type=None, - content_location=None): - """ - Makes this request field into a multipart request field. - - This method overrides "Content-Disposition", "Content-Type" and - "Content-Location" headers to the request parameter. - - :param content_type: - The 'Content-Type' of the request body. - :param content_location: - The 'Content-Location' of the request body. - - """ - self.headers['Content-Disposition'] = content_disposition or 'form-data' - self.headers['Content-Disposition'] += '; '.join([ - '', self._render_parts( - (('name', self._name), ('filename', self._filename)) - ) - ]) - self.headers['Content-Type'] = content_type - self.headers['Content-Location'] = content_location diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/filepost.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/filepost.py deleted file mode 100644 index 78f1e19..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/filepost.py +++ /dev/null @@ -1,98 +0,0 @@ -from __future__ import absolute_import -import binascii -import codecs -import os - -from io import BytesIO - -from .packages import six -from .packages.six import b -from .fields import RequestField - -writer = codecs.lookup('utf-8')[3] - - -def choose_boundary(): - """ - Our embarrassingly-simple replacement for mimetools.choose_boundary. - """ - boundary = binascii.hexlify(os.urandom(16)) - if six.PY3: - boundary = boundary.decode('ascii') - return boundary - - -def iter_field_objects(fields): - """ - Iterate over fields. - - Supports list of (k, v) tuples and dicts, and lists of - :class:`~urllib3.fields.RequestField`. - - """ - if isinstance(fields, dict): - i = six.iteritems(fields) - else: - i = iter(fields) - - for field in i: - if isinstance(field, RequestField): - yield field - else: - yield RequestField.from_tuples(*field) - - -def iter_fields(fields): - """ - .. deprecated:: 1.6 - - Iterate over fields. - - The addition of :class:`~urllib3.fields.RequestField` makes this function - obsolete. Instead, use :func:`iter_field_objects`, which returns - :class:`~urllib3.fields.RequestField` objects. - - Supports list of (k, v) tuples and dicts. - """ - if isinstance(fields, dict): - return ((k, v) for k, v in six.iteritems(fields)) - - return ((k, v) for k, v in fields) - - -def encode_multipart_formdata(fields, boundary=None): - """ - Encode a dictionary of ``fields`` using the multipart/form-data MIME format. - - :param fields: - Dictionary of fields or list of (key, :class:`~urllib3.fields.RequestField`). - - :param boundary: - If not specified, then a random boundary will be generated using - :func:`urllib3.filepost.choose_boundary`. - """ - body = BytesIO() - if boundary is None: - boundary = choose_boundary() - - for field in iter_field_objects(fields): - body.write(b('--%s\r\n' % (boundary))) - - writer(body).write(field.render_headers()) - data = field.data - - if isinstance(data, int): - data = str(data) # Backwards compatibility - - if isinstance(data, six.text_type): - writer(body).write(data) - else: - body.write(data) - - body.write(b'\r\n') - - body.write(b('--%s--\r\n' % (boundary))) - - content_type = str('multipart/form-data; boundary=%s' % boundary) - - return body.getvalue(), content_type diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/__init__.py deleted file mode 100644 index 170e974..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from __future__ import absolute_import - -from . import ssl_match_hostname - -__all__ = ('ssl_match_hostname', ) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py deleted file mode 100644 index 740db37..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py +++ /dev/null @@ -1,53 +0,0 @@ -# -*- coding: utf-8 -*- -""" -backports.makefile -~~~~~~~~~~~~~~~~~~ - -Backports the Python 3 ``socket.makefile`` method for use with anything that -wants to create a "fake" socket object. -""" -import io - -from socket import SocketIO - - -def backport_makefile(self, mode="r", buffering=None, encoding=None, - errors=None, newline=None): - """ - Backport of ``socket.makefile`` from Python 3.5. - """ - if not set(mode) <= {"r", "w", "b"}: - raise ValueError( - "invalid mode %r (only r, w, b allowed)" % (mode,) - ) - writing = "w" in mode - reading = "r" in mode or not writing - assert reading or writing - binary = "b" in mode - rawmode = "" - if reading: - rawmode += "r" - if writing: - rawmode += "w" - raw = SocketIO(self, rawmode) - self._makefile_refs += 1 - if buffering is None: - buffering = -1 - if buffering < 0: - buffering = io.DEFAULT_BUFFER_SIZE - if buffering == 0: - if not binary: - raise ValueError("unbuffered streams must be binary") - return raw - if reading and writing: - buffer = io.BufferedRWPair(raw, raw, buffering) - elif reading: - buffer = io.BufferedReader(raw, buffering) - else: - assert writing - buffer = io.BufferedWriter(raw, buffering) - if binary: - return buffer - text = io.TextIOWrapper(buffer, encoding, errors, newline) - text.mode = mode - return text diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/six.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/six.py deleted file mode 100644 index 190c023..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/six.py +++ /dev/null @@ -1,868 +0,0 @@ -"""Utilities for writing code that runs on Python 2 and 3""" - -# Copyright (c) 2010-2015 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. - -from __future__ import absolute_import - -import functools -import itertools -import operator -import sys -import types - -__author__ = "Benjamin Peterson <benjamin@python.org>" -__version__ = "1.10.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("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_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("email_mime_base", "email.MIMEBase", "email.mime.base"), - 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("urlencode", "urllib", "urllib.parse"), - MovedAttribute("splitquery", "urllib", "urllib.parse"), - MovedAttribute("splittag", "urllib", "urllib.parse"), - MovedAttribute("splituser", "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"), -] -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): - if value is None: - value = tp() - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - -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): - raise tp, value, tb -""") - - -if sys.version_info[:2] == (3, 2): - exec_("""def raise_from(value, from_value): - if from_value is None: - raise value - raise value from from_value -""") -elif sys.version_info[:2] > (3, 2): - exec_("""def raise_from(value, from_value): - raise value from from_value -""") -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(meta): - - def __new__(cls, name, this_bases, d): - return meta(name, bases, d) - 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) - return metaclass(cls.__name__, cls.__bases__, orig_vars) - return wrapper - - -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) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py deleted file mode 100644 index d6594eb..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -import sys - -try: - # Our match_hostname function is the same as 3.5's, so we only want to - # import the match_hostname function if it's at least that good. - if sys.version_info < (3, 5): - raise ImportError("Fallback to vendored code") - - from ssl import CertificateError, match_hostname -except ImportError: - try: - # Backport of the function from a pypi module - from backports.ssl_match_hostname import CertificateError, match_hostname - except ImportError: - # Our vendored copy - from ._implementation import CertificateError, match_hostname - -# Not needed, but documenting what we provide. -__all__ = ('CertificateError', 'match_hostname') diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py deleted file mode 100644 index 970cf65..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py +++ /dev/null @@ -1,156 +0,0 @@ -"""The match_hostname() function from Python 3.3.3, essential when using SSL.""" - -# Note: This file is under the PSF license as the code comes from the python -# stdlib. http://docs.python.org/3/license.html - -import re -import sys - -# ipaddress has been backported to 2.6+ in pypi. If it is installed on the -# system, use it to handle IPAddress ServerAltnames (this was added in -# python-3.5) otherwise only do DNS matching. This allows -# backports.ssl_match_hostname to continue to be used in Python 2.7. -try: - from pip._vendor import ipaddress -except ImportError: - ipaddress = None - -__version__ = '3.5.0.1' - - -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 - - # Ported from python3-syntax: - # leftmost, *remainder = dn.split(r'.') - parts = dn.split(r'.') - leftmost = parts[0] - remainder = 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 _to_unicode(obj): - if isinstance(obj, str) and sys.version_info < (3,): - obj = unicode(obj, encoding='ascii', errors='strict') - return obj - -def _ipaddress_match(ipname, host_ip): - """Exact matching of IP addresses. - - RFC 6125 explicitly doesn't define an algorithm for this - (section 1.7.2 - "Out of Scope"). - """ - # OpenSSL may add a trailing newline to a subjectAltName's IP address - # Divergence from upstream: ipaddress can't handle byte str - ip = ipaddress.ip_address(_to_unicode(ipname).rstrip()) - return ip == host_ip - - -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") - try: - # Divergence from upstream: ipaddress can't handle byte str - host_ip = ipaddress.ip_address(_to_unicode(hostname)) - except ValueError: - # Not an IP address (common case) - host_ip = None - except UnicodeError: - # Divergence from upstream: Have to deal with ipaddress not taking - # byte strings. addresses should be all ascii, so we consider it not - # an ipaddress in this case - host_ip = None - except AttributeError: - # Divergence from upstream: Make ipaddress library optional - if ipaddress is None: - host_ip = None - else: - raise - dnsnames = [] - san = cert.get('subjectAltName', ()) - for key, value in san: - if key == 'DNS': - if host_ip is None and _dnsname_match(value, hostname): - return - dnsnames.append(value) - elif key == 'IP Address': - if host_ip is not None and _ipaddress_match(value, host_ip): - 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") diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/poolmanager.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/poolmanager.py deleted file mode 100644 index fe5491c..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/poolmanager.py +++ /dev/null @@ -1,450 +0,0 @@ -from __future__ import absolute_import -import collections -import functools -import logging - -from ._collections import RecentlyUsedContainer -from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool -from .connectionpool import port_by_scheme -from .exceptions import LocationValueError, MaxRetryError, ProxySchemeUnknown -from .packages.six.moves.urllib.parse import urljoin -from .request import RequestMethods -from .util.url import parse_url -from .util.retry import Retry - - -__all__ = ['PoolManager', 'ProxyManager', 'proxy_from_url'] - - -log = logging.getLogger(__name__) - -SSL_KEYWORDS = ('key_file', 'cert_file', 'cert_reqs', 'ca_certs', - 'ssl_version', 'ca_cert_dir', 'ssl_context') - -# All known keyword arguments that could be provided to the pool manager, its -# pools, or the underlying connections. This is used to construct a pool key. -_key_fields = ( - 'key_scheme', # str - 'key_host', # str - 'key_port', # int - 'key_timeout', # int or float or Timeout - 'key_retries', # int or Retry - 'key_strict', # bool - 'key_block', # bool - 'key_source_address', # str - 'key_key_file', # str - 'key_cert_file', # str - 'key_cert_reqs', # str - 'key_ca_certs', # str - 'key_ssl_version', # str - 'key_ca_cert_dir', # str - 'key_ssl_context', # instance of ssl.SSLContext or urllib3.util.ssl_.SSLContext - 'key_maxsize', # int - 'key_headers', # dict - 'key__proxy', # parsed proxy url - 'key__proxy_headers', # dict - 'key_socket_options', # list of (level (int), optname (int), value (int or str)) tuples - 'key__socks_options', # dict - 'key_assert_hostname', # bool or string - 'key_assert_fingerprint', # str - 'key_server_hostname', #str -) - -#: The namedtuple class used to construct keys for the connection pool. -#: All custom key schemes should include the fields in this key at a minimum. -PoolKey = collections.namedtuple('PoolKey', _key_fields) - - -def _default_key_normalizer(key_class, request_context): - """ - Create a pool key out of a request context dictionary. - - According to RFC 3986, both the scheme and host are case-insensitive. - Therefore, this function normalizes both before constructing the pool - key for an HTTPS request. If you wish to change this behaviour, provide - alternate callables to ``key_fn_by_scheme``. - - :param key_class: - The class to use when constructing the key. This should be a namedtuple - with the ``scheme`` and ``host`` keys at a minimum. - :type key_class: namedtuple - :param request_context: - A dictionary-like object that contain the context for a request. - :type request_context: dict - - :return: A namedtuple that can be used as a connection pool key. - :rtype: PoolKey - """ - # Since we mutate the dictionary, make a copy first - context = request_context.copy() - context['scheme'] = context['scheme'].lower() - context['host'] = context['host'].lower() - - # These are both dictionaries and need to be transformed into frozensets - for key in ('headers', '_proxy_headers', '_socks_options'): - if key in context and context[key] is not None: - context[key] = frozenset(context[key].items()) - - # The socket_options key may be a list and needs to be transformed into a - # tuple. - socket_opts = context.get('socket_options') - if socket_opts is not None: - context['socket_options'] = tuple(socket_opts) - - # Map the kwargs to the names in the namedtuple - this is necessary since - # namedtuples can't have fields starting with '_'. - for key in list(context.keys()): - context['key_' + key] = context.pop(key) - - # Default to ``None`` for keys missing from the context - for field in key_class._fields: - if field not in context: - context[field] = None - - return key_class(**context) - - -#: A dictionary that maps a scheme to a callable that creates a pool key. -#: This can be used to alter the way pool keys are constructed, if desired. -#: Each PoolManager makes a copy of this dictionary so they can be configured -#: globally here, or individually on the instance. -key_fn_by_scheme = { - 'http': functools.partial(_default_key_normalizer, PoolKey), - 'https': functools.partial(_default_key_normalizer, PoolKey), -} - -pool_classes_by_scheme = { - 'http': HTTPConnectionPool, - 'https': HTTPSConnectionPool, -} - - -class PoolManager(RequestMethods): - """ - Allows for arbitrary requests while transparently keeping track of - necessary connection pools for you. - - :param num_pools: - Number of connection pools to cache before discarding the least - recently used pool. - - :param headers: - Headers to include with all requests, unless other headers are given - explicitly. - - :param \\**connection_pool_kw: - Additional parameters are used to create fresh - :class:`urllib3.connectionpool.ConnectionPool` instances. - - Example:: - - >>> manager = PoolManager(num_pools=2) - >>> r = manager.request('GET', 'http://google.com/') - >>> r = manager.request('GET', 'http://google.com/mail') - >>> r = manager.request('GET', 'http://yahoo.com/') - >>> len(manager.pools) - 2 - - """ - - proxy = None - - def __init__(self, num_pools=10, headers=None, **connection_pool_kw): - RequestMethods.__init__(self, headers) - self.connection_pool_kw = connection_pool_kw - self.pools = RecentlyUsedContainer(num_pools, - dispose_func=lambda p: p.close()) - - # Locally set the pool classes and keys so other PoolManagers can - # override them. - self.pool_classes_by_scheme = pool_classes_by_scheme - self.key_fn_by_scheme = key_fn_by_scheme.copy() - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self.clear() - # Return False to re-raise any potential exceptions - return False - - def _new_pool(self, scheme, host, port, request_context=None): - """ - Create a new :class:`ConnectionPool` based on host, port, scheme, and - any additional pool keyword arguments. - - If ``request_context`` is provided, it is provided as keyword arguments - to the pool class used. This method is used to actually create the - connection pools handed out by :meth:`connection_from_url` and - companion methods. It is intended to be overridden for customization. - """ - pool_cls = self.pool_classes_by_scheme[scheme] - if request_context is None: - request_context = self.connection_pool_kw.copy() - - # Although the context has everything necessary to create the pool, - # this function has historically only used the scheme, host, and port - # in the positional args. When an API change is acceptable these can - # be removed. - for key in ('scheme', 'host', 'port'): - request_context.pop(key, None) - - if scheme == 'http': - for kw in SSL_KEYWORDS: - request_context.pop(kw, None) - - return pool_cls(host, port, **request_context) - - def clear(self): - """ - Empty our store of pools and direct them all to close. - - This will not affect in-flight connections, but they will not be - re-used after completion. - """ - self.pools.clear() - - def connection_from_host(self, host, port=None, scheme='http', pool_kwargs=None): - """ - Get a :class:`ConnectionPool` based on the host, port, and scheme. - - If ``port`` isn't given, it will be derived from the ``scheme`` using - ``urllib3.connectionpool.port_by_scheme``. If ``pool_kwargs`` is - provided, it is merged with the instance's ``connection_pool_kw`` - variable and used to create the new connection pool, if one is - needed. - """ - - if not host: - raise LocationValueError("No host specified.") - - request_context = self._merge_pool_kwargs(pool_kwargs) - request_context['scheme'] = scheme or 'http' - if not port: - port = port_by_scheme.get(request_context['scheme'].lower(), 80) - request_context['port'] = port - request_context['host'] = host - - return self.connection_from_context(request_context) - - def connection_from_context(self, request_context): - """ - Get a :class:`ConnectionPool` based on the request context. - - ``request_context`` must at least contain the ``scheme`` key and its - value must be a key in ``key_fn_by_scheme`` instance variable. - """ - scheme = request_context['scheme'].lower() - pool_key_constructor = self.key_fn_by_scheme[scheme] - pool_key = pool_key_constructor(request_context) - - return self.connection_from_pool_key(pool_key, request_context=request_context) - - def connection_from_pool_key(self, pool_key, request_context=None): - """ - Get a :class:`ConnectionPool` based on the provided pool key. - - ``pool_key`` should be a namedtuple that only contains immutable - objects. At a minimum it must have the ``scheme``, ``host``, and - ``port`` fields. - """ - with self.pools.lock: - # If the scheme, host, or port doesn't match existing open - # connections, open a new ConnectionPool. - pool = self.pools.get(pool_key) - if pool: - return pool - - # Make a fresh ConnectionPool of the desired type - scheme = request_context['scheme'] - host = request_context['host'] - port = request_context['port'] - pool = self._new_pool(scheme, host, port, request_context=request_context) - self.pools[pool_key] = pool - - return pool - - def connection_from_url(self, url, pool_kwargs=None): - """ - Similar to :func:`urllib3.connectionpool.connection_from_url`. - - If ``pool_kwargs`` is not provided and a new pool needs to be - constructed, ``self.connection_pool_kw`` is used to initialize - the :class:`urllib3.connectionpool.ConnectionPool`. If ``pool_kwargs`` - is provided, it is used instead. Note that if a new pool does not - need to be created for the request, the provided ``pool_kwargs`` are - not used. - """ - u = parse_url(url) - return self.connection_from_host(u.host, port=u.port, scheme=u.scheme, - pool_kwargs=pool_kwargs) - - def _merge_pool_kwargs(self, override): - """ - Merge a dictionary of override values for self.connection_pool_kw. - - This does not modify self.connection_pool_kw and returns a new dict. - Any keys in the override dictionary with a value of ``None`` are - removed from the merged dictionary. - """ - base_pool_kwargs = self.connection_pool_kw.copy() - if override: - for key, value in override.items(): - if value is None: - try: - del base_pool_kwargs[key] - except KeyError: - pass - else: - base_pool_kwargs[key] = value - return base_pool_kwargs - - def urlopen(self, method, url, redirect=True, **kw): - """ - Same as :meth:`urllib3.connectionpool.HTTPConnectionPool.urlopen` - with custom cross-host redirect logic and only sends the request-uri - portion of the ``url``. - - The given ``url`` parameter must be absolute, such that an appropriate - :class:`urllib3.connectionpool.ConnectionPool` can be chosen for it. - """ - u = parse_url(url) - conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme) - - kw['assert_same_host'] = False - kw['redirect'] = False - - if 'headers' not in kw: - kw['headers'] = self.headers.copy() - - if self.proxy is not None and u.scheme == "http": - response = conn.urlopen(method, url, **kw) - else: - response = conn.urlopen(method, u.request_uri, **kw) - - redirect_location = redirect and response.get_redirect_location() - if not redirect_location: - return response - - # Support relative URLs for redirecting. - redirect_location = urljoin(url, redirect_location) - - # RFC 7231, Section 6.4.4 - if response.status == 303: - method = 'GET' - - retries = kw.get('retries') - if not isinstance(retries, Retry): - retries = Retry.from_int(retries, redirect=redirect) - - # Strip headers marked as unsafe to forward to the redirected location. - # Check remove_headers_on_redirect to avoid a potential network call within - # conn.is_same_host() which may use socket.gethostbyname() in the future. - if (retries.remove_headers_on_redirect - and not conn.is_same_host(redirect_location)): - for header in retries.remove_headers_on_redirect: - kw['headers'].pop(header, None) - - try: - retries = retries.increment(method, url, response=response, _pool=conn) - except MaxRetryError: - if retries.raise_on_redirect: - raise - return response - - kw['retries'] = retries - kw['redirect'] = redirect - - log.info("Redirecting %s -> %s", url, redirect_location) - return self.urlopen(method, redirect_location, **kw) - - -class ProxyManager(PoolManager): - """ - Behaves just like :class:`PoolManager`, but sends all requests through - the defined proxy, using the CONNECT method for HTTPS URLs. - - :param proxy_url: - The URL of the proxy to be used. - - :param proxy_headers: - A dictionary containing headers that will be sent to the proxy. In case - of HTTP they are being sent with each request, while in the - HTTPS/CONNECT case they are sent only once. Could be used for proxy - authentication. - - Example: - >>> proxy = urllib3.ProxyManager('http://localhost:3128/') - >>> r1 = proxy.request('GET', 'http://google.com/') - >>> r2 = proxy.request('GET', 'http://httpbin.org/') - >>> len(proxy.pools) - 1 - >>> r3 = proxy.request('GET', 'https://httpbin.org/') - >>> r4 = proxy.request('GET', 'https://twitter.com/') - >>> len(proxy.pools) - 3 - - """ - - def __init__(self, proxy_url, num_pools=10, headers=None, - proxy_headers=None, **connection_pool_kw): - - if isinstance(proxy_url, HTTPConnectionPool): - proxy_url = '%s://%s:%i' % (proxy_url.scheme, proxy_url.host, - proxy_url.port) - proxy = parse_url(proxy_url) - if not proxy.port: - port = port_by_scheme.get(proxy.scheme, 80) - proxy = proxy._replace(port=port) - - if proxy.scheme not in ("http", "https"): - raise ProxySchemeUnknown(proxy.scheme) - - self.proxy = proxy - self.proxy_headers = proxy_headers or {} - - connection_pool_kw['_proxy'] = self.proxy - connection_pool_kw['_proxy_headers'] = self.proxy_headers - - super(ProxyManager, self).__init__( - num_pools, headers, **connection_pool_kw) - - def connection_from_host(self, host, port=None, scheme='http', pool_kwargs=None): - if scheme == "https": - return super(ProxyManager, self).connection_from_host( - host, port, scheme, pool_kwargs=pool_kwargs) - - return super(ProxyManager, self).connection_from_host( - self.proxy.host, self.proxy.port, self.proxy.scheme, pool_kwargs=pool_kwargs) - - def _set_proxy_headers(self, url, headers=None): - """ - Sets headers needed by proxies: specifically, the Accept and Host - headers. Only sets headers not provided by the user. - """ - headers_ = {'Accept': '*/*'} - - netloc = parse_url(url).netloc - if netloc: - headers_['Host'] = netloc - - if headers: - headers_.update(headers) - return headers_ - - def urlopen(self, method, url, redirect=True, **kw): - "Same as HTTP(S)ConnectionPool.urlopen, ``url`` must be absolute." - u = parse_url(url) - - if u.scheme == "http": - # For proxied HTTPS requests, httplib sets the necessary headers - # on the CONNECT to the proxy. For HTTP, we'll definitely - # need to set 'Host' at the very least. - headers = kw.get('headers', self.headers) - kw['headers'] = self._set_proxy_headers(url, headers) - - return super(ProxyManager, self).urlopen(method, url, redirect=redirect, **kw) - - -def proxy_from_url(url, **kw): - return ProxyManager(proxy_url=url, **kw) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/request.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/request.py deleted file mode 100644 index 8f2f44b..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/request.py +++ /dev/null @@ -1,150 +0,0 @@ -from __future__ import absolute_import - -from .filepost import encode_multipart_formdata -from .packages.six.moves.urllib.parse import urlencode - - -__all__ = ['RequestMethods'] - - -class RequestMethods(object): - """ - Convenience mixin for classes who implement a :meth:`urlopen` method, such - as :class:`~urllib3.connectionpool.HTTPConnectionPool` and - :class:`~urllib3.poolmanager.PoolManager`. - - Provides behavior for making common types of HTTP request methods and - decides which type of request field encoding to use. - - Specifically, - - :meth:`.request_encode_url` is for sending requests whose fields are - encoded in the URL (such as GET, HEAD, DELETE). - - :meth:`.request_encode_body` is for sending requests whose fields are - encoded in the *body* of the request using multipart or www-form-urlencoded - (such as for POST, PUT, PATCH). - - :meth:`.request` is for making any kind of request, it will look up the - appropriate encoding format and use one of the above two methods to make - the request. - - Initializer parameters: - - :param headers: - Headers to include with all requests, unless other headers are given - explicitly. - """ - - _encode_url_methods = {'DELETE', 'GET', 'HEAD', 'OPTIONS'} - - def __init__(self, headers=None): - self.headers = headers or {} - - def urlopen(self, method, url, body=None, headers=None, - encode_multipart=True, multipart_boundary=None, - **kw): # Abstract - raise NotImplementedError("Classes extending RequestMethods must implement " - "their own ``urlopen`` method.") - - def request(self, method, url, fields=None, headers=None, **urlopen_kw): - """ - Make a request using :meth:`urlopen` with the appropriate encoding of - ``fields`` based on the ``method`` used. - - This is a convenience method that requires the least amount of manual - effort. It can be used in most situations, while still having the - option to drop down to more specific methods when necessary, such as - :meth:`request_encode_url`, :meth:`request_encode_body`, - or even the lowest level :meth:`urlopen`. - """ - method = method.upper() - - urlopen_kw['request_url'] = url - - if method in self._encode_url_methods: - return self.request_encode_url(method, url, fields=fields, - headers=headers, - **urlopen_kw) - else: - return self.request_encode_body(method, url, fields=fields, - headers=headers, - **urlopen_kw) - - def request_encode_url(self, method, url, fields=None, headers=None, - **urlopen_kw): - """ - Make a request using :meth:`urlopen` with the ``fields`` encoded in - the url. This is useful for request methods like GET, HEAD, DELETE, etc. - """ - if headers is None: - headers = self.headers - - extra_kw = {'headers': headers} - extra_kw.update(urlopen_kw) - - if fields: - url += '?' + urlencode(fields) - - return self.urlopen(method, url, **extra_kw) - - def request_encode_body(self, method, url, fields=None, headers=None, - encode_multipart=True, multipart_boundary=None, - **urlopen_kw): - """ - Make a request using :meth:`urlopen` with the ``fields`` encoded in - the body. This is useful for request methods like POST, PUT, PATCH, etc. - - When ``encode_multipart=True`` (default), then - :meth:`urllib3.filepost.encode_multipart_formdata` is used to encode - the payload with the appropriate content type. Otherwise - :meth:`urllib.urlencode` is used with the - 'application/x-www-form-urlencoded' content type. - - Multipart encoding must be used when posting files, and it's reasonably - safe to use it in other times too. However, it may break request - signing, such as with OAuth. - - Supports an optional ``fields`` parameter of key/value strings AND - key/filetuple. A filetuple is a (filename, data, MIME type) tuple where - the MIME type is optional. For example:: - - fields = { - 'foo': 'bar', - 'fakefile': ('foofile.txt', 'contents of foofile'), - 'realfile': ('barfile.txt', open('realfile').read()), - 'typedfile': ('bazfile.bin', open('bazfile').read(), - 'image/jpeg'), - 'nonamefile': 'contents of nonamefile field', - } - - When uploading a file, providing a filename (the first parameter of the - tuple) is optional but recommended to best mimic behavior of browsers. - - Note that if ``headers`` are supplied, the 'Content-Type' header will - be overwritten because it depends on the dynamic random boundary string - which is used to compose the body of the request. The random boundary - string can be explicitly set with the ``multipart_boundary`` parameter. - """ - if headers is None: - headers = self.headers - - extra_kw = {'headers': {}} - - if fields: - if 'body' in urlopen_kw: - raise TypeError( - "request got values for both 'fields' and 'body', can only specify one.") - - if encode_multipart: - body, content_type = encode_multipart_formdata(fields, boundary=multipart_boundary) - else: - body, content_type = urlencode(fields), 'application/x-www-form-urlencoded' - - extra_kw['body'] = body - extra_kw['headers'] = {'Content-Type': content_type} - - extra_kw['headers'].update(headers) - extra_kw.update(urlopen_kw) - - return self.urlopen(method, url, **extra_kw) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/response.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/response.py deleted file mode 100644 index c112690..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/response.py +++ /dev/null @@ -1,705 +0,0 @@ -from __future__ import absolute_import -from contextlib import contextmanager -import zlib -import io -import logging -from socket import timeout as SocketTimeout -from socket import error as SocketError - -from ._collections import HTTPHeaderDict -from .exceptions import ( - BodyNotHttplibCompatible, ProtocolError, DecodeError, ReadTimeoutError, - ResponseNotChunked, IncompleteRead, InvalidHeader -) -from .packages.six import string_types as basestring, PY3 -from .packages.six.moves import http_client as httplib -from .connection import HTTPException, BaseSSLError -from .util.response import is_fp_closed, is_response_to_head - -log = logging.getLogger(__name__) - - -class DeflateDecoder(object): - - def __init__(self): - self._first_try = True - self._data = b'' - self._obj = zlib.decompressobj() - - def __getattr__(self, name): - return getattr(self._obj, name) - - def decompress(self, data): - if not data: - return data - - if not self._first_try: - return self._obj.decompress(data) - - self._data += data - try: - decompressed = self._obj.decompress(data) - if decompressed: - self._first_try = False - self._data = None - return decompressed - except zlib.error: - self._first_try = False - self._obj = zlib.decompressobj(-zlib.MAX_WBITS) - try: - return self.decompress(self._data) - finally: - self._data = None - - -class GzipDecoderState(object): - - FIRST_MEMBER = 0 - OTHER_MEMBERS = 1 - SWALLOW_DATA = 2 - - -class GzipDecoder(object): - - def __init__(self): - self._obj = zlib.decompressobj(16 + zlib.MAX_WBITS) - self._state = GzipDecoderState.FIRST_MEMBER - - def __getattr__(self, name): - return getattr(self._obj, name) - - def decompress(self, data): - ret = bytearray() - if self._state == GzipDecoderState.SWALLOW_DATA or not data: - return bytes(ret) - while True: - try: - ret += self._obj.decompress(data) - except zlib.error: - previous_state = self._state - # Ignore data after the first error - self._state = GzipDecoderState.SWALLOW_DATA - if previous_state == GzipDecoderState.OTHER_MEMBERS: - # Allow trailing garbage acceptable in other gzip clients - return bytes(ret) - raise - data = self._obj.unused_data - if not data: - return bytes(ret) - self._state = GzipDecoderState.OTHER_MEMBERS - self._obj = zlib.decompressobj(16 + zlib.MAX_WBITS) - - -class MultiDecoder(object): - """ - From RFC7231: - If one or more encodings have been applied to a representation, the - sender that applied the encodings MUST generate a Content-Encoding - header field that lists the content codings in the order in which - they were applied. - """ - - def __init__(self, modes): - self._decoders = [_get_decoder(m.strip()) for m in modes.split(',')] - - def flush(self): - return self._decoders[0].flush() - - def decompress(self, data): - for d in reversed(self._decoders): - data = d.decompress(data) - return data - - -def _get_decoder(mode): - if ',' in mode: - return MultiDecoder(mode) - - if mode == 'gzip': - return GzipDecoder() - - return DeflateDecoder() - - -class HTTPResponse(io.IOBase): - """ - HTTP Response container. - - Backwards-compatible to httplib's HTTPResponse but the response ``body`` is - loaded and decoded on-demand when the ``data`` property is accessed. This - class is also compatible with the Python standard library's :mod:`io` - module, and can hence be treated as a readable object in the context of that - framework. - - Extra parameters for behaviour not present in httplib.HTTPResponse: - - :param preload_content: - If True, the response's body will be preloaded during construction. - - :param decode_content: - If True, will attempt to decode the body based on the - 'content-encoding' header. - - :param original_response: - When this HTTPResponse wrapper is generated from an httplib.HTTPResponse - object, it's convenient to include the original for debug purposes. It's - otherwise unused. - - :param retries: - The retries contains the last :class:`~urllib3.util.retry.Retry` that - was used during the request. - - :param enforce_content_length: - Enforce content length checking. Body returned by server must match - value of Content-Length header, if present. Otherwise, raise error. - """ - - CONTENT_DECODERS = ['gzip', 'deflate'] - REDIRECT_STATUSES = [301, 302, 303, 307, 308] - - def __init__(self, body='', headers=None, status=0, version=0, reason=None, - strict=0, preload_content=True, decode_content=True, - original_response=None, pool=None, connection=None, msg=None, - retries=None, enforce_content_length=False, - request_method=None, request_url=None): - - if isinstance(headers, HTTPHeaderDict): - self.headers = headers - else: - self.headers = HTTPHeaderDict(headers) - self.status = status - self.version = version - self.reason = reason - self.strict = strict - self.decode_content = decode_content - self.retries = retries - self.enforce_content_length = enforce_content_length - - self._decoder = None - self._body = None - self._fp = None - self._original_response = original_response - self._fp_bytes_read = 0 - self.msg = msg - self._request_url = request_url - - if body and isinstance(body, (basestring, bytes)): - self._body = body - - self._pool = pool - self._connection = connection - - if hasattr(body, 'read'): - self._fp = body - - # Are we using the chunked-style of transfer encoding? - self.chunked = False - self.chunk_left = None - tr_enc = self.headers.get('transfer-encoding', '').lower() - # Don't incur the penalty of creating a list and then discarding it - encodings = (enc.strip() for enc in tr_enc.split(",")) - if "chunked" in encodings: - self.chunked = True - - # Determine length of response - self.length_remaining = self._init_length(request_method) - - # If requested, preload the body. - if preload_content and not self._body: - self._body = self.read(decode_content=decode_content) - - def get_redirect_location(self): - """ - Should we redirect and where to? - - :returns: Truthy redirect location string if we got a redirect status - code and valid location. ``None`` if redirect status and no - location. ``False`` if not a redirect status code. - """ - if self.status in self.REDIRECT_STATUSES: - return self.headers.get('location') - - return False - - def release_conn(self): - if not self._pool or not self._connection: - return - - self._pool._put_conn(self._connection) - self._connection = None - - @property - def data(self): - # For backwords-compat with earlier urllib3 0.4 and earlier. - if self._body: - return self._body - - if self._fp: - return self.read(cache_content=True) - - @property - def connection(self): - return self._connection - - def isclosed(self): - return is_fp_closed(self._fp) - - def tell(self): - """ - Obtain the number of bytes pulled over the wire so far. May differ from - the amount of content returned by :meth:``HTTPResponse.read`` if bytes - are encoded on the wire (e.g, compressed). - """ - return self._fp_bytes_read - - def _init_length(self, request_method): - """ - Set initial length value for Response content if available. - """ - length = self.headers.get('content-length') - - if length is not None: - if self.chunked: - # This Response will fail with an IncompleteRead if it can't be - # received as chunked. This method falls back to attempt reading - # the response before raising an exception. - log.warning("Received response with both Content-Length and " - "Transfer-Encoding set. This is expressly forbidden " - "by RFC 7230 sec 3.3.2. Ignoring Content-Length and " - "attempting to process response as Transfer-Encoding: " - "chunked.") - return None - - try: - # RFC 7230 section 3.3.2 specifies multiple content lengths can - # be sent in a single Content-Length header - # (e.g. Content-Length: 42, 42). This line ensures the values - # are all valid ints and that as long as the `set` length is 1, - # all values are the same. Otherwise, the header is invalid. - lengths = set([int(val) for val in length.split(',')]) - if len(lengths) > 1: - raise InvalidHeader("Content-Length contained multiple " - "unmatching values (%s)" % length) - length = lengths.pop() - except ValueError: - length = None - else: - if length < 0: - length = None - - # Convert status to int for comparison - # In some cases, httplib returns a status of "_UNKNOWN" - try: - status = int(self.status) - except ValueError: - status = 0 - - # Check for responses that shouldn't include a body - if status in (204, 304) or 100 <= status < 200 or request_method == 'HEAD': - length = 0 - - return length - - def _init_decoder(self): - """ - Set-up the _decoder attribute if necessary. - """ - # Note: content-encoding value should be case-insensitive, per RFC 7230 - # Section 3.2 - content_encoding = self.headers.get('content-encoding', '').lower() - if self._decoder is None: - if content_encoding in self.CONTENT_DECODERS: - self._decoder = _get_decoder(content_encoding) - elif ',' in content_encoding: - encodings = [e.strip() for e in content_encoding.split(',') if e.strip() in self.CONTENT_DECODERS] - if len(encodings): - self._decoder = _get_decoder(content_encoding) - - def _decode(self, data, decode_content, flush_decoder): - """ - Decode the data passed in and potentially flush the decoder. - """ - try: - if decode_content and self._decoder: - data = self._decoder.decompress(data) - except (IOError, zlib.error) as e: - content_encoding = self.headers.get('content-encoding', '').lower() - raise DecodeError( - "Received response with content-encoding: %s, but " - "failed to decode it." % content_encoding, e) - - if flush_decoder and decode_content: - data += self._flush_decoder() - - return data - - def _flush_decoder(self): - """ - Flushes the decoder. Should only be called if the decoder is actually - being used. - """ - if self._decoder: - buf = self._decoder.decompress(b'') - return buf + self._decoder.flush() - - return b'' - - @contextmanager - def _error_catcher(self): - """ - Catch low-level python exceptions, instead re-raising urllib3 - variants, so that low-level exceptions are not leaked in the - high-level api. - - On exit, release the connection back to the pool. - """ - clean_exit = False - - try: - try: - yield - - except SocketTimeout: - # FIXME: Ideally we'd like to include the url in the ReadTimeoutError but - # there is yet no clean way to get at it from this context. - raise ReadTimeoutError(self._pool, None, 'Read timed out.') - - except BaseSSLError as e: - # FIXME: Is there a better way to differentiate between SSLErrors? - if 'read operation timed out' not in str(e): # Defensive: - # This shouldn't happen but just in case we're missing an edge - # case, let's avoid swallowing SSL errors. - raise - - raise ReadTimeoutError(self._pool, None, 'Read timed out.') - - except (HTTPException, SocketError) as e: - # This includes IncompleteRead. - raise ProtocolError('Connection broken: %r' % e, e) - - # If no exception is thrown, we should avoid cleaning up - # unnecessarily. - clean_exit = True - finally: - # If we didn't terminate cleanly, we need to throw away our - # connection. - if not clean_exit: - # The response may not be closed but we're not going to use it - # anymore so close it now to ensure that the connection is - # released back to the pool. - if self._original_response: - self._original_response.close() - - # Closing the response may not actually be sufficient to close - # everything, so if we have a hold of the connection close that - # too. - if self._connection: - self._connection.close() - - # If we hold the original response but it's closed now, we should - # return the connection back to the pool. - if self._original_response and self._original_response.isclosed(): - self.release_conn() - - def read(self, amt=None, decode_content=None, cache_content=False): - """ - Similar to :meth:`httplib.HTTPResponse.read`, but with two additional - parameters: ``decode_content`` and ``cache_content``. - - :param amt: - How much of the content to read. If specified, caching is skipped - because it doesn't make sense to cache partial content as the full - response. - - :param decode_content: - If True, will attempt to decode the body based on the - 'content-encoding' header. - - :param cache_content: - If True, will save the returned data such that the same result is - returned despite of the state of the underlying file object. This - is useful if you want the ``.data`` property to continue working - after having ``.read()`` the file object. (Overridden if ``amt`` is - set.) - """ - self._init_decoder() - if decode_content is None: - decode_content = self.decode_content - - if self._fp is None: - return - - flush_decoder = False - data = None - - with self._error_catcher(): - if amt is None: - # cStringIO doesn't like amt=None - data = self._fp.read() - flush_decoder = True - else: - cache_content = False - data = self._fp.read(amt) - if amt != 0 and not data: # Platform-specific: Buggy versions of Python. - # Close the connection when no data is returned - # - # This is redundant to what httplib/http.client _should_ - # already do. However, versions of python released before - # December 15, 2012 (http://bugs.python.org/issue16298) do - # not properly close the connection in all cases. There is - # no harm in redundantly calling close. - self._fp.close() - flush_decoder = True - if self.enforce_content_length and self.length_remaining not in (0, None): - # This is an edge case that httplib failed to cover due - # to concerns of backward compatibility. We're - # addressing it here to make sure IncompleteRead is - # raised during streaming, so all calls with incorrect - # Content-Length are caught. - raise IncompleteRead(self._fp_bytes_read, self.length_remaining) - - if data: - self._fp_bytes_read += len(data) - if self.length_remaining is not None: - self.length_remaining -= len(data) - - data = self._decode(data, decode_content, flush_decoder) - - if cache_content: - self._body = data - - return data - - def stream(self, amt=2**16, decode_content=None): - """ - A generator wrapper for the read() method. A call will block until - ``amt`` bytes have been read from the connection or until the - connection is closed. - - :param amt: - How much of the content to read. The generator will return up to - much data per iteration, but may return less. This is particularly - likely when using compressed data. However, the empty string will - never be returned. - - :param decode_content: - If True, will attempt to decode the body based on the - 'content-encoding' header. - """ - if self.chunked and self.supports_chunked_reads(): - for line in self.read_chunked(amt, decode_content=decode_content): - yield line - else: - while not is_fp_closed(self._fp): - data = self.read(amt=amt, decode_content=decode_content) - - if data: - yield data - - @classmethod - def from_httplib(ResponseCls, r, **response_kw): - """ - Given an :class:`httplib.HTTPResponse` instance ``r``, return a - corresponding :class:`urllib3.response.HTTPResponse` object. - - Remaining parameters are passed to the HTTPResponse constructor, along - with ``original_response=r``. - """ - headers = r.msg - - if not isinstance(headers, HTTPHeaderDict): - if PY3: # Python 3 - headers = HTTPHeaderDict(headers.items()) - else: # Python 2 - headers = HTTPHeaderDict.from_httplib(headers) - - # HTTPResponse objects in Python 3 don't have a .strict attribute - strict = getattr(r, 'strict', 0) - resp = ResponseCls(body=r, - headers=headers, - status=r.status, - version=r.version, - reason=r.reason, - strict=strict, - original_response=r, - **response_kw) - return resp - - # Backwards-compatibility methods for httplib.HTTPResponse - def getheaders(self): - return self.headers - - def getheader(self, name, default=None): - return self.headers.get(name, default) - - # Backwards compatibility for http.cookiejar - def info(self): - return self.headers - - # Overrides from io.IOBase - def close(self): - if not self.closed: - self._fp.close() - - if self._connection: - self._connection.close() - - @property - def closed(self): - if self._fp is None: - return True - elif hasattr(self._fp, 'isclosed'): - return self._fp.isclosed() - elif hasattr(self._fp, 'closed'): - return self._fp.closed - else: - return True - - def fileno(self): - if self._fp is None: - raise IOError("HTTPResponse has no file to get a fileno from") - elif hasattr(self._fp, "fileno"): - return self._fp.fileno() - else: - raise IOError("The file-like object this HTTPResponse is wrapped " - "around has no file descriptor") - - def flush(self): - if self._fp is not None and hasattr(self._fp, 'flush'): - return self._fp.flush() - - def readable(self): - # This method is required for `io` module compatibility. - return True - - def readinto(self, b): - # This method is required for `io` module compatibility. - temp = self.read(len(b)) - if len(temp) == 0: - return 0 - else: - b[:len(temp)] = temp - return len(temp) - - def supports_chunked_reads(self): - """ - Checks if the underlying file-like object looks like a - httplib.HTTPResponse object. We do this by testing for the fp - attribute. If it is present we assume it returns raw chunks as - processed by read_chunked(). - """ - return hasattr(self._fp, 'fp') - - def _update_chunk_length(self): - # First, we'll figure out length of a chunk and then - # we'll try to read it from socket. - if self.chunk_left is not None: - return - line = self._fp.fp.readline() - line = line.split(b';', 1)[0] - try: - self.chunk_left = int(line, 16) - except ValueError: - # Invalid chunked protocol response, abort. - self.close() - raise httplib.IncompleteRead(line) - - def _handle_chunk(self, amt): - returned_chunk = None - if amt is None: - chunk = self._fp._safe_read(self.chunk_left) - returned_chunk = chunk - self._fp._safe_read(2) # Toss the CRLF at the end of the chunk. - self.chunk_left = None - elif amt < self.chunk_left: - value = self._fp._safe_read(amt) - self.chunk_left = self.chunk_left - amt - returned_chunk = value - elif amt == self.chunk_left: - value = self._fp._safe_read(amt) - self._fp._safe_read(2) # Toss the CRLF at the end of the chunk. - self.chunk_left = None - returned_chunk = value - else: # amt > self.chunk_left - returned_chunk = self._fp._safe_read(self.chunk_left) - self._fp._safe_read(2) # Toss the CRLF at the end of the chunk. - self.chunk_left = None - return returned_chunk - - def read_chunked(self, amt=None, decode_content=None): - """ - Similar to :meth:`HTTPResponse.read`, but with an additional - parameter: ``decode_content``. - - :param amt: - How much of the content to read. If specified, caching is skipped - because it doesn't make sense to cache partial content as the full - response. - - :param decode_content: - If True, will attempt to decode the body based on the - 'content-encoding' header. - """ - self._init_decoder() - # FIXME: Rewrite this method and make it a class with a better structured logic. - if not self.chunked: - raise ResponseNotChunked( - "Response is not chunked. " - "Header 'transfer-encoding: chunked' is missing.") - if not self.supports_chunked_reads(): - raise BodyNotHttplibCompatible( - "Body should be httplib.HTTPResponse like. " - "It should have have an fp attribute which returns raw chunks.") - - with self._error_catcher(): - # Don't bother reading the body of a HEAD request. - if self._original_response and is_response_to_head(self._original_response): - self._original_response.close() - return - - # If a response is already read and closed - # then return immediately. - if self._fp.fp is None: - return - - while True: - self._update_chunk_length() - if self.chunk_left == 0: - break - chunk = self._handle_chunk(amt) - decoded = self._decode(chunk, decode_content=decode_content, - flush_decoder=False) - if decoded: - yield decoded - - if decode_content: - # On CPython and PyPy, we should never need to flush the - # decoder. However, on Jython we *might* need to, so - # lets defensively do it anyway. - decoded = self._flush_decoder() - if decoded: # Platform-specific: Jython. - yield decoded - - # Chunk content ends with \r\n: discard it. - while True: - line = self._fp.fp.readline() - if not line: - # Some sites may not end with '\r\n'. - break - if line == b'\r\n': - break - - # We read everything; close the "file". - if self._original_response: - self._original_response.close() - - def geturl(self): - """ - Returns the URL that was the source of this response. - If the request that generated this response redirected, this method - will return the final redirect location. - """ - if self.retries is not None and len(self.retries.history): - return self.retries.history[-1].redirect_location - else: - return self._request_url diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/__init__.py deleted file mode 100644 index 2f2770b..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/__init__.py +++ /dev/null @@ -1,54 +0,0 @@ -from __future__ import absolute_import -# For backwards compatibility, provide imports that used to be here. -from .connection import is_connection_dropped -from .request import make_headers -from .response import is_fp_closed -from .ssl_ import ( - SSLContext, - HAS_SNI, - IS_PYOPENSSL, - IS_SECURETRANSPORT, - assert_fingerprint, - resolve_cert_reqs, - resolve_ssl_version, - ssl_wrap_socket, -) -from .timeout import ( - current_time, - Timeout, -) - -from .retry import Retry -from .url import ( - get_host, - parse_url, - split_first, - Url, -) -from .wait import ( - wait_for_read, - wait_for_write -) - -__all__ = ( - 'HAS_SNI', - 'IS_PYOPENSSL', - 'IS_SECURETRANSPORT', - 'SSLContext', - 'Retry', - 'Timeout', - 'Url', - 'assert_fingerprint', - 'current_time', - 'is_connection_dropped', - 'is_fp_closed', - 'get_host', - 'parse_url', - 'make_headers', - 'resolve_cert_reqs', - 'resolve_ssl_version', - 'split_first', - 'ssl_wrap_socket', - 'wait_for_read', - 'wait_for_write' -) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/connection.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/connection.py deleted file mode 100644 index 5ad70b2..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/connection.py +++ /dev/null @@ -1,134 +0,0 @@ -from __future__ import absolute_import -import socket -from .wait import NoWayToWaitForSocketError, wait_for_read -from ..contrib import _appengine_environ - - -def is_connection_dropped(conn): # Platform-specific - """ - Returns True if the connection is dropped and should be closed. - - :param conn: - :class:`httplib.HTTPConnection` object. - - Note: For platforms like AppEngine, this will always return ``False`` to - let the platform handle connection recycling transparently for us. - """ - sock = getattr(conn, 'sock', False) - if sock is False: # Platform-specific: AppEngine - return False - if sock is None: # Connection already closed (such as by httplib). - return True - try: - # Returns True if readable, which here means it's been dropped - return wait_for_read(sock, timeout=0.0) - except NoWayToWaitForSocketError: # Platform-specific: AppEngine - return False - - -# This function is copied from socket.py in the Python 2.7 standard -# library test suite. Added to its signature is only `socket_options`. -# One additional modification is that we avoid binding to IPv6 servers -# discovered in DNS if the system doesn't have IPv6 functionality. -def create_connection(address, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, - source_address=None, socket_options=None): - """Connect to *address* and return the socket object. - - Convenience function. Connect to *address* (a 2-tuple ``(host, - port)``) and return the socket object. Passing the optional - *timeout* parameter will set the timeout on the socket instance - before attempting to connect. If no *timeout* is supplied, the - global default timeout setting returned by :func:`getdefaulttimeout` - is used. If *source_address* is set it must be a tuple of (host, port) - for the socket to bind as a source address before making the connection. - An host of '' or port 0 tells the OS to use the default. - """ - - host, port = address - if host.startswith('['): - host = host.strip('[]') - err = None - - # Using the value from allowed_gai_family() in the context of getaddrinfo lets - # us select whether to work with IPv4 DNS records, IPv6 records, or both. - # The original create_connection function always returns all records. - family = allowed_gai_family() - - for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): - af, socktype, proto, canonname, sa = res - sock = None - try: - sock = socket.socket(af, socktype, proto) - - # If provided, set socket level options before connecting. - _set_socket_options(sock, socket_options) - - if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT: - sock.settimeout(timeout) - if source_address: - sock.bind(source_address) - sock.connect(sa) - return sock - - except socket.error as e: - err = e - if sock is not None: - sock.close() - sock = None - - if err is not None: - raise err - - raise socket.error("getaddrinfo returns an empty list") - - -def _set_socket_options(sock, options): - if options is None: - return - - for opt in options: - sock.setsockopt(*opt) - - -def allowed_gai_family(): - """This function is designed to work in the context of - getaddrinfo, where family=socket.AF_UNSPEC is the default and - will perform a DNS search for both IPv6 and IPv4 records.""" - - family = socket.AF_INET - if HAS_IPV6: - family = socket.AF_UNSPEC - return family - - -def _has_ipv6(host): - """ Returns True if the system can bind an IPv6 address. """ - sock = None - has_ipv6 = False - - # App Engine doesn't support IPV6 sockets and actually has a quota on the - # number of sockets that can be used, so just early out here instead of - # creating a socket needlessly. - # See https://github.com/urllib3/urllib3/issues/1446 - if _appengine_environ.is_appengine_sandbox(): - return False - - if socket.has_ipv6: - # has_ipv6 returns true if cPython was compiled with IPv6 support. - # It does not tell us if the system has IPv6 support enabled. To - # determine that we must bind to an IPv6 address. - # https://github.com/shazow/urllib3/pull/611 - # https://bugs.python.org/issue658327 - try: - sock = socket.socket(socket.AF_INET6) - sock.bind((host, 0)) - has_ipv6 = True - except Exception: - pass - - if sock: - sock.close() - return has_ipv6 - - -HAS_IPV6 = _has_ipv6('::1') diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/queue.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/queue.py deleted file mode 100644 index d3d379a..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/queue.py +++ /dev/null @@ -1,21 +0,0 @@ -import collections -from ..packages import six -from ..packages.six.moves import queue - -if six.PY2: - # Queue is imported for side effects on MS Windows. See issue #229. - import Queue as _unused_module_Queue # noqa: F401 - - -class LifoQueue(queue.Queue): - def _init(self, _): - self.queue = collections.deque() - - def _qsize(self, len=len): - return len(self.queue) - - def _put(self, item): - self.queue.append(item) - - def _get(self): - return self.queue.pop() diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/request.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/request.py deleted file mode 100644 index 3ddfcd5..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/request.py +++ /dev/null @@ -1,118 +0,0 @@ -from __future__ import absolute_import -from base64 import b64encode - -from ..packages.six import b, integer_types -from ..exceptions import UnrewindableBodyError - -ACCEPT_ENCODING = 'gzip,deflate' -_FAILEDTELL = object() - - -def make_headers(keep_alive=None, accept_encoding=None, user_agent=None, - basic_auth=None, proxy_basic_auth=None, disable_cache=None): - """ - Shortcuts for generating request headers. - - :param keep_alive: - If ``True``, adds 'connection: keep-alive' header. - - :param accept_encoding: - Can be a boolean, list, or string. - ``True`` translates to 'gzip,deflate'. - List will get joined by comma. - String will be used as provided. - - :param user_agent: - String representing the user-agent you want, such as - "python-urllib3/0.6" - - :param basic_auth: - Colon-separated username:password string for 'authorization: basic ...' - auth header. - - :param proxy_basic_auth: - Colon-separated username:password string for 'proxy-authorization: basic ...' - auth header. - - :param disable_cache: - If ``True``, adds 'cache-control: no-cache' header. - - Example:: - - >>> make_headers(keep_alive=True, user_agent="Batman/1.0") - {'connection': 'keep-alive', 'user-agent': 'Batman/1.0'} - >>> make_headers(accept_encoding=True) - {'accept-encoding': 'gzip,deflate'} - """ - headers = {} - if accept_encoding: - if isinstance(accept_encoding, str): - pass - elif isinstance(accept_encoding, list): - accept_encoding = ','.join(accept_encoding) - else: - accept_encoding = ACCEPT_ENCODING - headers['accept-encoding'] = accept_encoding - - if user_agent: - headers['user-agent'] = user_agent - - if keep_alive: - headers['connection'] = 'keep-alive' - - if basic_auth: - headers['authorization'] = 'Basic ' + \ - b64encode(b(basic_auth)).decode('utf-8') - - if proxy_basic_auth: - headers['proxy-authorization'] = 'Basic ' + \ - b64encode(b(proxy_basic_auth)).decode('utf-8') - - if disable_cache: - headers['cache-control'] = 'no-cache' - - return headers - - -def set_file_position(body, pos): - """ - If a position is provided, move file to that point. - Otherwise, we'll attempt to record a position for future use. - """ - if pos is not None: - rewind_body(body, pos) - elif getattr(body, 'tell', None) is not None: - try: - pos = body.tell() - except (IOError, OSError): - # This differentiates from None, allowing us to catch - # a failed `tell()` later when trying to rewind the body. - pos = _FAILEDTELL - - return pos - - -def rewind_body(body, body_pos): - """ - Attempt to rewind body to a certain position. - Primarily used for request redirects and retries. - - :param body: - File-like object that supports seek. - - :param int pos: - Position to seek to in file. - """ - body_seek = getattr(body, 'seek', None) - if body_seek is not None and isinstance(body_pos, integer_types): - try: - body_seek(body_pos) - except (IOError, OSError): - raise UnrewindableBodyError("An error occurred when rewinding request " - "body for redirect/retry.") - elif body_pos is _FAILEDTELL: - raise UnrewindableBodyError("Unable to record file position for rewinding " - "request body during a redirect/retry.") - else: - raise ValueError("body_pos must be of type integer, " - "instead it was %s." % type(body_pos)) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/response.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/response.py deleted file mode 100644 index 3d54864..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/response.py +++ /dev/null @@ -1,87 +0,0 @@ -from __future__ import absolute_import -from ..packages.six.moves import http_client as httplib - -from ..exceptions import HeaderParsingError - - -def is_fp_closed(obj): - """ - Checks whether a given file-like object is closed. - - :param obj: - The file-like object to check. - """ - - try: - # Check `isclosed()` first, in case Python3 doesn't set `closed`. - # GH Issue #928 - return obj.isclosed() - except AttributeError: - pass - - try: - # Check via the official file-like-object way. - return obj.closed - except AttributeError: - pass - - try: - # Check if the object is a container for another file-like object that - # gets released on exhaustion (e.g. HTTPResponse). - return obj.fp is None - except AttributeError: - pass - - raise ValueError("Unable to determine whether fp is closed.") - - -def assert_header_parsing(headers): - """ - Asserts whether all headers have been successfully parsed. - Extracts encountered errors from the result of parsing headers. - - Only works on Python 3. - - :param headers: Headers to verify. - :type headers: `httplib.HTTPMessage`. - - :raises urllib3.exceptions.HeaderParsingError: - If parsing errors are found. - """ - - # This will fail silently if we pass in the wrong kind of parameter. - # To make debugging easier add an explicit check. - if not isinstance(headers, httplib.HTTPMessage): - raise TypeError('expected httplib.Message, got {0}.'.format( - type(headers))) - - defects = getattr(headers, 'defects', None) - get_payload = getattr(headers, 'get_payload', None) - - unparsed_data = None - if get_payload: - # get_payload is actually email.message.Message.get_payload; - # we're only interested in the result if it's not a multipart message - if not headers.is_multipart(): - payload = get_payload() - - if isinstance(payload, (bytes, str)): - unparsed_data = payload - - if defects or unparsed_data: - raise HeaderParsingError(defects=defects, unparsed_data=unparsed_data) - - -def is_response_to_head(response): - """ - Checks whether the request of a response has been a HEAD-request. - Handles the quirks of AppEngine. - - :param conn: - :type conn: :class:`httplib.HTTPResponse` - """ - # FIXME: Can we do this somehow without accessing private httplib _method? - method = response._method - if isinstance(method, int): # Platform-specific: Appengine - return method == 3 - return method.upper() == 'HEAD' diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/retry.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/retry.py deleted file mode 100644 index e7d0abd..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/retry.py +++ /dev/null @@ -1,411 +0,0 @@ -from __future__ import absolute_import -import time -import logging -from collections import namedtuple -from itertools import takewhile -import email -import re - -from ..exceptions import ( - ConnectTimeoutError, - MaxRetryError, - ProtocolError, - ReadTimeoutError, - ResponseError, - InvalidHeader, -) -from ..packages import six - - -log = logging.getLogger(__name__) - - -# Data structure for representing the metadata of requests that result in a retry. -RequestHistory = namedtuple('RequestHistory', ["method", "url", "error", - "status", "redirect_location"]) - - -class Retry(object): - """ Retry configuration. - - Each retry attempt will create a new Retry object with updated values, so - they can be safely reused. - - Retries can be defined as a default for a pool:: - - retries = Retry(connect=5, read=2, redirect=5) - http = PoolManager(retries=retries) - response = http.request('GET', 'http://example.com/') - - Or per-request (which overrides the default for the pool):: - - response = http.request('GET', 'http://example.com/', retries=Retry(10)) - - Retries can be disabled by passing ``False``:: - - response = http.request('GET', 'http://example.com/', retries=False) - - Errors will be wrapped in :class:`~urllib3.exceptions.MaxRetryError` unless - retries are disabled, in which case the causing exception will be raised. - - :param int total: - Total number of retries to allow. Takes precedence over other counts. - - Set to ``None`` to remove this constraint and fall back on other - counts. It's a good idea to set this to some sensibly-high value to - account for unexpected edge cases and avoid infinite retry loops. - - Set to ``0`` to fail on the first retry. - - Set to ``False`` to disable and imply ``raise_on_redirect=False``. - - :param int connect: - How many connection-related errors to retry on. - - These are errors raised before the request is sent to the remote server, - which we assume has not triggered the server to process the request. - - Set to ``0`` to fail on the first retry of this type. - - :param int read: - How many times to retry on read errors. - - These errors are raised after the request was sent to the server, so the - request may have side-effects. - - Set to ``0`` to fail on the first retry of this type. - - :param int redirect: - How many redirects to perform. Limit this to avoid infinite redirect - loops. - - A redirect is a HTTP response with a status code 301, 302, 303, 307 or - 308. - - Set to ``0`` to fail on the first retry of this type. - - Set to ``False`` to disable and imply ``raise_on_redirect=False``. - - :param int status: - How many times to retry on bad status codes. - - These are retries made on responses, where status code matches - ``status_forcelist``. - - Set to ``0`` to fail on the first retry of this type. - - :param iterable method_whitelist: - Set of uppercased HTTP method verbs that we should retry on. - - By default, we only retry on methods which are considered to be - idempotent (multiple requests with the same parameters end with the - same state). See :attr:`Retry.DEFAULT_METHOD_WHITELIST`. - - Set to a ``False`` value to retry on any verb. - - :param iterable status_forcelist: - A set of integer HTTP status codes that we should force a retry on. - A retry is initiated if the request method is in ``method_whitelist`` - and the response status code is in ``status_forcelist``. - - By default, this is disabled with ``None``. - - :param float backoff_factor: - A backoff factor to apply between attempts after the second try - (most errors are resolved immediately by a second try without a - delay). urllib3 will sleep for:: - - {backoff factor} * (2 ** ({number of total retries} - 1)) - - seconds. If the backoff_factor is 0.1, then :func:`.sleep` will sleep - for [0.0s, 0.2s, 0.4s, ...] between retries. It will never be longer - than :attr:`Retry.BACKOFF_MAX`. - - By default, backoff is disabled (set to 0). - - :param bool raise_on_redirect: Whether, if the number of redirects is - exhausted, to raise a MaxRetryError, or to return a response with a - response code in the 3xx range. - - :param bool raise_on_status: Similar meaning to ``raise_on_redirect``: - whether we should raise an exception, or return a response, - if status falls in ``status_forcelist`` range and retries have - been exhausted. - - :param tuple history: The history of the request encountered during - each call to :meth:`~Retry.increment`. The list is in the order - the requests occurred. Each list item is of class :class:`RequestHistory`. - - :param bool respect_retry_after_header: - Whether to respect Retry-After header on status codes defined as - :attr:`Retry.RETRY_AFTER_STATUS_CODES` or not. - - :param iterable remove_headers_on_redirect: - Sequence of headers to remove from the request when a response - indicating a redirect is returned before firing off the redirected - request. - """ - - DEFAULT_METHOD_WHITELIST = frozenset([ - 'HEAD', 'GET', 'PUT', 'DELETE', 'OPTIONS', 'TRACE']) - - RETRY_AFTER_STATUS_CODES = frozenset([413, 429, 503]) - - DEFAULT_REDIRECT_HEADERS_BLACKLIST = frozenset(['Authorization']) - - #: Maximum backoff time. - BACKOFF_MAX = 120 - - def __init__(self, total=10, connect=None, read=None, redirect=None, status=None, - method_whitelist=DEFAULT_METHOD_WHITELIST, status_forcelist=None, - backoff_factor=0, raise_on_redirect=True, raise_on_status=True, - history=None, respect_retry_after_header=True, - remove_headers_on_redirect=DEFAULT_REDIRECT_HEADERS_BLACKLIST): - - self.total = total - self.connect = connect - self.read = read - self.status = status - - if redirect is False or total is False: - redirect = 0 - raise_on_redirect = False - - self.redirect = redirect - self.status_forcelist = status_forcelist or set() - self.method_whitelist = method_whitelist - self.backoff_factor = backoff_factor - self.raise_on_redirect = raise_on_redirect - self.raise_on_status = raise_on_status - self.history = history or tuple() - self.respect_retry_after_header = respect_retry_after_header - self.remove_headers_on_redirect = remove_headers_on_redirect - - def new(self, **kw): - params = dict( - total=self.total, - connect=self.connect, read=self.read, redirect=self.redirect, status=self.status, - method_whitelist=self.method_whitelist, - status_forcelist=self.status_forcelist, - backoff_factor=self.backoff_factor, - raise_on_redirect=self.raise_on_redirect, - raise_on_status=self.raise_on_status, - history=self.history, - remove_headers_on_redirect=self.remove_headers_on_redirect - ) - params.update(kw) - return type(self)(**params) - - @classmethod - def from_int(cls, retries, redirect=True, default=None): - """ Backwards-compatibility for the old retries format.""" - if retries is None: - retries = default if default is not None else cls.DEFAULT - - if isinstance(retries, Retry): - return retries - - redirect = bool(redirect) and None - new_retries = cls(retries, redirect=redirect) - log.debug("Converted retries value: %r -> %r", retries, new_retries) - return new_retries - - def get_backoff_time(self): - """ Formula for computing the current backoff - - :rtype: float - """ - # We want to consider only the last consecutive errors sequence (Ignore redirects). - consecutive_errors_len = len(list(takewhile(lambda x: x.redirect_location is None, - reversed(self.history)))) - if consecutive_errors_len <= 1: - return 0 - - backoff_value = self.backoff_factor * (2 ** (consecutive_errors_len - 1)) - return min(self.BACKOFF_MAX, backoff_value) - - def parse_retry_after(self, retry_after): - # Whitespace: https://tools.ietf.org/html/rfc7230#section-3.2.4 - if re.match(r"^\s*[0-9]+\s*$", retry_after): - seconds = int(retry_after) - else: - retry_date_tuple = email.utils.parsedate(retry_after) - if retry_date_tuple is None: - raise InvalidHeader("Invalid Retry-After header: %s" % retry_after) - retry_date = time.mktime(retry_date_tuple) - seconds = retry_date - time.time() - - if seconds < 0: - seconds = 0 - - return seconds - - def get_retry_after(self, response): - """ Get the value of Retry-After in seconds. """ - - retry_after = response.getheader("Retry-After") - - if retry_after is None: - return None - - return self.parse_retry_after(retry_after) - - def sleep_for_retry(self, response=None): - retry_after = self.get_retry_after(response) - if retry_after: - time.sleep(retry_after) - return True - - return False - - def _sleep_backoff(self): - backoff = self.get_backoff_time() - if backoff <= 0: - return - time.sleep(backoff) - - def sleep(self, response=None): - """ Sleep between retry attempts. - - This method will respect a server's ``Retry-After`` response header - and sleep the duration of the time requested. If that is not present, it - will use an exponential backoff. By default, the backoff factor is 0 and - this method will return immediately. - """ - - if response: - slept = self.sleep_for_retry(response) - if slept: - return - - self._sleep_backoff() - - def _is_connection_error(self, err): - """ Errors when we're fairly sure that the server did not receive the - request, so it should be safe to retry. - """ - return isinstance(err, ConnectTimeoutError) - - def _is_read_error(self, err): - """ Errors that occur after the request has been started, so we should - assume that the server began processing it. - """ - return isinstance(err, (ReadTimeoutError, ProtocolError)) - - def _is_method_retryable(self, method): - """ Checks if a given HTTP method should be retried upon, depending if - it is included on the method whitelist. - """ - if self.method_whitelist and method.upper() not in self.method_whitelist: - return False - - return True - - def is_retry(self, method, status_code, has_retry_after=False): - """ Is this method/status code retryable? (Based on whitelists and control - variables such as the number of total retries to allow, whether to - respect the Retry-After header, whether this header is present, and - whether the returned status code is on the list of status codes to - be retried upon on the presence of the aforementioned header) - """ - if not self._is_method_retryable(method): - return False - - if self.status_forcelist and status_code in self.status_forcelist: - return True - - return (self.total and self.respect_retry_after_header and - has_retry_after and (status_code in self.RETRY_AFTER_STATUS_CODES)) - - def is_exhausted(self): - """ Are we out of retries? """ - retry_counts = (self.total, self.connect, self.read, self.redirect, self.status) - retry_counts = list(filter(None, retry_counts)) - if not retry_counts: - return False - - return min(retry_counts) < 0 - - def increment(self, method=None, url=None, response=None, error=None, - _pool=None, _stacktrace=None): - """ Return a new Retry object with incremented retry counters. - - :param response: A response object, or None, if the server did not - return a response. - :type response: :class:`~urllib3.response.HTTPResponse` - :param Exception error: An error encountered during the request, or - None if the response was received successfully. - - :return: A new ``Retry`` object. - """ - if self.total is False and error: - # Disabled, indicate to re-raise the error. - raise six.reraise(type(error), error, _stacktrace) - - total = self.total - if total is not None: - total -= 1 - - connect = self.connect - read = self.read - redirect = self.redirect - status_count = self.status - cause = 'unknown' - status = None - redirect_location = None - - if error and self._is_connection_error(error): - # Connect retry? - if connect is False: - raise six.reraise(type(error), error, _stacktrace) - elif connect is not None: - connect -= 1 - - elif error and self._is_read_error(error): - # Read retry? - if read is False or not self._is_method_retryable(method): - raise six.reraise(type(error), error, _stacktrace) - elif read is not None: - read -= 1 - - elif response and response.get_redirect_location(): - # Redirect retry? - if redirect is not None: - redirect -= 1 - cause = 'too many redirects' - redirect_location = response.get_redirect_location() - status = response.status - - else: - # Incrementing because of a server error like a 500 in - # status_forcelist and a the given method is in the whitelist - cause = ResponseError.GENERIC_ERROR - if response and response.status: - if status_count is not None: - status_count -= 1 - cause = ResponseError.SPECIFIC_ERROR.format( - status_code=response.status) - status = response.status - - history = self.history + (RequestHistory(method, url, error, status, redirect_location),) - - new_retry = self.new( - total=total, - connect=connect, read=read, redirect=redirect, status=status_count, - history=history) - - if new_retry.is_exhausted(): - raise MaxRetryError(_pool, url, error or ResponseError(cause)) - - log.debug("Incremented Retry for (url='%s'): %r", url, new_retry) - - return new_retry - - def __repr__(self): - return ('{cls.__name__}(total={self.total}, connect={self.connect}, ' - 'read={self.read}, redirect={self.redirect}, status={self.status})').format( - cls=type(self), self=self) - - -# For backwards compatibility (equivalent to pre-v1.9): -Retry.DEFAULT = Retry(3) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/ssl_.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/ssl_.py deleted file mode 100644 index dfc553f..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/ssl_.py +++ /dev/null @@ -1,381 +0,0 @@ -from __future__ import absolute_import -import errno -import warnings -import hmac -import socket - -from binascii import hexlify, unhexlify -from hashlib import md5, sha1, sha256 - -from ..exceptions import SSLError, InsecurePlatformWarning, SNIMissingWarning -from ..packages import six - - -SSLContext = None -HAS_SNI = False -IS_PYOPENSSL = False -IS_SECURETRANSPORT = False - -# Maps the length of a digest to a possible hash function producing this digest -HASHFUNC_MAP = { - 32: md5, - 40: sha1, - 64: sha256, -} - - -def _const_compare_digest_backport(a, b): - """ - Compare two digests of equal length in constant time. - - The digests must be of type str/bytes. - Returns True if the digests match, and False otherwise. - """ - result = abs(len(a) - len(b)) - for l, r in zip(bytearray(a), bytearray(b)): - result |= l ^ r - return result == 0 - - -_const_compare_digest = getattr(hmac, 'compare_digest', - _const_compare_digest_backport) - - -try: # Test for SSL features - import ssl - from ssl import wrap_socket, CERT_NONE, PROTOCOL_SSLv23 - from ssl import HAS_SNI # Has SNI? -except ImportError: - pass - - -try: - from ssl import OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_COMPRESSION -except ImportError: - OP_NO_SSLv2, OP_NO_SSLv3 = 0x1000000, 0x2000000 - OP_NO_COMPRESSION = 0x20000 - - -# Python 2.7 doesn't have inet_pton on non-Linux so we fallback on inet_aton in -# those cases. This means that we can only detect IPv4 addresses in this case. -if hasattr(socket, 'inet_pton'): - inet_pton = socket.inet_pton -else: - # Maybe we can use ipaddress if the user has urllib3[secure]? - try: - from pip._vendor import ipaddress - - def inet_pton(_, host): - if isinstance(host, bytes): - host = host.decode('ascii') - return ipaddress.ip_address(host) - - except ImportError: # Platform-specific: Non-Linux - def inet_pton(_, host): - return socket.inet_aton(host) - - -# A secure default. -# Sources for more information on TLS ciphers: -# -# - https://wiki.mozilla.org/Security/Server_Side_TLS -# - https://www.ssllabs.com/projects/best-practices/index.html -# - https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ -# -# The general intent is: -# - Prefer TLS 1.3 cipher suites -# - prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE), -# - prefer ECDHE over DHE for better performance, -# - prefer any AES-GCM and ChaCha20 over any AES-CBC for better performance and -# security, -# - prefer AES-GCM over ChaCha20 because hardware-accelerated AES is common, -# - disable NULL authentication, MD5 MACs and DSS for security reasons. -DEFAULT_CIPHERS = ':'.join([ - 'TLS13-AES-256-GCM-SHA384', - 'TLS13-CHACHA20-POLY1305-SHA256', - 'TLS13-AES-128-GCM-SHA256', - 'ECDH+AESGCM', - 'ECDH+CHACHA20', - 'DH+AESGCM', - 'DH+CHACHA20', - 'ECDH+AES256', - 'DH+AES256', - 'ECDH+AES128', - 'DH+AES', - 'RSA+AESGCM', - 'RSA+AES', - '!aNULL', - '!eNULL', - '!MD5', -]) - -try: - from ssl import SSLContext # Modern SSL? -except ImportError: - import sys - - class SSLContext(object): # Platform-specific: Python 2 - def __init__(self, protocol_version): - self.protocol = protocol_version - # Use default values from a real SSLContext - self.check_hostname = False - self.verify_mode = ssl.CERT_NONE - self.ca_certs = None - self.options = 0 - self.certfile = None - self.keyfile = None - self.ciphers = None - - def load_cert_chain(self, certfile, keyfile): - self.certfile = certfile - self.keyfile = keyfile - - def load_verify_locations(self, cafile=None, capath=None): - self.ca_certs = cafile - - if capath is not None: - raise SSLError("CA directories not supported in older Pythons") - - def set_ciphers(self, cipher_suite): - self.ciphers = cipher_suite - - def wrap_socket(self, socket, server_hostname=None, server_side=False): - warnings.warn( - 'A true SSLContext object is not available. This prevents ' - 'urllib3 from configuring SSL appropriately and may cause ' - 'certain SSL connections to fail. You can upgrade to a newer ' - 'version of Python to solve this. For more information, see ' - 'https://urllib3.readthedocs.io/en/latest/advanced-usage.html' - '#ssl-warnings', - InsecurePlatformWarning - ) - kwargs = { - 'keyfile': self.keyfile, - 'certfile': self.certfile, - 'ca_certs': self.ca_certs, - 'cert_reqs': self.verify_mode, - 'ssl_version': self.protocol, - 'server_side': server_side, - } - return wrap_socket(socket, ciphers=self.ciphers, **kwargs) - - -def assert_fingerprint(cert, fingerprint): - """ - Checks if given fingerprint matches the supplied certificate. - - :param cert: - Certificate as bytes object. - :param fingerprint: - Fingerprint as string of hexdigits, can be interspersed by colons. - """ - - fingerprint = fingerprint.replace(':', '').lower() - digest_length = len(fingerprint) - hashfunc = HASHFUNC_MAP.get(digest_length) - if not hashfunc: - raise SSLError( - 'Fingerprint of invalid length: {0}'.format(fingerprint)) - - # We need encode() here for py32; works on py2 and p33. - fingerprint_bytes = unhexlify(fingerprint.encode()) - - cert_digest = hashfunc(cert).digest() - - if not _const_compare_digest(cert_digest, fingerprint_bytes): - raise SSLError('Fingerprints did not match. Expected "{0}", got "{1}".' - .format(fingerprint, hexlify(cert_digest))) - - -def resolve_cert_reqs(candidate): - """ - Resolves the argument to a numeric constant, which can be passed to - the wrap_socket function/method from the ssl module. - Defaults to :data:`ssl.CERT_NONE`. - If given a string it is assumed to be the name of the constant in the - :mod:`ssl` module or its abbreviation. - (So you can specify `REQUIRED` instead of `CERT_REQUIRED`. - If it's neither `None` nor a string we assume it is already the numeric - constant which can directly be passed to wrap_socket. - """ - if candidate is None: - return CERT_NONE - - if isinstance(candidate, str): - res = getattr(ssl, candidate, None) - if res is None: - res = getattr(ssl, 'CERT_' + candidate) - return res - - return candidate - - -def resolve_ssl_version(candidate): - """ - like resolve_cert_reqs - """ - if candidate is None: - return PROTOCOL_SSLv23 - - if isinstance(candidate, str): - res = getattr(ssl, candidate, None) - if res is None: - res = getattr(ssl, 'PROTOCOL_' + candidate) - return res - - return candidate - - -def create_urllib3_context(ssl_version=None, cert_reqs=None, - options=None, ciphers=None): - """All arguments have the same meaning as ``ssl_wrap_socket``. - - By default, this function does a lot of the same work that - ``ssl.create_default_context`` does on Python 3.4+. It: - - - Disables SSLv2, SSLv3, and compression - - Sets a restricted set of server ciphers - - If you wish to enable SSLv3, you can do:: - - from pip._vendor.urllib3.util import ssl_ - context = ssl_.create_urllib3_context() - context.options &= ~ssl_.OP_NO_SSLv3 - - You can do the same to enable compression (substituting ``COMPRESSION`` - for ``SSLv3`` in the last line above). - - :param ssl_version: - The desired protocol version to use. This will default to - PROTOCOL_SSLv23 which will negotiate the highest protocol that both - the server and your installation of OpenSSL support. - :param cert_reqs: - Whether to require the certificate verification. This defaults to - ``ssl.CERT_REQUIRED``. - :param options: - Specific OpenSSL options. These default to ``ssl.OP_NO_SSLv2``, - ``ssl.OP_NO_SSLv3``, ``ssl.OP_NO_COMPRESSION``. - :param ciphers: - Which cipher suites to allow the server to select. - :returns: - Constructed SSLContext object with specified options - :rtype: SSLContext - """ - context = SSLContext(ssl_version or ssl.PROTOCOL_SSLv23) - - context.set_ciphers(ciphers or DEFAULT_CIPHERS) - - # Setting the default here, as we may have no ssl module on import - cert_reqs = ssl.CERT_REQUIRED if cert_reqs is None else cert_reqs - - if options is None: - options = 0 - # SSLv2 is easily broken and is considered harmful and dangerous - options |= OP_NO_SSLv2 - # SSLv3 has several problems and is now dangerous - options |= OP_NO_SSLv3 - # Disable compression to prevent CRIME attacks for OpenSSL 1.0+ - # (issue #309) - options |= OP_NO_COMPRESSION - - context.options |= options - - context.verify_mode = cert_reqs - if getattr(context, 'check_hostname', None) is not None: # Platform-specific: Python 3.2 - # We do our own verification, including fingerprints and alternative - # hostnames. So disable it here - context.check_hostname = False - return context - - -def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None, - ca_certs=None, server_hostname=None, - ssl_version=None, ciphers=None, ssl_context=None, - ca_cert_dir=None): - """ - All arguments except for server_hostname, ssl_context, and ca_cert_dir have - the same meaning as they do when using :func:`ssl.wrap_socket`. - - :param server_hostname: - When SNI is supported, the expected hostname of the certificate - :param ssl_context: - A pre-made :class:`SSLContext` object. If none is provided, one will - be created using :func:`create_urllib3_context`. - :param ciphers: - A string of ciphers we wish the client to support. - :param ca_cert_dir: - A directory containing CA certificates in multiple separate files, as - supported by OpenSSL's -CApath flag or the capath argument to - SSLContext.load_verify_locations(). - """ - context = ssl_context - if context is None: - # Note: This branch of code and all the variables in it are no longer - # used by urllib3 itself. We should consider deprecating and removing - # this code. - context = create_urllib3_context(ssl_version, cert_reqs, - ciphers=ciphers) - - if ca_certs or ca_cert_dir: - try: - context.load_verify_locations(ca_certs, ca_cert_dir) - except IOError as e: # Platform-specific: Python 2.7 - raise SSLError(e) - # Py33 raises FileNotFoundError which subclasses OSError - # These are not equivalent unless we check the errno attribute - except OSError as e: # Platform-specific: Python 3.3 and beyond - if e.errno == errno.ENOENT: - raise SSLError(e) - raise - elif getattr(context, 'load_default_certs', None) is not None: - # try to load OS default certs; works well on Windows (require Python3.4+) - context.load_default_certs() - - if certfile: - context.load_cert_chain(certfile, keyfile) - - # If we detect server_hostname is an IP address then the SNI - # extension should not be used according to RFC3546 Section 3.1 - # We shouldn't warn the user if SNI isn't available but we would - # not be using SNI anyways due to IP address for server_hostname. - if ((server_hostname is not None and not is_ipaddress(server_hostname)) - or IS_SECURETRANSPORT): - if HAS_SNI and server_hostname is not None: - return context.wrap_socket(sock, server_hostname=server_hostname) - - warnings.warn( - 'An HTTPS request has been made, but the SNI (Server Name ' - 'Indication) extension to TLS is not available on this platform. ' - 'This may cause the server to present an incorrect TLS ' - 'certificate, which can cause validation failures. You can upgrade to ' - 'a newer version of Python to solve this. For more information, see ' - 'https://urllib3.readthedocs.io/en/latest/advanced-usage.html' - '#ssl-warnings', - SNIMissingWarning - ) - - return context.wrap_socket(sock) - - -def is_ipaddress(hostname): - """Detects whether the hostname given is an IP address. - - :param str hostname: Hostname to examine. - :return: True if the hostname is an IP address, False otherwise. - """ - if six.PY3 and isinstance(hostname, bytes): - # IDN A-label bytes are ASCII compatible. - hostname = hostname.decode('ascii') - - families = [socket.AF_INET] - if hasattr(socket, 'AF_INET6'): - families.append(socket.AF_INET6) - - for af in families: - try: - inet_pton(af, hostname) - except (socket.error, ValueError, OSError): - pass - else: - return True - return False diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/timeout.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/timeout.py deleted file mode 100644 index cec817e..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/timeout.py +++ /dev/null @@ -1,242 +0,0 @@ -from __future__ import absolute_import -# The default socket timeout, used by httplib to indicate that no timeout was -# specified by the user -from socket import _GLOBAL_DEFAULT_TIMEOUT -import time - -from ..exceptions import TimeoutStateError - -# A sentinel value to indicate that no timeout was specified by the user in -# urllib3 -_Default = object() - - -# Use time.monotonic if available. -current_time = getattr(time, "monotonic", time.time) - - -class Timeout(object): - """ Timeout configuration. - - Timeouts can be defined as a default for a pool:: - - timeout = Timeout(connect=2.0, read=7.0) - http = PoolManager(timeout=timeout) - response = http.request('GET', 'http://example.com/') - - Or per-request (which overrides the default for the pool):: - - response = http.request('GET', 'http://example.com/', timeout=Timeout(10)) - - Timeouts can be disabled by setting all the parameters to ``None``:: - - no_timeout = Timeout(connect=None, read=None) - response = http.request('GET', 'http://example.com/, timeout=no_timeout) - - - :param total: - This combines the connect and read timeouts into one; the read timeout - will be set to the time leftover from the connect attempt. In the - event that both a connect timeout and a total are specified, or a read - timeout and a total are specified, the shorter timeout will be applied. - - Defaults to None. - - :type total: integer, float, or None - - :param connect: - The maximum amount of time to wait for a connection attempt to a server - to succeed. Omitting the parameter will default the connect timeout to - the system default, probably `the global default timeout in socket.py - <http://hg.python.org/cpython/file/603b4d593758/Lib/socket.py#l535>`_. - None will set an infinite timeout for connection attempts. - - :type connect: integer, float, or None - - :param read: - The maximum amount of time to wait between consecutive - read operations for a response from the server. Omitting - the parameter will default the read timeout to the system - default, probably `the global default timeout in socket.py - <http://hg.python.org/cpython/file/603b4d593758/Lib/socket.py#l535>`_. - None will set an infinite timeout. - - :type read: integer, float, or None - - .. note:: - - Many factors can affect the total amount of time for urllib3 to return - an HTTP response. - - For example, Python's DNS resolver does not obey the timeout specified - on the socket. Other factors that can affect total request time include - high CPU load, high swap, the program running at a low priority level, - or other behaviors. - - In addition, the read and total timeouts only measure the time between - read operations on the socket connecting the client and the server, - not the total amount of time for the request to return a complete - response. For most requests, the timeout is raised because the server - has not sent the first byte in the specified time. This is not always - the case; if a server streams one byte every fifteen seconds, a timeout - of 20 seconds will not trigger, even though the request will take - several minutes to complete. - - If your goal is to cut off any request after a set amount of wall clock - time, consider having a second "watcher" thread to cut off a slow - request. - """ - - #: A sentinel object representing the default timeout value - DEFAULT_TIMEOUT = _GLOBAL_DEFAULT_TIMEOUT - - def __init__(self, total=None, connect=_Default, read=_Default): - self._connect = self._validate_timeout(connect, 'connect') - self._read = self._validate_timeout(read, 'read') - self.total = self._validate_timeout(total, 'total') - self._start_connect = None - - def __str__(self): - return '%s(connect=%r, read=%r, total=%r)' % ( - type(self).__name__, self._connect, self._read, self.total) - - @classmethod - def _validate_timeout(cls, value, name): - """ Check that a timeout attribute is valid. - - :param value: The timeout value to validate - :param name: The name of the timeout attribute to validate. This is - used to specify in error messages. - :return: The validated and casted version of the given value. - :raises ValueError: If it is a numeric value less than or equal to - zero, or the type is not an integer, float, or None. - """ - if value is _Default: - return cls.DEFAULT_TIMEOUT - - if value is None or value is cls.DEFAULT_TIMEOUT: - return value - - if isinstance(value, bool): - raise ValueError("Timeout cannot be a boolean value. It must " - "be an int, float or None.") - try: - float(value) - except (TypeError, ValueError): - raise ValueError("Timeout value %s was %s, but it must be an " - "int, float or None." % (name, value)) - - try: - if value <= 0: - raise ValueError("Attempted to set %s timeout to %s, but the " - "timeout cannot be set to a value less " - "than or equal to 0." % (name, value)) - except TypeError: # Python 3 - raise ValueError("Timeout value %s was %s, but it must be an " - "int, float or None." % (name, value)) - - return value - - @classmethod - def from_float(cls, timeout): - """ Create a new Timeout from a legacy timeout value. - - The timeout value used by httplib.py sets the same timeout on the - connect(), and recv() socket requests. This creates a :class:`Timeout` - object that sets the individual timeouts to the ``timeout`` value - passed to this function. - - :param timeout: The legacy timeout value. - :type timeout: integer, float, sentinel default object, or None - :return: Timeout object - :rtype: :class:`Timeout` - """ - return Timeout(read=timeout, connect=timeout) - - def clone(self): - """ Create a copy of the timeout object - - Timeout properties are stored per-pool but each request needs a fresh - Timeout object to ensure each one has its own start/stop configured. - - :return: a copy of the timeout object - :rtype: :class:`Timeout` - """ - # We can't use copy.deepcopy because that will also create a new object - # for _GLOBAL_DEFAULT_TIMEOUT, which socket.py uses as a sentinel to - # detect the user default. - return Timeout(connect=self._connect, read=self._read, - total=self.total) - - def start_connect(self): - """ Start the timeout clock, used during a connect() attempt - - :raises urllib3.exceptions.TimeoutStateError: if you attempt - to start a timer that has been started already. - """ - if self._start_connect is not None: - raise TimeoutStateError("Timeout timer has already been started.") - self._start_connect = current_time() - return self._start_connect - - def get_connect_duration(self): - """ Gets the time elapsed since the call to :meth:`start_connect`. - - :return: Elapsed time. - :rtype: float - :raises urllib3.exceptions.TimeoutStateError: if you attempt - to get duration for a timer that hasn't been started. - """ - if self._start_connect is None: - raise TimeoutStateError("Can't get connect duration for timer " - "that has not started.") - return current_time() - self._start_connect - - @property - def connect_timeout(self): - """ Get the value to use when setting a connection timeout. - - This will be a positive float or integer, the value None - (never timeout), or the default system timeout. - - :return: Connect timeout. - :rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None - """ - if self.total is None: - return self._connect - - if self._connect is None or self._connect is self.DEFAULT_TIMEOUT: - return self.total - - return min(self._connect, self.total) - - @property - def read_timeout(self): - """ Get the value for the read timeout. - - This assumes some time has elapsed in the connection timeout and - computes the read timeout appropriately. - - If self.total is set, the read timeout is dependent on the amount of - time taken by the connect timeout. If the connection time has not been - established, a :exc:`~urllib3.exceptions.TimeoutStateError` will be - raised. - - :return: Value to use for the read timeout. - :rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None - :raises urllib3.exceptions.TimeoutStateError: If :meth:`start_connect` - has not yet been called on this object. - """ - if (self.total is not None and - self.total is not self.DEFAULT_TIMEOUT and - self._read is not None and - self._read is not self.DEFAULT_TIMEOUT): - # In case the connect timeout has not yet been established. - if self._start_connect is None: - return self._read - return max(0, min(self.total - self.get_connect_duration(), - self._read)) - elif self.total is not None and self.total is not self.DEFAULT_TIMEOUT: - return max(0, self.total - self.get_connect_duration()) - else: - return self._read diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/url.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/url.py deleted file mode 100644 index 6b6f996..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/url.py +++ /dev/null @@ -1,230 +0,0 @@ -from __future__ import absolute_import -from collections import namedtuple - -from ..exceptions import LocationParseError - - -url_attrs = ['scheme', 'auth', 'host', 'port', 'path', 'query', 'fragment'] - -# We only want to normalize urls with an HTTP(S) scheme. -# urllib3 infers URLs without a scheme (None) to be http. -NORMALIZABLE_SCHEMES = ('http', 'https', None) - - -class Url(namedtuple('Url', url_attrs)): - """ - Datastructure for representing an HTTP URL. Used as a return value for - :func:`parse_url`. Both the scheme and host are normalized as they are - both case-insensitive according to RFC 3986. - """ - __slots__ = () - - def __new__(cls, scheme=None, auth=None, host=None, port=None, path=None, - query=None, fragment=None): - if path and not path.startswith('/'): - path = '/' + path - if scheme: - scheme = scheme.lower() - if host and scheme in NORMALIZABLE_SCHEMES: - host = host.lower() - return super(Url, cls).__new__(cls, scheme, auth, host, port, path, - query, fragment) - - @property - def hostname(self): - """For backwards-compatibility with urlparse. We're nice like that.""" - return self.host - - @property - def request_uri(self): - """Absolute path including the query string.""" - uri = self.path or '/' - - if self.query is not None: - uri += '?' + self.query - - return uri - - @property - def netloc(self): - """Network location including host and port""" - if self.port: - return '%s:%d' % (self.host, self.port) - return self.host - - @property - def url(self): - """ - Convert self into a url - - This function should more or less round-trip with :func:`.parse_url`. The - returned url may not be exactly the same as the url inputted to - :func:`.parse_url`, but it should be equivalent by the RFC (e.g., urls - with a blank port will have : removed). - - Example: :: - - >>> U = parse_url('http://google.com/mail/') - >>> U.url - 'http://google.com/mail/' - >>> Url('http', 'username:password', 'host.com', 80, - ... '/path', 'query', 'fragment').url - 'http://username:password@host.com:80/path?query#fragment' - """ - scheme, auth, host, port, path, query, fragment = self - url = '' - - # We use "is not None" we want things to happen with empty strings (or 0 port) - if scheme is not None: - url += scheme + '://' - if auth is not None: - url += auth + '@' - if host is not None: - url += host - if port is not None: - url += ':' + str(port) - if path is not None: - url += path - if query is not None: - url += '?' + query - if fragment is not None: - url += '#' + fragment - - return url - - def __str__(self): - return self.url - - -def split_first(s, delims): - """ - Given a string and an iterable of delimiters, split on the first found - delimiter. Return two split parts and the matched delimiter. - - If not found, then the first part is the full input string. - - Example:: - - >>> split_first('foo/bar?baz', '?/=') - ('foo', 'bar?baz', '/') - >>> split_first('foo/bar?baz', '123') - ('foo/bar?baz', '', None) - - Scales linearly with number of delims. Not ideal for large number of delims. - """ - min_idx = None - min_delim = None - for d in delims: - idx = s.find(d) - if idx < 0: - continue - - if min_idx is None or idx < min_idx: - min_idx = idx - min_delim = d - - if min_idx is None or min_idx < 0: - return s, '', None - - return s[:min_idx], s[min_idx + 1:], min_delim - - -def parse_url(url): - """ - Given a url, return a parsed :class:`.Url` namedtuple. Best-effort is - performed to parse incomplete urls. Fields not provided will be None. - - Partly backwards-compatible with :mod:`urlparse`. - - Example:: - - >>> parse_url('http://google.com/mail/') - Url(scheme='http', host='google.com', port=None, path='/mail/', ...) - >>> parse_url('google.com:80') - Url(scheme=None, host='google.com', port=80, path=None, ...) - >>> parse_url('/foo?bar') - Url(scheme=None, host=None, port=None, path='/foo', query='bar', ...) - """ - - # While this code has overlap with stdlib's urlparse, it is much - # simplified for our needs and less annoying. - # Additionally, this implementations does silly things to be optimal - # on CPython. - - if not url: - # Empty - return Url() - - scheme = None - auth = None - host = None - port = None - path = None - fragment = None - query = None - - # Scheme - if '://' in url: - scheme, url = url.split('://', 1) - - # Find the earliest Authority Terminator - # (http://tools.ietf.org/html/rfc3986#section-3.2) - url, path_, delim = split_first(url, ['/', '?', '#']) - - if delim: - # Reassemble the path - path = delim + path_ - - # Auth - if '@' in url: - # Last '@' denotes end of auth part - auth, url = url.rsplit('@', 1) - - # IPv6 - if url and url[0] == '[': - host, url = url.split(']', 1) - host += ']' - - # Port - if ':' in url: - _host, port = url.split(':', 1) - - if not host: - host = _host - - if port: - # If given, ports must be integers. No whitespace, no plus or - # minus prefixes, no non-integer digits such as ^2 (superscript). - if not port.isdigit(): - raise LocationParseError(url) - try: - port = int(port) - except ValueError: - raise LocationParseError(url) - else: - # Blank ports are cool, too. (rfc3986#section-3.2.3) - port = None - - elif not host and url: - host = url - - if not path: - return Url(scheme, auth, host, port, path, query, fragment) - - # Fragment - if '#' in path: - path, fragment = path.split('#', 1) - - # Query - if '?' in path: - path, query = path.split('?', 1) - - return Url(scheme, auth, host, port, path, query, fragment) - - -def get_host(url): - """ - Deprecated. Use :func:`parse_url` instead. - """ - p = parse_url(url) - return p.scheme or 'http', p.hostname, p.port diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/wait.py b/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/wait.py deleted file mode 100644 index 4db71ba..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/urllib3/util/wait.py +++ /dev/null @@ -1,150 +0,0 @@ -import errno -from functools import partial -import select -import sys -try: - from time import monotonic -except ImportError: - from time import time as monotonic - -__all__ = ["NoWayToWaitForSocketError", "wait_for_read", "wait_for_write"] - - -class NoWayToWaitForSocketError(Exception): - pass - - -# How should we wait on sockets? -# -# There are two types of APIs you can use for waiting on sockets: the fancy -# modern stateful APIs like epoll/kqueue, and the older stateless APIs like -# select/poll. The stateful APIs are more efficient when you have a lots of -# sockets to keep track of, because you can set them up once and then use them -# lots of times. But we only ever want to wait on a single socket at a time -# and don't want to keep track of state, so the stateless APIs are actually -# more efficient. So we want to use select() or poll(). -# -# Now, how do we choose between select() and poll()? On traditional Unixes, -# select() has a strange calling convention that makes it slow, or fail -# altogether, for high-numbered file descriptors. The point of poll() is to fix -# that, so on Unixes, we prefer poll(). -# -# On Windows, there is no poll() (or at least Python doesn't provide a wrapper -# for it), but that's OK, because on Windows, select() doesn't have this -# strange calling convention; plain select() works fine. -# -# So: on Windows we use select(), and everywhere else we use poll(). We also -# fall back to select() in case poll() is somehow broken or missing. - -if sys.version_info >= (3, 5): - # Modern Python, that retries syscalls by default - def _retry_on_intr(fn, timeout): - return fn(timeout) -else: - # Old and broken Pythons. - def _retry_on_intr(fn, timeout): - if timeout is None: - deadline = float("inf") - else: - deadline = monotonic() + timeout - - while True: - try: - return fn(timeout) - # OSError for 3 <= pyver < 3.5, select.error for pyver <= 2.7 - except (OSError, select.error) as e: - # 'e.args[0]' incantation works for both OSError and select.error - if e.args[0] != errno.EINTR: - raise - else: - timeout = deadline - monotonic() - if timeout < 0: - timeout = 0 - if timeout == float("inf"): - timeout = None - continue - - -def select_wait_for_socket(sock, read=False, write=False, timeout=None): - if not read and not write: - raise RuntimeError("must specify at least one of read=True, write=True") - rcheck = [] - wcheck = [] - if read: - rcheck.append(sock) - if write: - wcheck.append(sock) - # When doing a non-blocking connect, most systems signal success by - # marking the socket writable. Windows, though, signals success by marked - # it as "exceptional". We paper over the difference by checking the write - # sockets for both conditions. (The stdlib selectors module does the same - # thing.) - fn = partial(select.select, rcheck, wcheck, wcheck) - rready, wready, xready = _retry_on_intr(fn, timeout) - return bool(rready or wready or xready) - - -def poll_wait_for_socket(sock, read=False, write=False, timeout=None): - if not read and not write: - raise RuntimeError("must specify at least one of read=True, write=True") - mask = 0 - if read: - mask |= select.POLLIN - if write: - mask |= select.POLLOUT - poll_obj = select.poll() - poll_obj.register(sock, mask) - - # For some reason, poll() takes timeout in milliseconds - def do_poll(t): - if t is not None: - t *= 1000 - return poll_obj.poll(t) - - return bool(_retry_on_intr(do_poll, timeout)) - - -def null_wait_for_socket(*args, **kwargs): - raise NoWayToWaitForSocketError("no select-equivalent available") - - -def _have_working_poll(): - # Apparently some systems have a select.poll that fails as soon as you try - # to use it, either due to strange configuration or broken monkeypatching - # from libraries like eventlet/greenlet. - try: - poll_obj = select.poll() - _retry_on_intr(poll_obj.poll, 0) - except (AttributeError, OSError): - return False - else: - return True - - -def wait_for_socket(*args, **kwargs): - # We delay choosing which implementation to use until the first time we're - # called. We could do it at import time, but then we might make the wrong - # decision if someone goes wild with monkeypatching select.poll after - # we're imported. - global wait_for_socket - if _have_working_poll(): - wait_for_socket = poll_wait_for_socket - elif hasattr(select, "select"): - wait_for_socket = select_wait_for_socket - else: # Platform-specific: Appengine. - wait_for_socket = null_wait_for_socket - return wait_for_socket(*args, **kwargs) - - -def wait_for_read(sock, timeout=None): - """ Waits for reading to be available on a given socket. - Returns True if the socket is readable, or False if the timeout expired. - """ - return wait_for_socket(sock, read=True, timeout=timeout) - - -def wait_for_write(sock, timeout=None): - """ Waits for writing to be available on a given socket. - Returns True if the socket is readable, or False if the timeout expired. - """ - return wait_for_socket(sock, write=True, timeout=timeout) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/__init__.py b/venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/__init__.py deleted file mode 100644 index d21d697..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/__init__.py +++ /dev/null @@ -1,342 +0,0 @@ -# coding: utf-8 -""" - - webencodings - ~~~~~~~~~~~~ - - This is a Python implementation of the `WHATWG Encoding standard - <http://encoding.spec.whatwg.org/>`. 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 - <http://encoding.spec.whatwg.org/#ascii-case-insensitive>`_ - matching of encoding labels. - The same matching is also used, among other things, - for `CSS keywords <http://dev.w3.org/csswg/css-values/#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 - <http://encoding.spec.whatwg.org/#concept-encoding-get>`_ 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 '<Encoding %s>' % 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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/labels.py b/venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/labels.py deleted file mode 100644 index 29cbf91..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/labels.py +++ /dev/null @@ -1,231 +0,0 @@ -""" - - 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', -} diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/mklabels.py b/venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/mklabels.py deleted file mode 100644 index 295dc92..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/mklabels.py +++ /dev/null @@ -1,59 +0,0 @@ -""" - - 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')) diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/tests.py b/venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/tests.py deleted file mode 100644 index e12c10d..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/tests.py +++ /dev/null @@ -1,153 +0,0 @@ -# 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 diff --git a/venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/x_user_defined.py b/venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/x_user_defined.py deleted file mode 100644 index d16e326..0000000 --- a/venv2/lib/python2.7/site-packages/pip/_vendor/webencodings/x_user_defined.py +++ /dev/null @@ -1,325 +0,0 @@ -# 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) diff --git a/venv2/lib/python2.7/site-packages/pkg_resources/__init__.py b/venv2/lib/python2.7/site-packages/pkg_resources/__init__.py deleted file mode 100644 index 97e08d6..0000000 --- a/venv2/lib/python2.7/site-packages/pkg_resources/__init__.py +++ /dev/null @@ -1,3286 +0,0 @@ -# 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 = sys.version[:3] -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 "" - value = self._get(self._fn(self.egg_info, name)) - return value.decode('utf-8') if six.PY3 else value - - 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<name>[^-]+) ( - -(?P<ver>[^-]+) ( - -py(?P<pyver>[^-]+) ( - -(?P<plat>.+) - )? - )? - )? - """, - 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<name>.+?)\s*' - r'=\s*' - r'(?P<module>[\w.]+)\s*' - r'(:\s*(?P<attr>[\w.]+))?\s*' - r'(?P<extras>\[.*\])?\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.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. - """ diff --git a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/__init__.py b/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.py b/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.py deleted file mode 100644 index ae67001..0000000 --- a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.py +++ /dev/null @@ -1,608 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# Copyright (c) 2005-2010 ActiveState Software Inc. -# Copyright (c) 2013 Eddy Petrișor - -"""Utilities for determining application-specific dirs. - -See <http://github.com/ActiveState/appdirs> for details and usage. -""" -# Dev Notes: -# - MSDN on where to store app data files: -# http://support.microsoft.com/default.aspx?scid=kb;en-us;310294#XSLTH3194121123120121120120 -# - Mac OS X: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/index.html -# - XDG spec for Un*x: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html - -__version_info__ = (1, 4, 3) -__version__ = '.'.join(map(str, __version_info__)) - - -import sys -import os - -PY3 = sys.version_info[0] == 3 - -if PY3: - unicode = str - -if sys.platform.startswith('java'): - import platform - os_name = platform.java_ver()[3][0] - if os_name.startswith('Windows'): # "Windows XP", "Windows 7", etc. - system = 'win32' - elif os_name.startswith('Mac'): # "Mac OS X", etc. - system = 'darwin' - else: # "Linux", "SunOS", "FreeBSD", etc. - # Setting this to "linux2" is not ideal, but only Windows or Mac - # are actually checked for and the rest of the module expects - # *sys.platform* style strings. - system = 'linux2' -else: - system = sys.platform - - - -def user_data_dir(appname=None, appauthor=None, version=None, roaming=False): - r"""Return full path to the user-specific data dir for this application. - - "appname" is the name of application. - If None, just the system directory is returned. - "appauthor" (only used on Windows) is the name of the - appauthor or distributing body for this application. Typically - it is the owning company name. This falls back to appname. You may - pass False to disable it. - "version" is an optional version path element to append to the - path. You might want to use this if you want multiple versions - of your app to be able to run independently. If used, this - would typically be "<major>.<minor>". - Only applied when appname is present. - "roaming" (boolean, default False) can be set True to use the Windows - roaming appdata directory. That means that for users on a Windows - network setup for roaming profiles, this user data will be - sync'd on login. See - <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> - for a discussion of issues. - - Typical user data directories are: - Mac OS X: ~/Library/Application Support/<AppName> - Unix: ~/.local/share/<AppName> # or in $XDG_DATA_HOME, if defined - Win XP (not roaming): C:\Documents and Settings\<username>\Application Data\<AppAuthor>\<AppName> - Win XP (roaming): C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName> - Win 7 (not roaming): C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName> - Win 7 (roaming): C:\Users\<username>\AppData\Roaming\<AppAuthor>\<AppName> - - For Unix, we follow the XDG spec and support $XDG_DATA_HOME. - That means, by default "~/.local/share/<AppName>". - """ - if system == "win32": - if appauthor is None: - appauthor = appname - const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA" - path = os.path.normpath(_get_win_folder(const)) - if appname: - if appauthor is not False: - path = os.path.join(path, appauthor, appname) - else: - path = os.path.join(path, appname) - elif system == 'darwin': - path = os.path.expanduser('~/Library/Application Support/') - if appname: - path = os.path.join(path, appname) - else: - path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/.local/share")) - if appname: - path = os.path.join(path, appname) - if appname and version: - path = os.path.join(path, version) - return path - - -def site_data_dir(appname=None, appauthor=None, version=None, multipath=False): - r"""Return full path to the user-shared data dir for this application. - - "appname" is the name of application. - If None, just the system directory is returned. - "appauthor" (only used on Windows) is the name of the - appauthor or distributing body for this application. Typically - it is the owning company name. This falls back to appname. You may - pass False to disable it. - "version" is an optional version path element to append to the - path. You might want to use this if you want multiple versions - of your app to be able to run independently. If used, this - would typically be "<major>.<minor>". - Only applied when appname is present. - "multipath" is an optional parameter only applicable to *nix - which indicates that the entire list of data dirs should be - returned. By default, the first item from XDG_DATA_DIRS is - returned, or '/usr/local/share/<AppName>', - if XDG_DATA_DIRS is not set - - Typical site data directories are: - Mac OS X: /Library/Application Support/<AppName> - Unix: /usr/local/share/<AppName> or /usr/share/<AppName> - Win XP: C:\Documents and Settings\All Users\Application Data\<AppAuthor>\<AppName> - Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) - Win 7: C:\ProgramData\<AppAuthor>\<AppName> # Hidden, but writeable on Win 7. - - For Unix, this is using the $XDG_DATA_DIRS[0] default. - - WARNING: Do not use this on Windows. See the Vista-Fail note above for why. - """ - if system == "win32": - if appauthor is None: - appauthor = appname - path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA")) - if appname: - if appauthor is not False: - path = os.path.join(path, appauthor, appname) - else: - path = os.path.join(path, appname) - elif system == 'darwin': - path = os.path.expanduser('/Library/Application Support') - if appname: - path = os.path.join(path, appname) - else: - # XDG default for $XDG_DATA_DIRS - # only first, if multipath is False - path = os.getenv('XDG_DATA_DIRS', - os.pathsep.join(['/usr/local/share', '/usr/share'])) - pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] - if appname: - if version: - appname = os.path.join(appname, version) - pathlist = [os.sep.join([x, appname]) for x in pathlist] - - if multipath: - path = os.pathsep.join(pathlist) - else: - path = pathlist[0] - return path - - if appname and version: - path = os.path.join(path, version) - return path - - -def user_config_dir(appname=None, appauthor=None, version=None, roaming=False): - r"""Return full path to the user-specific config dir for this application. - - "appname" is the name of application. - If None, just the system directory is returned. - "appauthor" (only used on Windows) is the name of the - appauthor or distributing body for this application. Typically - it is the owning company name. This falls back to appname. You may - pass False to disable it. - "version" is an optional version path element to append to the - path. You might want to use this if you want multiple versions - of your app to be able to run independently. If used, this - would typically be "<major>.<minor>". - Only applied when appname is present. - "roaming" (boolean, default False) can be set True to use the Windows - roaming appdata directory. That means that for users on a Windows - network setup for roaming profiles, this user data will be - sync'd on login. See - <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> - for a discussion of issues. - - Typical user config directories are: - Mac OS X: same as user_data_dir - Unix: ~/.config/<AppName> # or in $XDG_CONFIG_HOME, if defined - Win *: same as user_data_dir - - For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME. - That means, by default "~/.config/<AppName>". - """ - if system in ["win32", "darwin"]: - path = user_data_dir(appname, appauthor, None, roaming) - else: - path = os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config")) - if appname: - path = os.path.join(path, appname) - if appname and version: - path = os.path.join(path, version) - return path - - -def site_config_dir(appname=None, appauthor=None, version=None, multipath=False): - r"""Return full path to the user-shared data dir for this application. - - "appname" is the name of application. - If None, just the system directory is returned. - "appauthor" (only used on Windows) is the name of the - appauthor or distributing body for this application. Typically - it is the owning company name. This falls back to appname. You may - pass False to disable it. - "version" is an optional version path element to append to the - path. You might want to use this if you want multiple versions - of your app to be able to run independently. If used, this - would typically be "<major>.<minor>". - Only applied when appname is present. - "multipath" is an optional parameter only applicable to *nix - which indicates that the entire list of config dirs should be - returned. By default, the first item from XDG_CONFIG_DIRS is - returned, or '/etc/xdg/<AppName>', if XDG_CONFIG_DIRS is not set - - Typical site config directories are: - Mac OS X: same as site_data_dir - Unix: /etc/xdg/<AppName> or $XDG_CONFIG_DIRS[i]/<AppName> for each value in - $XDG_CONFIG_DIRS - Win *: same as site_data_dir - Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) - - For Unix, this is using the $XDG_CONFIG_DIRS[0] default, if multipath=False - - WARNING: Do not use this on Windows. See the Vista-Fail note above for why. - """ - if system in ["win32", "darwin"]: - path = site_data_dir(appname, appauthor) - if appname and version: - path = os.path.join(path, version) - else: - # XDG default for $XDG_CONFIG_DIRS - # only first, if multipath is False - path = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg') - pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] - if appname: - if version: - appname = os.path.join(appname, version) - pathlist = [os.sep.join([x, appname]) for x in pathlist] - - if multipath: - path = os.pathsep.join(pathlist) - else: - path = pathlist[0] - return path - - -def user_cache_dir(appname=None, appauthor=None, version=None, opinion=True): - r"""Return full path to the user-specific cache dir for this application. - - "appname" is the name of application. - If None, just the system directory is returned. - "appauthor" (only used on Windows) is the name of the - appauthor or distributing body for this application. Typically - it is the owning company name. This falls back to appname. You may - pass False to disable it. - "version" is an optional version path element to append to the - path. You might want to use this if you want multiple versions - of your app to be able to run independently. If used, this - would typically be "<major>.<minor>". - Only applied when appname is present. - "opinion" (boolean) can be False to disable the appending of - "Cache" to the base app data dir for Windows. See - discussion below. - - Typical user cache directories are: - Mac OS X: ~/Library/Caches/<AppName> - Unix: ~/.cache/<AppName> (XDG default) - Win XP: C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Cache - Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Cache - - On Windows the only suggestion in the MSDN docs is that local settings go in - the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming - app data dir (the default returned by `user_data_dir` above). Apps typically - put cache data somewhere *under* the given dir here. Some examples: - ...\Mozilla\Firefox\Profiles\<ProfileName>\Cache - ...\Acme\SuperApp\Cache\1.0 - OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. - This can be disabled with the `opinion=False` option. - """ - if system == "win32": - if appauthor is None: - appauthor = appname - path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA")) - if appname: - if appauthor is not False: - path = os.path.join(path, appauthor, appname) - else: - path = os.path.join(path, appname) - if opinion: - path = os.path.join(path, "Cache") - elif system == 'darwin': - path = os.path.expanduser('~/Library/Caches') - if appname: - path = os.path.join(path, appname) - else: - path = os.getenv('XDG_CACHE_HOME', os.path.expanduser('~/.cache')) - if appname: - path = os.path.join(path, appname) - if appname and version: - path = os.path.join(path, version) - return path - - -def user_state_dir(appname=None, appauthor=None, version=None, roaming=False): - r"""Return full path to the user-specific state dir for this application. - - "appname" is the name of application. - If None, just the system directory is returned. - "appauthor" (only used on Windows) is the name of the - appauthor or distributing body for this application. Typically - it is the owning company name. This falls back to appname. You may - pass False to disable it. - "version" is an optional version path element to append to the - path. You might want to use this if you want multiple versions - of your app to be able to run independently. If used, this - would typically be "<major>.<minor>". - Only applied when appname is present. - "roaming" (boolean, default False) can be set True to use the Windows - roaming appdata directory. That means that for users on a Windows - network setup for roaming profiles, this user data will be - sync'd on login. See - <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> - for a discussion of issues. - - Typical user state directories are: - Mac OS X: same as user_data_dir - Unix: ~/.local/state/<AppName> # or in $XDG_STATE_HOME, if defined - Win *: same as user_data_dir - - For Unix, we follow this Debian proposal <https://wiki.debian.org/XDGBaseDirectorySpecification#state> - to extend the XDG spec and support $XDG_STATE_HOME. - - That means, by default "~/.local/state/<AppName>". - """ - if system in ["win32", "darwin"]: - path = user_data_dir(appname, appauthor, None, roaming) - else: - path = os.getenv('XDG_STATE_HOME', os.path.expanduser("~/.local/state")) - if appname: - path = os.path.join(path, appname) - if appname and version: - path = os.path.join(path, version) - return path - - -def user_log_dir(appname=None, appauthor=None, version=None, opinion=True): - r"""Return full path to the user-specific log dir for this application. - - "appname" is the name of application. - If None, just the system directory is returned. - "appauthor" (only used on Windows) is the name of the - appauthor or distributing body for this application. Typically - it is the owning company name. This falls back to appname. You may - pass False to disable it. - "version" is an optional version path element to append to the - path. You might want to use this if you want multiple versions - of your app to be able to run independently. If used, this - would typically be "<major>.<minor>". - Only applied when appname is present. - "opinion" (boolean) can be False to disable the appending of - "Logs" to the base app data dir for Windows, and "log" to the - base cache dir for Unix. See discussion below. - - Typical user log directories are: - Mac OS X: ~/Library/Logs/<AppName> - Unix: ~/.cache/<AppName>/log # or under $XDG_CACHE_HOME if defined - Win XP: C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Logs - Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Logs - - On Windows the only suggestion in the MSDN docs is that local settings - go in the `CSIDL_LOCAL_APPDATA` directory. (Note: I'm interested in - examples of what some windows apps use for a logs dir.) - - OPINION: This function appends "Logs" to the `CSIDL_LOCAL_APPDATA` - value for Windows and appends "log" to the user cache dir for Unix. - This can be disabled with the `opinion=False` option. - """ - if system == "darwin": - path = os.path.join( - os.path.expanduser('~/Library/Logs'), - appname) - elif system == "win32": - path = user_data_dir(appname, appauthor, version) - version = False - if opinion: - path = os.path.join(path, "Logs") - else: - path = user_cache_dir(appname, appauthor, version) - version = False - if opinion: - path = os.path.join(path, "log") - if appname and version: - path = os.path.join(path, version) - return path - - -class AppDirs(object): - """Convenience wrapper for getting application dirs.""" - def __init__(self, appname=None, appauthor=None, version=None, - roaming=False, multipath=False): - self.appname = appname - self.appauthor = appauthor - self.version = version - self.roaming = roaming - self.multipath = multipath - - @property - def user_data_dir(self): - return user_data_dir(self.appname, self.appauthor, - version=self.version, roaming=self.roaming) - - @property - def site_data_dir(self): - return site_data_dir(self.appname, self.appauthor, - version=self.version, multipath=self.multipath) - - @property - def user_config_dir(self): - return user_config_dir(self.appname, self.appauthor, - version=self.version, roaming=self.roaming) - - @property - def site_config_dir(self): - return site_config_dir(self.appname, self.appauthor, - version=self.version, multipath=self.multipath) - - @property - def user_cache_dir(self): - return user_cache_dir(self.appname, self.appauthor, - version=self.version) - - @property - def user_state_dir(self): - return user_state_dir(self.appname, self.appauthor, - version=self.version) - - @property - def user_log_dir(self): - return user_log_dir(self.appname, self.appauthor, - version=self.version) - - -#---- internal support stuff - -def _get_win_folder_from_registry(csidl_name): - """This is a fallback technique at best. I'm not sure if using the - registry for this guarantees us the correct answer for all CSIDL_* - names. - """ - if PY3: - import winreg as _winreg - else: - import _winreg - - shell_folder_name = { - "CSIDL_APPDATA": "AppData", - "CSIDL_COMMON_APPDATA": "Common AppData", - "CSIDL_LOCAL_APPDATA": "Local AppData", - }[csidl_name] - - key = _winreg.OpenKey( - _winreg.HKEY_CURRENT_USER, - r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" - ) - dir, type = _winreg.QueryValueEx(key, shell_folder_name) - return dir - - -def _get_win_folder_with_pywin32(csidl_name): - from win32com.shell import shellcon, shell - dir = shell.SHGetFolderPath(0, getattr(shellcon, csidl_name), 0, 0) - # Try to make this a unicode path because SHGetFolderPath does - # not return unicode strings when there is unicode data in the - # path. - try: - dir = unicode(dir) - - # Downgrade to short path name if have highbit chars. See - # <http://bugs.activestate.com/show_bug.cgi?id=85099>. - has_high_char = False - for c in dir: - if ord(c) > 255: - has_high_char = True - break - if has_high_char: - try: - import win32api - dir = win32api.GetShortPathName(dir) - except ImportError: - pass - except UnicodeError: - pass - return dir - - -def _get_win_folder_with_ctypes(csidl_name): - import ctypes - - csidl_const = { - "CSIDL_APPDATA": 26, - "CSIDL_COMMON_APPDATA": 35, - "CSIDL_LOCAL_APPDATA": 28, - }[csidl_name] - - buf = ctypes.create_unicode_buffer(1024) - ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf) - - # Downgrade to short path name if have highbit chars. See - # <http://bugs.activestate.com/show_bug.cgi?id=85099>. - has_high_char = False - for c in buf: - if ord(c) > 255: - has_high_char = True - break - if has_high_char: - buf2 = ctypes.create_unicode_buffer(1024) - if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024): - buf = buf2 - - return buf.value - -def _get_win_folder_with_jna(csidl_name): - import array - from com.sun import jna - from com.sun.jna.platform import win32 - - buf_size = win32.WinDef.MAX_PATH * 2 - buf = array.zeros('c', buf_size) - shell = win32.Shell32.INSTANCE - shell.SHGetFolderPath(None, getattr(win32.ShlObj, csidl_name), None, win32.ShlObj.SHGFP_TYPE_CURRENT, buf) - dir = jna.Native.toString(buf.tostring()).rstrip("\0") - - # Downgrade to short path name if have highbit chars. See - # <http://bugs.activestate.com/show_bug.cgi?id=85099>. - has_high_char = False - for c in dir: - if ord(c) > 255: - has_high_char = True - break - if has_high_char: - buf = array.zeros('c', buf_size) - kernel = win32.Kernel32.INSTANCE - if kernel.GetShortPathName(dir, buf, buf_size): - dir = jna.Native.toString(buf.tostring()).rstrip("\0") - - return dir - -if system == "win32": - try: - import win32com.shell - _get_win_folder = _get_win_folder_with_pywin32 - except ImportError: - try: - from ctypes import windll - _get_win_folder = _get_win_folder_with_ctypes - except ImportError: - try: - import com.sun.jna - _get_win_folder = _get_win_folder_with_jna - except ImportError: - _get_win_folder = _get_win_folder_from_registry - - -#---- self test code - -if __name__ == "__main__": - appname = "MyApp" - appauthor = "MyCompany" - - props = ("user_data_dir", - "user_config_dir", - "user_cache_dir", - "user_state_dir", - "user_log_dir", - "site_data_dir", - "site_config_dir") - - print("-- app dirs %s --" % __version__) - - print("-- app dirs (with optional 'version')") - dirs = AppDirs(appname, appauthor, version="1.0") - for prop in props: - print("%s: %s" % (prop, getattr(dirs, prop))) - - print("\n-- app dirs (without optional 'version')") - dirs = AppDirs(appname, appauthor) - for prop in props: - print("%s: %s" % (prop, getattr(dirs, prop))) - - print("\n-- app dirs (without optional 'appauthor')") - dirs = AppDirs(appname) - for prop in props: - print("%s: %s" % (prop, getattr(dirs, prop))) - - print("\n-- app dirs (with disabled 'appauthor')") - dirs = AppDirs(appname, appauthor=False) - for prop in props: - print("%s: %s" % (prop, getattr(dirs, prop))) diff --git a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/__about__.py b/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/__about__.py deleted file mode 100644 index 95d330e..0000000 --- a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/__about__.py +++ /dev/null @@ -1,21 +0,0 @@ -# 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__ = "16.8" - -__author__ = "Donald Stufft and individual contributors" -__email__ = "donald@stufft.io" - -__license__ = "BSD or Apache License, Version 2.0" -__copyright__ = "Copyright 2014-2016 %s" % __author__ diff --git a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/__init__.py b/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/__init__.py deleted file mode 100644 index 5ee6220..0000000 --- a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# 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__", -] diff --git a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_compat.py b/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_compat.py deleted file mode 100644 index 210bb80..0000000 --- a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_compat.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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', (), {}) diff --git a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.py b/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.py deleted file mode 100644 index ccc2786..0000000 --- a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.py +++ /dev/null @@ -1,68 +0,0 @@ -# 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() diff --git a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.py b/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.py deleted file mode 100644 index 892e578..0000000 --- a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.py +++ /dev/null @@ -1,301 +0,0 @@ -# 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 pkg_resources.extern.pyparsing import ParseException, ParseResults, stringStart, stringEnd -from pkg_resources.extern.pyparsing import ZeroOrMore, Group, Forward, QuotedString -from pkg_resources.extern.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") | # PEP-345 - L("sys.platform") | # PEP-345 - L("platform.version") | # PEP-345 - L("platform.machine") | # PEP-345 - L("platform.python_implementation") | # PEP-345 - L("python_implementation") | # undocumented setuptools legacy - L("extra") -) -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": platform.python_version()[:3], - "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 "<Marker({0!r})>".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) diff --git a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.py b/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.py deleted file mode 100644 index 0c8c4a3..0000000 --- a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.py +++ /dev/null @@ -1,127 +0,0 @@ -# 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 pkg_resources.extern.pyparsing import stringStart, stringEnd, originalTextFor, ParseException -from pkg_resources.extern.pyparsing import ZeroOrMore, Word, Optional, Regex, Combine -from pkg_resources.extern.pyparsing import Literal as L # noqa -from pkg_resources.extern.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_SEPERATOR = SEMICOLON -MARKER = MARKER_SEPERATOR + 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 - - -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( - "Invalid requirement, parse error at \"{0!r}\"".format( - requirement_string[e.loc:e.loc + 8])) - - self.name = req.name - if req.url: - parsed_url = urlparse.urlparse(req.url) - if not (parsed_url.scheme and parsed_url.netloc) or ( - not parsed_url.scheme and not parsed_url.netloc): - raise InvalidRequirement("Invalid URL given") - 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("; {0}".format(self.marker)) - - return "".join(parts) - - def __repr__(self): - return "<Requirement({0!r})>".format(str(self)) diff --git a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.py b/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.py deleted file mode 100644 index 7f5a76c..0000000 --- a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.py +++ /dev/null @@ -1,774 +0,0 @@ -# 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 begining. - 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<operator>(==|!=|<=|>=|<|>)) - \s* - (?P<version> - [^,;\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<operator>(~=|==|!=|<=|>=|<|>|===)) - (?P<version> - (?: - # 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. - (?<!==|!=|~=) # We have special cases for these - # operators so we want to make sure they - # don't match here. - - \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]*) - )? - (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release - ) - ) - """ - ) - - _regex = re.compile( - r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) - - _operators = { - "~=": "compatible", - "==": "equal", - "!=": "not_equal", - "<=": "less_than_equal", - ">=": "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 techincally 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 "<SpecifierSet({0!r}{1})>".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 diff --git a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/utils.py b/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/utils.py deleted file mode 100644 index 942387c..0000000 --- a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/utils.py +++ /dev/null @@ -1,14 +0,0 @@ -# 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 - - -_canonicalize_regex = re.compile(r"[-_.]+") - - -def canonicalize_name(name): - # This is taken from PEP 503. - return _canonicalize_regex.sub("-", name).lower() diff --git a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.py b/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.py deleted file mode 100644 index 83b5ee8..0000000 --- a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.py +++ /dev/null @@ -1,393 +0,0 @@ -# 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 "<LegacyVersion({0})>".format(repr(str(self))) - - @property - def public(self): - return self._version - - @property - def base_version(self): - return self._version - - @property - def local(self): - return None - - @property - def is_prerelease(self): - return False - - @property - def is_postrelease(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<epoch>[0-9]+)!)? # epoch - (?P<release>[0-9]+(?:\.[0-9]+)*) # release segment - (?P<pre> # pre-release - [-_\.]? - (?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview)) - [-_\.]? - (?P<pre_n>[0-9]+)? - )? - (?P<post> # post release - (?:-(?P<post_n1>[0-9]+)) - | - (?: - [-_\.]? - (?P<post_l>post|rev|r) - [-_\.]? - (?P<post_n2>[0-9]+)? - ) - )? - (?P<dev> # dev release - [-_\.]? - (?P<dev_l>dev) - [-_\.]? - (?P<dev_n>[0-9]+)? - )? - ) - (?:\+(?P<local>[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 "<Version({0})>".format(repr(str(self))) - - def __str__(self): - parts = [] - - # Epoch - if self._version.epoch != 0: - parts.append("{0}!".format(self._version.epoch)) - - # Release segment - parts.append(".".join(str(x) for x in self._version.release)) - - # Pre-release - if self._version.pre is not None: - parts.append("".join(str(x) for x in self._version.pre)) - - # Post-release - if self._version.post is not None: - parts.append(".post{0}".format(self._version.post[1])) - - # Development release - if self._version.dev is not None: - parts.append(".dev{0}".format(self._version.dev[1])) - - # Local version segment - if self._version.local is not None: - parts.append( - "+{0}".format(".".join(str(x) for x in self._version.local)) - ) - - return "".join(parts) - - @property - def public(self): - return str(self).split("+", 1)[0] - - @property - def base_version(self): - parts = [] - - # Epoch - if self._version.epoch != 0: - parts.append("{0}!".format(self._version.epoch)) - - # Release segment - parts.append(".".join(str(x) for x in self._version.release)) - - return "".join(parts) - - @property - def local(self): - version_string = str(self) - if "+" in version_string: - return version_string.split("+", 1)[1] - - @property - def is_prerelease(self): - return bool(self._version.dev or self._version.pre) - - @property - def is_postrelease(self): - return bool(self._version.post) - - -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_seperators = 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_seperators.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 diff --git a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.py b/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.py deleted file mode 100644 index cf75e1e..0000000 --- a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.py +++ /dev/null @@ -1,5742 +0,0 @@ -# module pyparsing.py -# -# Copyright (c) 2003-2018 Paul T. McGuire -# -# 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. -# - -__doc__ = \ -""" -pyparsing module - Classes and methods to define and execute parsing grammars -============================================================================= - -The pyparsing module is an alternative approach to creating and executing simple grammars, -vs. the traditional lex/yacc approach, or the use of regular expressions. With pyparsing, you -don't need to learn a new syntax for defining grammars or matching expressions - the parsing module -provides a library of classes that you use to construct the grammar directly in Python. - -Here is a program to parse "Hello, World!" (or any greeting of the form -C{"<salutation>, <addressee>!"}), built up using L{Word}, L{Literal}, and L{And} elements -(L{'+'<ParserElement.__add__>} operator gives L{And} expressions, strings are auto-converted to -L{Literal} expressions):: - - from pyparsing import Word, alphas - - # define grammar of a greeting - greet = Word(alphas) + "," + Word(alphas) + "!" - - hello = "Hello, World!" - print (hello, "->", greet.parseString(hello)) - -The program outputs the following:: - - Hello, World! -> ['Hello', ',', 'World', '!'] - -The Python representation of the grammar is quite readable, owing to the self-explanatory -class names, and the use of '+', '|' and '^' operators. - -The L{ParseResults} object returned from L{ParserElement.parseString<ParserElement.parseString>} can be accessed as a nested list, a dictionary, or an -object with named attributes. - -The pyparsing module handles some of the problems that are typically vexing when writing text parsers: - - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello , World !", etc.) - - quoted strings - - embedded comments - - -Getting Started - ------------------ -Visit the classes L{ParserElement} and L{ParseResults} to see the base classes that most other pyparsing -classes inherit from. Use the docstrings for examples of how to: - - construct literal match expressions from L{Literal} and L{CaselessLiteral} classes - - construct character word-group expressions using the L{Word} class - - see how to create repetitive expressions using L{ZeroOrMore} and L{OneOrMore} classes - - use L{'+'<And>}, L{'|'<MatchFirst>}, L{'^'<Or>}, and L{'&'<Each>} operators to combine simple expressions into more complex ones - - associate names with your parsed results using L{ParserElement.setResultsName} - - find some helpful expression short-cuts like L{delimitedList} and L{oneOf} - - find more useful common expressions in the L{pyparsing_common} namespace class -""" - -__version__ = "2.2.1" -__versionTime__ = "18 Sep 2018 00:49 UTC" -__author__ = "Paul McGuire <ptmcg@users.sourceforge.net>" - -import string -from weakref import ref as wkref -import copy -import sys -import warnings -import re -import sre_constants -import collections -import pprint -import traceback -import types -from datetime import datetime - -try: - from _thread import RLock -except ImportError: - from threading import RLock - -try: - # Python 3 - from collections.abc import Iterable - from collections.abc import MutableMapping -except ImportError: - # Python 2.7 - from collections import Iterable - from collections import MutableMapping - -try: - from collections import OrderedDict as _OrderedDict -except ImportError: - try: - from ordereddict import OrderedDict as _OrderedDict - except ImportError: - _OrderedDict = None - -#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) ) - -__all__ = [ -'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty', -'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal', -'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or', -'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException', -'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException', -'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', -'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore', -'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col', -'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString', -'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'hexnums', -'htmlComment', 'javaStyleComment', 'line', 'lineEnd', 'lineStart', 'lineno', -'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral', -'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables', -'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', -'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd', -'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute', -'indentedBlock', 'originalTextFor', 'ungroup', 'infixNotation','locatedExpr', 'withClass', -'CloseMatch', 'tokenMap', 'pyparsing_common', -] - -system_version = tuple(sys.version_info)[:3] -PY_3 = system_version[0] == 3 -if PY_3: - _MAX_INT = sys.maxsize - basestring = str - unichr = chr - _ustr = str - - # build list of single arg builtins, that can be used as parse actions - singleArgBuiltins = [sum, len, sorted, reversed, list, tuple, set, any, all, min, max] - -else: - _MAX_INT = sys.maxint - range = xrange - - def _ustr(obj): - """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries - str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It - then < returns the unicode object | encodes it with the default encoding | ... >. - """ - if isinstance(obj,unicode): - return obj - - try: - # If this works, then _ustr(obj) has the same behaviour as str(obj), so - # it won't break any existing code. - return str(obj) - - except UnicodeEncodeError: - # Else encode it - ret = unicode(obj).encode(sys.getdefaultencoding(), 'xmlcharrefreplace') - xmlcharref = Regex(r'&#\d+;') - xmlcharref.setParseAction(lambda t: '\\u' + hex(int(t[0][2:-1]))[2:]) - return xmlcharref.transformString(ret) - - # build list of single arg builtins, tolerant of Python version, that can be used as parse actions - singleArgBuiltins = [] - import __builtin__ - for fname in "sum len sorted reversed list tuple set any all min max".split(): - try: - singleArgBuiltins.append(getattr(__builtin__,fname)) - except AttributeError: - continue - -_generatorType = type((y for y in range(1))) - -def _xml_escape(data): - """Escape &, <, >, ", ', etc. in a string of data.""" - - # ampersand must be replaced first - from_symbols = '&><"\'' - to_symbols = ('&'+s+';' for s in "amp gt lt quot apos".split()) - for from_,to_ in zip(from_symbols, to_symbols): - data = data.replace(from_, to_) - return data - -class _Constants(object): - pass - -alphas = string.ascii_uppercase + string.ascii_lowercase -nums = "0123456789" -hexnums = nums + "ABCDEFabcdef" -alphanums = alphas + nums -_bslash = chr(92) -printables = "".join(c for c in string.printable if c not in string.whitespace) - -class ParseBaseException(Exception): - """base exception class for all parsing runtime exceptions""" - # Performance tuning: we construct a *lot* of these, so keep this - # constructor as small and fast as possible - def __init__( self, pstr, loc=0, msg=None, elem=None ): - self.loc = loc - if msg is None: - self.msg = pstr - self.pstr = "" - else: - self.msg = msg - self.pstr = pstr - self.parserElement = elem - self.args = (pstr, loc, msg) - - @classmethod - def _from_exception(cls, pe): - """ - internal factory method to simplify creating one type of ParseException - from another - avoids having __init__ signature conflicts among subclasses - """ - return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement) - - def __getattr__( self, aname ): - """supported attributes by name are: - - lineno - returns the line number of the exception text - - col - returns the column number of the exception text - - line - returns the line containing the exception text - """ - if( aname == "lineno" ): - return lineno( self.loc, self.pstr ) - elif( aname in ("col", "column") ): - return col( self.loc, self.pstr ) - elif( aname == "line" ): - return line( self.loc, self.pstr ) - else: - raise AttributeError(aname) - - def __str__( self ): - return "%s (at char %d), (line:%d, col:%d)" % \ - ( self.msg, self.loc, self.lineno, self.column ) - def __repr__( self ): - return _ustr(self) - def markInputline( self, markerString = ">!<" ): - """Extracts the exception line from the input string, and marks - the location of the exception with a special symbol. - """ - line_str = self.line - line_column = self.column - 1 - if markerString: - line_str = "".join((line_str[:line_column], - markerString, line_str[line_column:])) - return line_str.strip() - def __dir__(self): - return "lineno col line".split() + dir(type(self)) - -class ParseException(ParseBaseException): - """ - Exception thrown when parse expressions don't match class; - supported attributes by name are: - - lineno - returns the line number of the exception text - - col - returns the column number of the exception text - - line - returns the line containing the exception text - - Example:: - try: - Word(nums).setName("integer").parseString("ABC") - except ParseException as pe: - print(pe) - print("column: {}".format(pe.col)) - - prints:: - Expected integer (at char 0), (line:1, col:1) - column: 1 - """ - pass - -class ParseFatalException(ParseBaseException): - """user-throwable exception thrown when inconsistent parse content - is found; stops all parsing immediately""" - pass - -class ParseSyntaxException(ParseFatalException): - """just like L{ParseFatalException}, but thrown internally when an - L{ErrorStop<And._ErrorStop>} ('-' operator) indicates that parsing is to stop - immediately because an unbacktrackable syntax error has been found""" - pass - -#~ class ReparseException(ParseBaseException): - #~ """Experimental class - parse actions can raise this exception to cause - #~ pyparsing to reparse the input string: - #~ - with a modified input string, and/or - #~ - with a modified start location - #~ Set the values of the ReparseException in the constructor, and raise the - #~ exception in a parse action to cause pyparsing to use the new string/location. - #~ Setting the values as None causes no change to be made. - #~ """ - #~ def __init_( self, newstring, restartLoc ): - #~ self.newParseText = newstring - #~ self.reparseLoc = restartLoc - -class RecursiveGrammarException(Exception): - """exception thrown by L{ParserElement.validate} if the grammar could be improperly recursive""" - def __init__( self, parseElementList ): - self.parseElementTrace = parseElementList - - def __str__( self ): - return "RecursiveGrammarException: %s" % self.parseElementTrace - -class _ParseResultsWithOffset(object): - def __init__(self,p1,p2): - self.tup = (p1,p2) - def __getitem__(self,i): - return self.tup[i] - def __repr__(self): - return repr(self.tup[0]) - def setOffset(self,i): - self.tup = (self.tup[0],i) - -class ParseResults(object): - """ - Structured parse results, to provide multiple means of access to the parsed data: - - as a list (C{len(results)}) - - by list index (C{results[0], results[1]}, etc.) - - by attribute (C{results.<resultsName>} - see L{ParserElement.setResultsName}) - - Example:: - integer = Word(nums) - date_str = (integer.setResultsName("year") + '/' - + integer.setResultsName("month") + '/' - + integer.setResultsName("day")) - # equivalent form: - # date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - # parseString returns a ParseResults object - result = date_str.parseString("1999/12/31") - - def test(s, fn=repr): - print("%s -> %s" % (s, fn(eval(s)))) - test("list(result)") - test("result[0]") - test("result['month']") - test("result.day") - test("'month' in result") - test("'minutes' in result") - test("result.dump()", str) - prints:: - list(result) -> ['1999', '/', '12', '/', '31'] - result[0] -> '1999' - result['month'] -> '12' - result.day -> '31' - 'month' in result -> True - 'minutes' in result -> False - result.dump() -> ['1999', '/', '12', '/', '31'] - - day: 31 - - month: 12 - - year: 1999 - """ - def __new__(cls, toklist=None, name=None, asList=True, modal=True ): - if isinstance(toklist, cls): - return toklist - retobj = object.__new__(cls) - retobj.__doinit = True - return retobj - - # Performance tuning: we construct a *lot* of these, so keep this - # constructor as small and fast as possible - def __init__( self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance ): - if self.__doinit: - self.__doinit = False - self.__name = None - self.__parent = None - self.__accumNames = {} - self.__asList = asList - self.__modal = modal - if toklist is None: - toklist = [] - if isinstance(toklist, list): - self.__toklist = toklist[:] - elif isinstance(toklist, _generatorType): - self.__toklist = list(toklist) - else: - self.__toklist = [toklist] - self.__tokdict = dict() - - if name is not None and name: - if not modal: - self.__accumNames[name] = 0 - if isinstance(name,int): - name = _ustr(name) # will always return a str, but use _ustr for consistency - self.__name = name - if not (isinstance(toklist, (type(None), basestring, list)) and toklist in (None,'',[])): - if isinstance(toklist,basestring): - toklist = [ toklist ] - if asList: - if isinstance(toklist,ParseResults): - self[name] = _ParseResultsWithOffset(toklist.copy(),0) - else: - self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0) - self[name].__name = name - else: - try: - self[name] = toklist[0] - except (KeyError,TypeError,IndexError): - self[name] = toklist - - def __getitem__( self, i ): - if isinstance( i, (int,slice) ): - return self.__toklist[i] - else: - if i not in self.__accumNames: - return self.__tokdict[i][-1][0] - else: - return ParseResults([ v[0] for v in self.__tokdict[i] ]) - - def __setitem__( self, k, v, isinstance=isinstance ): - if isinstance(v,_ParseResultsWithOffset): - self.__tokdict[k] = self.__tokdict.get(k,list()) + [v] - sub = v[0] - elif isinstance(k,(int,slice)): - self.__toklist[k] = v - sub = v - else: - self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)] - sub = v - if isinstance(sub,ParseResults): - sub.__parent = wkref(self) - - def __delitem__( self, i ): - if isinstance(i,(int,slice)): - mylen = len( self.__toklist ) - del self.__toklist[i] - - # convert int to slice - if isinstance(i, int): - if i < 0: - i += mylen - i = slice(i, i+1) - # get removed indices - removed = list(range(*i.indices(mylen))) - removed.reverse() - # fixup indices in token dictionary - for name,occurrences in self.__tokdict.items(): - for j in removed: - for k, (value, position) in enumerate(occurrences): - occurrences[k] = _ParseResultsWithOffset(value, position - (position > j)) - else: - del self.__tokdict[i] - - def __contains__( self, k ): - return k in self.__tokdict - - def __len__( self ): return len( self.__toklist ) - def __bool__(self): return ( not not self.__toklist ) - __nonzero__ = __bool__ - def __iter__( self ): return iter( self.__toklist ) - def __reversed__( self ): return iter( self.__toklist[::-1] ) - def _iterkeys( self ): - if hasattr(self.__tokdict, "iterkeys"): - return self.__tokdict.iterkeys() - else: - return iter(self.__tokdict) - - def _itervalues( self ): - return (self[k] for k in self._iterkeys()) - - def _iteritems( self ): - return ((k, self[k]) for k in self._iterkeys()) - - if PY_3: - keys = _iterkeys - """Returns an iterator of all named result keys (Python 3.x only).""" - - values = _itervalues - """Returns an iterator of all named result values (Python 3.x only).""" - - items = _iteritems - """Returns an iterator of all named result key-value tuples (Python 3.x only).""" - - else: - iterkeys = _iterkeys - """Returns an iterator of all named result keys (Python 2.x only).""" - - itervalues = _itervalues - """Returns an iterator of all named result values (Python 2.x only).""" - - iteritems = _iteritems - """Returns an iterator of all named result key-value tuples (Python 2.x only).""" - - def keys( self ): - """Returns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x).""" - return list(self.iterkeys()) - - def values( self ): - """Returns all named result values (as a list in Python 2.x, as an iterator in Python 3.x).""" - return list(self.itervalues()) - - def items( self ): - """Returns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x).""" - return list(self.iteritems()) - - def haskeys( self ): - """Since keys() returns an iterator, this method is helpful in bypassing - code that looks for the existence of any defined results names.""" - return bool(self.__tokdict) - - def pop( self, *args, **kwargs): - """ - Removes and returns item at specified index (default=C{last}). - Supports both C{list} and C{dict} semantics for C{pop()}. If passed no - argument or an integer argument, it will use C{list} semantics - and pop tokens from the list of parsed tokens. If passed a - non-integer argument (most likely a string), it will use C{dict} - semantics and pop the corresponding value from any defined - results names. A second default return value argument is - supported, just as in C{dict.pop()}. - - Example:: - def remove_first(tokens): - tokens.pop(0) - print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] - print(OneOrMore(Word(nums)).addParseAction(remove_first).parseString("0 123 321")) # -> ['123', '321'] - - label = Word(alphas) - patt = label("LABEL") + OneOrMore(Word(nums)) - print(patt.parseString("AAB 123 321").dump()) - - # Use pop() in a parse action to remove named result (note that corresponding value is not - # removed from list form of results) - def remove_LABEL(tokens): - tokens.pop("LABEL") - return tokens - patt.addParseAction(remove_LABEL) - print(patt.parseString("AAB 123 321").dump()) - prints:: - ['AAB', '123', '321'] - - LABEL: AAB - - ['AAB', '123', '321'] - """ - if not args: - args = [-1] - for k,v in kwargs.items(): - if k == 'default': - args = (args[0], v) - else: - raise TypeError("pop() got an unexpected keyword argument '%s'" % k) - if (isinstance(args[0], int) or - len(args) == 1 or - args[0] in self): - index = args[0] - ret = self[index] - del self[index] - return ret - else: - defaultvalue = args[1] - return defaultvalue - - def get(self, key, defaultValue=None): - """ - Returns named result matching the given key, or if there is no - such name, then returns the given C{defaultValue} or C{None} if no - C{defaultValue} is specified. - - Similar to C{dict.get()}. - - Example:: - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - result = date_str.parseString("1999/12/31") - print(result.get("year")) # -> '1999' - print(result.get("hour", "not specified")) # -> 'not specified' - print(result.get("hour")) # -> None - """ - if key in self: - return self[key] - else: - return defaultValue - - def insert( self, index, insStr ): - """ - Inserts new element at location index in the list of parsed tokens. - - Similar to C{list.insert()}. - - Example:: - print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] - - # use a parse action to insert the parse location in the front of the parsed results - def insert_locn(locn, tokens): - tokens.insert(0, locn) - print(OneOrMore(Word(nums)).addParseAction(insert_locn).parseString("0 123 321")) # -> [0, '0', '123', '321'] - """ - self.__toklist.insert(index, insStr) - # fixup indices in token dictionary - for name,occurrences in self.__tokdict.items(): - for k, (value, position) in enumerate(occurrences): - occurrences[k] = _ParseResultsWithOffset(value, position + (position > index)) - - def append( self, item ): - """ - Add single element to end of ParseResults list of elements. - - Example:: - print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] - - # use a parse action to compute the sum of the parsed integers, and add it to the end - def append_sum(tokens): - tokens.append(sum(map(int, tokens))) - print(OneOrMore(Word(nums)).addParseAction(append_sum).parseString("0 123 321")) # -> ['0', '123', '321', 444] - """ - self.__toklist.append(item) - - def extend( self, itemseq ): - """ - Add sequence of elements to end of ParseResults list of elements. - - Example:: - patt = OneOrMore(Word(alphas)) - - # use a parse action to append the reverse of the matched strings, to make a palindrome - def make_palindrome(tokens): - tokens.extend(reversed([t[::-1] for t in tokens])) - return ''.join(tokens) - print(patt.addParseAction(make_palindrome).parseString("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl' - """ - if isinstance(itemseq, ParseResults): - self += itemseq - else: - self.__toklist.extend(itemseq) - - def clear( self ): - """ - Clear all elements and results names. - """ - del self.__toklist[:] - self.__tokdict.clear() - - def __getattr__( self, name ): - try: - return self[name] - except KeyError: - return "" - - if name in self.__tokdict: - if name not in self.__accumNames: - return self.__tokdict[name][-1][0] - else: - return ParseResults([ v[0] for v in self.__tokdict[name] ]) - else: - return "" - - def __add__( self, other ): - ret = self.copy() - ret += other - return ret - - def __iadd__( self, other ): - if other.__tokdict: - offset = len(self.__toklist) - addoffset = lambda a: offset if a<0 else a+offset - otheritems = other.__tokdict.items() - otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) ) - for (k,vlist) in otheritems for v in vlist] - for k,v in otherdictitems: - self[k] = v - if isinstance(v[0],ParseResults): - v[0].__parent = wkref(self) - - self.__toklist += other.__toklist - self.__accumNames.update( other.__accumNames ) - return self - - def __radd__(self, other): - if isinstance(other,int) and other == 0: - # useful for merging many ParseResults using sum() builtin - return self.copy() - else: - # this may raise a TypeError - so be it - return other + self - - def __repr__( self ): - return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) ) - - def __str__( self ): - return '[' + ', '.join(_ustr(i) if isinstance(i, ParseResults) else repr(i) for i in self.__toklist) + ']' - - def _asStringList( self, sep='' ): - out = [] - for item in self.__toklist: - if out and sep: - out.append(sep) - if isinstance( item, ParseResults ): - out += item._asStringList() - else: - out.append( _ustr(item) ) - return out - - def asList( self ): - """ - Returns the parse results as a nested list of matching tokens, all converted to strings. - - Example:: - patt = OneOrMore(Word(alphas)) - result = patt.parseString("sldkj lsdkj sldkj") - # even though the result prints in string-like form, it is actually a pyparsing ParseResults - print(type(result), result) # -> <class 'pyparsing.ParseResults'> ['sldkj', 'lsdkj', 'sldkj'] - - # Use asList() to create an actual list - result_list = result.asList() - print(type(result_list), result_list) # -> <class 'list'> ['sldkj', 'lsdkj', 'sldkj'] - """ - return [res.asList() if isinstance(res,ParseResults) else res for res in self.__toklist] - - def asDict( self ): - """ - Returns the named parse results as a nested dictionary. - - Example:: - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - result = date_str.parseString('12/31/1999') - print(type(result), repr(result)) # -> <class 'pyparsing.ParseResults'> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]}) - - result_dict = result.asDict() - print(type(result_dict), repr(result_dict)) # -> <class 'dict'> {'day': '1999', 'year': '12', 'month': '31'} - - # even though a ParseResults supports dict-like access, sometime you just need to have a dict - import json - print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable - print(json.dumps(result.asDict())) # -> {"month": "31", "day": "1999", "year": "12"} - """ - if PY_3: - item_fn = self.items - else: - item_fn = self.iteritems - - def toItem(obj): - if isinstance(obj, ParseResults): - if obj.haskeys(): - return obj.asDict() - else: - return [toItem(v) for v in obj] - else: - return obj - - return dict((k,toItem(v)) for k,v in item_fn()) - - def copy( self ): - """ - Returns a new copy of a C{ParseResults} object. - """ - ret = ParseResults( self.__toklist ) - ret.__tokdict = self.__tokdict.copy() - ret.__parent = self.__parent - ret.__accumNames.update( self.__accumNames ) - ret.__name = self.__name - return ret - - def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ): - """ - (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names. - """ - nl = "\n" - out = [] - namedItems = dict((v[1],k) for (k,vlist) in self.__tokdict.items() - for v in vlist) - nextLevelIndent = indent + " " - - # collapse out indents if formatting is not desired - if not formatted: - indent = "" - nextLevelIndent = "" - nl = "" - - selfTag = None - if doctag is not None: - selfTag = doctag - else: - if self.__name: - selfTag = self.__name - - if not selfTag: - if namedItemsOnly: - return "" - else: - selfTag = "ITEM" - - out += [ nl, indent, "<", selfTag, ">" ] - - for i,res in enumerate(self.__toklist): - if isinstance(res,ParseResults): - if i in namedItems: - out += [ res.asXML(namedItems[i], - namedItemsOnly and doctag is None, - nextLevelIndent, - formatted)] - else: - out += [ res.asXML(None, - namedItemsOnly and doctag is None, - nextLevelIndent, - formatted)] - else: - # individual token, see if there is a name for it - resTag = None - if i in namedItems: - resTag = namedItems[i] - if not resTag: - if namedItemsOnly: - continue - else: - resTag = "ITEM" - xmlBodyText = _xml_escape(_ustr(res)) - out += [ nl, nextLevelIndent, "<", resTag, ">", - xmlBodyText, - "</", resTag, ">" ] - - out += [ nl, indent, "</", selfTag, ">" ] - return "".join(out) - - def __lookup(self,sub): - for k,vlist in self.__tokdict.items(): - for v,loc in vlist: - if sub is v: - return k - return None - - def getName(self): - r""" - Returns the results name for this token expression. Useful when several - different expressions might match at a particular location. - - Example:: - integer = Word(nums) - ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d") - house_number_expr = Suppress('#') + Word(nums, alphanums) - user_data = (Group(house_number_expr)("house_number") - | Group(ssn_expr)("ssn") - | Group(integer)("age")) - user_info = OneOrMore(user_data) - - result = user_info.parseString("22 111-22-3333 #221B") - for item in result: - print(item.getName(), ':', item[0]) - prints:: - age : 22 - ssn : 111-22-3333 - house_number : 221B - """ - if self.__name: - return self.__name - elif self.__parent: - par = self.__parent() - if par: - return par.__lookup(self) - else: - return None - elif (len(self) == 1 and - len(self.__tokdict) == 1 and - next(iter(self.__tokdict.values()))[0][1] in (0,-1)): - return next(iter(self.__tokdict.keys())) - else: - return None - - def dump(self, indent='', depth=0, full=True): - """ - Diagnostic method for listing out the contents of a C{ParseResults}. - Accepts an optional C{indent} argument so that this string can be embedded - in a nested display of other data. - - Example:: - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - result = date_str.parseString('12/31/1999') - print(result.dump()) - prints:: - ['12', '/', '31', '/', '1999'] - - day: 1999 - - month: 31 - - year: 12 - """ - out = [] - NL = '\n' - out.append( indent+_ustr(self.asList()) ) - if full: - if self.haskeys(): - items = sorted((str(k), v) for k,v in self.items()) - for k,v in items: - if out: - out.append(NL) - out.append( "%s%s- %s: " % (indent,(' '*depth), k) ) - if isinstance(v,ParseResults): - if v: - out.append( v.dump(indent,depth+1) ) - else: - out.append(_ustr(v)) - else: - out.append(repr(v)) - elif any(isinstance(vv,ParseResults) for vv in self): - v = self - for i,vv in enumerate(v): - if isinstance(vv,ParseResults): - out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),vv.dump(indent,depth+1) )) - else: - out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),_ustr(vv))) - - return "".join(out) - - def pprint(self, *args, **kwargs): - """ - Pretty-printer for parsed results as a list, using the C{pprint} module. - Accepts additional positional or keyword args as defined for the - C{pprint.pprint} method. (U{http://docs.python.org/3/library/pprint.html#pprint.pprint}) - - Example:: - ident = Word(alphas, alphanums) - num = Word(nums) - func = Forward() - term = ident | num | Group('(' + func + ')') - func <<= ident + Group(Optional(delimitedList(term))) - result = func.parseString("fna a,b,(fnb c,d,200),100") - result.pprint(width=40) - prints:: - ['fna', - ['a', - 'b', - ['(', 'fnb', ['c', 'd', '200'], ')'], - '100']] - """ - pprint.pprint(self.asList(), *args, **kwargs) - - # add support for pickle protocol - def __getstate__(self): - return ( self.__toklist, - ( self.__tokdict.copy(), - self.__parent is not None and self.__parent() or None, - self.__accumNames, - self.__name ) ) - - def __setstate__(self,state): - self.__toklist = state[0] - (self.__tokdict, - par, - inAccumNames, - self.__name) = state[1] - self.__accumNames = {} - self.__accumNames.update(inAccumNames) - if par is not None: - self.__parent = wkref(par) - else: - self.__parent = None - - def __getnewargs__(self): - return self.__toklist, self.__name, self.__asList, self.__modal - - def __dir__(self): - return (dir(type(self)) + list(self.keys())) - -MutableMapping.register(ParseResults) - -def col (loc,strg): - """Returns current column within a string, counting newlines as line separators. - The first column is number 1. - - Note: the default parsing behavior is to expand tabs in the input string - before starting the parsing process. See L{I{ParserElement.parseString}<ParserElement.parseString>} for more information - on parsing strings containing C{<TAB>}s, and suggested methods to maintain a - consistent view of the parsed string, the parse location, and line and column - positions within the parsed string. - """ - s = strg - return 1 if 0<loc<len(s) and s[loc-1] == '\n' else loc - s.rfind("\n", 0, loc) - -def lineno(loc,strg): - """Returns current line number within a string, counting newlines as line separators. - The first line is number 1. - - Note: the default parsing behavior is to expand tabs in the input string - before starting the parsing process. See L{I{ParserElement.parseString}<ParserElement.parseString>} for more information - on parsing strings containing C{<TAB>}s, and suggested methods to maintain a - consistent view of the parsed string, the parse location, and line and column - positions within the parsed string. - """ - return strg.count("\n",0,loc) + 1 - -def line( loc, strg ): - """Returns the line of text containing loc within a string, counting newlines as line separators. - """ - lastCR = strg.rfind("\n", 0, loc) - nextCR = strg.find("\n", loc) - if nextCR >= 0: - return strg[lastCR+1:nextCR] - else: - return strg[lastCR+1:] - -def _defaultStartDebugAction( instring, loc, expr ): - print (("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ))) - -def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ): - print ("Matched " + _ustr(expr) + " -> " + str(toks.asList())) - -def _defaultExceptionDebugAction( instring, loc, expr, exc ): - print ("Exception raised:" + _ustr(exc)) - -def nullDebugAction(*args): - """'Do-nothing' debug action, to suppress debugging output during parsing.""" - pass - -# Only works on Python 3.x - nonlocal is toxic to Python 2 installs -#~ 'decorator to trim function calls to match the arity of the target' -#~ def _trim_arity(func, maxargs=3): - #~ if func in singleArgBuiltins: - #~ return lambda s,l,t: func(t) - #~ limit = 0 - #~ foundArity = False - #~ def wrapper(*args): - #~ nonlocal limit,foundArity - #~ while 1: - #~ try: - #~ ret = func(*args[limit:]) - #~ foundArity = True - #~ return ret - #~ except TypeError: - #~ if limit == maxargs or foundArity: - #~ raise - #~ limit += 1 - #~ continue - #~ return wrapper - -# this version is Python 2.x-3.x cross-compatible -'decorator to trim function calls to match the arity of the target' -def _trim_arity(func, maxargs=2): - if func in singleArgBuiltins: - return lambda s,l,t: func(t) - limit = [0] - foundArity = [False] - - # traceback return data structure changed in Py3.5 - normalize back to plain tuples - if system_version[:2] >= (3,5): - def extract_stack(limit=0): - # special handling for Python 3.5.0 - extra deep call stack by 1 - offset = -3 if system_version == (3,5,0) else -2 - frame_summary = traceback.extract_stack(limit=-offset+limit-1)[offset] - return [frame_summary[:2]] - def extract_tb(tb, limit=0): - frames = traceback.extract_tb(tb, limit=limit) - frame_summary = frames[-1] - return [frame_summary[:2]] - else: - extract_stack = traceback.extract_stack - extract_tb = traceback.extract_tb - - # synthesize what would be returned by traceback.extract_stack at the call to - # user's parse action 'func', so that we don't incur call penalty at parse time - - LINE_DIFF = 6 - # IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND - # THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!! - this_line = extract_stack(limit=2)[-1] - pa_call_line_synth = (this_line[0], this_line[1]+LINE_DIFF) - - def wrapper(*args): - while 1: - try: - ret = func(*args[limit[0]:]) - foundArity[0] = True - return ret - except TypeError: - # re-raise TypeErrors if they did not come from our arity testing - if foundArity[0]: - raise - else: - try: - tb = sys.exc_info()[-1] - if not extract_tb(tb, limit=2)[-1][:2] == pa_call_line_synth: - raise - finally: - del tb - - if limit[0] <= maxargs: - limit[0] += 1 - continue - raise - - # copy func name to wrapper for sensible debug output - func_name = "<parse action>" - try: - func_name = getattr(func, '__name__', - getattr(func, '__class__').__name__) - except Exception: - func_name = str(func) - wrapper.__name__ = func_name - - return wrapper - -class ParserElement(object): - """Abstract base level parser element class.""" - DEFAULT_WHITE_CHARS = " \n\t\r" - verbose_stacktrace = False - - @staticmethod - def setDefaultWhitespaceChars( chars ): - r""" - Overrides the default whitespace chars - - Example:: - # default whitespace chars are space, <TAB> and newline - OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def', 'ghi', 'jkl'] - - # change to just treat newline as significant - ParserElement.setDefaultWhitespaceChars(" \t") - OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def'] - """ - ParserElement.DEFAULT_WHITE_CHARS = chars - - @staticmethod - def inlineLiteralsUsing(cls): - """ - Set class to be used for inclusion of string literals into a parser. - - Example:: - # default literal class used is Literal - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] - - - # change to Suppress - ParserElement.inlineLiteralsUsing(Suppress) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - date_str.parseString("1999/12/31") # -> ['1999', '12', '31'] - """ - ParserElement._literalStringClass = cls - - def __init__( self, savelist=False ): - self.parseAction = list() - self.failAction = None - #~ self.name = "<unknown>" # don't define self.name, let subclasses try/except upcall - self.strRepr = None - self.resultsName = None - self.saveAsList = savelist - self.skipWhitespace = True - self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS - self.copyDefaultWhiteChars = True - self.mayReturnEmpty = False # used when checking for left-recursion - self.keepTabs = False - self.ignoreExprs = list() - self.debug = False - self.streamlined = False - self.mayIndexError = True # used to optimize exception handling for subclasses that don't advance parse index - self.errmsg = "" - self.modalResults = True # used to mark results names as modal (report only last) or cumulative (list all) - self.debugActions = ( None, None, None ) #custom debug actions - self.re = None - self.callPreparse = True # used to avoid redundant calls to preParse - self.callDuringTry = False - - def copy( self ): - """ - Make a copy of this C{ParserElement}. Useful for defining different parse actions - for the same parsing pattern, using copies of the original parse element. - - Example:: - integer = Word(nums).setParseAction(lambda toks: int(toks[0])) - integerK = integer.copy().addParseAction(lambda toks: toks[0]*1024) + Suppress("K") - integerM = integer.copy().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") - - print(OneOrMore(integerK | integerM | integer).parseString("5K 100 640K 256M")) - prints:: - [5120, 100, 655360, 268435456] - Equivalent form of C{expr.copy()} is just C{expr()}:: - integerM = integer().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") - """ - cpy = copy.copy( self ) - cpy.parseAction = self.parseAction[:] - cpy.ignoreExprs = self.ignoreExprs[:] - if self.copyDefaultWhiteChars: - cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS - return cpy - - def setName( self, name ): - """ - Define name for this expression, makes debugging and exception messages clearer. - - Example:: - Word(nums).parseString("ABC") # -> Exception: Expected W:(0123...) (at char 0), (line:1, col:1) - Word(nums).setName("integer").parseString("ABC") # -> Exception: Expected integer (at char 0), (line:1, col:1) - """ - self.name = name - self.errmsg = "Expected " + self.name - if hasattr(self,"exception"): - self.exception.msg = self.errmsg - return self - - def setResultsName( self, name, listAllMatches=False ): - """ - Define name for referencing matching tokens as a nested attribute - of the returned parse results. - NOTE: this returns a *copy* of the original C{ParserElement} object; - this is so that the client can define a basic element, such as an - integer, and reference it in multiple places with different names. - - You can also set results names using the abbreviated syntax, - C{expr("name")} in place of C{expr.setResultsName("name")} - - see L{I{__call__}<__call__>}. - - Example:: - date_str = (integer.setResultsName("year") + '/' - + integer.setResultsName("month") + '/' - + integer.setResultsName("day")) - - # equivalent form: - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - """ - newself = self.copy() - if name.endswith("*"): - name = name[:-1] - listAllMatches=True - newself.resultsName = name - newself.modalResults = not listAllMatches - return newself - - def setBreak(self,breakFlag = True): - """Method to invoke the Python pdb debugger when this element is - about to be parsed. Set C{breakFlag} to True to enable, False to - disable. - """ - if breakFlag: - _parseMethod = self._parse - def breaker(instring, loc, doActions=True, callPreParse=True): - import pdb - pdb.set_trace() - return _parseMethod( instring, loc, doActions, callPreParse ) - breaker._originalParseMethod = _parseMethod - self._parse = breaker - else: - if hasattr(self._parse,"_originalParseMethod"): - self._parse = self._parse._originalParseMethod - return self - - def setParseAction( self, *fns, **kwargs ): - """ - Define one or more actions to perform when successfully matching parse element definition. - Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)}, - C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where: - - s = the original string being parsed (see note below) - - loc = the location of the matching substring - - toks = a list of the matched tokens, packaged as a C{L{ParseResults}} object - If the functions in fns modify the tokens, they can return them as the return - value from fn, and the modified list of tokens will replace the original. - Otherwise, fn does not need to return any value. - - Optional keyword arguments: - - callDuringTry = (default=C{False}) indicate if parse action should be run during lookaheads and alternate testing - - Note: the default parsing behavior is to expand tabs in the input string - before starting the parsing process. See L{I{parseString}<parseString>} for more information - on parsing strings containing C{<TAB>}s, and suggested methods to maintain a - consistent view of the parsed string, the parse location, and line and column - positions within the parsed string. - - Example:: - integer = Word(nums) - date_str = integer + '/' + integer + '/' + integer - - date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] - - # use parse action to convert to ints at parse time - integer = Word(nums).setParseAction(lambda toks: int(toks[0])) - date_str = integer + '/' + integer + '/' + integer - - # note that integer fields are now ints, not strings - date_str.parseString("1999/12/31") # -> [1999, '/', 12, '/', 31] - """ - self.parseAction = list(map(_trim_arity, list(fns))) - self.callDuringTry = kwargs.get("callDuringTry", False) - return self - - def addParseAction( self, *fns, **kwargs ): - """ - Add one or more parse actions to expression's list of parse actions. See L{I{setParseAction}<setParseAction>}. - - See examples in L{I{copy}<copy>}. - """ - self.parseAction += list(map(_trim_arity, list(fns))) - self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) - return self - - def addCondition(self, *fns, **kwargs): - """Add a boolean predicate function to expression's list of parse actions. See - L{I{setParseAction}<setParseAction>} for function call signatures. Unlike C{setParseAction}, - functions passed to C{addCondition} need to return boolean success/fail of the condition. - - Optional keyword arguments: - - message = define a custom message to be used in the raised exception - - fatal = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException - - Example:: - integer = Word(nums).setParseAction(lambda toks: int(toks[0])) - year_int = integer.copy() - year_int.addCondition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later") - date_str = year_int + '/' + integer + '/' + integer - - result = date_str.parseString("1999/12/31") # -> Exception: Only support years 2000 and later (at char 0), (line:1, col:1) - """ - msg = kwargs.get("message", "failed user-defined condition") - exc_type = ParseFatalException if kwargs.get("fatal", False) else ParseException - for fn in fns: - def pa(s,l,t): - if not bool(_trim_arity(fn)(s,l,t)): - raise exc_type(s,l,msg) - self.parseAction.append(pa) - self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) - return self - - def setFailAction( self, fn ): - """Define action to perform if parsing fails at this expression. - Fail acton fn is a callable function that takes the arguments - C{fn(s,loc,expr,err)} where: - - s = string being parsed - - loc = location where expression match was attempted and failed - - expr = the parse expression that failed - - err = the exception thrown - The function returns no value. It may throw C{L{ParseFatalException}} - if it is desired to stop parsing immediately.""" - self.failAction = fn - return self - - def _skipIgnorables( self, instring, loc ): - exprsFound = True - while exprsFound: - exprsFound = False - for e in self.ignoreExprs: - try: - while 1: - loc,dummy = e._parse( instring, loc ) - exprsFound = True - except ParseException: - pass - return loc - - def preParse( self, instring, loc ): - if self.ignoreExprs: - loc = self._skipIgnorables( instring, loc ) - - if self.skipWhitespace: - wt = self.whiteChars - instrlen = len(instring) - while loc < instrlen and instring[loc] in wt: - loc += 1 - - return loc - - def parseImpl( self, instring, loc, doActions=True ): - return loc, [] - - def postParse( self, instring, loc, tokenlist ): - return tokenlist - - #~ @profile - def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ): - debugging = ( self.debug ) #and doActions ) - - if debugging or self.failAction: - #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )) - if (self.debugActions[0] ): - self.debugActions[0]( instring, loc, self ) - if callPreParse and self.callPreparse: - preloc = self.preParse( instring, loc ) - else: - preloc = loc - tokensStart = preloc - try: - try: - loc,tokens = self.parseImpl( instring, preloc, doActions ) - except IndexError: - raise ParseException( instring, len(instring), self.errmsg, self ) - except ParseBaseException as err: - #~ print ("Exception raised:", err) - if self.debugActions[2]: - self.debugActions[2]( instring, tokensStart, self, err ) - if self.failAction: - self.failAction( instring, tokensStart, self, err ) - raise - else: - if callPreParse and self.callPreparse: - preloc = self.preParse( instring, loc ) - else: - preloc = loc - tokensStart = preloc - if self.mayIndexError or preloc >= len(instring): - try: - loc,tokens = self.parseImpl( instring, preloc, doActions ) - except IndexError: - raise ParseException( instring, len(instring), self.errmsg, self ) - else: - loc,tokens = self.parseImpl( instring, preloc, doActions ) - - tokens = self.postParse( instring, loc, tokens ) - - retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults ) - if self.parseAction and (doActions or self.callDuringTry): - if debugging: - try: - for fn in self.parseAction: - tokens = fn( instring, tokensStart, retTokens ) - if tokens is not None: - retTokens = ParseResults( tokens, - self.resultsName, - asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), - modal=self.modalResults ) - except ParseBaseException as err: - #~ print "Exception raised in user parse action:", err - if (self.debugActions[2] ): - self.debugActions[2]( instring, tokensStart, self, err ) - raise - else: - for fn in self.parseAction: - tokens = fn( instring, tokensStart, retTokens ) - if tokens is not None: - retTokens = ParseResults( tokens, - self.resultsName, - asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), - modal=self.modalResults ) - if debugging: - #~ print ("Matched",self,"->",retTokens.asList()) - if (self.debugActions[1] ): - self.debugActions[1]( instring, tokensStart, loc, self, retTokens ) - - return loc, retTokens - - def tryParse( self, instring, loc ): - try: - return self._parse( instring, loc, doActions=False )[0] - except ParseFatalException: - raise ParseException( instring, loc, self.errmsg, self) - - def canParseNext(self, instring, loc): - try: - self.tryParse(instring, loc) - except (ParseException, IndexError): - return False - else: - return True - - class _UnboundedCache(object): - def __init__(self): - cache = {} - self.not_in_cache = not_in_cache = object() - - def get(self, key): - return cache.get(key, not_in_cache) - - def set(self, key, value): - cache[key] = value - - def clear(self): - cache.clear() - - def cache_len(self): - return len(cache) - - self.get = types.MethodType(get, self) - self.set = types.MethodType(set, self) - self.clear = types.MethodType(clear, self) - self.__len__ = types.MethodType(cache_len, self) - - if _OrderedDict is not None: - class _FifoCache(object): - def __init__(self, size): - self.not_in_cache = not_in_cache = object() - - cache = _OrderedDict() - - def get(self, key): - return cache.get(key, not_in_cache) - - def set(self, key, value): - cache[key] = value - while len(cache) > size: - try: - cache.popitem(False) - except KeyError: - pass - - def clear(self): - cache.clear() - - def cache_len(self): - return len(cache) - - self.get = types.MethodType(get, self) - self.set = types.MethodType(set, self) - self.clear = types.MethodType(clear, self) - self.__len__ = types.MethodType(cache_len, self) - - else: - class _FifoCache(object): - def __init__(self, size): - self.not_in_cache = not_in_cache = object() - - cache = {} - key_fifo = collections.deque([], size) - - def get(self, key): - return cache.get(key, not_in_cache) - - def set(self, key, value): - cache[key] = value - while len(key_fifo) > size: - cache.pop(key_fifo.popleft(), None) - key_fifo.append(key) - - def clear(self): - cache.clear() - key_fifo.clear() - - def cache_len(self): - return len(cache) - - self.get = types.MethodType(get, self) - self.set = types.MethodType(set, self) - self.clear = types.MethodType(clear, self) - self.__len__ = types.MethodType(cache_len, self) - - # argument cache for optimizing repeated calls when backtracking through recursive expressions - packrat_cache = {} # this is set later by enabledPackrat(); this is here so that resetCache() doesn't fail - packrat_cache_lock = RLock() - packrat_cache_stats = [0, 0] - - # this method gets repeatedly called during backtracking with the same arguments - - # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression - def _parseCache( self, instring, loc, doActions=True, callPreParse=True ): - HIT, MISS = 0, 1 - lookup = (self, instring, loc, callPreParse, doActions) - with ParserElement.packrat_cache_lock: - cache = ParserElement.packrat_cache - value = cache.get(lookup) - if value is cache.not_in_cache: - ParserElement.packrat_cache_stats[MISS] += 1 - try: - value = self._parseNoCache(instring, loc, doActions, callPreParse) - except ParseBaseException as pe: - # cache a copy of the exception, without the traceback - cache.set(lookup, pe.__class__(*pe.args)) - raise - else: - cache.set(lookup, (value[0], value[1].copy())) - return value - else: - ParserElement.packrat_cache_stats[HIT] += 1 - if isinstance(value, Exception): - raise value - return (value[0], value[1].copy()) - - _parse = _parseNoCache - - @staticmethod - def resetCache(): - ParserElement.packrat_cache.clear() - ParserElement.packrat_cache_stats[:] = [0] * len(ParserElement.packrat_cache_stats) - - _packratEnabled = False - @staticmethod - def enablePackrat(cache_size_limit=128): - """Enables "packrat" parsing, which adds memoizing to the parsing logic. - Repeated parse attempts at the same string location (which happens - often in many complex grammars) can immediately return a cached value, - instead of re-executing parsing/validating code. Memoizing is done of - both valid results and parsing exceptions. - - Parameters: - - cache_size_limit - (default=C{128}) - if an integer value is provided - will limit the size of the packrat cache; if None is passed, then - the cache size will be unbounded; if 0 is passed, the cache will - be effectively disabled. - - This speedup may break existing programs that use parse actions that - have side-effects. For this reason, packrat parsing is disabled when - you first import pyparsing. To activate the packrat feature, your - program must call the class method C{ParserElement.enablePackrat()}. If - your program uses C{psyco} to "compile as you go", you must call - C{enablePackrat} before calling C{psyco.full()}. If you do not do this, - Python will crash. For best results, call C{enablePackrat()} immediately - after importing pyparsing. - - Example:: - import pyparsing - pyparsing.ParserElement.enablePackrat() - """ - if not ParserElement._packratEnabled: - ParserElement._packratEnabled = True - if cache_size_limit is None: - ParserElement.packrat_cache = ParserElement._UnboundedCache() - else: - ParserElement.packrat_cache = ParserElement._FifoCache(cache_size_limit) - ParserElement._parse = ParserElement._parseCache - - def parseString( self, instring, parseAll=False ): - """ - Execute the parse expression with the given string. - This is the main interface to the client code, once the complete - expression has been built. - - If you want the grammar to require that the entire input string be - successfully parsed, then set C{parseAll} to True (equivalent to ending - the grammar with C{L{StringEnd()}}). - - Note: C{parseString} implicitly calls C{expandtabs()} on the input string, - in order to report proper column numbers in parse actions. - If the input string contains tabs and - the grammar uses parse actions that use the C{loc} argument to index into the - string being parsed, you can ensure you have a consistent view of the input - string by: - - calling C{parseWithTabs} on your grammar before calling C{parseString} - (see L{I{parseWithTabs}<parseWithTabs>}) - - define your parse action using the full C{(s,loc,toks)} signature, and - reference the input string using the parse action's C{s} argument - - explictly expand the tabs in your input string before calling - C{parseString} - - Example:: - Word('a').parseString('aaaaabaaa') # -> ['aaaaa'] - Word('a').parseString('aaaaabaaa', parseAll=True) # -> Exception: Expected end of text - """ - ParserElement.resetCache() - if not self.streamlined: - self.streamline() - #~ self.saveAsList = True - for e in self.ignoreExprs: - e.streamline() - if not self.keepTabs: - instring = instring.expandtabs() - try: - loc, tokens = self._parse( instring, 0 ) - if parseAll: - loc = self.preParse( instring, loc ) - se = Empty() + StringEnd() - se._parse( instring, loc ) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - else: - return tokens - - def scanString( self, instring, maxMatches=_MAX_INT, overlap=False ): - """ - Scan the input string for expression matches. Each match will return the - matching tokens, start location, and end location. May be called with optional - C{maxMatches} argument, to clip scanning after 'n' matches are found. If - C{overlap} is specified, then overlapping matches will be reported. - - Note that the start and end locations are reported relative to the string - being parsed. See L{I{parseString}<parseString>} for more information on parsing - strings with embedded tabs. - - Example:: - source = "sldjf123lsdjjkf345sldkjf879lkjsfd987" - print(source) - for tokens,start,end in Word(alphas).scanString(source): - print(' '*start + '^'*(end-start)) - print(' '*start + tokens[0]) - - prints:: - - sldjf123lsdjjkf345sldkjf879lkjsfd987 - ^^^^^ - sldjf - ^^^^^^^ - lsdjjkf - ^^^^^^ - sldkjf - ^^^^^^ - lkjsfd - """ - if not self.streamlined: - self.streamline() - for e in self.ignoreExprs: - e.streamline() - - if not self.keepTabs: - instring = _ustr(instring).expandtabs() - instrlen = len(instring) - loc = 0 - preparseFn = self.preParse - parseFn = self._parse - ParserElement.resetCache() - matches = 0 - try: - while loc <= instrlen and matches < maxMatches: - try: - preloc = preparseFn( instring, loc ) - nextLoc,tokens = parseFn( instring, preloc, callPreParse=False ) - except ParseException: - loc = preloc+1 - else: - if nextLoc > loc: - matches += 1 - yield tokens, preloc, nextLoc - if overlap: - nextloc = preparseFn( instring, loc ) - if nextloc > loc: - loc = nextLoc - else: - loc += 1 - else: - loc = nextLoc - else: - loc = preloc+1 - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - - def transformString( self, instring ): - """ - Extension to C{L{scanString}}, to modify matching text with modified tokens that may - be returned from a parse action. To use C{transformString}, define a grammar and - attach a parse action to it that modifies the returned token list. - Invoking C{transformString()} on a target string will then scan for matches, - and replace the matched text patterns according to the logic in the parse - action. C{transformString()} returns the resulting transformed string. - - Example:: - wd = Word(alphas) - wd.setParseAction(lambda toks: toks[0].title()) - - print(wd.transformString("now is the winter of our discontent made glorious summer by this sun of york.")) - Prints:: - Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York. - """ - out = [] - lastE = 0 - # force preservation of <TAB>s, to minimize unwanted transformation of string, and to - # keep string locs straight between transformString and scanString - self.keepTabs = True - try: - for t,s,e in self.scanString( instring ): - out.append( instring[lastE:s] ) - if t: - if isinstance(t,ParseResults): - out += t.asList() - elif isinstance(t,list): - out += t - else: - out.append(t) - lastE = e - out.append(instring[lastE:]) - out = [o for o in out if o] - return "".join(map(_ustr,_flatten(out))) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - - def searchString( self, instring, maxMatches=_MAX_INT ): - """ - Another extension to C{L{scanString}}, simplifying the access to the tokens found - to match the given parse expression. May be called with optional - C{maxMatches} argument, to clip searching after 'n' matches are found. - - Example:: - # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters - cap_word = Word(alphas.upper(), alphas.lower()) - - print(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity")) - - # the sum() builtin can be used to merge results into a single ParseResults object - print(sum(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity"))) - prints:: - [['More'], ['Iron'], ['Lead'], ['Gold'], ['I'], ['Electricity']] - ['More', 'Iron', 'Lead', 'Gold', 'I', 'Electricity'] - """ - try: - return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ]) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - - def split(self, instring, maxsplit=_MAX_INT, includeSeparators=False): - """ - Generator method to split a string using the given expression as a separator. - May be called with optional C{maxsplit} argument, to limit the number of splits; - and the optional C{includeSeparators} argument (default=C{False}), if the separating - matching text should be included in the split results. - - Example:: - punc = oneOf(list(".,;:/-!?")) - print(list(punc.split("This, this?, this sentence, is badly punctuated!"))) - prints:: - ['This', ' this', '', ' this sentence', ' is badly punctuated', ''] - """ - splits = 0 - last = 0 - for t,s,e in self.scanString(instring, maxMatches=maxsplit): - yield instring[last:s] - if includeSeparators: - yield t[0] - last = e - yield instring[last:] - - def __add__(self, other ): - """ - Implementation of + operator - returns C{L{And}}. Adding strings to a ParserElement - converts them to L{Literal}s by default. - - Example:: - greet = Word(alphas) + "," + Word(alphas) + "!" - hello = "Hello, World!" - print (hello, "->", greet.parseString(hello)) - Prints:: - Hello, World! -> ['Hello', ',', 'World', '!'] - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return And( [ self, other ] ) - - def __radd__(self, other ): - """ - Implementation of + operator when left operand is not a C{L{ParserElement}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other + self - - def __sub__(self, other): - """ - Implementation of - operator, returns C{L{And}} with error stop - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return self + And._ErrorStop() + other - - def __rsub__(self, other ): - """ - Implementation of - operator when left operand is not a C{L{ParserElement}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other - self - - def __mul__(self,other): - """ - Implementation of * operator, allows use of C{expr * 3} in place of - C{expr + expr + expr}. Expressions may also me multiplied by a 2-integer - tuple, similar to C{{min,max}} multipliers in regular expressions. Tuples - may also include C{None} as in: - - C{expr*(n,None)} or C{expr*(n,)} is equivalent - to C{expr*n + L{ZeroOrMore}(expr)} - (read as "at least n instances of C{expr}") - - C{expr*(None,n)} is equivalent to C{expr*(0,n)} - (read as "0 to n instances of C{expr}") - - C{expr*(None,None)} is equivalent to C{L{ZeroOrMore}(expr)} - - C{expr*(1,None)} is equivalent to C{L{OneOrMore}(expr)} - - Note that C{expr*(None,n)} does not raise an exception if - more than n exprs exist in the input stream; that is, - C{expr*(None,n)} does not enforce a maximum number of expr - occurrences. If this behavior is desired, then write - C{expr*(None,n) + ~expr} - """ - if isinstance(other,int): - minElements, optElements = other,0 - elif isinstance(other,tuple): - other = (other + (None, None))[:2] - if other[0] is None: - other = (0, other[1]) - if isinstance(other[0],int) and other[1] is None: - if other[0] == 0: - return ZeroOrMore(self) - if other[0] == 1: - return OneOrMore(self) - else: - return self*other[0] + ZeroOrMore(self) - elif isinstance(other[0],int) and isinstance(other[1],int): - minElements, optElements = other - optElements -= minElements - else: - raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1])) - else: - raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other)) - - if minElements < 0: - raise ValueError("cannot multiply ParserElement by negative value") - if optElements < 0: - raise ValueError("second tuple value must be greater or equal to first tuple value") - if minElements == optElements == 0: - raise ValueError("cannot multiply ParserElement by 0 or (0,0)") - - if (optElements): - def makeOptionalList(n): - if n>1: - return Optional(self + makeOptionalList(n-1)) - else: - return Optional(self) - if minElements: - if minElements == 1: - ret = self + makeOptionalList(optElements) - else: - ret = And([self]*minElements) + makeOptionalList(optElements) - else: - ret = makeOptionalList(optElements) - else: - if minElements == 1: - ret = self - else: - ret = And([self]*minElements) - return ret - - def __rmul__(self, other): - return self.__mul__(other) - - def __or__(self, other ): - """ - Implementation of | operator - returns C{L{MatchFirst}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return MatchFirst( [ self, other ] ) - - def __ror__(self, other ): - """ - Implementation of | operator when left operand is not a C{L{ParserElement}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other | self - - def __xor__(self, other ): - """ - Implementation of ^ operator - returns C{L{Or}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return Or( [ self, other ] ) - - def __rxor__(self, other ): - """ - Implementation of ^ operator when left operand is not a C{L{ParserElement}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other ^ self - - def __and__(self, other ): - """ - Implementation of & operator - returns C{L{Each}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return Each( [ self, other ] ) - - def __rand__(self, other ): - """ - Implementation of & operator when left operand is not a C{L{ParserElement}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other & self - - def __invert__( self ): - """ - Implementation of ~ operator - returns C{L{NotAny}} - """ - return NotAny( self ) - - def __call__(self, name=None): - """ - Shortcut for C{L{setResultsName}}, with C{listAllMatches=False}. - - If C{name} is given with a trailing C{'*'} character, then C{listAllMatches} will be - passed as C{True}. - - If C{name} is omitted, same as calling C{L{copy}}. - - Example:: - # these are equivalent - userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno") - userdata = Word(alphas)("name") + Word(nums+"-")("socsecno") - """ - if name is not None: - return self.setResultsName(name) - else: - return self.copy() - - def suppress( self ): - """ - Suppresses the output of this C{ParserElement}; useful to keep punctuation from - cluttering up returned output. - """ - return Suppress( self ) - - def leaveWhitespace( self ): - """ - Disables the skipping of whitespace before matching the characters in the - C{ParserElement}'s defined pattern. This is normally only used internally by - the pyparsing module, but may be needed in some whitespace-sensitive grammars. - """ - self.skipWhitespace = False - return self - - def setWhitespaceChars( self, chars ): - """ - Overrides the default whitespace chars - """ - self.skipWhitespace = True - self.whiteChars = chars - self.copyDefaultWhiteChars = False - return self - - def parseWithTabs( self ): - """ - Overrides default behavior to expand C{<TAB>}s to spaces before parsing the input string. - Must be called before C{parseString} when the input grammar contains elements that - match C{<TAB>} characters. - """ - self.keepTabs = True - return self - - def ignore( self, other ): - """ - Define expression to be ignored (e.g., comments) while doing pattern - matching; may be called repeatedly, to define multiple comment or other - ignorable patterns. - - Example:: - patt = OneOrMore(Word(alphas)) - patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj'] - - patt.ignore(cStyleComment) - patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd'] - """ - if isinstance(other, basestring): - other = Suppress(other) - - if isinstance( other, Suppress ): - if other not in self.ignoreExprs: - self.ignoreExprs.append(other) - else: - self.ignoreExprs.append( Suppress( other.copy() ) ) - return self - - def setDebugActions( self, startAction, successAction, exceptionAction ): - """ - Enable display of debugging messages while doing pattern matching. - """ - self.debugActions = (startAction or _defaultStartDebugAction, - successAction or _defaultSuccessDebugAction, - exceptionAction or _defaultExceptionDebugAction) - self.debug = True - return self - - def setDebug( self, flag=True ): - """ - Enable display of debugging messages while doing pattern matching. - Set C{flag} to True to enable, False to disable. - - Example:: - wd = Word(alphas).setName("alphaword") - integer = Word(nums).setName("numword") - term = wd | integer - - # turn on debugging for wd - wd.setDebug() - - OneOrMore(term).parseString("abc 123 xyz 890") - - prints:: - Match alphaword at loc 0(1,1) - Matched alphaword -> ['abc'] - Match alphaword at loc 3(1,4) - Exception raised:Expected alphaword (at char 4), (line:1, col:5) - Match alphaword at loc 7(1,8) - Matched alphaword -> ['xyz'] - Match alphaword at loc 11(1,12) - Exception raised:Expected alphaword (at char 12), (line:1, col:13) - Match alphaword at loc 15(1,16) - Exception raised:Expected alphaword (at char 15), (line:1, col:16) - - The output shown is that produced by the default debug actions - custom debug actions can be - specified using L{setDebugActions}. Prior to attempting - to match the C{wd} expression, the debugging message C{"Match <exprname> at loc <n>(<line>,<col>)"} - is shown. Then if the parse succeeds, a C{"Matched"} message is shown, or an C{"Exception raised"} - message is shown. Also note the use of L{setName} to assign a human-readable name to the expression, - which makes debugging and exception messages easier to understand - for instance, the default - name created for the C{Word} expression without calling C{setName} is C{"W:(ABCD...)"}. - """ - if flag: - self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction ) - else: - self.debug = False - return self - - def __str__( self ): - return self.name - - def __repr__( self ): - return _ustr(self) - - def streamline( self ): - self.streamlined = True - self.strRepr = None - return self - - def checkRecursion( self, parseElementList ): - pass - - def validate( self, validateTrace=[] ): - """ - Check defined expressions for valid structure, check for infinite recursive definitions. - """ - self.checkRecursion( [] ) - - def parseFile( self, file_or_filename, parseAll=False ): - """ - Execute the parse expression on the given file or filename. - If a filename is specified (instead of a file object), - the entire file is opened, read, and closed before parsing. - """ - try: - file_contents = file_or_filename.read() - except AttributeError: - with open(file_or_filename, "r") as f: - file_contents = f.read() - try: - return self.parseString(file_contents, parseAll) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - - def __eq__(self,other): - if isinstance(other, ParserElement): - return self is other or vars(self) == vars(other) - elif isinstance(other, basestring): - return self.matches(other) - else: - return super(ParserElement,self)==other - - def __ne__(self,other): - return not (self == other) - - def __hash__(self): - return hash(id(self)) - - def __req__(self,other): - return self == other - - def __rne__(self,other): - return not (self == other) - - def matches(self, testString, parseAll=True): - """ - Method for quick testing of a parser against a test string. Good for simple - inline microtests of sub expressions while building up larger parser. - - Parameters: - - testString - to test against this expression for a match - - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests - - Example:: - expr = Word(nums) - assert expr.matches("100") - """ - try: - self.parseString(_ustr(testString), parseAll=parseAll) - return True - except ParseBaseException: - return False - - def runTests(self, tests, parseAll=True, comment='#', fullDump=True, printResults=True, failureTests=False): - """ - Execute the parse expression on a series of test strings, showing each - test, the parsed results or where the parse failed. Quick and easy way to - run a parse expression against a list of sample strings. - - Parameters: - - tests - a list of separate test strings, or a multiline string of test strings - - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests - - comment - (default=C{'#'}) - expression for indicating embedded comments in the test - string; pass None to disable comment filtering - - fullDump - (default=C{True}) - dump results as list followed by results names in nested outline; - if False, only dump nested list - - printResults - (default=C{True}) prints test output to stdout - - failureTests - (default=C{False}) indicates if these tests are expected to fail parsing - - Returns: a (success, results) tuple, where success indicates that all tests succeeded - (or failed if C{failureTests} is True), and the results contain a list of lines of each - test's output - - Example:: - number_expr = pyparsing_common.number.copy() - - result = number_expr.runTests(''' - # unsigned integer - 100 - # negative integer - -100 - # float with scientific notation - 6.02e23 - # integer with scientific notation - 1e-12 - ''') - print("Success" if result[0] else "Failed!") - - result = number_expr.runTests(''' - # stray character - 100Z - # missing leading digit before '.' - -.100 - # too many '.' - 3.14.159 - ''', failureTests=True) - print("Success" if result[0] else "Failed!") - prints:: - # unsigned integer - 100 - [100] - - # negative integer - -100 - [-100] - - # float with scientific notation - 6.02e23 - [6.02e+23] - - # integer with scientific notation - 1e-12 - [1e-12] - - Success - - # stray character - 100Z - ^ - FAIL: Expected end of text (at char 3), (line:1, col:4) - - # missing leading digit before '.' - -.100 - ^ - FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1) - - # too many '.' - 3.14.159 - ^ - FAIL: Expected end of text (at char 4), (line:1, col:5) - - Success - - Each test string must be on a single line. If you want to test a string that spans multiple - lines, create a test like this:: - - expr.runTest(r"this is a test\\n of strings that spans \\n 3 lines") - - (Note that this is a raw string literal, you must include the leading 'r'.) - """ - if isinstance(tests, basestring): - tests = list(map(str.strip, tests.rstrip().splitlines())) - if isinstance(comment, basestring): - comment = Literal(comment) - allResults = [] - comments = [] - success = True - for t in tests: - if comment is not None and comment.matches(t, False) or comments and not t: - comments.append(t) - continue - if not t: - continue - out = ['\n'.join(comments), t] - comments = [] - try: - t = t.replace(r'\n','\n') - result = self.parseString(t, parseAll=parseAll) - out.append(result.dump(full=fullDump)) - success = success and not failureTests - except ParseBaseException as pe: - fatal = "(FATAL)" if isinstance(pe, ParseFatalException) else "" - if '\n' in t: - out.append(line(pe.loc, t)) - out.append(' '*(col(pe.loc,t)-1) + '^' + fatal) - else: - out.append(' '*pe.loc + '^' + fatal) - out.append("FAIL: " + str(pe)) - success = success and failureTests - result = pe - except Exception as exc: - out.append("FAIL-EXCEPTION: " + str(exc)) - success = success and failureTests - result = exc - - if printResults: - if fullDump: - out.append('') - print('\n'.join(out)) - - allResults.append((t, result)) - - return success, allResults - - -class Token(ParserElement): - """ - Abstract C{ParserElement} subclass, for defining atomic matching patterns. - """ - def __init__( self ): - super(Token,self).__init__( savelist=False ) - - -class Empty(Token): - """ - An empty token, will always match. - """ - def __init__( self ): - super(Empty,self).__init__() - self.name = "Empty" - self.mayReturnEmpty = True - self.mayIndexError = False - - -class NoMatch(Token): - """ - A token that will never match. - """ - def __init__( self ): - super(NoMatch,self).__init__() - self.name = "NoMatch" - self.mayReturnEmpty = True - self.mayIndexError = False - self.errmsg = "Unmatchable token" - - def parseImpl( self, instring, loc, doActions=True ): - raise ParseException(instring, loc, self.errmsg, self) - - -class Literal(Token): - """ - Token to exactly match a specified string. - - Example:: - Literal('blah').parseString('blah') # -> ['blah'] - Literal('blah').parseString('blahfooblah') # -> ['blah'] - Literal('blah').parseString('bla') # -> Exception: Expected "blah" - - For case-insensitive matching, use L{CaselessLiteral}. - - For keyword matching (force word break before and after the matched string), - use L{Keyword} or L{CaselessKeyword}. - """ - def __init__( self, matchString ): - super(Literal,self).__init__() - self.match = matchString - self.matchLen = len(matchString) - try: - self.firstMatchChar = matchString[0] - except IndexError: - warnings.warn("null string passed to Literal; use Empty() instead", - SyntaxWarning, stacklevel=2) - self.__class__ = Empty - self.name = '"%s"' % _ustr(self.match) - self.errmsg = "Expected " + self.name - self.mayReturnEmpty = False - self.mayIndexError = False - - # Performance tuning: this routine gets called a *lot* - # if this is a single character match string and the first character matches, - # short-circuit as quickly as possible, and avoid calling startswith - #~ @profile - def parseImpl( self, instring, loc, doActions=True ): - if (instring[loc] == self.firstMatchChar and - (self.matchLen==1 or instring.startswith(self.match,loc)) ): - return loc+self.matchLen, self.match - raise ParseException(instring, loc, self.errmsg, self) -_L = Literal -ParserElement._literalStringClass = Literal - -class Keyword(Token): - """ - Token to exactly match a specified string as a keyword, that is, it must be - immediately followed by a non-keyword character. Compare with C{L{Literal}}: - - C{Literal("if")} will match the leading C{'if'} in C{'ifAndOnlyIf'}. - - C{Keyword("if")} will not; it will only match the leading C{'if'} in C{'if x=1'}, or C{'if(y==2)'} - Accepts two optional constructor arguments in addition to the keyword string: - - C{identChars} is a string of characters that would be valid identifier characters, - defaulting to all alphanumerics + "_" and "$" - - C{caseless} allows case-insensitive matching, default is C{False}. - - Example:: - Keyword("start").parseString("start") # -> ['start'] - Keyword("start").parseString("starting") # -> Exception - - For case-insensitive matching, use L{CaselessKeyword}. - """ - DEFAULT_KEYWORD_CHARS = alphanums+"_$" - - def __init__( self, matchString, identChars=None, caseless=False ): - super(Keyword,self).__init__() - if identChars is None: - identChars = Keyword.DEFAULT_KEYWORD_CHARS - self.match = matchString - self.matchLen = len(matchString) - try: - self.firstMatchChar = matchString[0] - except IndexError: - warnings.warn("null string passed to Keyword; use Empty() instead", - SyntaxWarning, stacklevel=2) - self.name = '"%s"' % self.match - self.errmsg = "Expected " + self.name - self.mayReturnEmpty = False - self.mayIndexError = False - self.caseless = caseless - if caseless: - self.caselessmatch = matchString.upper() - identChars = identChars.upper() - self.identChars = set(identChars) - - def parseImpl( self, instring, loc, doActions=True ): - if self.caseless: - if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and - (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and - (loc == 0 or instring[loc-1].upper() not in self.identChars) ): - return loc+self.matchLen, self.match - else: - if (instring[loc] == self.firstMatchChar and - (self.matchLen==1 or instring.startswith(self.match,loc)) and - (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and - (loc == 0 or instring[loc-1] not in self.identChars) ): - return loc+self.matchLen, self.match - raise ParseException(instring, loc, self.errmsg, self) - - def copy(self): - c = super(Keyword,self).copy() - c.identChars = Keyword.DEFAULT_KEYWORD_CHARS - return c - - @staticmethod - def setDefaultKeywordChars( chars ): - """Overrides the default Keyword chars - """ - Keyword.DEFAULT_KEYWORD_CHARS = chars - -class CaselessLiteral(Literal): - """ - Token to match a specified string, ignoring case of letters. - Note: the matched results will always be in the case of the given - match string, NOT the case of the input text. - - Example:: - OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD'] - - (Contrast with example for L{CaselessKeyword}.) - """ - def __init__( self, matchString ): - super(CaselessLiteral,self).__init__( matchString.upper() ) - # Preserve the defining literal. - self.returnString = matchString - self.name = "'%s'" % self.returnString - self.errmsg = "Expected " + self.name - - def parseImpl( self, instring, loc, doActions=True ): - if instring[ loc:loc+self.matchLen ].upper() == self.match: - return loc+self.matchLen, self.returnString - raise ParseException(instring, loc, self.errmsg, self) - -class CaselessKeyword(Keyword): - """ - Caseless version of L{Keyword}. - - Example:: - OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD'] - - (Contrast with example for L{CaselessLiteral}.) - """ - def __init__( self, matchString, identChars=None ): - super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True ) - - def parseImpl( self, instring, loc, doActions=True ): - if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and - (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ): - return loc+self.matchLen, self.match - raise ParseException(instring, loc, self.errmsg, self) - -class CloseMatch(Token): - """ - A variation on L{Literal} which matches "close" matches, that is, - strings with at most 'n' mismatching characters. C{CloseMatch} takes parameters: - - C{match_string} - string to be matched - - C{maxMismatches} - (C{default=1}) maximum number of mismatches allowed to count as a match - - The results from a successful parse will contain the matched text from the input string and the following named results: - - C{mismatches} - a list of the positions within the match_string where mismatches were found - - C{original} - the original match_string used to compare against the input string - - If C{mismatches} is an empty list, then the match was an exact match. - - Example:: - patt = CloseMatch("ATCATCGAATGGA") - patt.parseString("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']}) - patt.parseString("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1) - - # exact match - patt.parseString("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']}) - - # close match allowing up to 2 mismatches - patt = CloseMatch("ATCATCGAATGGA", maxMismatches=2) - patt.parseString("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']}) - """ - def __init__(self, match_string, maxMismatches=1): - super(CloseMatch,self).__init__() - self.name = match_string - self.match_string = match_string - self.maxMismatches = maxMismatches - self.errmsg = "Expected %r (with up to %d mismatches)" % (self.match_string, self.maxMismatches) - self.mayIndexError = False - self.mayReturnEmpty = False - - def parseImpl( self, instring, loc, doActions=True ): - start = loc - instrlen = len(instring) - maxloc = start + len(self.match_string) - - if maxloc <= instrlen: - match_string = self.match_string - match_stringloc = 0 - mismatches = [] - maxMismatches = self.maxMismatches - - for match_stringloc,s_m in enumerate(zip(instring[loc:maxloc], self.match_string)): - src,mat = s_m - if src != mat: - mismatches.append(match_stringloc) - if len(mismatches) > maxMismatches: - break - else: - loc = match_stringloc + 1 - results = ParseResults([instring[start:loc]]) - results['original'] = self.match_string - results['mismatches'] = mismatches - return loc, results - - raise ParseException(instring, loc, self.errmsg, self) - - -class Word(Token): - """ - Token for matching words composed of allowed character sets. - Defined with string containing all allowed initial characters, - an optional string containing allowed body characters (if omitted, - defaults to the initial character set), and an optional minimum, - maximum, and/or exact length. The default value for C{min} is 1 (a - minimum value < 1 is not valid); the default values for C{max} and C{exact} - are 0, meaning no maximum or exact length restriction. An optional - C{excludeChars} parameter can list characters that might be found in - the input C{bodyChars} string; useful to define a word of all printables - except for one or two characters, for instance. - - L{srange} is useful for defining custom character set strings for defining - C{Word} expressions, using range notation from regular expression character sets. - - A common mistake is to use C{Word} to match a specific literal string, as in - C{Word("Address")}. Remember that C{Word} uses the string argument to define - I{sets} of matchable characters. This expression would match "Add", "AAA", - "dAred", or any other word made up of the characters 'A', 'd', 'r', 'e', and 's'. - To match an exact literal string, use L{Literal} or L{Keyword}. - - pyparsing includes helper strings for building Words: - - L{alphas} - - L{nums} - - L{alphanums} - - L{hexnums} - - L{alphas8bit} (alphabetic characters in ASCII range 128-255 - accented, tilded, umlauted, etc.) - - L{punc8bit} (non-alphabetic characters in ASCII range 128-255 - currency, symbols, superscripts, diacriticals, etc.) - - L{printables} (any non-whitespace character) - - Example:: - # a word composed of digits - integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9")) - - # a word with a leading capital, and zero or more lowercase - capital_word = Word(alphas.upper(), alphas.lower()) - - # hostnames are alphanumeric, with leading alpha, and '-' - hostname = Word(alphas, alphanums+'-') - - # roman numeral (not a strict parser, accepts invalid mix of characters) - roman = Word("IVXLCDM") - - # any string of non-whitespace characters, except for ',' - csv_value = Word(printables, excludeChars=",") - """ - def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0, asKeyword=False, excludeChars=None ): - super(Word,self).__init__() - if excludeChars: - initChars = ''.join(c for c in initChars if c not in excludeChars) - if bodyChars: - bodyChars = ''.join(c for c in bodyChars if c not in excludeChars) - self.initCharsOrig = initChars - self.initChars = set(initChars) - if bodyChars : - self.bodyCharsOrig = bodyChars - self.bodyChars = set(bodyChars) - else: - self.bodyCharsOrig = initChars - self.bodyChars = set(initChars) - - self.maxSpecified = max > 0 - - if min < 1: - raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted") - - self.minLen = min - - if max > 0: - self.maxLen = max - else: - self.maxLen = _MAX_INT - - if exact > 0: - self.maxLen = exact - self.minLen = exact - - self.name = _ustr(self) - self.errmsg = "Expected " + self.name - self.mayIndexError = False - self.asKeyword = asKeyword - - if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0): - if self.bodyCharsOrig == self.initCharsOrig: - self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig) - elif len(self.initCharsOrig) == 1: - self.reString = "%s[%s]*" % \ - (re.escape(self.initCharsOrig), - _escapeRegexRangeChars(self.bodyCharsOrig),) - else: - self.reString = "[%s][%s]*" % \ - (_escapeRegexRangeChars(self.initCharsOrig), - _escapeRegexRangeChars(self.bodyCharsOrig),) - if self.asKeyword: - self.reString = r"\b"+self.reString+r"\b" - try: - self.re = re.compile( self.reString ) - except Exception: - self.re = None - - def parseImpl( self, instring, loc, doActions=True ): - if self.re: - result = self.re.match(instring,loc) - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - return loc, result.group() - - if not(instring[ loc ] in self.initChars): - raise ParseException(instring, loc, self.errmsg, self) - - start = loc - loc += 1 - instrlen = len(instring) - bodychars = self.bodyChars - maxloc = start + self.maxLen - maxloc = min( maxloc, instrlen ) - while loc < maxloc and instring[loc] in bodychars: - loc += 1 - - throwException = False - if loc - start < self.minLen: - throwException = True - if self.maxSpecified and loc < instrlen and instring[loc] in bodychars: - throwException = True - if self.asKeyword: - if (start>0 and instring[start-1] in bodychars) or (loc<instrlen and instring[loc] in bodychars): - throwException = True - - if throwException: - raise ParseException(instring, loc, self.errmsg, self) - - return loc, instring[start:loc] - - def __str__( self ): - try: - return super(Word,self).__str__() - except Exception: - pass - - - if self.strRepr is None: - - def charsAsStr(s): - if len(s)>4: - return s[:4]+"..." - else: - return s - - if ( self.initCharsOrig != self.bodyCharsOrig ): - self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) ) - else: - self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig) - - return self.strRepr - - -class Regex(Token): - r""" - Token for matching strings that match a given regular expression. - Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module. - If the given regex contains named groups (defined using C{(?P<name>...)}), these will be preserved as - named parse results. - - Example:: - realnum = Regex(r"[+-]?\d+\.\d*") - date = Regex(r'(?P<year>\d{4})-(?P<month>\d\d?)-(?P<day>\d\d?)') - # ref: http://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression - roman = Regex(r"M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})") - """ - compiledREtype = type(re.compile("[A-Z]")) - def __init__( self, pattern, flags=0): - """The parameters C{pattern} and C{flags} are passed to the C{re.compile()} function as-is. See the Python C{re} module for an explanation of the acceptable patterns and flags.""" - super(Regex,self).__init__() - - if isinstance(pattern, basestring): - if not pattern: - warnings.warn("null string passed to Regex; use Empty() instead", - SyntaxWarning, stacklevel=2) - - self.pattern = pattern - self.flags = flags - - try: - self.re = re.compile(self.pattern, self.flags) - self.reString = self.pattern - except sre_constants.error: - warnings.warn("invalid pattern (%s) passed to Regex" % pattern, - SyntaxWarning, stacklevel=2) - raise - - elif isinstance(pattern, Regex.compiledREtype): - self.re = pattern - self.pattern = \ - self.reString = str(pattern) - self.flags = flags - - else: - raise ValueError("Regex may only be constructed with a string or a compiled RE object") - - self.name = _ustr(self) - self.errmsg = "Expected " + self.name - self.mayIndexError = False - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - result = self.re.match(instring,loc) - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - d = result.groupdict() - ret = ParseResults(result.group()) - if d: - for k in d: - ret[k] = d[k] - return loc,ret - - def __str__( self ): - try: - return super(Regex,self).__str__() - except Exception: - pass - - if self.strRepr is None: - self.strRepr = "Re:(%s)" % repr(self.pattern) - - return self.strRepr - - -class QuotedString(Token): - r""" - Token for matching strings that are delimited by quoting characters. - - Defined with the following parameters: - - quoteChar - string of one or more characters defining the quote delimiting string - - escChar - character to escape quotes, typically backslash (default=C{None}) - - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=C{None}) - - multiline - boolean indicating whether quotes can span multiple lines (default=C{False}) - - unquoteResults - boolean indicating whether the matched text should be unquoted (default=C{True}) - - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=C{None} => same as quoteChar) - - convertWhitespaceEscapes - convert escaped whitespace (C{'\t'}, C{'\n'}, etc.) to actual whitespace (default=C{True}) - - Example:: - qs = QuotedString('"') - print(qs.searchString('lsjdf "This is the quote" sldjf')) - complex_qs = QuotedString('{{', endQuoteChar='}}') - print(complex_qs.searchString('lsjdf {{This is the "quote"}} sldjf')) - sql_qs = QuotedString('"', escQuote='""') - print(sql_qs.searchString('lsjdf "This is the quote with ""embedded"" quotes" sldjf')) - prints:: - [['This is the quote']] - [['This is the "quote"']] - [['This is the quote with "embedded" quotes']] - """ - def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None, convertWhitespaceEscapes=True): - super(QuotedString,self).__init__() - - # remove white space from quote chars - wont work anyway - quoteChar = quoteChar.strip() - if not quoteChar: - warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) - raise SyntaxError() - - if endQuoteChar is None: - endQuoteChar = quoteChar - else: - endQuoteChar = endQuoteChar.strip() - if not endQuoteChar: - warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) - raise SyntaxError() - - self.quoteChar = quoteChar - self.quoteCharLen = len(quoteChar) - self.firstQuoteChar = quoteChar[0] - self.endQuoteChar = endQuoteChar - self.endQuoteCharLen = len(endQuoteChar) - self.escChar = escChar - self.escQuote = escQuote - self.unquoteResults = unquoteResults - self.convertWhitespaceEscapes = convertWhitespaceEscapes - - if multiline: - self.flags = re.MULTILINE | re.DOTALL - self.pattern = r'%s(?:[^%s%s]' % \ - ( re.escape(self.quoteChar), - _escapeRegexRangeChars(self.endQuoteChar[0]), - (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) - else: - self.flags = 0 - self.pattern = r'%s(?:[^%s\n\r%s]' % \ - ( re.escape(self.quoteChar), - _escapeRegexRangeChars(self.endQuoteChar[0]), - (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) - if len(self.endQuoteChar) > 1: - self.pattern += ( - '|(?:' + ')|(?:'.join("%s[^%s]" % (re.escape(self.endQuoteChar[:i]), - _escapeRegexRangeChars(self.endQuoteChar[i])) - for i in range(len(self.endQuoteChar)-1,0,-1)) + ')' - ) - if escQuote: - self.pattern += (r'|(?:%s)' % re.escape(escQuote)) - if escChar: - self.pattern += (r'|(?:%s.)' % re.escape(escChar)) - self.escCharReplacePattern = re.escape(self.escChar)+"(.)" - self.pattern += (r')*%s' % re.escape(self.endQuoteChar)) - - try: - self.re = re.compile(self.pattern, self.flags) - self.reString = self.pattern - except sre_constants.error: - warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern, - SyntaxWarning, stacklevel=2) - raise - - self.name = _ustr(self) - self.errmsg = "Expected " + self.name - self.mayIndexError = False - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - ret = result.group() - - if self.unquoteResults: - - # strip off quotes - ret = ret[self.quoteCharLen:-self.endQuoteCharLen] - - if isinstance(ret,basestring): - # replace escaped whitespace - if '\\' in ret and self.convertWhitespaceEscapes: - ws_map = { - r'\t' : '\t', - r'\n' : '\n', - r'\f' : '\f', - r'\r' : '\r', - } - for wslit,wschar in ws_map.items(): - ret = ret.replace(wslit, wschar) - - # replace escaped characters - if self.escChar: - ret = re.sub(self.escCharReplacePattern, r"\g<1>", ret) - - # replace escaped quotes - if self.escQuote: - ret = ret.replace(self.escQuote, self.endQuoteChar) - - return loc, ret - - def __str__( self ): - try: - return super(QuotedString,self).__str__() - except Exception: - pass - - if self.strRepr is None: - self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar) - - return self.strRepr - - -class CharsNotIn(Token): - """ - Token for matching words composed of characters I{not} in a given set (will - include whitespace in matched characters if not listed in the provided exclusion set - see example). - Defined with string containing all disallowed characters, and an optional - minimum, maximum, and/or exact length. The default value for C{min} is 1 (a - minimum value < 1 is not valid); the default values for C{max} and C{exact} - are 0, meaning no maximum or exact length restriction. - - Example:: - # define a comma-separated-value as anything that is not a ',' - csv_value = CharsNotIn(',') - print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213")) - prints:: - ['dkls', 'lsdkjf', 's12 34', '@!#', '213'] - """ - def __init__( self, notChars, min=1, max=0, exact=0 ): - super(CharsNotIn,self).__init__() - self.skipWhitespace = False - self.notChars = notChars - - if min < 1: - raise ValueError("cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted") - - self.minLen = min - - if max > 0: - self.maxLen = max - else: - self.maxLen = _MAX_INT - - if exact > 0: - self.maxLen = exact - self.minLen = exact - - self.name = _ustr(self) - self.errmsg = "Expected " + self.name - self.mayReturnEmpty = ( self.minLen == 0 ) - self.mayIndexError = False - - def parseImpl( self, instring, loc, doActions=True ): - if instring[loc] in self.notChars: - raise ParseException(instring, loc, self.errmsg, self) - - start = loc - loc += 1 - notchars = self.notChars - maxlen = min( start+self.maxLen, len(instring) ) - while loc < maxlen and \ - (instring[loc] not in notchars): - loc += 1 - - if loc - start < self.minLen: - raise ParseException(instring, loc, self.errmsg, self) - - return loc, instring[start:loc] - - def __str__( self ): - try: - return super(CharsNotIn, self).__str__() - except Exception: - pass - - if self.strRepr is None: - if len(self.notChars) > 4: - self.strRepr = "!W:(%s...)" % self.notChars[:4] - else: - self.strRepr = "!W:(%s)" % self.notChars - - return self.strRepr - -class White(Token): - """ - Special matching class for matching whitespace. Normally, whitespace is ignored - by pyparsing grammars. This class is included when some whitespace structures - are significant. Define with a string containing the whitespace characters to be - matched; default is C{" \\t\\r\\n"}. Also takes optional C{min}, C{max}, and C{exact} arguments, - as defined for the C{L{Word}} class. - """ - whiteStrs = { - " " : "<SPC>", - "\t": "<TAB>", - "\n": "<LF>", - "\r": "<CR>", - "\f": "<FF>", - } - def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0): - super(White,self).__init__() - self.matchWhite = ws - self.setWhitespaceChars( "".join(c for c in self.whiteChars if c not in self.matchWhite) ) - #~ self.leaveWhitespace() - self.name = ("".join(White.whiteStrs[c] for c in self.matchWhite)) - self.mayReturnEmpty = True - self.errmsg = "Expected " + self.name - - self.minLen = min - - if max > 0: - self.maxLen = max - else: - self.maxLen = _MAX_INT - - if exact > 0: - self.maxLen = exact - self.minLen = exact - - def parseImpl( self, instring, loc, doActions=True ): - if not(instring[ loc ] in self.matchWhite): - raise ParseException(instring, loc, self.errmsg, self) - start = loc - loc += 1 - maxloc = start + self.maxLen - maxloc = min( maxloc, len(instring) ) - while loc < maxloc and instring[loc] in self.matchWhite: - loc += 1 - - if loc - start < self.minLen: - raise ParseException(instring, loc, self.errmsg, self) - - return loc, instring[start:loc] - - -class _PositionToken(Token): - def __init__( self ): - super(_PositionToken,self).__init__() - self.name=self.__class__.__name__ - self.mayReturnEmpty = True - self.mayIndexError = False - -class GoToColumn(_PositionToken): - """ - Token to advance to a specific column of input text; useful for tabular report scraping. - """ - def __init__( self, colno ): - super(GoToColumn,self).__init__() - self.col = colno - - def preParse( self, instring, loc ): - if col(loc,instring) != self.col: - instrlen = len(instring) - if self.ignoreExprs: - loc = self._skipIgnorables( instring, loc ) - while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col : - loc += 1 - return loc - - def parseImpl( self, instring, loc, doActions=True ): - thiscol = col( loc, instring ) - if thiscol > self.col: - raise ParseException( instring, loc, "Text not in expected column", self ) - newloc = loc + self.col - thiscol - ret = instring[ loc: newloc ] - return newloc, ret - - -class LineStart(_PositionToken): - """ - Matches if current position is at the beginning of a line within the parse string - - Example:: - - test = '''\ - AAA this line - AAA and this line - AAA but not this one - B AAA and definitely not this one - ''' - - for t in (LineStart() + 'AAA' + restOfLine).searchString(test): - print(t) - - Prints:: - ['AAA', ' this line'] - ['AAA', ' and this line'] - - """ - def __init__( self ): - super(LineStart,self).__init__() - self.errmsg = "Expected start of line" - - def parseImpl( self, instring, loc, doActions=True ): - if col(loc, instring) == 1: - return loc, [] - raise ParseException(instring, loc, self.errmsg, self) - -class LineEnd(_PositionToken): - """ - Matches if current position is at the end of a line within the parse string - """ - def __init__( self ): - super(LineEnd,self).__init__() - self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") ) - self.errmsg = "Expected end of line" - - def parseImpl( self, instring, loc, doActions=True ): - if loc<len(instring): - if instring[loc] == "\n": - return loc+1, "\n" - else: - raise ParseException(instring, loc, self.errmsg, self) - elif loc == len(instring): - return loc+1, [] - else: - raise ParseException(instring, loc, self.errmsg, self) - -class StringStart(_PositionToken): - """ - Matches if current position is at the beginning of the parse string - """ - def __init__( self ): - super(StringStart,self).__init__() - self.errmsg = "Expected start of text" - - def parseImpl( self, instring, loc, doActions=True ): - if loc != 0: - # see if entire string up to here is just whitespace and ignoreables - if loc != self.preParse( instring, 0 ): - raise ParseException(instring, loc, self.errmsg, self) - return loc, [] - -class StringEnd(_PositionToken): - """ - Matches if current position is at the end of the parse string - """ - def __init__( self ): - super(StringEnd,self).__init__() - self.errmsg = "Expected end of text" - - def parseImpl( self, instring, loc, doActions=True ): - if loc < len(instring): - raise ParseException(instring, loc, self.errmsg, self) - elif loc == len(instring): - return loc+1, [] - elif loc > len(instring): - return loc, [] - else: - raise ParseException(instring, loc, self.errmsg, self) - -class WordStart(_PositionToken): - """ - Matches if the current position is at the beginning of a Word, and - is not preceded by any character in a given set of C{wordChars} - (default=C{printables}). To emulate the C{\b} behavior of regular expressions, - use C{WordStart(alphanums)}. C{WordStart} will also match at the beginning of - the string being parsed, or at the beginning of a line. - """ - def __init__(self, wordChars = printables): - super(WordStart,self).__init__() - self.wordChars = set(wordChars) - self.errmsg = "Not at the start of a word" - - def parseImpl(self, instring, loc, doActions=True ): - if loc != 0: - if (instring[loc-1] in self.wordChars or - instring[loc] not in self.wordChars): - raise ParseException(instring, loc, self.errmsg, self) - return loc, [] - -class WordEnd(_PositionToken): - """ - Matches if the current position is at the end of a Word, and - is not followed by any character in a given set of C{wordChars} - (default=C{printables}). To emulate the C{\b} behavior of regular expressions, - use C{WordEnd(alphanums)}. C{WordEnd} will also match at the end of - the string being parsed, or at the end of a line. - """ - def __init__(self, wordChars = printables): - super(WordEnd,self).__init__() - self.wordChars = set(wordChars) - self.skipWhitespace = False - self.errmsg = "Not at the end of a word" - - def parseImpl(self, instring, loc, doActions=True ): - instrlen = len(instring) - if instrlen>0 and loc<instrlen: - if (instring[loc] in self.wordChars or - instring[loc-1] not in self.wordChars): - raise ParseException(instring, loc, self.errmsg, self) - return loc, [] - - -class ParseExpression(ParserElement): - """ - Abstract subclass of ParserElement, for combining and post-processing parsed tokens. - """ - def __init__( self, exprs, savelist = False ): - super(ParseExpression,self).__init__(savelist) - if isinstance( exprs, _generatorType ): - exprs = list(exprs) - - if isinstance( exprs, basestring ): - self.exprs = [ ParserElement._literalStringClass( exprs ) ] - elif isinstance( exprs, Iterable ): - exprs = list(exprs) - # if sequence of strings provided, wrap with Literal - if all(isinstance(expr, basestring) for expr in exprs): - exprs = map(ParserElement._literalStringClass, exprs) - self.exprs = list(exprs) - else: - try: - self.exprs = list( exprs ) - except TypeError: - self.exprs = [ exprs ] - self.callPreparse = False - - def __getitem__( self, i ): - return self.exprs[i] - - def append( self, other ): - self.exprs.append( other ) - self.strRepr = None - return self - - def leaveWhitespace( self ): - """Extends C{leaveWhitespace} defined in base class, and also invokes C{leaveWhitespace} on - all contained expressions.""" - self.skipWhitespace = False - self.exprs = [ e.copy() for e in self.exprs ] - for e in self.exprs: - e.leaveWhitespace() - return self - - def ignore( self, other ): - if isinstance( other, Suppress ): - if other not in self.ignoreExprs: - super( ParseExpression, self).ignore( other ) - for e in self.exprs: - e.ignore( self.ignoreExprs[-1] ) - else: - super( ParseExpression, self).ignore( other ) - for e in self.exprs: - e.ignore( self.ignoreExprs[-1] ) - return self - - def __str__( self ): - try: - return super(ParseExpression,self).__str__() - except Exception: - pass - - if self.strRepr is None: - self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.exprs) ) - return self.strRepr - - def streamline( self ): - super(ParseExpression,self).streamline() - - for e in self.exprs: - e.streamline() - - # collapse nested And's of the form And( And( And( a,b), c), d) to And( a,b,c,d ) - # but only if there are no parse actions or resultsNames on the nested And's - # (likewise for Or's and MatchFirst's) - if ( len(self.exprs) == 2 ): - other = self.exprs[0] - if ( isinstance( other, self.__class__ ) and - not(other.parseAction) and - other.resultsName is None and - not other.debug ): - self.exprs = other.exprs[:] + [ self.exprs[1] ] - self.strRepr = None - self.mayReturnEmpty |= other.mayReturnEmpty - self.mayIndexError |= other.mayIndexError - - other = self.exprs[-1] - if ( isinstance( other, self.__class__ ) and - not(other.parseAction) and - other.resultsName is None and - not other.debug ): - self.exprs = self.exprs[:-1] + other.exprs[:] - self.strRepr = None - self.mayReturnEmpty |= other.mayReturnEmpty - self.mayIndexError |= other.mayIndexError - - self.errmsg = "Expected " + _ustr(self) - - return self - - def setResultsName( self, name, listAllMatches=False ): - ret = super(ParseExpression,self).setResultsName(name,listAllMatches) - return ret - - def validate( self, validateTrace=[] ): - tmp = validateTrace[:]+[self] - for e in self.exprs: - e.validate(tmp) - self.checkRecursion( [] ) - - def copy(self): - ret = super(ParseExpression,self).copy() - ret.exprs = [e.copy() for e in self.exprs] - return ret - -class And(ParseExpression): - """ - Requires all given C{ParseExpression}s to be found in the given order. - Expressions may be separated by whitespace. - May be constructed using the C{'+'} operator. - May also be constructed using the C{'-'} operator, which will suppress backtracking. - - Example:: - integer = Word(nums) - name_expr = OneOrMore(Word(alphas)) - - expr = And([integer("id"),name_expr("name"),integer("age")]) - # more easily written as: - expr = integer("id") + name_expr("name") + integer("age") - """ - - class _ErrorStop(Empty): - def __init__(self, *args, **kwargs): - super(And._ErrorStop,self).__init__(*args, **kwargs) - self.name = '-' - self.leaveWhitespace() - - def __init__( self, exprs, savelist = True ): - super(And,self).__init__(exprs, savelist) - self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) - self.setWhitespaceChars( self.exprs[0].whiteChars ) - self.skipWhitespace = self.exprs[0].skipWhitespace - self.callPreparse = True - - def parseImpl( self, instring, loc, doActions=True ): - # pass False as last arg to _parse for first element, since we already - # pre-parsed the string as part of our And pre-parsing - loc, resultlist = self.exprs[0]._parse( instring, loc, doActions, callPreParse=False ) - errorStop = False - for e in self.exprs[1:]: - if isinstance(e, And._ErrorStop): - errorStop = True - continue - if errorStop: - try: - loc, exprtokens = e._parse( instring, loc, doActions ) - except ParseSyntaxException: - raise - except ParseBaseException as pe: - pe.__traceback__ = None - raise ParseSyntaxException._from_exception(pe) - except IndexError: - raise ParseSyntaxException(instring, len(instring), self.errmsg, self) - else: - loc, exprtokens = e._parse( instring, loc, doActions ) - if exprtokens or exprtokens.haskeys(): - resultlist += exprtokens - return loc, resultlist - - def __iadd__(self, other ): - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - return self.append( other ) #And( [ self, other ] ) - - def checkRecursion( self, parseElementList ): - subRecCheckList = parseElementList[:] + [ self ] - for e in self.exprs: - e.checkRecursion( subRecCheckList ) - if not e.mayReturnEmpty: - break - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + " ".join(_ustr(e) for e in self.exprs) + "}" - - return self.strRepr - - -class Or(ParseExpression): - """ - Requires that at least one C{ParseExpression} is found. - If two expressions match, the expression that matches the longest string will be used. - May be constructed using the C{'^'} operator. - - Example:: - # construct Or using '^' operator - - number = Word(nums) ^ Combine(Word(nums) + '.' + Word(nums)) - print(number.searchString("123 3.1416 789")) - prints:: - [['123'], ['3.1416'], ['789']] - """ - def __init__( self, exprs, savelist = False ): - super(Or,self).__init__(exprs, savelist) - if self.exprs: - self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) - else: - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - maxExcLoc = -1 - maxException = None - matches = [] - for e in self.exprs: - try: - loc2 = e.tryParse( instring, loc ) - except ParseException as err: - err.__traceback__ = None - if err.loc > maxExcLoc: - maxException = err - maxExcLoc = err.loc - except IndexError: - if len(instring) > maxExcLoc: - maxException = ParseException(instring,len(instring),e.errmsg,self) - maxExcLoc = len(instring) - else: - # save match among all matches, to retry longest to shortest - matches.append((loc2, e)) - - if matches: - matches.sort(key=lambda x: -x[0]) - for _,e in matches: - try: - return e._parse( instring, loc, doActions ) - except ParseException as err: - err.__traceback__ = None - if err.loc > maxExcLoc: - maxException = err - maxExcLoc = err.loc - - if maxException is not None: - maxException.msg = self.errmsg - raise maxException - else: - raise ParseException(instring, loc, "no defined alternatives to match", self) - - - def __ixor__(self, other ): - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - return self.append( other ) #Or( [ self, other ] ) - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + " ^ ".join(_ustr(e) for e in self.exprs) + "}" - - return self.strRepr - - def checkRecursion( self, parseElementList ): - subRecCheckList = parseElementList[:] + [ self ] - for e in self.exprs: - e.checkRecursion( subRecCheckList ) - - -class MatchFirst(ParseExpression): - """ - Requires that at least one C{ParseExpression} is found. - If two expressions match, the first one listed is the one that will match. - May be constructed using the C{'|'} operator. - - Example:: - # construct MatchFirst using '|' operator - - # watch the order of expressions to match - number = Word(nums) | Combine(Word(nums) + '.' + Word(nums)) - print(number.searchString("123 3.1416 789")) # Fail! -> [['123'], ['3'], ['1416'], ['789']] - - # put more selective expression first - number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums) - print(number.searchString("123 3.1416 789")) # Better -> [['123'], ['3.1416'], ['789']] - """ - def __init__( self, exprs, savelist = False ): - super(MatchFirst,self).__init__(exprs, savelist) - if self.exprs: - self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) - else: - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - maxExcLoc = -1 - maxException = None - for e in self.exprs: - try: - ret = e._parse( instring, loc, doActions ) - return ret - except ParseException as err: - if err.loc > maxExcLoc: - maxException = err - maxExcLoc = err.loc - except IndexError: - if len(instring) > maxExcLoc: - maxException = ParseException(instring,len(instring),e.errmsg,self) - maxExcLoc = len(instring) - - # only got here if no expression matched, raise exception for match that made it the furthest - else: - if maxException is not None: - maxException.msg = self.errmsg - raise maxException - else: - raise ParseException(instring, loc, "no defined alternatives to match", self) - - def __ior__(self, other ): - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - return self.append( other ) #MatchFirst( [ self, other ] ) - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + " | ".join(_ustr(e) for e in self.exprs) + "}" - - return self.strRepr - - def checkRecursion( self, parseElementList ): - subRecCheckList = parseElementList[:] + [ self ] - for e in self.exprs: - e.checkRecursion( subRecCheckList ) - - -class Each(ParseExpression): - """ - Requires all given C{ParseExpression}s to be found, but in any order. - Expressions may be separated by whitespace. - May be constructed using the C{'&'} operator. - - Example:: - color = oneOf("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN") - shape_type = oneOf("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON") - integer = Word(nums) - shape_attr = "shape:" + shape_type("shape") - posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn") - color_attr = "color:" + color("color") - size_attr = "size:" + integer("size") - - # use Each (using operator '&') to accept attributes in any order - # (shape and posn are required, color and size are optional) - shape_spec = shape_attr & posn_attr & Optional(color_attr) & Optional(size_attr) - - shape_spec.runTests(''' - shape: SQUARE color: BLACK posn: 100, 120 - shape: CIRCLE size: 50 color: BLUE posn: 50,80 - color:GREEN size:20 shape:TRIANGLE posn:20,40 - ''' - ) - prints:: - shape: SQUARE color: BLACK posn: 100, 120 - ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']] - - color: BLACK - - posn: ['100', ',', '120'] - - x: 100 - - y: 120 - - shape: SQUARE - - - shape: CIRCLE size: 50 color: BLUE posn: 50,80 - ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']] - - color: BLUE - - posn: ['50', ',', '80'] - - x: 50 - - y: 80 - - shape: CIRCLE - - size: 50 - - - color: GREEN size: 20 shape: TRIANGLE posn: 20,40 - ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']] - - color: GREEN - - posn: ['20', ',', '40'] - - x: 20 - - y: 40 - - shape: TRIANGLE - - size: 20 - """ - def __init__( self, exprs, savelist = True ): - super(Each,self).__init__(exprs, savelist) - self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) - self.skipWhitespace = True - self.initExprGroups = True - - def parseImpl( self, instring, loc, doActions=True ): - if self.initExprGroups: - self.opt1map = dict((id(e.expr),e) for e in self.exprs if isinstance(e,Optional)) - opt1 = [ e.expr for e in self.exprs if isinstance(e,Optional) ] - opt2 = [ e for e in self.exprs if e.mayReturnEmpty and not isinstance(e,Optional)] - self.optionals = opt1 + opt2 - self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ] - self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ] - self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ] - self.required += self.multirequired - self.initExprGroups = False - tmpLoc = loc - tmpReqd = self.required[:] - tmpOpt = self.optionals[:] - matchOrder = [] - - keepMatching = True - while keepMatching: - tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired - failed = [] - for e in tmpExprs: - try: - tmpLoc = e.tryParse( instring, tmpLoc ) - except ParseException: - failed.append(e) - else: - matchOrder.append(self.opt1map.get(id(e),e)) - if e in tmpReqd: - tmpReqd.remove(e) - elif e in tmpOpt: - tmpOpt.remove(e) - if len(failed) == len(tmpExprs): - keepMatching = False - - if tmpReqd: - missing = ", ".join(_ustr(e) for e in tmpReqd) - raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing ) - - # add any unmatched Optionals, in case they have default values defined - matchOrder += [e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt] - - resultlist = [] - for e in matchOrder: - loc,results = e._parse(instring,loc,doActions) - resultlist.append(results) - - finalResults = sum(resultlist, ParseResults([])) - return loc, finalResults - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + " & ".join(_ustr(e) for e in self.exprs) + "}" - - return self.strRepr - - def checkRecursion( self, parseElementList ): - subRecCheckList = parseElementList[:] + [ self ] - for e in self.exprs: - e.checkRecursion( subRecCheckList ) - - -class ParseElementEnhance(ParserElement): - """ - Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens. - """ - def __init__( self, expr, savelist=False ): - super(ParseElementEnhance,self).__init__(savelist) - if isinstance( expr, basestring ): - if issubclass(ParserElement._literalStringClass, Token): - expr = ParserElement._literalStringClass(expr) - else: - expr = ParserElement._literalStringClass(Literal(expr)) - self.expr = expr - self.strRepr = None - if expr is not None: - self.mayIndexError = expr.mayIndexError - self.mayReturnEmpty = expr.mayReturnEmpty - self.setWhitespaceChars( expr.whiteChars ) - self.skipWhitespace = expr.skipWhitespace - self.saveAsList = expr.saveAsList - self.callPreparse = expr.callPreparse - self.ignoreExprs.extend(expr.ignoreExprs) - - def parseImpl( self, instring, loc, doActions=True ): - if self.expr is not None: - return self.expr._parse( instring, loc, doActions, callPreParse=False ) - else: - raise ParseException("",loc,self.errmsg,self) - - def leaveWhitespace( self ): - self.skipWhitespace = False - self.expr = self.expr.copy() - if self.expr is not None: - self.expr.leaveWhitespace() - return self - - def ignore( self, other ): - if isinstance( other, Suppress ): - if other not in self.ignoreExprs: - super( ParseElementEnhance, self).ignore( other ) - if self.expr is not None: - self.expr.ignore( self.ignoreExprs[-1] ) - else: - super( ParseElementEnhance, self).ignore( other ) - if self.expr is not None: - self.expr.ignore( self.ignoreExprs[-1] ) - return self - - def streamline( self ): - super(ParseElementEnhance,self).streamline() - if self.expr is not None: - self.expr.streamline() - return self - - def checkRecursion( self, parseElementList ): - if self in parseElementList: - raise RecursiveGrammarException( parseElementList+[self] ) - subRecCheckList = parseElementList[:] + [ self ] - if self.expr is not None: - self.expr.checkRecursion( subRecCheckList ) - - def validate( self, validateTrace=[] ): - tmp = validateTrace[:]+[self] - if self.expr is not None: - self.expr.validate(tmp) - self.checkRecursion( [] ) - - def __str__( self ): - try: - return super(ParseElementEnhance,self).__str__() - except Exception: - pass - - if self.strRepr is None and self.expr is not None: - self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) ) - return self.strRepr - - -class FollowedBy(ParseElementEnhance): - """ - Lookahead matching of the given parse expression. C{FollowedBy} - does I{not} advance the parsing position within the input string, it only - verifies that the specified parse expression matches at the current - position. C{FollowedBy} always returns a null token list. - - Example:: - # use FollowedBy to match a label only if it is followed by a ':' - data_word = Word(alphas) - label = data_word + FollowedBy(':') - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) - - OneOrMore(attr_expr).parseString("shape: SQUARE color: BLACK posn: upper left").pprint() - prints:: - [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']] - """ - def __init__( self, expr ): - super(FollowedBy,self).__init__(expr) - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - self.expr.tryParse( instring, loc ) - return loc, [] - - -class NotAny(ParseElementEnhance): - """ - Lookahead to disallow matching with the given parse expression. C{NotAny} - does I{not} advance the parsing position within the input string, it only - verifies that the specified parse expression does I{not} match at the current - position. Also, C{NotAny} does I{not} skip over leading whitespace. C{NotAny} - always returns a null token list. May be constructed using the '~' operator. - - Example:: - - """ - def __init__( self, expr ): - super(NotAny,self).__init__(expr) - #~ self.leaveWhitespace() - self.skipWhitespace = False # do NOT use self.leaveWhitespace(), don't want to propagate to exprs - self.mayReturnEmpty = True - self.errmsg = "Found unwanted token, "+_ustr(self.expr) - - def parseImpl( self, instring, loc, doActions=True ): - if self.expr.canParseNext(instring, loc): - raise ParseException(instring, loc, self.errmsg, self) - return loc, [] - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "~{" + _ustr(self.expr) + "}" - - return self.strRepr - -class _MultipleMatch(ParseElementEnhance): - def __init__( self, expr, stopOn=None): - super(_MultipleMatch, self).__init__(expr) - self.saveAsList = True - ender = stopOn - if isinstance(ender, basestring): - ender = ParserElement._literalStringClass(ender) - self.not_ender = ~ender if ender is not None else None - - def parseImpl( self, instring, loc, doActions=True ): - self_expr_parse = self.expr._parse - self_skip_ignorables = self._skipIgnorables - check_ender = self.not_ender is not None - if check_ender: - try_not_ender = self.not_ender.tryParse - - # must be at least one (but first see if we are the stopOn sentinel; - # if so, fail) - if check_ender: - try_not_ender(instring, loc) - loc, tokens = self_expr_parse( instring, loc, doActions, callPreParse=False ) - try: - hasIgnoreExprs = (not not self.ignoreExprs) - while 1: - if check_ender: - try_not_ender(instring, loc) - if hasIgnoreExprs: - preloc = self_skip_ignorables( instring, loc ) - else: - preloc = loc - loc, tmptokens = self_expr_parse( instring, preloc, doActions ) - if tmptokens or tmptokens.haskeys(): - tokens += tmptokens - except (ParseException,IndexError): - pass - - return loc, tokens - -class OneOrMore(_MultipleMatch): - """ - Repetition of one or more of the given expression. - - Parameters: - - expr - expression that must match one or more times - - stopOn - (default=C{None}) - expression for a terminating sentinel - (only required if the sentinel would ordinarily match the repetition - expression) - - Example:: - data_word = Word(alphas) - label = data_word + FollowedBy(':') - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) - - text = "shape: SQUARE posn: upper left color: BLACK" - OneOrMore(attr_expr).parseString(text).pprint() # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']] - - # use stopOn attribute for OneOrMore to avoid reading label string as part of the data - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) - OneOrMore(attr_expr).parseString(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']] - - # could also be written as - (attr_expr * (1,)).parseString(text).pprint() - """ - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + _ustr(self.expr) + "}..." - - return self.strRepr - -class ZeroOrMore(_MultipleMatch): - """ - Optional repetition of zero or more of the given expression. - - Parameters: - - expr - expression that must match zero or more times - - stopOn - (default=C{None}) - expression for a terminating sentinel - (only required if the sentinel would ordinarily match the repetition - expression) - - Example: similar to L{OneOrMore} - """ - def __init__( self, expr, stopOn=None): - super(ZeroOrMore,self).__init__(expr, stopOn=stopOn) - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - try: - return super(ZeroOrMore, self).parseImpl(instring, loc, doActions) - except (ParseException,IndexError): - return loc, [] - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "[" + _ustr(self.expr) + "]..." - - return self.strRepr - -class _NullToken(object): - def __bool__(self): - return False - __nonzero__ = __bool__ - def __str__(self): - return "" - -_optionalNotMatched = _NullToken() -class Optional(ParseElementEnhance): - """ - Optional matching of the given expression. - - Parameters: - - expr - expression that must match zero or more times - - default (optional) - value to be returned if the optional expression is not found. - - Example:: - # US postal code can be a 5-digit zip, plus optional 4-digit qualifier - zip = Combine(Word(nums, exact=5) + Optional('-' + Word(nums, exact=4))) - zip.runTests(''' - # traditional ZIP code - 12345 - - # ZIP+4 form - 12101-0001 - - # invalid ZIP - 98765- - ''') - prints:: - # traditional ZIP code - 12345 - ['12345'] - - # ZIP+4 form - 12101-0001 - ['12101-0001'] - - # invalid ZIP - 98765- - ^ - FAIL: Expected end of text (at char 5), (line:1, col:6) - """ - def __init__( self, expr, default=_optionalNotMatched ): - super(Optional,self).__init__( expr, savelist=False ) - self.saveAsList = self.expr.saveAsList - self.defaultValue = default - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - try: - loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False ) - except (ParseException,IndexError): - if self.defaultValue is not _optionalNotMatched: - if self.expr.resultsName: - tokens = ParseResults([ self.defaultValue ]) - tokens[self.expr.resultsName] = self.defaultValue - else: - tokens = [ self.defaultValue ] - else: - tokens = [] - return loc, tokens - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "[" + _ustr(self.expr) + "]" - - return self.strRepr - -class SkipTo(ParseElementEnhance): - """ - Token for skipping over all undefined text until the matched expression is found. - - Parameters: - - expr - target expression marking the end of the data to be skipped - - include - (default=C{False}) if True, the target expression is also parsed - (the skipped text and target expression are returned as a 2-element list). - - ignore - (default=C{None}) used to define grammars (typically quoted strings and - comments) that might contain false matches to the target expression - - failOn - (default=C{None}) define expressions that are not allowed to be - included in the skipped test; if found before the target expression is found, - the SkipTo is not a match - - Example:: - report = ''' - Outstanding Issues Report - 1 Jan 2000 - - # | Severity | Description | Days Open - -----+----------+-------------------------------------------+----------- - 101 | Critical | Intermittent system crash | 6 - 94 | Cosmetic | Spelling error on Login ('log|n') | 14 - 79 | Minor | System slow when running too many reports | 47 - ''' - integer = Word(nums) - SEP = Suppress('|') - # use SkipTo to simply match everything up until the next SEP - # - ignore quoted strings, so that a '|' character inside a quoted string does not match - # - parse action will call token.strip() for each matched token, i.e., the description body - string_data = SkipTo(SEP, ignore=quotedString) - string_data.setParseAction(tokenMap(str.strip)) - ticket_expr = (integer("issue_num") + SEP - + string_data("sev") + SEP - + string_data("desc") + SEP - + integer("days_open")) - - for tkt in ticket_expr.searchString(report): - print tkt.dump() - prints:: - ['101', 'Critical', 'Intermittent system crash', '6'] - - days_open: 6 - - desc: Intermittent system crash - - issue_num: 101 - - sev: Critical - ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14'] - - days_open: 14 - - desc: Spelling error on Login ('log|n') - - issue_num: 94 - - sev: Cosmetic - ['79', 'Minor', 'System slow when running too many reports', '47'] - - days_open: 47 - - desc: System slow when running too many reports - - issue_num: 79 - - sev: Minor - """ - def __init__( self, other, include=False, ignore=None, failOn=None ): - super( SkipTo, self ).__init__( other ) - self.ignoreExpr = ignore - self.mayReturnEmpty = True - self.mayIndexError = False - self.includeMatch = include - self.asList = False - if isinstance(failOn, basestring): - self.failOn = ParserElement._literalStringClass(failOn) - else: - self.failOn = failOn - self.errmsg = "No match found for "+_ustr(self.expr) - - def parseImpl( self, instring, loc, doActions=True ): - startloc = loc - instrlen = len(instring) - expr = self.expr - expr_parse = self.expr._parse - self_failOn_canParseNext = self.failOn.canParseNext if self.failOn is not None else None - self_ignoreExpr_tryParse = self.ignoreExpr.tryParse if self.ignoreExpr is not None else None - - tmploc = loc - while tmploc <= instrlen: - if self_failOn_canParseNext is not None: - # break if failOn expression matches - if self_failOn_canParseNext(instring, tmploc): - break - - if self_ignoreExpr_tryParse is not None: - # advance past ignore expressions - while 1: - try: - tmploc = self_ignoreExpr_tryParse(instring, tmploc) - except ParseBaseException: - break - - try: - expr_parse(instring, tmploc, doActions=False, callPreParse=False) - except (ParseException, IndexError): - # no match, advance loc in string - tmploc += 1 - else: - # matched skipto expr, done - break - - else: - # ran off the end of the input string without matching skipto expr, fail - raise ParseException(instring, loc, self.errmsg, self) - - # build up return values - loc = tmploc - skiptext = instring[startloc:loc] - skipresult = ParseResults(skiptext) - - if self.includeMatch: - loc, mat = expr_parse(instring,loc,doActions,callPreParse=False) - skipresult += mat - - return loc, skipresult - -class Forward(ParseElementEnhance): - """ - Forward declaration of an expression to be defined later - - used for recursive grammars, such as algebraic infix notation. - When the expression is known, it is assigned to the C{Forward} variable using the '<<' operator. - - Note: take care when assigning to C{Forward} not to overlook precedence of operators. - Specifically, '|' has a lower precedence than '<<', so that:: - fwdExpr << a | b | c - will actually be evaluated as:: - (fwdExpr << a) | b | c - thereby leaving b and c out as parseable alternatives. It is recommended that you - explicitly group the values inserted into the C{Forward}:: - fwdExpr << (a | b | c) - Converting to use the '<<=' operator instead will avoid this problem. - - See L{ParseResults.pprint} for an example of a recursive parser created using - C{Forward}. - """ - def __init__( self, other=None ): - super(Forward,self).__init__( other, savelist=False ) - - def __lshift__( self, other ): - if isinstance( other, basestring ): - other = ParserElement._literalStringClass(other) - self.expr = other - self.strRepr = None - self.mayIndexError = self.expr.mayIndexError - self.mayReturnEmpty = self.expr.mayReturnEmpty - self.setWhitespaceChars( self.expr.whiteChars ) - self.skipWhitespace = self.expr.skipWhitespace - self.saveAsList = self.expr.saveAsList - self.ignoreExprs.extend(self.expr.ignoreExprs) - return self - - def __ilshift__(self, other): - return self << other - - def leaveWhitespace( self ): - self.skipWhitespace = False - return self - - def streamline( self ): - if not self.streamlined: - self.streamlined = True - if self.expr is not None: - self.expr.streamline() - return self - - def validate( self, validateTrace=[] ): - if self not in validateTrace: - tmp = validateTrace[:]+[self] - if self.expr is not None: - self.expr.validate(tmp) - self.checkRecursion([]) - - def __str__( self ): - if hasattr(self,"name"): - return self.name - return self.__class__.__name__ + ": ..." - - # stubbed out for now - creates awful memory and perf issues - self._revertClass = self.__class__ - self.__class__ = _ForwardNoRecurse - try: - if self.expr is not None: - retString = _ustr(self.expr) - else: - retString = "None" - finally: - self.__class__ = self._revertClass - return self.__class__.__name__ + ": " + retString - - def copy(self): - if self.expr is not None: - return super(Forward,self).copy() - else: - ret = Forward() - ret <<= self - return ret - -class _ForwardNoRecurse(Forward): - def __str__( self ): - return "..." - -class TokenConverter(ParseElementEnhance): - """ - Abstract subclass of C{ParseExpression}, for converting parsed results. - """ - def __init__( self, expr, savelist=False ): - super(TokenConverter,self).__init__( expr )#, savelist ) - self.saveAsList = False - -class Combine(TokenConverter): - """ - Converter to concatenate all matching tokens to a single string. - By default, the matching patterns must also be contiguous in the input string; - this can be disabled by specifying C{'adjacent=False'} in the constructor. - - Example:: - real = Word(nums) + '.' + Word(nums) - print(real.parseString('3.1416')) # -> ['3', '.', '1416'] - # will also erroneously match the following - print(real.parseString('3. 1416')) # -> ['3', '.', '1416'] - - real = Combine(Word(nums) + '.' + Word(nums)) - print(real.parseString('3.1416')) # -> ['3.1416'] - # no match when there are internal spaces - print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...) - """ - def __init__( self, expr, joinString="", adjacent=True ): - super(Combine,self).__init__( expr ) - # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself - if adjacent: - self.leaveWhitespace() - self.adjacent = adjacent - self.skipWhitespace = True - self.joinString = joinString - self.callPreparse = True - - def ignore( self, other ): - if self.adjacent: - ParserElement.ignore(self, other) - else: - super( Combine, self).ignore( other ) - return self - - def postParse( self, instring, loc, tokenlist ): - retToks = tokenlist.copy() - del retToks[:] - retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults) - - if self.resultsName and retToks.haskeys(): - return [ retToks ] - else: - return retToks - -class Group(TokenConverter): - """ - Converter to return the matched tokens as a list - useful for returning tokens of C{L{ZeroOrMore}} and C{L{OneOrMore}} expressions. - - Example:: - ident = Word(alphas) - num = Word(nums) - term = ident | num - func = ident + Optional(delimitedList(term)) - print(func.parseString("fn a,b,100")) # -> ['fn', 'a', 'b', '100'] - - func = ident + Group(Optional(delimitedList(term))) - print(func.parseString("fn a,b,100")) # -> ['fn', ['a', 'b', '100']] - """ - def __init__( self, expr ): - super(Group,self).__init__( expr ) - self.saveAsList = True - - def postParse( self, instring, loc, tokenlist ): - return [ tokenlist ] - -class Dict(TokenConverter): - """ - Converter to return a repetitive expression as a list, but also as a dictionary. - Each element can also be referenced using the first token in the expression as its key. - Useful for tabular report scraping when the first column can be used as a item key. - - Example:: - data_word = Word(alphas) - label = data_word + FollowedBy(':') - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) - - text = "shape: SQUARE posn: upper left color: light blue texture: burlap" - attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) - - # print attributes as plain groups - print(OneOrMore(attr_expr).parseString(text).dump()) - - # instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names - result = Dict(OneOrMore(Group(attr_expr))).parseString(text) - print(result.dump()) - - # access named fields as dict entries, or output as dict - print(result['shape']) - print(result.asDict()) - prints:: - ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap'] - - [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] - - color: light blue - - posn: upper left - - shape: SQUARE - - texture: burlap - SQUARE - {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'} - See more examples at L{ParseResults} of accessing fields by results name. - """ - def __init__( self, expr ): - super(Dict,self).__init__( expr ) - self.saveAsList = True - - def postParse( self, instring, loc, tokenlist ): - for i,tok in enumerate(tokenlist): - if len(tok) == 0: - continue - ikey = tok[0] - if isinstance(ikey,int): - ikey = _ustr(tok[0]).strip() - if len(tok)==1: - tokenlist[ikey] = _ParseResultsWithOffset("",i) - elif len(tok)==2 and not isinstance(tok[1],ParseResults): - tokenlist[ikey] = _ParseResultsWithOffset(tok[1],i) - else: - dictvalue = tok.copy() #ParseResults(i) - del dictvalue[0] - if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.haskeys()): - tokenlist[ikey] = _ParseResultsWithOffset(dictvalue,i) - else: - tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0],i) - - if self.resultsName: - return [ tokenlist ] - else: - return tokenlist - - -class Suppress(TokenConverter): - """ - Converter for ignoring the results of a parsed expression. - - Example:: - source = "a, b, c,d" - wd = Word(alphas) - wd_list1 = wd + ZeroOrMore(',' + wd) - print(wd_list1.parseString(source)) - - # often, delimiters that are useful during parsing are just in the - # way afterward - use Suppress to keep them out of the parsed output - wd_list2 = wd + ZeroOrMore(Suppress(',') + wd) - print(wd_list2.parseString(source)) - prints:: - ['a', ',', 'b', ',', 'c', ',', 'd'] - ['a', 'b', 'c', 'd'] - (See also L{delimitedList}.) - """ - def postParse( self, instring, loc, tokenlist ): - return [] - - def suppress( self ): - return self - - -class OnlyOnce(object): - """ - Wrapper for parse actions, to ensure they are only called once. - """ - def __init__(self, methodCall): - self.callable = _trim_arity(methodCall) - self.called = False - def __call__(self,s,l,t): - if not self.called: - results = self.callable(s,l,t) - self.called = True - return results - raise ParseException(s,l,"") - def reset(self): - self.called = False - -def traceParseAction(f): - """ - Decorator for debugging parse actions. - - When the parse action is called, this decorator will print C{">> entering I{method-name}(line:I{current_source_line}, I{parse_location}, I{matched_tokens})".} - When the parse action completes, the decorator will print C{"<<"} followed by the returned value, or any exception that the parse action raised. - - Example:: - wd = Word(alphas) - - @traceParseAction - def remove_duplicate_chars(tokens): - return ''.join(sorted(set(''.join(tokens)))) - - wds = OneOrMore(wd).setParseAction(remove_duplicate_chars) - print(wds.parseString("slkdjs sld sldd sdlf sdljf")) - prints:: - >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {})) - <<leaving remove_duplicate_chars (ret: 'dfjkls') - ['dfjkls'] - """ - f = _trim_arity(f) - def z(*paArgs): - thisFunc = f.__name__ - s,l,t = paArgs[-3:] - if len(paArgs)>3: - thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc - sys.stderr.write( ">>entering %s(line: '%s', %d, %r)\n" % (thisFunc,line(l,s),l,t) ) - try: - ret = f(*paArgs) - except Exception as exc: - sys.stderr.write( "<<leaving %s (exception: %s)\n" % (thisFunc,exc) ) - raise - sys.stderr.write( "<<leaving %s (ret: %r)\n" % (thisFunc,ret) ) - return ret - try: - z.__name__ = f.__name__ - except AttributeError: - pass - return z - -# -# global helpers -# -def delimitedList( expr, delim=",", combine=False ): - """ - Helper to define a delimited list of expressions - the delimiter defaults to ','. - By default, the list elements and delimiters can have intervening whitespace, and - comments, but this can be overridden by passing C{combine=True} in the constructor. - If C{combine} is set to C{True}, the matching tokens are returned as a single token - string, with the delimiters included; otherwise, the matching tokens are returned - as a list of tokens, with the delimiters suppressed. - - Example:: - delimitedList(Word(alphas)).parseString("aa,bb,cc") # -> ['aa', 'bb', 'cc'] - delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE'] - """ - dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..." - if combine: - return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName) - else: - return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName) - -def countedArray( expr, intExpr=None ): - """ - Helper to define a counted list of expressions. - This helper defines a pattern of the form:: - integer expr expr expr... - where the leading integer tells how many expr expressions follow. - The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed. - - If C{intExpr} is specified, it should be a pyparsing expression that produces an integer value. - - Example:: - countedArray(Word(alphas)).parseString('2 ab cd ef') # -> ['ab', 'cd'] - - # in this parser, the leading integer value is given in binary, - # '10' indicating that 2 values are in the array - binaryConstant = Word('01').setParseAction(lambda t: int(t[0], 2)) - countedArray(Word(alphas), intExpr=binaryConstant).parseString('10 ab cd ef') # -> ['ab', 'cd'] - """ - arrayExpr = Forward() - def countFieldParseAction(s,l,t): - n = t[0] - arrayExpr << (n and Group(And([expr]*n)) or Group(empty)) - return [] - if intExpr is None: - intExpr = Word(nums).setParseAction(lambda t:int(t[0])) - else: - intExpr = intExpr.copy() - intExpr.setName("arrayLen") - intExpr.addParseAction(countFieldParseAction, callDuringTry=True) - return ( intExpr + arrayExpr ).setName('(len) ' + _ustr(expr) + '...') - -def _flatten(L): - ret = [] - for i in L: - if isinstance(i,list): - ret.extend(_flatten(i)) - else: - ret.append(i) - return ret - -def matchPreviousLiteral(expr): - """ - Helper to define an expression that is indirectly defined from - the tokens matched in a previous expression, that is, it looks - for a 'repeat' of a previous expression. For example:: - first = Word(nums) - second = matchPreviousLiteral(first) - matchExpr = first + ":" + second - will match C{"1:1"}, but not C{"1:2"}. Because this matches a - previous literal, will also match the leading C{"1:1"} in C{"1:10"}. - If this is not desired, use C{matchPreviousExpr}. - Do I{not} use with packrat parsing enabled. - """ - rep = Forward() - def copyTokenToRepeater(s,l,t): - if t: - if len(t) == 1: - rep << t[0] - else: - # flatten t tokens - tflat = _flatten(t.asList()) - rep << And(Literal(tt) for tt in tflat) - else: - rep << Empty() - expr.addParseAction(copyTokenToRepeater, callDuringTry=True) - rep.setName('(prev) ' + _ustr(expr)) - return rep - -def matchPreviousExpr(expr): - """ - Helper to define an expression that is indirectly defined from - the tokens matched in a previous expression, that is, it looks - for a 'repeat' of a previous expression. For example:: - first = Word(nums) - second = matchPreviousExpr(first) - matchExpr = first + ":" + second - will match C{"1:1"}, but not C{"1:2"}. Because this matches by - expressions, will I{not} match the leading C{"1:1"} in C{"1:10"}; - the expressions are evaluated first, and then compared, so - C{"1"} is compared with C{"10"}. - Do I{not} use with packrat parsing enabled. - """ - rep = Forward() - e2 = expr.copy() - rep <<= e2 - def copyTokenToRepeater(s,l,t): - matchTokens = _flatten(t.asList()) - def mustMatchTheseTokens(s,l,t): - theseTokens = _flatten(t.asList()) - if theseTokens != matchTokens: - raise ParseException("",0,"") - rep.setParseAction( mustMatchTheseTokens, callDuringTry=True ) - expr.addParseAction(copyTokenToRepeater, callDuringTry=True) - rep.setName('(prev) ' + _ustr(expr)) - return rep - -def _escapeRegexRangeChars(s): - #~ escape these chars: ^-] - for c in r"\^-]": - s = s.replace(c,_bslash+c) - s = s.replace("\n",r"\n") - s = s.replace("\t",r"\t") - return _ustr(s) - -def oneOf( strs, caseless=False, useRegex=True ): - """ - Helper to quickly define a set of alternative Literals, and makes sure to do - longest-first testing when there is a conflict, regardless of the input order, - but returns a C{L{MatchFirst}} for best performance. - - Parameters: - - strs - a string of space-delimited literals, or a collection of string literals - - caseless - (default=C{False}) - treat all literals as caseless - - useRegex - (default=C{True}) - as an optimization, will generate a Regex - object; otherwise, will generate a C{MatchFirst} object (if C{caseless=True}, or - if creating a C{Regex} raises an exception) - - Example:: - comp_oper = oneOf("< = > <= >= !=") - var = Word(alphas) - number = Word(nums) - term = var | number - comparison_expr = term + comp_oper + term - print(comparison_expr.searchString("B = 12 AA=23 B<=AA AA>12")) - prints:: - [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']] - """ - if caseless: - isequal = ( lambda a,b: a.upper() == b.upper() ) - masks = ( lambda a,b: b.upper().startswith(a.upper()) ) - parseElementClass = CaselessLiteral - else: - isequal = ( lambda a,b: a == b ) - masks = ( lambda a,b: b.startswith(a) ) - parseElementClass = Literal - - symbols = [] - if isinstance(strs,basestring): - symbols = strs.split() - elif isinstance(strs, Iterable): - symbols = list(strs) - else: - warnings.warn("Invalid argument to oneOf, expected string or iterable", - SyntaxWarning, stacklevel=2) - if not symbols: - return NoMatch() - - i = 0 - while i < len(symbols)-1: - cur = symbols[i] - for j,other in enumerate(symbols[i+1:]): - if ( isequal(other, cur) ): - del symbols[i+j+1] - break - elif ( masks(cur, other) ): - del symbols[i+j+1] - symbols.insert(i,other) - cur = other - break - else: - i += 1 - - if not caseless and useRegex: - #~ print (strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] )) - try: - if len(symbols)==len("".join(symbols)): - return Regex( "[%s]" % "".join(_escapeRegexRangeChars(sym) for sym in symbols) ).setName(' | '.join(symbols)) - else: - return Regex( "|".join(re.escape(sym) for sym in symbols) ).setName(' | '.join(symbols)) - except Exception: - warnings.warn("Exception creating Regex for oneOf, building MatchFirst", - SyntaxWarning, stacklevel=2) - - - # last resort, just use MatchFirst - return MatchFirst(parseElementClass(sym) for sym in symbols).setName(' | '.join(symbols)) - -def dictOf( key, value ): - """ - Helper to easily and clearly define a dictionary by specifying the respective patterns - for the key and value. Takes care of defining the C{L{Dict}}, C{L{ZeroOrMore}}, and C{L{Group}} tokens - in the proper order. The key pattern can include delimiting markers or punctuation, - as long as they are suppressed, thereby leaving the significant key text. The value - pattern can include named results, so that the C{Dict} results can include named token - fields. - - Example:: - text = "shape: SQUARE posn: upper left color: light blue texture: burlap" - attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) - print(OneOrMore(attr_expr).parseString(text).dump()) - - attr_label = label - attr_value = Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join) - - # similar to Dict, but simpler call format - result = dictOf(attr_label, attr_value).parseString(text) - print(result.dump()) - print(result['shape']) - print(result.shape) # object attribute access works too - print(result.asDict()) - prints:: - [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] - - color: light blue - - posn: upper left - - shape: SQUARE - - texture: burlap - SQUARE - SQUARE - {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'} - """ - return Dict( ZeroOrMore( Group ( key + value ) ) ) - -def originalTextFor(expr, asString=True): - """ - Helper to return the original, untokenized text for a given expression. Useful to - restore the parsed fields of an HTML start tag into the raw tag text itself, or to - revert separate tokens with intervening whitespace back to the original matching - input text. By default, returns astring containing the original parsed text. - - If the optional C{asString} argument is passed as C{False}, then the return value is a - C{L{ParseResults}} containing any results names that were originally matched, and a - single token containing the original matched text from the input string. So if - the expression passed to C{L{originalTextFor}} contains expressions with defined - results names, you must set C{asString} to C{False} if you want to preserve those - results name values. - - Example:: - src = "this is test <b> bold <i>text</i> </b> normal text " - for tag in ("b","i"): - opener,closer = makeHTMLTags(tag) - patt = originalTextFor(opener + SkipTo(closer) + closer) - print(patt.searchString(src)[0]) - prints:: - ['<b> bold <i>text</i> </b>'] - ['<i>text</i>'] - """ - locMarker = Empty().setParseAction(lambda s,loc,t: loc) - endlocMarker = locMarker.copy() - endlocMarker.callPreparse = False - matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end") - if asString: - extractText = lambda s,l,t: s[t._original_start:t._original_end] - else: - def extractText(s,l,t): - t[:] = [s[t.pop('_original_start'):t.pop('_original_end')]] - matchExpr.setParseAction(extractText) - matchExpr.ignoreExprs = expr.ignoreExprs - return matchExpr - -def ungroup(expr): - """ - Helper to undo pyparsing's default grouping of And expressions, even - if all but one are non-empty. - """ - return TokenConverter(expr).setParseAction(lambda t:t[0]) - -def locatedExpr(expr): - """ - Helper to decorate a returned token with its starting and ending locations in the input string. - This helper adds the following results names: - - locn_start = location where matched expression begins - - locn_end = location where matched expression ends - - value = the actual parsed results - - Be careful if the input text contains C{<TAB>} characters, you may want to call - C{L{ParserElement.parseWithTabs}} - - Example:: - wd = Word(alphas) - for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"): - print(match) - prints:: - [[0, 'ljsdf', 5]] - [[8, 'lksdjjf', 15]] - [[18, 'lkkjj', 23]] - """ - locator = Empty().setParseAction(lambda s,l,t: l) - return Group(locator("locn_start") + expr("value") + locator.copy().leaveWhitespace()("locn_end")) - - -# convenience constants for positional expressions -empty = Empty().setName("empty") -lineStart = LineStart().setName("lineStart") -lineEnd = LineEnd().setName("lineEnd") -stringStart = StringStart().setName("stringStart") -stringEnd = StringEnd().setName("stringEnd") - -_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1]) -_escapedHexChar = Regex(r"\\0?[xX][0-9a-fA-F]+").setParseAction(lambda s,l,t:unichr(int(t[0].lstrip(r'\0x'),16))) -_escapedOctChar = Regex(r"\\0[0-7]+").setParseAction(lambda s,l,t:unichr(int(t[0][1:],8))) -_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | CharsNotIn(r'\]', exact=1) -_charRange = Group(_singleChar + Suppress("-") + _singleChar) -_reBracketExpr = Literal("[") + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]" - -def srange(s): - r""" - Helper to easily define string ranges for use in Word construction. Borrows - syntax from regexp '[]' string range definitions:: - srange("[0-9]") -> "0123456789" - srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz" - srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_" - The input string must be enclosed in []'s, and the returned string is the expanded - character set joined into a single string. - The values enclosed in the []'s may be: - - a single character - - an escaped character with a leading backslash (such as C{\-} or C{\]}) - - an escaped hex character with a leading C{'\x'} (C{\x21}, which is a C{'!'} character) - (C{\0x##} is also supported for backwards compatibility) - - an escaped octal character with a leading C{'\0'} (C{\041}, which is a C{'!'} character) - - a range of any of the above, separated by a dash (C{'a-z'}, etc.) - - any combination of the above (C{'aeiouy'}, C{'a-zA-Z0-9_$'}, etc.) - """ - _expanded = lambda p: p if not isinstance(p,ParseResults) else ''.join(unichr(c) for c in range(ord(p[0]),ord(p[1])+1)) - try: - return "".join(_expanded(part) for part in _reBracketExpr.parseString(s).body) - except Exception: - return "" - -def matchOnlyAtCol(n): - """ - Helper method for defining parse actions that require matching at a specific - column in the input text. - """ - def verifyCol(strg,locn,toks): - if col(locn,strg) != n: - raise ParseException(strg,locn,"matched token not at column %d" % n) - return verifyCol - -def replaceWith(replStr): - """ - Helper method for common parse actions that simply return a literal value. Especially - useful when used with C{L{transformString<ParserElement.transformString>}()}. - - Example:: - num = Word(nums).setParseAction(lambda toks: int(toks[0])) - na = oneOf("N/A NA").setParseAction(replaceWith(math.nan)) - term = na | num - - OneOrMore(term).parseString("324 234 N/A 234") # -> [324, 234, nan, 234] - """ - return lambda s,l,t: [replStr] - -def removeQuotes(s,l,t): - """ - Helper parse action for removing quotation marks from parsed quoted strings. - - Example:: - # by default, quotation marks are included in parsed results - quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"] - - # use removeQuotes to strip quotation marks from parsed results - quotedString.setParseAction(removeQuotes) - quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"] - """ - return t[0][1:-1] - -def tokenMap(func, *args): - """ - Helper to define a parse action by mapping a function to all elements of a ParseResults list.If any additional - args are passed, they are forwarded to the given function as additional arguments after - the token, as in C{hex_integer = Word(hexnums).setParseAction(tokenMap(int, 16))}, which will convert the - parsed data to an integer using base 16. - - Example (compare the last to example in L{ParserElement.transformString}:: - hex_ints = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16)) - hex_ints.runTests(''' - 00 11 22 aa FF 0a 0d 1a - ''') - - upperword = Word(alphas).setParseAction(tokenMap(str.upper)) - OneOrMore(upperword).runTests(''' - my kingdom for a horse - ''') - - wd = Word(alphas).setParseAction(tokenMap(str.title)) - OneOrMore(wd).setParseAction(' '.join).runTests(''' - now is the winter of our discontent made glorious summer by this sun of york - ''') - prints:: - 00 11 22 aa FF 0a 0d 1a - [0, 17, 34, 170, 255, 10, 13, 26] - - my kingdom for a horse - ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE'] - - now is the winter of our discontent made glorious summer by this sun of york - ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York'] - """ - def pa(s,l,t): - return [func(tokn, *args) for tokn in t] - - try: - func_name = getattr(func, '__name__', - getattr(func, '__class__').__name__) - except Exception: - func_name = str(func) - pa.__name__ = func_name - - return pa - -upcaseTokens = tokenMap(lambda t: _ustr(t).upper()) -"""(Deprecated) Helper parse action to convert tokens to upper case. Deprecated in favor of L{pyparsing_common.upcaseTokens}""" - -downcaseTokens = tokenMap(lambda t: _ustr(t).lower()) -"""(Deprecated) Helper parse action to convert tokens to lower case. Deprecated in favor of L{pyparsing_common.downcaseTokens}""" - -def _makeTags(tagStr, xml): - """Internal helper to construct opening and closing tag expressions, given a tag name""" - if isinstance(tagStr,basestring): - resname = tagStr - tagStr = Keyword(tagStr, caseless=not xml) - else: - resname = tagStr.name - - tagAttrName = Word(alphas,alphanums+"_-:") - if (xml): - tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes ) - openTag = Suppress("<") + tagStr("tag") + \ - Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \ - Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") - else: - printablesLessRAbrack = "".join(c for c in printables if c not in ">") - tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack) - openTag = Suppress("<") + tagStr("tag") + \ - Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \ - Optional( Suppress("=") + tagAttrValue ) ))) + \ - Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") - closeTag = Combine(_L("</") + tagStr + ">") - - openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % resname) - closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("</%s>" % resname) - openTag.tag = resname - closeTag.tag = resname - return openTag, closeTag - -def makeHTMLTags(tagStr): - """ - Helper to construct opening and closing tag expressions for HTML, given a tag name. Matches - tags in either upper or lower case, attributes with namespaces and with quoted or unquoted values. - - Example:: - text = '<td>More info at the <a href="http://pyparsing.wikispaces.com">pyparsing</a> wiki page</td>' - # makeHTMLTags returns pyparsing expressions for the opening and closing tags as a 2-tuple - a,a_end = makeHTMLTags("A") - link_expr = a + SkipTo(a_end)("link_text") + a_end - - for link in link_expr.searchString(text): - # attributes in the <A> tag (like "href" shown here) are also accessible as named results - print(link.link_text, '->', link.href) - prints:: - pyparsing -> http://pyparsing.wikispaces.com - """ - return _makeTags( tagStr, False ) - -def makeXMLTags(tagStr): - """ - Helper to construct opening and closing tag expressions for XML, given a tag name. Matches - tags only in the given upper/lower case. - - Example: similar to L{makeHTMLTags} - """ - return _makeTags( tagStr, True ) - -def withAttribute(*args,**attrDict): - """ - Helper to create a validating parse action to be used with start tags created - with C{L{makeXMLTags}} or C{L{makeHTMLTags}}. Use C{withAttribute} to qualify a starting tag - with a required attribute value, to avoid false matches on common tags such as - C{<TD>} or C{<DIV>}. - - Call C{withAttribute} with a series of attribute names and values. Specify the list - of filter attributes names and values as: - - keyword arguments, as in C{(align="right")}, or - - as an explicit dict with C{**} operator, when an attribute name is also a Python - reserved word, as in C{**{"class":"Customer", "align":"right"}} - - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) - For attribute names with a namespace prefix, you must use the second form. Attribute - names are matched insensitive to upper/lower case. - - If just testing for C{class} (with or without a namespace), use C{L{withClass}}. - - To verify that the attribute exists, but without specifying a value, pass - C{withAttribute.ANY_VALUE} as the value. - - Example:: - html = ''' - <div> - Some text - <div type="grid">1 4 0 1 0</div> - <div type="graph">1,3 2,3 1,1</div> - <div>this has no type</div> - </div> - - ''' - div,div_end = makeHTMLTags("div") - - # only match div tag having a type attribute with value "grid" - div_grid = div().setParseAction(withAttribute(type="grid")) - grid_expr = div_grid + SkipTo(div | div_end)("body") - for grid_header in grid_expr.searchString(html): - print(grid_header.body) - - # construct a match with any div tag having a type attribute, regardless of the value - div_any_type = div().setParseAction(withAttribute(type=withAttribute.ANY_VALUE)) - div_expr = div_any_type + SkipTo(div | div_end)("body") - for div_header in div_expr.searchString(html): - print(div_header.body) - prints:: - 1 4 0 1 0 - - 1 4 0 1 0 - 1,3 2,3 1,1 - """ - if args: - attrs = args[:] - else: - attrs = attrDict.items() - attrs = [(k,v) for k,v in attrs] - def pa(s,l,tokens): - for attrName,attrValue in attrs: - if attrName not in tokens: - raise ParseException(s,l,"no matching attribute " + attrName) - if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: - raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" % - (attrName, tokens[attrName], attrValue)) - return pa -withAttribute.ANY_VALUE = object() - -def withClass(classname, namespace=''): - """ - Simplified version of C{L{withAttribute}} when matching on a div class - made - difficult because C{class} is a reserved word in Python. - - Example:: - html = ''' - <div> - Some text - <div class="grid">1 4 0 1 0</div> - <div class="graph">1,3 2,3 1,1</div> - <div>this <div> has no class</div> - </div> - - ''' - div,div_end = makeHTMLTags("div") - div_grid = div().setParseAction(withClass("grid")) - - grid_expr = div_grid + SkipTo(div | div_end)("body") - for grid_header in grid_expr.searchString(html): - print(grid_header.body) - - div_any_type = div().setParseAction(withClass(withAttribute.ANY_VALUE)) - div_expr = div_any_type + SkipTo(div | div_end)("body") - for div_header in div_expr.searchString(html): - print(div_header.body) - prints:: - 1 4 0 1 0 - - 1 4 0 1 0 - 1,3 2,3 1,1 - """ - classattr = "%s:class" % namespace if namespace else "class" - return withAttribute(**{classattr : classname}) - -opAssoc = _Constants() -opAssoc.LEFT = object() -opAssoc.RIGHT = object() - -def infixNotation( baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')') ): - """ - Helper method for constructing grammars of expressions made up of - operators working in a precedence hierarchy. Operators may be unary or - binary, left- or right-associative. Parse actions can also be attached - to operator expressions. The generated parser will also recognize the use - of parentheses to override operator precedences (see example below). - - Note: if you define a deep operator list, you may see performance issues - when using infixNotation. See L{ParserElement.enablePackrat} for a - mechanism to potentially improve your parser performance. - - Parameters: - - baseExpr - expression representing the most basic element for the nested - - opList - list of tuples, one for each operator precedence level in the - expression grammar; each tuple is of the form - (opExpr, numTerms, rightLeftAssoc, parseAction), where: - - opExpr is the pyparsing expression for the operator; - may also be a string, which will be converted to a Literal; - if numTerms is 3, opExpr is a tuple of two expressions, for the - two operators separating the 3 terms - - numTerms is the number of terms for this operator (must - be 1, 2, or 3) - - rightLeftAssoc is the indicator whether the operator is - right or left associative, using the pyparsing-defined - constants C{opAssoc.RIGHT} and C{opAssoc.LEFT}. - - parseAction is the parse action to be associated with - expressions matching this operator expression (the - parse action tuple member may be omitted); if the parse action - is passed a tuple or list of functions, this is equivalent to - calling C{setParseAction(*fn)} (L{ParserElement.setParseAction}) - - lpar - expression for matching left-parentheses (default=C{Suppress('(')}) - - rpar - expression for matching right-parentheses (default=C{Suppress(')')}) - - Example:: - # simple example of four-function arithmetic with ints and variable names - integer = pyparsing_common.signed_integer - varname = pyparsing_common.identifier - - arith_expr = infixNotation(integer | varname, - [ - ('-', 1, opAssoc.RIGHT), - (oneOf('* /'), 2, opAssoc.LEFT), - (oneOf('+ -'), 2, opAssoc.LEFT), - ]) - - arith_expr.runTests(''' - 5+3*6 - (5+3)*6 - -2--11 - ''', fullDump=False) - prints:: - 5+3*6 - [[5, '+', [3, '*', 6]]] - - (5+3)*6 - [[[5, '+', 3], '*', 6]] - - -2--11 - [[['-', 2], '-', ['-', 11]]] - """ - ret = Forward() - lastExpr = baseExpr | ( lpar + ret + rpar ) - for i,operDef in enumerate(opList): - opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] - termName = "%s term" % opExpr if arity < 3 else "%s%s term" % opExpr - if arity == 3: - if opExpr is None or len(opExpr) != 2: - raise ValueError("if numterms=3, opExpr must be a tuple or list of two expressions") - opExpr1, opExpr2 = opExpr - thisExpr = Forward().setName(termName) - if rightLeftAssoc == opAssoc.LEFT: - if arity == 1: - matchExpr = FollowedBy(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) ) - elif arity == 2: - if opExpr is not None: - matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) - else: - matchExpr = FollowedBy(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) ) - elif arity == 3: - matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \ - Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr ) - else: - raise ValueError("operator must be unary (1), binary (2), or ternary (3)") - elif rightLeftAssoc == opAssoc.RIGHT: - if arity == 1: - # try to avoid LR with this extra test - if not isinstance(opExpr, Optional): - opExpr = Optional(opExpr) - matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) - elif arity == 2: - if opExpr is not None: - matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) - else: - matchExpr = FollowedBy(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) ) - elif arity == 3: - matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \ - Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr ) - else: - raise ValueError("operator must be unary (1), binary (2), or ternary (3)") - else: - raise ValueError("operator must indicate right or left associativity") - if pa: - if isinstance(pa, (tuple, list)): - matchExpr.setParseAction(*pa) - else: - matchExpr.setParseAction(pa) - thisExpr <<= ( matchExpr.setName(termName) | lastExpr ) - lastExpr = thisExpr - ret <<= lastExpr - return ret - -operatorPrecedence = infixNotation -"""(Deprecated) Former name of C{L{infixNotation}}, will be dropped in a future release.""" - -dblQuotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"').setName("string enclosed in double quotes") -sglQuotedString = Combine(Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("string enclosed in single quotes") -quotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"'| - Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("quotedString using single or double quotes") -unicodeString = Combine(_L('u') + quotedString.copy()).setName("unicode string literal") - -def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString.copy()): - """ - Helper method for defining nested lists enclosed in opening and closing - delimiters ("(" and ")" are the default). - - Parameters: - - opener - opening character for a nested list (default=C{"("}); can also be a pyparsing expression - - closer - closing character for a nested list (default=C{")"}); can also be a pyparsing expression - - content - expression for items within the nested lists (default=C{None}) - - ignoreExpr - expression for ignoring opening and closing delimiters (default=C{quotedString}) - - If an expression is not provided for the content argument, the nested - expression will capture all whitespace-delimited content between delimiters - as a list of separate values. - - Use the C{ignoreExpr} argument to define expressions that may contain - opening or closing characters that should not be treated as opening - or closing characters for nesting, such as quotedString or a comment - expression. Specify multiple expressions using an C{L{Or}} or C{L{MatchFirst}}. - The default is L{quotedString}, but if no expressions are to be ignored, - then pass C{None} for this argument. - - Example:: - data_type = oneOf("void int short long char float double") - decl_data_type = Combine(data_type + Optional(Word('*'))) - ident = Word(alphas+'_', alphanums+'_') - number = pyparsing_common.number - arg = Group(decl_data_type + ident) - LPAR,RPAR = map(Suppress, "()") - - code_body = nestedExpr('{', '}', ignoreExpr=(quotedString | cStyleComment)) - - c_function = (decl_data_type("type") - + ident("name") - + LPAR + Optional(delimitedList(arg), [])("args") + RPAR - + code_body("body")) - c_function.ignore(cStyleComment) - - source_code = ''' - int is_odd(int x) { - return (x%2); - } - - int dec_to_hex(char hchar) { - if (hchar >= '0' && hchar <= '9') { - return (ord(hchar)-ord('0')); - } else { - return (10+ord(hchar)-ord('A')); - } - } - ''' - for func in c_function.searchString(source_code): - print("%(name)s (%(type)s) args: %(args)s" % func) - - prints:: - is_odd (int) args: [['int', 'x']] - dec_to_hex (int) args: [['char', 'hchar']] - """ - if opener == closer: - raise ValueError("opening and closing strings cannot be the same") - if content is None: - if isinstance(opener,basestring) and isinstance(closer,basestring): - if len(opener) == 1 and len(closer)==1: - if ignoreExpr is not None: - content = (Combine(OneOrMore(~ignoreExpr + - CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS,exact=1)) - ).setParseAction(lambda t:t[0].strip())) - else: - content = (empty.copy()+CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS - ).setParseAction(lambda t:t[0].strip())) - else: - if ignoreExpr is not None: - content = (Combine(OneOrMore(~ignoreExpr + - ~Literal(opener) + ~Literal(closer) + - CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) - ).setParseAction(lambda t:t[0].strip())) - else: - content = (Combine(OneOrMore(~Literal(opener) + ~Literal(closer) + - CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) - ).setParseAction(lambda t:t[0].strip())) - else: - raise ValueError("opening and closing arguments must be strings if no content expression is given") - ret = Forward() - if ignoreExpr is not None: - ret <<= Group( Suppress(opener) + ZeroOrMore( ignoreExpr | ret | content ) + Suppress(closer) ) - else: - ret <<= Group( Suppress(opener) + ZeroOrMore( ret | content ) + Suppress(closer) ) - ret.setName('nested %s%s expression' % (opener,closer)) - return ret - -def indentedBlock(blockStatementExpr, indentStack, indent=True): - """ - Helper method for defining space-delimited indentation blocks, such as - those used to define block statements in Python source code. - - Parameters: - - blockStatementExpr - expression defining syntax of statement that - is repeated within the indented block - - indentStack - list created by caller to manage indentation stack - (multiple statementWithIndentedBlock expressions within a single grammar - should share a common indentStack) - - indent - boolean indicating whether block must be indented beyond the - the current level; set to False for block of left-most statements - (default=C{True}) - - A valid block must contain at least one C{blockStatement}. - - Example:: - data = ''' - def A(z): - A1 - B = 100 - G = A2 - A2 - A3 - B - def BB(a,b,c): - BB1 - def BBA(): - bba1 - bba2 - bba3 - C - D - def spam(x,y): - def eggs(z): - pass - ''' - - - indentStack = [1] - stmt = Forward() - - identifier = Word(alphas, alphanums) - funcDecl = ("def" + identifier + Group( "(" + Optional( delimitedList(identifier) ) + ")" ) + ":") - func_body = indentedBlock(stmt, indentStack) - funcDef = Group( funcDecl + func_body ) - - rvalue = Forward() - funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")") - rvalue << (funcCall | identifier | Word(nums)) - assignment = Group(identifier + "=" + rvalue) - stmt << ( funcDef | assignment | identifier ) - - module_body = OneOrMore(stmt) - - parseTree = module_body.parseString(data) - parseTree.pprint() - prints:: - [['def', - 'A', - ['(', 'z', ')'], - ':', - [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], - 'B', - ['def', - 'BB', - ['(', 'a', 'b', 'c', ')'], - ':', - [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], - 'C', - 'D', - ['def', - 'spam', - ['(', 'x', 'y', ')'], - ':', - [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] - """ - def checkPeerIndent(s,l,t): - if l >= len(s): return - curCol = col(l,s) - if curCol != indentStack[-1]: - if curCol > indentStack[-1]: - raise ParseFatalException(s,l,"illegal nesting") - raise ParseException(s,l,"not a peer entry") - - def checkSubIndent(s,l,t): - curCol = col(l,s) - if curCol > indentStack[-1]: - indentStack.append( curCol ) - else: - raise ParseException(s,l,"not a subentry") - - def checkUnindent(s,l,t): - if l >= len(s): return - curCol = col(l,s) - if not(indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]): - raise ParseException(s,l,"not an unindent") - indentStack.pop() - - NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress()) - INDENT = (Empty() + Empty().setParseAction(checkSubIndent)).setName('INDENT') - PEER = Empty().setParseAction(checkPeerIndent).setName('') - UNDENT = Empty().setParseAction(checkUnindent).setName('UNINDENT') - if indent: - smExpr = Group( Optional(NL) + - #~ FollowedBy(blockStatementExpr) + - INDENT + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) + UNDENT) - else: - smExpr = Group( Optional(NL) + - (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) ) - blockStatementExpr.ignore(_bslash + LineEnd()) - return smExpr.setName('indented block') - -alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]") -punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]") - -anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_:").setName('any tag')) -_htmlEntityMap = dict(zip("gt lt amp nbsp quot apos".split(),'><& "\'')) -commonHTMLEntity = Regex('&(?P<entity>' + '|'.join(_htmlEntityMap.keys()) +");").setName("common HTML entity") -def replaceHTMLEntity(t): - """Helper parser action to replace common HTML entities with their special characters""" - return _htmlEntityMap.get(t.entity) - -# it's easy to get these comment structures wrong - they're very common, so may as well make them available -cStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/').setName("C style comment") -"Comment of the form C{/* ... */}" - -htmlComment = Regex(r"<!--[\s\S]*?-->").setName("HTML comment") -"Comment of the form C{<!-- ... -->}" - -restOfLine = Regex(r".*").leaveWhitespace().setName("rest of line") -dblSlashComment = Regex(r"//(?:\\\n|[^\n])*").setName("// comment") -"Comment of the form C{// ... (to end of line)}" - -cppStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/'| dblSlashComment).setName("C++ style comment") -"Comment of either form C{L{cStyleComment}} or C{L{dblSlashComment}}" - -javaStyleComment = cppStyleComment -"Same as C{L{cppStyleComment}}" - -pythonStyleComment = Regex(r"#.*").setName("Python style comment") -"Comment of the form C{# ... (to end of line)}" - -_commasepitem = Combine(OneOrMore(Word(printables, excludeChars=',') + - Optional( Word(" \t") + - ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem") -commaSeparatedList = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("commaSeparatedList") -"""(Deprecated) Predefined expression of 1 or more printable words or quoted strings, separated by commas. - This expression is deprecated in favor of L{pyparsing_common.comma_separated_list}.""" - -# some other useful expressions - using lower-case class name since we are really using this as a namespace -class pyparsing_common: - """ - Here are some common low-level expressions that may be useful in jump-starting parser development: - - numeric forms (L{integers<integer>}, L{reals<real>}, L{scientific notation<sci_real>}) - - common L{programming identifiers<identifier>} - - network addresses (L{MAC<mac_address>}, L{IPv4<ipv4_address>}, L{IPv6<ipv6_address>}) - - ISO8601 L{dates<iso8601_date>} and L{datetime<iso8601_datetime>} - - L{UUID<uuid>} - - L{comma-separated list<comma_separated_list>} - Parse actions: - - C{L{convertToInteger}} - - C{L{convertToFloat}} - - C{L{convertToDate}} - - C{L{convertToDatetime}} - - C{L{stripHTMLTags}} - - C{L{upcaseTokens}} - - C{L{downcaseTokens}} - - Example:: - pyparsing_common.number.runTests(''' - # any int or real number, returned as the appropriate type - 100 - -100 - +100 - 3.14159 - 6.02e23 - 1e-12 - ''') - - pyparsing_common.fnumber.runTests(''' - # any int or real number, returned as float - 100 - -100 - +100 - 3.14159 - 6.02e23 - 1e-12 - ''') - - pyparsing_common.hex_integer.runTests(''' - # hex numbers - 100 - FF - ''') - - pyparsing_common.fraction.runTests(''' - # fractions - 1/2 - -3/4 - ''') - - pyparsing_common.mixed_integer.runTests(''' - # mixed fractions - 1 - 1/2 - -3/4 - 1-3/4 - ''') - - import uuid - pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) - pyparsing_common.uuid.runTests(''' - # uuid - 12345678-1234-5678-1234-567812345678 - ''') - prints:: - # any int or real number, returned as the appropriate type - 100 - [100] - - -100 - [-100] - - +100 - [100] - - 3.14159 - [3.14159] - - 6.02e23 - [6.02e+23] - - 1e-12 - [1e-12] - - # any int or real number, returned as float - 100 - [100.0] - - -100 - [-100.0] - - +100 - [100.0] - - 3.14159 - [3.14159] - - 6.02e23 - [6.02e+23] - - 1e-12 - [1e-12] - - # hex numbers - 100 - [256] - - FF - [255] - - # fractions - 1/2 - [0.5] - - -3/4 - [-0.75] - - # mixed fractions - 1 - [1] - - 1/2 - [0.5] - - -3/4 - [-0.75] - - 1-3/4 - [1.75] - - # uuid - 12345678-1234-5678-1234-567812345678 - [UUID('12345678-1234-5678-1234-567812345678')] - """ - - convertToInteger = tokenMap(int) - """ - Parse action for converting parsed integers to Python int - """ - - convertToFloat = tokenMap(float) - """ - Parse action for converting parsed numbers to Python float - """ - - integer = Word(nums).setName("integer").setParseAction(convertToInteger) - """expression that parses an unsigned integer, returns an int""" - - hex_integer = Word(hexnums).setName("hex integer").setParseAction(tokenMap(int,16)) - """expression that parses a hexadecimal integer, returns an int""" - - signed_integer = Regex(r'[+-]?\d+').setName("signed integer").setParseAction(convertToInteger) - """expression that parses an integer with optional leading sign, returns an int""" - - fraction = (signed_integer().setParseAction(convertToFloat) + '/' + signed_integer().setParseAction(convertToFloat)).setName("fraction") - """fractional expression of an integer divided by an integer, returns a float""" - fraction.addParseAction(lambda t: t[0]/t[-1]) - - mixed_integer = (fraction | signed_integer + Optional(Optional('-').suppress() + fraction)).setName("fraction or mixed integer-fraction") - """mixed integer of the form 'integer - fraction', with optional leading integer, returns float""" - mixed_integer.addParseAction(sum) - - real = Regex(r'[+-]?\d+\.\d*').setName("real number").setParseAction(convertToFloat) - """expression that parses a floating point number and returns a float""" - - sci_real = Regex(r'[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)').setName("real number with scientific notation").setParseAction(convertToFloat) - """expression that parses a floating point number with optional scientific notation and returns a float""" - - # streamlining this expression makes the docs nicer-looking - number = (sci_real | real | signed_integer).streamline() - """any numeric expression, returns the corresponding Python type""" - - fnumber = Regex(r'[+-]?\d+\.?\d*([eE][+-]?\d+)?').setName("fnumber").setParseAction(convertToFloat) - """any int or real number, returned as float""" - - identifier = Word(alphas+'_', alphanums+'_').setName("identifier") - """typical code identifier (leading alpha or '_', followed by 0 or more alphas, nums, or '_')""" - - ipv4_address = Regex(r'(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}').setName("IPv4 address") - "IPv4 address (C{0.0.0.0 - 255.255.255.255})" - - _ipv6_part = Regex(r'[0-9a-fA-F]{1,4}').setName("hex_integer") - _full_ipv6_address = (_ipv6_part + (':' + _ipv6_part)*7).setName("full IPv6 address") - _short_ipv6_address = (Optional(_ipv6_part + (':' + _ipv6_part)*(0,6)) + "::" + Optional(_ipv6_part + (':' + _ipv6_part)*(0,6))).setName("short IPv6 address") - _short_ipv6_address.addCondition(lambda t: sum(1 for tt in t if pyparsing_common._ipv6_part.matches(tt)) < 8) - _mixed_ipv6_address = ("::ffff:" + ipv4_address).setName("mixed IPv6 address") - ipv6_address = Combine((_full_ipv6_address | _mixed_ipv6_address | _short_ipv6_address).setName("IPv6 address")).setName("IPv6 address") - "IPv6 address (long, short, or mixed form)" - - mac_address = Regex(r'[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}').setName("MAC address") - "MAC address xx:xx:xx:xx:xx (may also have '-' or '.' delimiters)" - - @staticmethod - def convertToDate(fmt="%Y-%m-%d"): - """ - Helper to create a parse action for converting parsed date string to Python datetime.date - - Params - - - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%d"}) - - Example:: - date_expr = pyparsing_common.iso8601_date.copy() - date_expr.setParseAction(pyparsing_common.convertToDate()) - print(date_expr.parseString("1999-12-31")) - prints:: - [datetime.date(1999, 12, 31)] - """ - def cvt_fn(s,l,t): - try: - return datetime.strptime(t[0], fmt).date() - except ValueError as ve: - raise ParseException(s, l, str(ve)) - return cvt_fn - - @staticmethod - def convertToDatetime(fmt="%Y-%m-%dT%H:%M:%S.%f"): - """ - Helper to create a parse action for converting parsed datetime string to Python datetime.datetime - - Params - - - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%dT%H:%M:%S.%f"}) - - Example:: - dt_expr = pyparsing_common.iso8601_datetime.copy() - dt_expr.setParseAction(pyparsing_common.convertToDatetime()) - print(dt_expr.parseString("1999-12-31T23:59:59.999")) - prints:: - [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] - """ - def cvt_fn(s,l,t): - try: - return datetime.strptime(t[0], fmt) - except ValueError as ve: - raise ParseException(s, l, str(ve)) - return cvt_fn - - iso8601_date = Regex(r'(?P<year>\d{4})(?:-(?P<month>\d\d)(?:-(?P<day>\d\d))?)?').setName("ISO8601 date") - "ISO8601 date (C{yyyy-mm-dd})" - - iso8601_datetime = Regex(r'(?P<year>\d{4})-(?P<month>\d\d)-(?P<day>\d\d)[T ](?P<hour>\d\d):(?P<minute>\d\d)(:(?P<second>\d\d(\.\d*)?)?)?(?P<tz>Z|[+-]\d\d:?\d\d)?').setName("ISO8601 datetime") - "ISO8601 datetime (C{yyyy-mm-ddThh:mm:ss.s(Z|+-00:00)}) - trailing seconds, milliseconds, and timezone optional; accepts separating C{'T'} or C{' '}" - - uuid = Regex(r'[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}').setName("UUID") - "UUID (C{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx})" - - _html_stripper = anyOpenTag.suppress() | anyCloseTag.suppress() - @staticmethod - def stripHTMLTags(s, l, tokens): - """ - Parse action to remove HTML tags from web page HTML source - - Example:: - # strip HTML links from normal text - text = '<td>More info at the <a href="http://pyparsing.wikispaces.com">pyparsing</a> wiki page</td>' - td,td_end = makeHTMLTags("TD") - table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end - - print(table_text.parseString(text).body) # -> 'More info at the pyparsing wiki page' - """ - return pyparsing_common._html_stripper.transformString(tokens[0]) - - _commasepitem = Combine(OneOrMore(~Literal(",") + ~LineEnd() + Word(printables, excludeChars=',') - + Optional( White(" \t") ) ) ).streamline().setName("commaItem") - comma_separated_list = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("comma separated list") - """Predefined expression of 1 or more printable words or quoted strings, separated by commas.""" - - upcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).upper())) - """Parse action to convert tokens to upper case.""" - - downcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).lower())) - """Parse action to convert tokens to lower case.""" - - -if __name__ == "__main__": - - selectToken = CaselessLiteral("select") - fromToken = CaselessLiteral("from") - - ident = Word(alphas, alphanums + "_$") - - columnName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) - columnNameList = Group(delimitedList(columnName)).setName("columns") - columnSpec = ('*' | columnNameList) - - tableName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) - tableNameList = Group(delimitedList(tableName)).setName("tables") - - simpleSQL = selectToken("command") + columnSpec("columns") + fromToken + tableNameList("tables") - - # demo runTests method, including embedded comments in test string - simpleSQL.runTests(""" - # '*' as column list and dotted table name - select * from SYS.XYZZY - - # caseless match on "SELECT", and casts back to "select" - SELECT * from XYZZY, ABC - - # list of column names, and mixed case SELECT keyword - Select AA,BB,CC from Sys.dual - - # multiple tables - Select A, B, C from Sys.dual, Table2 - - # invalid SELECT keyword - should fail - Xelect A, B, C from Sys.dual - - # incomplete command - should fail - Select - - # invalid column name - should fail - Select ^^^ frox Sys.dual - - """) - - pyparsing_common.number.runTests(""" - 100 - -100 - +100 - 3.14159 - 6.02e23 - 1e-12 - """) - - # any int or real number, returned as float - pyparsing_common.fnumber.runTests(""" - 100 - -100 - +100 - 3.14159 - 6.02e23 - 1e-12 - """) - - pyparsing_common.hex_integer.runTests(""" - 100 - FF - """) - - import uuid - pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) - pyparsing_common.uuid.runTests(""" - 12345678-1234-5678-1234-567812345678 - """) diff --git a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/six.py b/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/six.py deleted file mode 100644 index 190c023..0000000 --- a/venv2/lib/python2.7/site-packages/pkg_resources/_vendor/six.py +++ /dev/null @@ -1,868 +0,0 @@ -"""Utilities for writing code that runs on Python 2 and 3""" - -# Copyright (c) 2010-2015 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. - -from __future__ import absolute_import - -import functools -import itertools -import operator -import sys -import types - -__author__ = "Benjamin Peterson <benjamin@python.org>" -__version__ = "1.10.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("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_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("email_mime_base", "email.MIMEBase", "email.mime.base"), - 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("urlencode", "urllib", "urllib.parse"), - MovedAttribute("splitquery", "urllib", "urllib.parse"), - MovedAttribute("splittag", "urllib", "urllib.parse"), - MovedAttribute("splituser", "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"), -] -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): - if value is None: - value = tp() - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - -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): - raise tp, value, tb -""") - - -if sys.version_info[:2] == (3, 2): - exec_("""def raise_from(value, from_value): - if from_value is None: - raise value - raise value from from_value -""") -elif sys.version_info[:2] > (3, 2): - exec_("""def raise_from(value, from_value): - raise value from from_value -""") -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(meta): - - def __new__(cls, name, this_bases, d): - return meta(name, bases, d) - 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) - return metaclass(cls.__name__, cls.__bases__, orig_vars) - return wrapper - - -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) diff --git a/venv2/lib/python2.7/site-packages/pkg_resources/extern/__init__.py b/venv2/lib/python2.7/site-packages/pkg_resources/extern/__init__.py deleted file mode 100644 index c1eb9e9..0000000 --- a/venv2/lib/python2.7/site-packages/pkg_resources/extern/__init__.py +++ /dev/null @@ -1,73 +0,0 @@ -import sys - - -class VendorImporter: - """ - A PEP 302 meta path importer for finding optionally-vendored - or otherwise naturally-installed packages from root_name. - """ - - def __init__(self, root_name, vendored_names=(), vendor_pkg=None): - self.root_name = root_name - self.vendored_names = set(vendored_names) - self.vendor_pkg = vendor_pkg or root_name.replace('extern', '_vendor') - - @property - def search_path(self): - """ - Search first the vendor package then as a natural package. - """ - yield self.vendor_pkg + '.' - yield '' - - def find_module(self, fullname, path=None): - """ - Return self when fullname starts with root_name and the - target module is one vendored through this importer. - """ - root, base, target = fullname.partition(self.root_name + '.') - if root: - return - if not any(map(target.startswith, self.vendored_names)): - return - return self - - def load_module(self, fullname): - """ - Iterate over the search path to locate and load fullname. - """ - root, base, target = fullname.partition(self.root_name + '.') - for prefix in self.search_path: - try: - extant = prefix + target - __import__(extant) - mod = sys.modules[extant] - sys.modules[fullname] = mod - # mysterious hack: - # Remove the reference to the extant package/module - # on later Python versions to cause relative imports - # in the vendor package to resolve the same modules - # as those going through this importer. - if prefix and sys.version_info > (3, 3): - del sys.modules[extant] - return mod - except ImportError: - pass - else: - raise ImportError( - "The '{target}' package is required; " - "normally this is bundled with this package so if you get " - "this warning, consult the packager of your " - "distribution.".format(**locals()) - ) - - def install(self): - """ - Install this importer into sys.meta_path if not already present. - """ - if self not in sys.meta_path: - sys.meta_path.append(self) - - -names = 'packaging', 'pyparsing', 'six', 'appdirs' -VendorImporter(__name__, names).install() diff --git a/venv2/lib/python2.7/site-packages/pkg_resources/py31compat.py b/venv2/lib/python2.7/site-packages/pkg_resources/py31compat.py deleted file mode 100644 index a381c42..0000000 --- a/venv2/lib/python2.7/site-packages/pkg_resources/py31compat.py +++ /dev/null @@ -1,23 +0,0 @@ -import os -import errno -import sys - -from .extern import six - - -def _makedirs_31(path, exist_ok=False): - try: - os.makedirs(path) - except OSError as exc: - if not exist_ok or exc.errno != errno.EEXIST: - raise - - -# rely on compatibility behavior until mode considerations -# and exists_ok considerations are disentangled. -# See https://github.com/pypa/setuptools/pull/1083#issuecomment-315168663 -needs_makedirs = ( - six.PY2 or - (3, 4) <= sys.version_info < (3, 4, 1) -) -makedirs = _makedirs_31 if needs_makedirs else os.makedirs diff --git a/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/INSTALLER b/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/LICENSE b/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/LICENSE deleted file mode 100644 index 6e0693b..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (C) 2016 Jason R Coombs <jaraco@jaraco.com> - -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. diff --git a/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/METADATA b/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/METADATA deleted file mode 100644 index 571a5cb..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/METADATA +++ /dev/null @@ -1,77 +0,0 @@ -Metadata-Version: 2.1 -Name: setuptools -Version: 41.0.1 -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: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: System :: Archiving :: Packaging -Classifier: Topic :: System :: Systems Administration -Classifier: Topic :: Utilities -Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* -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 -<https://packaging.python.org/installing/>`_ 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 <http://mail.python.org/pipermail/distutils-sig/>`_. -Bug reports and especially tested patches may be -submitted directly to the `bug tracker -<https://github.com/pypa/setuptools/issues>`_. - -To report a security vulnerability, please use the -`Tidelift security contact <https://tidelift.com/security>`_. -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 <https://www.pypa.io/en/latest/code-of-conduct/>`_. - - diff --git a/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/RECORD b/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/RECORD deleted file mode 100644 index 00582fe..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/RECORD +++ /dev/null @@ -1,186 +0,0 @@ -../../../bin/easy_install,sha256=OiyMOfM-g-pLIS1KjMdbhED4SQ7Qr6-xfGf8Nh6uYuo,266 -../../../bin/easy_install-2.7,sha256=OiyMOfM-g-pLIS1KjMdbhED4SQ7Qr6-xfGf8Nh6uYuo,266 -easy_install.py,sha256=MDC9vt5AxDsXX5qcKlBz2TnW6Tpuv_AobnfhCJ9X3PM,126 -easy_install.pyc,, -pkg_resources/__init__.py,sha256=pp8b7Asoaheso-q8lIMS1tpQp88xjAkYgCIRX-JsPlE,107982 -pkg_resources/__init__.pyc,, -pkg_resources/_vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pkg_resources/_vendor/__init__.pyc,, -pkg_resources/_vendor/appdirs.py,sha256=MievUEuv3l_mQISH5SF0shDk_BNhHHzYiAPrT3ITN4I,24701 -pkg_resources/_vendor/appdirs.pyc,, -pkg_resources/_vendor/packaging/__about__.py,sha256=zkcCPTN_6TcLW0Nrlg0176-R1QQ_WVPTm8sz1R4-HjM,720 -pkg_resources/_vendor/packaging/__about__.pyc,, -pkg_resources/_vendor/packaging/__init__.py,sha256=_vNac5TrzwsrzbOFIbF-5cHqc_Y2aPT2D7zrIR06BOo,513 -pkg_resources/_vendor/packaging/__init__.pyc,, -pkg_resources/_vendor/packaging/_compat.py,sha256=Vi_A0rAQeHbU-a9X0tt1yQm9RqkgQbDSxzRw8WlU9kA,860 -pkg_resources/_vendor/packaging/_compat.pyc,, -pkg_resources/_vendor/packaging/_structures.py,sha256=RImECJ4c_wTlaTYYwZYLHEiebDMaAJmK1oPARhw1T5o,1416 -pkg_resources/_vendor/packaging/_structures.pyc,, -pkg_resources/_vendor/packaging/markers.py,sha256=uEcBBtGvzqltgnArqb9c4RrcInXezDLos14zbBHhWJo,8248 -pkg_resources/_vendor/packaging/markers.pyc,, -pkg_resources/_vendor/packaging/requirements.py,sha256=SikL2UynbsT0qtY9ltqngndha_sfo0w6XGFhAhoSoaQ,4355 -pkg_resources/_vendor/packaging/requirements.pyc,, -pkg_resources/_vendor/packaging/specifiers.py,sha256=SAMRerzO3fK2IkFZCaZkuwZaL_EGqHNOz4pni4vhnN0,28025 -pkg_resources/_vendor/packaging/specifiers.pyc,, -pkg_resources/_vendor/packaging/utils.py,sha256=3m6WvPm6NNxE8rkTGmn0r75B_GZSGg7ikafxHsBN1WA,421 -pkg_resources/_vendor/packaging/utils.pyc,, -pkg_resources/_vendor/packaging/version.py,sha256=OwGnxYfr2ghNzYx59qWIBkrK3SnB6n-Zfd1XaLpnnM0,11556 -pkg_resources/_vendor/packaging/version.pyc,, -pkg_resources/_vendor/pyparsing.py,sha256=tmrp-lu-qO1i75ZzIN5A12nKRRD1Cm4Vpk-5LR9rims,232055 -pkg_resources/_vendor/pyparsing.pyc,, -pkg_resources/_vendor/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 -pkg_resources/_vendor/six.pyc,, -pkg_resources/extern/__init__.py,sha256=cHiEfHuLmm6rs5Ve_ztBfMI7Lr31vss-D4wkqF5xzlI,2498 -pkg_resources/extern/__init__.pyc,, -pkg_resources/py31compat.py,sha256=-WQ0e4c3RG_acdhwC3gLiXhP_lg4G5q7XYkZkQg0gxU,558 -pkg_resources/py31compat.pyc,, -setuptools-41.0.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -setuptools-41.0.1.dist-info/LICENSE,sha256=wyo6w5WvYyHv0ovnPQagDw22q4h9HCHU_sRhKNIFbVo,1078 -setuptools-41.0.1.dist-info/METADATA,sha256=_i0otxacylu95CLISnMjTjG7DZ2vYZOvwedcoJ06JNE,3303 -setuptools-41.0.1.dist-info/RECORD,, -setuptools-41.0.1.dist-info/WHEEL,sha256=HX-v9-noUkyUoxyZ1PMSuS7auUxDAR4VBdoYLqD0xws,110 -setuptools-41.0.1.dist-info/dependency_links.txt,sha256=HlkCFkoK5TbZ5EMLbLKYhLcY_E31kBWD8TqW2EgmatQ,239 -setuptools-41.0.1.dist-info/entry_points.txt,sha256=jBqCYDlVjl__sjYFGXo1JQGIMAYFJE-prYWUtnMZEew,2990 -setuptools-41.0.1.dist-info/top_level.txt,sha256=2HUXVVwA4Pff1xgTFr3GsTXXKaPaO6vlG6oNJ_4u4Tg,38 -setuptools-41.0.1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 -setuptools/__init__.py,sha256=WBpCcn2lvdckotabeae1TTYonPOcgCIF3raD2zRWzBc,7283 -setuptools/__init__.pyc,, -setuptools/_deprecation_warning.py,sha256=jU9-dtfv6cKmtQJOXN8nP1mm7gONw5kKEtiPtbwnZyI,218 -setuptools/_deprecation_warning.pyc,, -setuptools/_vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -setuptools/_vendor/__init__.pyc,, -setuptools/_vendor/packaging/__about__.py,sha256=zkcCPTN_6TcLW0Nrlg0176-R1QQ_WVPTm8sz1R4-HjM,720 -setuptools/_vendor/packaging/__about__.pyc,, -setuptools/_vendor/packaging/__init__.py,sha256=_vNac5TrzwsrzbOFIbF-5cHqc_Y2aPT2D7zrIR06BOo,513 -setuptools/_vendor/packaging/__init__.pyc,, -setuptools/_vendor/packaging/_compat.py,sha256=Vi_A0rAQeHbU-a9X0tt1yQm9RqkgQbDSxzRw8WlU9kA,860 -setuptools/_vendor/packaging/_compat.pyc,, -setuptools/_vendor/packaging/_structures.py,sha256=RImECJ4c_wTlaTYYwZYLHEiebDMaAJmK1oPARhw1T5o,1416 -setuptools/_vendor/packaging/_structures.pyc,, -setuptools/_vendor/packaging/markers.py,sha256=Gvpk9EY20yKaMTiKgQZ8yFEEpodqVgVYtfekoic1Yts,8239 -setuptools/_vendor/packaging/markers.pyc,, -setuptools/_vendor/packaging/requirements.py,sha256=t44M2HVWtr8phIz2OhnILzuGT3rTATaovctV1dpnVIg,4343 -setuptools/_vendor/packaging/requirements.pyc,, -setuptools/_vendor/packaging/specifiers.py,sha256=SAMRerzO3fK2IkFZCaZkuwZaL_EGqHNOz4pni4vhnN0,28025 -setuptools/_vendor/packaging/specifiers.pyc,, -setuptools/_vendor/packaging/utils.py,sha256=3m6WvPm6NNxE8rkTGmn0r75B_GZSGg7ikafxHsBN1WA,421 -setuptools/_vendor/packaging/utils.pyc,, -setuptools/_vendor/packaging/version.py,sha256=OwGnxYfr2ghNzYx59qWIBkrK3SnB6n-Zfd1XaLpnnM0,11556 -setuptools/_vendor/packaging/version.pyc,, -setuptools/_vendor/pyparsing.py,sha256=tmrp-lu-qO1i75ZzIN5A12nKRRD1Cm4Vpk-5LR9rims,232055 -setuptools/_vendor/pyparsing.pyc,, -setuptools/_vendor/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 -setuptools/_vendor/six.pyc,, -setuptools/archive_util.py,sha256=kw8Ib_lKjCcnPKNbS7h8HztRVK0d5RacU3r_KRdVnmM,6592 -setuptools/archive_util.pyc,, -setuptools/build_meta.py,sha256=ioZE7tGSWY6vy7KLune0Iq334ugXuO39imcKC8prjBY,9387 -setuptools/build_meta.pyc,, -setuptools/cli-32.exe,sha256=dfEuovMNnA2HLa3jRfMPVi5tk4R7alCbpTvuxtCyw0Y,65536 -setuptools/cli-64.exe,sha256=KLABu5pyrnokJCv6skjXZ6GsXeyYHGcqOUT3oHI3Xpo,74752 -setuptools/cli.exe,sha256=dfEuovMNnA2HLa3jRfMPVi5tk4R7alCbpTvuxtCyw0Y,65536 -setuptools/command/__init__.py,sha256=NWzJ0A1BEengZpVeqUyWLNm2bk4P3F4iL5QUErHy7kA,594 -setuptools/command/__init__.pyc,, -setuptools/command/alias.py,sha256=KjpE0sz_SDIHv3fpZcIQK-sCkJz-SrC6Gmug6b9Nkc8,2426 -setuptools/command/alias.pyc,, -setuptools/command/bdist_egg.py,sha256=be-IBpr1zhS9i6GjKANJgzkbH3ChImdWY7S-j0r2BK8,18167 -setuptools/command/bdist_egg.pyc,, -setuptools/command/bdist_rpm.py,sha256=B7l0TnzCGb-0nLlm6rS00jWLkojASwVmdhW2w5Qz_Ak,1508 -setuptools/command/bdist_rpm.pyc,, -setuptools/command/bdist_wininst.py,sha256=_6dz3lpB1tY200LxKPLM7qgwTCceOMgaWFF-jW2-pm0,637 -setuptools/command/bdist_wininst.pyc,, -setuptools/command/build_clib.py,sha256=bQ9aBr-5ZSO-9fGsGsDLz0mnnFteHUZnftVLkhvHDq0,4484 -setuptools/command/build_clib.pyc,, -setuptools/command/build_ext.py,sha256=81CTgsqjBjNl_HOgCJ1lQ5vv1NIM3RBpcoVGpqT4N1M,12897 -setuptools/command/build_ext.pyc,, -setuptools/command/build_py.py,sha256=yWyYaaS9F3o9JbIczn064A5g1C5_UiKRDxGaTqYbtLE,9596 -setuptools/command/build_py.pyc,, -setuptools/command/develop.py,sha256=MQlnGS6uP19erK2JCNOyQYoYyquk3PADrqrrinqqLtA,8184 -setuptools/command/develop.pyc,, -setuptools/command/dist_info.py,sha256=5t6kOfrdgALT-P3ogss6PF9k-Leyesueycuk3dUyZnI,960 -setuptools/command/dist_info.pyc,, -setuptools/command/easy_install.py,sha256=telww7CuPsoTtvlpY-ktnZGT85cZ6xGCGZa0vHvFJ-Q,87273 -setuptools/command/easy_install.pyc,, -setuptools/command/egg_info.py,sha256=w73EdxYSOk2gsaAiHGL2dZrCldoPiuRr2eTfqcFvCds,25570 -setuptools/command/egg_info.pyc,, -setuptools/command/install.py,sha256=a0EZpL_A866KEdhicTGbuyD_TYl1sykfzdrri-zazT4,4683 -setuptools/command/install.pyc,, -setuptools/command/install_egg_info.py,sha256=bMgeIeRiXzQ4DAGPV1328kcjwQjHjOWU4FngAWLV78Q,2203 -setuptools/command/install_egg_info.pyc,, -setuptools/command/install_lib.py,sha256=11mxf0Ch12NsuYwS8PHwXBRvyh671QAM4cTRh7epzG0,3840 -setuptools/command/install_lib.pyc,, -setuptools/command/install_scripts.py,sha256=UD0rEZ6861mTYhIdzcsqKnUl8PozocXWl9VBQ1VTWnc,2439 -setuptools/command/install_scripts.pyc,, -setuptools/command/launcher manifest.xml,sha256=xlLbjWrB01tKC0-hlVkOKkiSPbzMml2eOPtJ_ucCnbE,628 -setuptools/command/py36compat.py,sha256=SzjZcOxF7zdFUT47Zv2n7AM3H8koDys_0OpS-n9gIfc,4986 -setuptools/command/py36compat.pyc,, -setuptools/command/register.py,sha256=LO3MvYKPE8dN1m-KkrBRHC68ZFoPvA_vI8Xgp7vv6zI,534 -setuptools/command/register.pyc,, -setuptools/command/rotate.py,sha256=co5C1EkI7P0GGT6Tqz-T2SIj2LBJTZXYELpmao6d4KQ,2164 -setuptools/command/rotate.pyc,, -setuptools/command/saveopts.py,sha256=za7QCBcQimKKriWcoCcbhxPjUz30gSB74zuTL47xpP4,658 -setuptools/command/saveopts.pyc,, -setuptools/command/sdist.py,sha256=gr5hFrDzUtGfp_0tu0sllzIyr3jMQegIkFmlDauQJxw,7388 -setuptools/command/sdist.pyc,, -setuptools/command/setopt.py,sha256=NTWDyx-gjDF-txf4dO577s7LOzHVoKR0Mq33rFxaRr8,5085 -setuptools/command/setopt.pyc,, -setuptools/command/test.py,sha256=oePJ49u17ENKtrM-rOrrLlRhtNnrzcSr0IW-gE9XVq0,9285 -setuptools/command/test.pyc,, -setuptools/command/upload.py,sha256=GxtNkIl7SA0r8mACkbDcSCN1m2_WPppK9gZXJmQSiow,6811 -setuptools/command/upload.pyc,, -setuptools/command/upload_docs.py,sha256=oXiGplM_cUKLwE4CWWw98RzCufAu8tBhMC97GegFcms,7311 -setuptools/command/upload_docs.pyc,, -setuptools/config.py,sha256=lz19l1AtoHctpp1_tbYZv176nrEj4Gpf7ykNIYTIkAQ,20425 -setuptools/config.pyc,, -setuptools/dep_util.py,sha256=fgixvC1R7sH3r13ktyf7N0FALoqEXL1cBarmNpSEoWg,935 -setuptools/dep_util.pyc,, -setuptools/depends.py,sha256=hC8QIDcM3VDpRXvRVA6OfL9AaQfxvhxHcN_w6sAyNq8,5837 -setuptools/depends.pyc,, -setuptools/dist.py,sha256=qYPmmVlLPWCLHrILR0J74bqoYgTSZh5ocLeyRKqnVyU,49913 -setuptools/dist.pyc,, -setuptools/extension.py,sha256=uc6nHI-MxwmNCNPbUiBnybSyqhpJqjbhvOQ-emdvt_E,1729 -setuptools/extension.pyc,, -setuptools/extern/__init__.py,sha256=TxeNKFMSfBMzBpBDiHx8Dh3RzsdVmvWaXhtZ03DZMs0,2499 -setuptools/extern/__init__.pyc,, -setuptools/glibc.py,sha256=X64VvGPL2AbURKwYRsWJOXXGAYOiF_v2qixeTkAULuU,3146 -setuptools/glibc.pyc,, -setuptools/glob.py,sha256=o75cHrOxYsvn854thSxE0x9k8JrKDuhP_rRXlVB00Q4,5084 -setuptools/glob.pyc,, -setuptools/gui-32.exe,sha256=XBr0bHMA6Hpz2s9s9Bzjl-PwXfa9nH4ie0rFn4V2kWA,65536 -setuptools/gui-64.exe,sha256=aYKMhX1IJLn4ULHgWX0sE0yREUt6B3TEHf_jOw6yNyE,75264 -setuptools/gui.exe,sha256=XBr0bHMA6Hpz2s9s9Bzjl-PwXfa9nH4ie0rFn4V2kWA,65536 -setuptools/launch.py,sha256=sd7ejwhBocCDx_wG9rIs0OaZ8HtmmFU8ZC6IR_S0Lvg,787 -setuptools/launch.pyc,, -setuptools/lib2to3_ex.py,sha256=t5e12hbR2pi9V4ezWDTB4JM-AISUnGOkmcnYHek3xjg,2013 -setuptools/lib2to3_ex.pyc,, -setuptools/monkey.py,sha256=FGc9fffh7gAxMLFmJs2DW_OYWpBjkdbNS2n14UAK4NA,5264 -setuptools/monkey.pyc,, -setuptools/msvc.py,sha256=uuRFaZzjJt5Fv3ZmyKUUuLtjx12_8G9RILigGec4irI,40838 -setuptools/msvc.pyc,, -setuptools/namespaces.py,sha256=F0Nrbv8KCT2OrO7rwa03om4N4GZKAlnce-rr-cgDQa8,3199 -setuptools/namespaces.pyc,, -setuptools/package_index.py,sha256=F9LBC-hQ5fkjeEVflxif0mo_DzRMrepahdFTPenOtGM,40587 -setuptools/package_index.pyc,, -setuptools/pep425tags.py,sha256=o_D_WVeWcXZiI2xjPSg7pouGOvaWRgGRxEDK9DzAXIA,10861 -setuptools/pep425tags.pyc,, -setuptools/py27compat.py,sha256=3mwxRMDk5Q5O1rSXOERbQDXhFqwDJhhUitfMW_qpUCo,536 -setuptools/py27compat.pyc,, -setuptools/py31compat.py,sha256=h2rtZghOfwoGYd8sQ0-auaKiF3TcL3qX0bX3VessqcE,838 -setuptools/py31compat.pyc,, -setuptools/py33compat.py,sha256=OubjldHJH1KGE1CKt1kRU-Q55keftHT3ea1YoL0ZSco,1195 -setuptools/py33compat.pyc,, -setuptools/sandbox.py,sha256=9UbwfEL5QY436oMI1LtFWohhoZ-UzwHvGyZjUH_qhkw,14276 -setuptools/sandbox.pyc,, -setuptools/script (dev).tmpl,sha256=RUzQzCQUaXtwdLtYHWYbIQmOaES5Brqq1FvUA_tu-5I,218 -setuptools/script.tmpl,sha256=WGTt5piezO27c-Dbx6l5Q4T3Ff20A5z7872hv3aAhYY,138 -setuptools/site-patch.py,sha256=OumkIHMuoSenRSW1382kKWI1VAwxNE86E5W8iDd34FY,2302 -setuptools/site-patch.pyc,, -setuptools/ssl_support.py,sha256=nLjPUBBw7RTTx6O4RJZ5eAMGgjJG8beiDbkFXDZpLuM,8493 -setuptools/ssl_support.pyc,, -setuptools/unicode_utils.py,sha256=NOiZ_5hD72A6w-4wVj8awHFM3n51Kmw1Ic_vx15XFqw,996 -setuptools/unicode_utils.pyc,, -setuptools/version.py,sha256=og_cuZQb0QI6ukKZFfZWPlr1HgJBPPn2vO2m_bI9ZTE,144 -setuptools/version.pyc,, -setuptools/wheel.py,sha256=94uqXsOaKt91d9hW5z6ZppZmNSs_nO66R4uiwhcr4V0,8094 -setuptools/wheel.pyc,, -setuptools/windows_support.py,sha256=5GrfqSP2-dLGJoZTq2g6dCKkyQxxa2n5IQiXlJCoYEE,714 -setuptools/windows_support.pyc,, diff --git a/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/WHEEL b/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/WHEEL deleted file mode 100644 index c8240f0..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.33.1) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/dependency_links.txt b/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/dependency_links.txt deleted file mode 100644 index e87d021..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/dependency_links.txt +++ /dev/null @@ -1,2 +0,0 @@ -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 diff --git a/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/entry_points.txt b/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/entry_points.txt deleted file mode 100644 index 4159fd0..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/entry_points.txt +++ /dev/null @@ -1,65 +0,0 @@ -[console_scripts] -easy_install = setuptools.command.easy_install:main -easy_install-3.6 = 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 - diff --git a/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/top_level.txt b/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/top_level.txt deleted file mode 100644 index 4577c6a..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/top_level.txt +++ /dev/null @@ -1,3 +0,0 @@ -easy_install -pkg_resources -setuptools diff --git a/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/zip-safe b/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/zip-safe deleted file mode 100644 index 8b13789..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools-41.0.1.dist-info/zip-safe +++ /dev/null @@ -1 +0,0 @@ - diff --git a/venv2/lib/python2.7/site-packages/setuptools/__init__.py b/venv2/lib/python2.7/site-packages/setuptools/__init__.py deleted file mode 100644 index a71b2bb..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/__init__.py +++ /dev/null @@ -1,228 +0,0 @@ -"""Extensions to the 'distutils' for large or complex distributions""" - -import os -import sys -import functools -import distutils.core -import distutils.filelist -import re -from distutils.errors import DistutilsOptionError -from distutils.util import convert_path -from fnmatch import fnmatchcase - -from ._deprecation_warning import SetuptoolsDeprecationWarning - -from setuptools.extern.six import PY3, string_types -from setuptools.extern.six.moves import filter, map - -import setuptools.version -from setuptools.extension import Extension -from setuptools.dist import Distribution, Feature -from setuptools.depends import Require -from . import monkey - -__metaclass__ = type - - -__all__ = [ - 'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require', - 'SetuptoolsDeprecationWarning', - 'find_packages' -] - -if PY3: - __all__.append('find_namespace_packages') - -__version__ = setuptools.version.__version__ - -bootstrap_install_from = None - -# If we run 2to3 on .py files, should we also convert docstrings? -# Default: yes; assume that we can detect doctests reliably -run_2to3_on_doctests = True -# Standard package names for fixer packages -lib2to3_fixer_packages = ['lib2to3.fixes'] - - -class PackageFinder: - """ - Generate a list of all Python packages found within a directory - """ - - @classmethod - def find(cls, where='.', exclude=(), include=('*',)): - """Return a list all Python packages found within directory 'where' - - 'where' is the root directory which will be searched for packages. It - should be supplied as a "cross-platform" (i.e. URL-style) path; it will - be converted to the appropriate local path syntax. - - 'exclude' is a sequence of package names to exclude; '*' can be used - as a wildcard in the names, such that 'foo.*' will exclude all - subpackages of 'foo' (but not 'foo' itself). - - 'include' is a sequence of package names to include. If it's - specified, only the named packages will be included. If it's not - specified, all found packages will be included. 'include' can contain - shell style wildcard patterns just like 'exclude'. - """ - - return list(cls._find_packages_iter( - convert_path(where), - cls._build_filter('ez_setup', '*__pycache__', *exclude), - cls._build_filter(*include))) - - @classmethod - def _find_packages_iter(cls, where, exclude, include): - """ - All the packages found in 'where' that pass the 'include' filter, but - not the 'exclude' filter. - """ - for root, dirs, files in os.walk(where, followlinks=True): - # Copy dirs to iterate over it, then empty dirs. - all_dirs = dirs[:] - dirs[:] = [] - - for dir in all_dirs: - full_path = os.path.join(root, dir) - rel_path = os.path.relpath(full_path, where) - package = rel_path.replace(os.path.sep, '.') - - # Skip directory trees that are not valid packages - if ('.' in dir or not cls._looks_like_package(full_path)): - continue - - # Should this package be included? - if include(package) and not exclude(package): - yield package - - # Keep searching subdirectories, as there may be more packages - # down there, even if the parent was excluded. - dirs.append(dir) - - @staticmethod - def _looks_like_package(path): - """Does a directory look like a package?""" - return os.path.isfile(os.path.join(path, '__init__.py')) - - @staticmethod - def _build_filter(*patterns): - """ - Given a list of patterns, return a callable that will be true only if - the input matches at least one of the patterns. - """ - return lambda name: any(fnmatchcase(name, pat=pat) for pat in patterns) - - -class PEP420PackageFinder(PackageFinder): - @staticmethod - def _looks_like_package(path): - return True - - -find_packages = PackageFinder.find - -if PY3: - find_namespace_packages = PEP420PackageFinder.find - - -def _install_setup_requires(attrs): - # Note: do not use `setuptools.Distribution` directly, as - # our PEP 517 backend patch `distutils.core.Distribution`. - dist = distutils.core.Distribution(dict( - (k, v) for k, v in attrs.items() - if k in ('dependency_links', 'setup_requires') - )) - # Honor setup.cfg's options. - dist.parse_config_files(ignore_option_errors=True) - if dist.setup_requires: - dist.fetch_build_eggs(dist.setup_requires) - - -def setup(**attrs): - # Make sure we have any requirements needed to interpret 'attrs'. - _install_setup_requires(attrs) - return distutils.core.setup(**attrs) - -setup.__doc__ = distutils.core.setup.__doc__ - - -_Command = monkey.get_unpatched(distutils.core.Command) - - -class Command(_Command): - __doc__ = _Command.__doc__ - - command_consumes_arguments = False - - def __init__(self, dist, **kw): - """ - Construct the command for dist, updating - vars(self) with any keyword parameters. - """ - _Command.__init__(self, dist) - vars(self).update(kw) - - def _ensure_stringlike(self, option, what, default=None): - val = getattr(self, option) - if val is None: - setattr(self, option, default) - return default - elif not isinstance(val, string_types): - raise DistutilsOptionError("'%s' must be a %s (got `%s`)" - % (option, what, val)) - return val - - def ensure_string_list(self, option): - r"""Ensure that 'option' is a list of strings. If 'option' is - currently a string, we split it either on /,\s*/ or /\s+/, so - "foo bar baz", "foo,bar,baz", and "foo, bar baz" all become - ["foo", "bar", "baz"]. - """ - val = getattr(self, option) - if val is None: - return - elif isinstance(val, string_types): - setattr(self, option, re.split(r',\s*|\s+', val)) - else: - if isinstance(val, list): - ok = all(isinstance(v, string_types) for v in val) - else: - ok = False - if not ok: - raise DistutilsOptionError( - "'%s' must be a list of strings (got %r)" - % (option, val)) - - def reinitialize_command(self, command, reinit_subcommands=0, **kw): - cmd = _Command.reinitialize_command(self, command, reinit_subcommands) - vars(cmd).update(kw) - return cmd - - -def _find_all_simple(path): - """ - Find all files under 'path' - """ - results = ( - os.path.join(base, file) - for base, dirs, files in os.walk(path, followlinks=True) - for file in files - ) - return filter(os.path.isfile, results) - - -def findall(dir=os.curdir): - """ - Find all files under 'dir' and return the list of full filenames. - Unless dir is '.', return full filenames with dir prepended. - """ - files = _find_all_simple(dir) - if dir == os.curdir: - make_rel = functools.partial(os.path.relpath, start=dir) - files = map(make_rel, files) - return list(files) - - -# Apply monkey patches -monkey.patch_all() diff --git a/venv2/lib/python2.7/site-packages/setuptools/_deprecation_warning.py b/venv2/lib/python2.7/site-packages/setuptools/_deprecation_warning.py deleted file mode 100644 index 086b64d..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/_deprecation_warning.py +++ /dev/null @@ -1,7 +0,0 @@ -class SetuptoolsDeprecationWarning(Warning): - """ - Base class for warning deprecations in ``setuptools`` - - This class is not derived from ``DeprecationWarning``, and as such is - visible by default. - """ diff --git a/venv2/lib/python2.7/site-packages/setuptools/_vendor/__init__.py b/venv2/lib/python2.7/site-packages/setuptools/_vendor/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/__about__.py b/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/__about__.py deleted file mode 100644 index 95d330e..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/__about__.py +++ /dev/null @@ -1,21 +0,0 @@ -# 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__ = "16.8" - -__author__ = "Donald Stufft and individual contributors" -__email__ = "donald@stufft.io" - -__license__ = "BSD or Apache License, Version 2.0" -__copyright__ = "Copyright 2014-2016 %s" % __author__ diff --git a/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/__init__.py b/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/__init__.py deleted file mode 100644 index 5ee6220..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# 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__", -] diff --git a/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/_compat.py b/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/_compat.py deleted file mode 100644 index 210bb80..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/_compat.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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', (), {}) diff --git a/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/_structures.py b/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/_structures.py deleted file mode 100644 index ccc2786..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/_structures.py +++ /dev/null @@ -1,68 +0,0 @@ -# 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() diff --git a/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/markers.py b/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/markers.py deleted file mode 100644 index 031332a..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/markers.py +++ /dev/null @@ -1,301 +0,0 @@ -# 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 setuptools.extern.pyparsing import ParseException, ParseResults, stringStart, stringEnd -from setuptools.extern.pyparsing import ZeroOrMore, Group, Forward, QuotedString -from setuptools.extern.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") | # PEP-345 - L("sys.platform") | # PEP-345 - L("platform.version") | # PEP-345 - L("platform.machine") | # PEP-345 - L("platform.python_implementation") | # PEP-345 - L("python_implementation") | # undocumented setuptools legacy - L("extra") -) -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": platform.python_version()[:3], - "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 "<Marker({0!r})>".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) diff --git a/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/requirements.py b/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/requirements.py deleted file mode 100644 index 5b49341..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/requirements.py +++ /dev/null @@ -1,127 +0,0 @@ -# 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 setuptools.extern.pyparsing import stringStart, stringEnd, originalTextFor, ParseException -from setuptools.extern.pyparsing import ZeroOrMore, Word, Optional, Regex, Combine -from setuptools.extern.pyparsing import Literal as L # noqa -from setuptools.extern.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_SEPERATOR = SEMICOLON -MARKER = MARKER_SEPERATOR + 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 - - -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( - "Invalid requirement, parse error at \"{0!r}\"".format( - requirement_string[e.loc:e.loc + 8])) - - self.name = req.name - if req.url: - parsed_url = urlparse.urlparse(req.url) - if not (parsed_url.scheme and parsed_url.netloc) or ( - not parsed_url.scheme and not parsed_url.netloc): - raise InvalidRequirement("Invalid URL given") - 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("; {0}".format(self.marker)) - - return "".join(parts) - - def __repr__(self): - return "<Requirement({0!r})>".format(str(self)) diff --git a/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/specifiers.py b/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/specifiers.py deleted file mode 100644 index 7f5a76c..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/specifiers.py +++ /dev/null @@ -1,774 +0,0 @@ -# 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 begining. - 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<operator>(==|!=|<=|>=|<|>)) - \s* - (?P<version> - [^,;\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<operator>(~=|==|!=|<=|>=|<|>|===)) - (?P<version> - (?: - # 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. - (?<!==|!=|~=) # We have special cases for these - # operators so we want to make sure they - # don't match here. - - \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]*) - )? - (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release - ) - ) - """ - ) - - _regex = re.compile( - r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) - - _operators = { - "~=": "compatible", - "==": "equal", - "!=": "not_equal", - "<=": "less_than_equal", - ">=": "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 techincally 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 "<SpecifierSet({0!r}{1})>".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 diff --git a/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/utils.py b/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/utils.py deleted file mode 100644 index 942387c..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/utils.py +++ /dev/null @@ -1,14 +0,0 @@ -# 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 - - -_canonicalize_regex = re.compile(r"[-_.]+") - - -def canonicalize_name(name): - # This is taken from PEP 503. - return _canonicalize_regex.sub("-", name).lower() diff --git a/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/version.py b/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/version.py deleted file mode 100644 index 83b5ee8..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/_vendor/packaging/version.py +++ /dev/null @@ -1,393 +0,0 @@ -# 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 "<LegacyVersion({0})>".format(repr(str(self))) - - @property - def public(self): - return self._version - - @property - def base_version(self): - return self._version - - @property - def local(self): - return None - - @property - def is_prerelease(self): - return False - - @property - def is_postrelease(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<epoch>[0-9]+)!)? # epoch - (?P<release>[0-9]+(?:\.[0-9]+)*) # release segment - (?P<pre> # pre-release - [-_\.]? - (?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview)) - [-_\.]? - (?P<pre_n>[0-9]+)? - )? - (?P<post> # post release - (?:-(?P<post_n1>[0-9]+)) - | - (?: - [-_\.]? - (?P<post_l>post|rev|r) - [-_\.]? - (?P<post_n2>[0-9]+)? - ) - )? - (?P<dev> # dev release - [-_\.]? - (?P<dev_l>dev) - [-_\.]? - (?P<dev_n>[0-9]+)? - )? - ) - (?:\+(?P<local>[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 "<Version({0})>".format(repr(str(self))) - - def __str__(self): - parts = [] - - # Epoch - if self._version.epoch != 0: - parts.append("{0}!".format(self._version.epoch)) - - # Release segment - parts.append(".".join(str(x) for x in self._version.release)) - - # Pre-release - if self._version.pre is not None: - parts.append("".join(str(x) for x in self._version.pre)) - - # Post-release - if self._version.post is not None: - parts.append(".post{0}".format(self._version.post[1])) - - # Development release - if self._version.dev is not None: - parts.append(".dev{0}".format(self._version.dev[1])) - - # Local version segment - if self._version.local is not None: - parts.append( - "+{0}".format(".".join(str(x) for x in self._version.local)) - ) - - return "".join(parts) - - @property - def public(self): - return str(self).split("+", 1)[0] - - @property - def base_version(self): - parts = [] - - # Epoch - if self._version.epoch != 0: - parts.append("{0}!".format(self._version.epoch)) - - # Release segment - parts.append(".".join(str(x) for x in self._version.release)) - - return "".join(parts) - - @property - def local(self): - version_string = str(self) - if "+" in version_string: - return version_string.split("+", 1)[1] - - @property - def is_prerelease(self): - return bool(self._version.dev or self._version.pre) - - @property - def is_postrelease(self): - return bool(self._version.post) - - -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_seperators = 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_seperators.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 diff --git a/venv2/lib/python2.7/site-packages/setuptools/_vendor/pyparsing.py b/venv2/lib/python2.7/site-packages/setuptools/_vendor/pyparsing.py deleted file mode 100644 index cf75e1e..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/_vendor/pyparsing.py +++ /dev/null @@ -1,5742 +0,0 @@ -# module pyparsing.py -# -# Copyright (c) 2003-2018 Paul T. McGuire -# -# 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. -# - -__doc__ = \ -""" -pyparsing module - Classes and methods to define and execute parsing grammars -============================================================================= - -The pyparsing module is an alternative approach to creating and executing simple grammars, -vs. the traditional lex/yacc approach, or the use of regular expressions. With pyparsing, you -don't need to learn a new syntax for defining grammars or matching expressions - the parsing module -provides a library of classes that you use to construct the grammar directly in Python. - -Here is a program to parse "Hello, World!" (or any greeting of the form -C{"<salutation>, <addressee>!"}), built up using L{Word}, L{Literal}, and L{And} elements -(L{'+'<ParserElement.__add__>} operator gives L{And} expressions, strings are auto-converted to -L{Literal} expressions):: - - from pyparsing import Word, alphas - - # define grammar of a greeting - greet = Word(alphas) + "," + Word(alphas) + "!" - - hello = "Hello, World!" - print (hello, "->", greet.parseString(hello)) - -The program outputs the following:: - - Hello, World! -> ['Hello', ',', 'World', '!'] - -The Python representation of the grammar is quite readable, owing to the self-explanatory -class names, and the use of '+', '|' and '^' operators. - -The L{ParseResults} object returned from L{ParserElement.parseString<ParserElement.parseString>} can be accessed as a nested list, a dictionary, or an -object with named attributes. - -The pyparsing module handles some of the problems that are typically vexing when writing text parsers: - - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello , World !", etc.) - - quoted strings - - embedded comments - - -Getting Started - ------------------ -Visit the classes L{ParserElement} and L{ParseResults} to see the base classes that most other pyparsing -classes inherit from. Use the docstrings for examples of how to: - - construct literal match expressions from L{Literal} and L{CaselessLiteral} classes - - construct character word-group expressions using the L{Word} class - - see how to create repetitive expressions using L{ZeroOrMore} and L{OneOrMore} classes - - use L{'+'<And>}, L{'|'<MatchFirst>}, L{'^'<Or>}, and L{'&'<Each>} operators to combine simple expressions into more complex ones - - associate names with your parsed results using L{ParserElement.setResultsName} - - find some helpful expression short-cuts like L{delimitedList} and L{oneOf} - - find more useful common expressions in the L{pyparsing_common} namespace class -""" - -__version__ = "2.2.1" -__versionTime__ = "18 Sep 2018 00:49 UTC" -__author__ = "Paul McGuire <ptmcg@users.sourceforge.net>" - -import string -from weakref import ref as wkref -import copy -import sys -import warnings -import re -import sre_constants -import collections -import pprint -import traceback -import types -from datetime import datetime - -try: - from _thread import RLock -except ImportError: - from threading import RLock - -try: - # Python 3 - from collections.abc import Iterable - from collections.abc import MutableMapping -except ImportError: - # Python 2.7 - from collections import Iterable - from collections import MutableMapping - -try: - from collections import OrderedDict as _OrderedDict -except ImportError: - try: - from ordereddict import OrderedDict as _OrderedDict - except ImportError: - _OrderedDict = None - -#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) ) - -__all__ = [ -'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty', -'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal', -'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or', -'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException', -'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException', -'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', -'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore', -'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col', -'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString', -'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'hexnums', -'htmlComment', 'javaStyleComment', 'line', 'lineEnd', 'lineStart', 'lineno', -'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral', -'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables', -'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', -'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd', -'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute', -'indentedBlock', 'originalTextFor', 'ungroup', 'infixNotation','locatedExpr', 'withClass', -'CloseMatch', 'tokenMap', 'pyparsing_common', -] - -system_version = tuple(sys.version_info)[:3] -PY_3 = system_version[0] == 3 -if PY_3: - _MAX_INT = sys.maxsize - basestring = str - unichr = chr - _ustr = str - - # build list of single arg builtins, that can be used as parse actions - singleArgBuiltins = [sum, len, sorted, reversed, list, tuple, set, any, all, min, max] - -else: - _MAX_INT = sys.maxint - range = xrange - - def _ustr(obj): - """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries - str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It - then < returns the unicode object | encodes it with the default encoding | ... >. - """ - if isinstance(obj,unicode): - return obj - - try: - # If this works, then _ustr(obj) has the same behaviour as str(obj), so - # it won't break any existing code. - return str(obj) - - except UnicodeEncodeError: - # Else encode it - ret = unicode(obj).encode(sys.getdefaultencoding(), 'xmlcharrefreplace') - xmlcharref = Regex(r'&#\d+;') - xmlcharref.setParseAction(lambda t: '\\u' + hex(int(t[0][2:-1]))[2:]) - return xmlcharref.transformString(ret) - - # build list of single arg builtins, tolerant of Python version, that can be used as parse actions - singleArgBuiltins = [] - import __builtin__ - for fname in "sum len sorted reversed list tuple set any all min max".split(): - try: - singleArgBuiltins.append(getattr(__builtin__,fname)) - except AttributeError: - continue - -_generatorType = type((y for y in range(1))) - -def _xml_escape(data): - """Escape &, <, >, ", ', etc. in a string of data.""" - - # ampersand must be replaced first - from_symbols = '&><"\'' - to_symbols = ('&'+s+';' for s in "amp gt lt quot apos".split()) - for from_,to_ in zip(from_symbols, to_symbols): - data = data.replace(from_, to_) - return data - -class _Constants(object): - pass - -alphas = string.ascii_uppercase + string.ascii_lowercase -nums = "0123456789" -hexnums = nums + "ABCDEFabcdef" -alphanums = alphas + nums -_bslash = chr(92) -printables = "".join(c for c in string.printable if c not in string.whitespace) - -class ParseBaseException(Exception): - """base exception class for all parsing runtime exceptions""" - # Performance tuning: we construct a *lot* of these, so keep this - # constructor as small and fast as possible - def __init__( self, pstr, loc=0, msg=None, elem=None ): - self.loc = loc - if msg is None: - self.msg = pstr - self.pstr = "" - else: - self.msg = msg - self.pstr = pstr - self.parserElement = elem - self.args = (pstr, loc, msg) - - @classmethod - def _from_exception(cls, pe): - """ - internal factory method to simplify creating one type of ParseException - from another - avoids having __init__ signature conflicts among subclasses - """ - return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement) - - def __getattr__( self, aname ): - """supported attributes by name are: - - lineno - returns the line number of the exception text - - col - returns the column number of the exception text - - line - returns the line containing the exception text - """ - if( aname == "lineno" ): - return lineno( self.loc, self.pstr ) - elif( aname in ("col", "column") ): - return col( self.loc, self.pstr ) - elif( aname == "line" ): - return line( self.loc, self.pstr ) - else: - raise AttributeError(aname) - - def __str__( self ): - return "%s (at char %d), (line:%d, col:%d)" % \ - ( self.msg, self.loc, self.lineno, self.column ) - def __repr__( self ): - return _ustr(self) - def markInputline( self, markerString = ">!<" ): - """Extracts the exception line from the input string, and marks - the location of the exception with a special symbol. - """ - line_str = self.line - line_column = self.column - 1 - if markerString: - line_str = "".join((line_str[:line_column], - markerString, line_str[line_column:])) - return line_str.strip() - def __dir__(self): - return "lineno col line".split() + dir(type(self)) - -class ParseException(ParseBaseException): - """ - Exception thrown when parse expressions don't match class; - supported attributes by name are: - - lineno - returns the line number of the exception text - - col - returns the column number of the exception text - - line - returns the line containing the exception text - - Example:: - try: - Word(nums).setName("integer").parseString("ABC") - except ParseException as pe: - print(pe) - print("column: {}".format(pe.col)) - - prints:: - Expected integer (at char 0), (line:1, col:1) - column: 1 - """ - pass - -class ParseFatalException(ParseBaseException): - """user-throwable exception thrown when inconsistent parse content - is found; stops all parsing immediately""" - pass - -class ParseSyntaxException(ParseFatalException): - """just like L{ParseFatalException}, but thrown internally when an - L{ErrorStop<And._ErrorStop>} ('-' operator) indicates that parsing is to stop - immediately because an unbacktrackable syntax error has been found""" - pass - -#~ class ReparseException(ParseBaseException): - #~ """Experimental class - parse actions can raise this exception to cause - #~ pyparsing to reparse the input string: - #~ - with a modified input string, and/or - #~ - with a modified start location - #~ Set the values of the ReparseException in the constructor, and raise the - #~ exception in a parse action to cause pyparsing to use the new string/location. - #~ Setting the values as None causes no change to be made. - #~ """ - #~ def __init_( self, newstring, restartLoc ): - #~ self.newParseText = newstring - #~ self.reparseLoc = restartLoc - -class RecursiveGrammarException(Exception): - """exception thrown by L{ParserElement.validate} if the grammar could be improperly recursive""" - def __init__( self, parseElementList ): - self.parseElementTrace = parseElementList - - def __str__( self ): - return "RecursiveGrammarException: %s" % self.parseElementTrace - -class _ParseResultsWithOffset(object): - def __init__(self,p1,p2): - self.tup = (p1,p2) - def __getitem__(self,i): - return self.tup[i] - def __repr__(self): - return repr(self.tup[0]) - def setOffset(self,i): - self.tup = (self.tup[0],i) - -class ParseResults(object): - """ - Structured parse results, to provide multiple means of access to the parsed data: - - as a list (C{len(results)}) - - by list index (C{results[0], results[1]}, etc.) - - by attribute (C{results.<resultsName>} - see L{ParserElement.setResultsName}) - - Example:: - integer = Word(nums) - date_str = (integer.setResultsName("year") + '/' - + integer.setResultsName("month") + '/' - + integer.setResultsName("day")) - # equivalent form: - # date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - # parseString returns a ParseResults object - result = date_str.parseString("1999/12/31") - - def test(s, fn=repr): - print("%s -> %s" % (s, fn(eval(s)))) - test("list(result)") - test("result[0]") - test("result['month']") - test("result.day") - test("'month' in result") - test("'minutes' in result") - test("result.dump()", str) - prints:: - list(result) -> ['1999', '/', '12', '/', '31'] - result[0] -> '1999' - result['month'] -> '12' - result.day -> '31' - 'month' in result -> True - 'minutes' in result -> False - result.dump() -> ['1999', '/', '12', '/', '31'] - - day: 31 - - month: 12 - - year: 1999 - """ - def __new__(cls, toklist=None, name=None, asList=True, modal=True ): - if isinstance(toklist, cls): - return toklist - retobj = object.__new__(cls) - retobj.__doinit = True - return retobj - - # Performance tuning: we construct a *lot* of these, so keep this - # constructor as small and fast as possible - def __init__( self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance ): - if self.__doinit: - self.__doinit = False - self.__name = None - self.__parent = None - self.__accumNames = {} - self.__asList = asList - self.__modal = modal - if toklist is None: - toklist = [] - if isinstance(toklist, list): - self.__toklist = toklist[:] - elif isinstance(toklist, _generatorType): - self.__toklist = list(toklist) - else: - self.__toklist = [toklist] - self.__tokdict = dict() - - if name is not None and name: - if not modal: - self.__accumNames[name] = 0 - if isinstance(name,int): - name = _ustr(name) # will always return a str, but use _ustr for consistency - self.__name = name - if not (isinstance(toklist, (type(None), basestring, list)) and toklist in (None,'',[])): - if isinstance(toklist,basestring): - toklist = [ toklist ] - if asList: - if isinstance(toklist,ParseResults): - self[name] = _ParseResultsWithOffset(toklist.copy(),0) - else: - self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0) - self[name].__name = name - else: - try: - self[name] = toklist[0] - except (KeyError,TypeError,IndexError): - self[name] = toklist - - def __getitem__( self, i ): - if isinstance( i, (int,slice) ): - return self.__toklist[i] - else: - if i not in self.__accumNames: - return self.__tokdict[i][-1][0] - else: - return ParseResults([ v[0] for v in self.__tokdict[i] ]) - - def __setitem__( self, k, v, isinstance=isinstance ): - if isinstance(v,_ParseResultsWithOffset): - self.__tokdict[k] = self.__tokdict.get(k,list()) + [v] - sub = v[0] - elif isinstance(k,(int,slice)): - self.__toklist[k] = v - sub = v - else: - self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)] - sub = v - if isinstance(sub,ParseResults): - sub.__parent = wkref(self) - - def __delitem__( self, i ): - if isinstance(i,(int,slice)): - mylen = len( self.__toklist ) - del self.__toklist[i] - - # convert int to slice - if isinstance(i, int): - if i < 0: - i += mylen - i = slice(i, i+1) - # get removed indices - removed = list(range(*i.indices(mylen))) - removed.reverse() - # fixup indices in token dictionary - for name,occurrences in self.__tokdict.items(): - for j in removed: - for k, (value, position) in enumerate(occurrences): - occurrences[k] = _ParseResultsWithOffset(value, position - (position > j)) - else: - del self.__tokdict[i] - - def __contains__( self, k ): - return k in self.__tokdict - - def __len__( self ): return len( self.__toklist ) - def __bool__(self): return ( not not self.__toklist ) - __nonzero__ = __bool__ - def __iter__( self ): return iter( self.__toklist ) - def __reversed__( self ): return iter( self.__toklist[::-1] ) - def _iterkeys( self ): - if hasattr(self.__tokdict, "iterkeys"): - return self.__tokdict.iterkeys() - else: - return iter(self.__tokdict) - - def _itervalues( self ): - return (self[k] for k in self._iterkeys()) - - def _iteritems( self ): - return ((k, self[k]) for k in self._iterkeys()) - - if PY_3: - keys = _iterkeys - """Returns an iterator of all named result keys (Python 3.x only).""" - - values = _itervalues - """Returns an iterator of all named result values (Python 3.x only).""" - - items = _iteritems - """Returns an iterator of all named result key-value tuples (Python 3.x only).""" - - else: - iterkeys = _iterkeys - """Returns an iterator of all named result keys (Python 2.x only).""" - - itervalues = _itervalues - """Returns an iterator of all named result values (Python 2.x only).""" - - iteritems = _iteritems - """Returns an iterator of all named result key-value tuples (Python 2.x only).""" - - def keys( self ): - """Returns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x).""" - return list(self.iterkeys()) - - def values( self ): - """Returns all named result values (as a list in Python 2.x, as an iterator in Python 3.x).""" - return list(self.itervalues()) - - def items( self ): - """Returns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x).""" - return list(self.iteritems()) - - def haskeys( self ): - """Since keys() returns an iterator, this method is helpful in bypassing - code that looks for the existence of any defined results names.""" - return bool(self.__tokdict) - - def pop( self, *args, **kwargs): - """ - Removes and returns item at specified index (default=C{last}). - Supports both C{list} and C{dict} semantics for C{pop()}. If passed no - argument or an integer argument, it will use C{list} semantics - and pop tokens from the list of parsed tokens. If passed a - non-integer argument (most likely a string), it will use C{dict} - semantics and pop the corresponding value from any defined - results names. A second default return value argument is - supported, just as in C{dict.pop()}. - - Example:: - def remove_first(tokens): - tokens.pop(0) - print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] - print(OneOrMore(Word(nums)).addParseAction(remove_first).parseString("0 123 321")) # -> ['123', '321'] - - label = Word(alphas) - patt = label("LABEL") + OneOrMore(Word(nums)) - print(patt.parseString("AAB 123 321").dump()) - - # Use pop() in a parse action to remove named result (note that corresponding value is not - # removed from list form of results) - def remove_LABEL(tokens): - tokens.pop("LABEL") - return tokens - patt.addParseAction(remove_LABEL) - print(patt.parseString("AAB 123 321").dump()) - prints:: - ['AAB', '123', '321'] - - LABEL: AAB - - ['AAB', '123', '321'] - """ - if not args: - args = [-1] - for k,v in kwargs.items(): - if k == 'default': - args = (args[0], v) - else: - raise TypeError("pop() got an unexpected keyword argument '%s'" % k) - if (isinstance(args[0], int) or - len(args) == 1 or - args[0] in self): - index = args[0] - ret = self[index] - del self[index] - return ret - else: - defaultvalue = args[1] - return defaultvalue - - def get(self, key, defaultValue=None): - """ - Returns named result matching the given key, or if there is no - such name, then returns the given C{defaultValue} or C{None} if no - C{defaultValue} is specified. - - Similar to C{dict.get()}. - - Example:: - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - result = date_str.parseString("1999/12/31") - print(result.get("year")) # -> '1999' - print(result.get("hour", "not specified")) # -> 'not specified' - print(result.get("hour")) # -> None - """ - if key in self: - return self[key] - else: - return defaultValue - - def insert( self, index, insStr ): - """ - Inserts new element at location index in the list of parsed tokens. - - Similar to C{list.insert()}. - - Example:: - print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] - - # use a parse action to insert the parse location in the front of the parsed results - def insert_locn(locn, tokens): - tokens.insert(0, locn) - print(OneOrMore(Word(nums)).addParseAction(insert_locn).parseString("0 123 321")) # -> [0, '0', '123', '321'] - """ - self.__toklist.insert(index, insStr) - # fixup indices in token dictionary - for name,occurrences in self.__tokdict.items(): - for k, (value, position) in enumerate(occurrences): - occurrences[k] = _ParseResultsWithOffset(value, position + (position > index)) - - def append( self, item ): - """ - Add single element to end of ParseResults list of elements. - - Example:: - print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] - - # use a parse action to compute the sum of the parsed integers, and add it to the end - def append_sum(tokens): - tokens.append(sum(map(int, tokens))) - print(OneOrMore(Word(nums)).addParseAction(append_sum).parseString("0 123 321")) # -> ['0', '123', '321', 444] - """ - self.__toklist.append(item) - - def extend( self, itemseq ): - """ - Add sequence of elements to end of ParseResults list of elements. - - Example:: - patt = OneOrMore(Word(alphas)) - - # use a parse action to append the reverse of the matched strings, to make a palindrome - def make_palindrome(tokens): - tokens.extend(reversed([t[::-1] for t in tokens])) - return ''.join(tokens) - print(patt.addParseAction(make_palindrome).parseString("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl' - """ - if isinstance(itemseq, ParseResults): - self += itemseq - else: - self.__toklist.extend(itemseq) - - def clear( self ): - """ - Clear all elements and results names. - """ - del self.__toklist[:] - self.__tokdict.clear() - - def __getattr__( self, name ): - try: - return self[name] - except KeyError: - return "" - - if name in self.__tokdict: - if name not in self.__accumNames: - return self.__tokdict[name][-1][0] - else: - return ParseResults([ v[0] for v in self.__tokdict[name] ]) - else: - return "" - - def __add__( self, other ): - ret = self.copy() - ret += other - return ret - - def __iadd__( self, other ): - if other.__tokdict: - offset = len(self.__toklist) - addoffset = lambda a: offset if a<0 else a+offset - otheritems = other.__tokdict.items() - otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) ) - for (k,vlist) in otheritems for v in vlist] - for k,v in otherdictitems: - self[k] = v - if isinstance(v[0],ParseResults): - v[0].__parent = wkref(self) - - self.__toklist += other.__toklist - self.__accumNames.update( other.__accumNames ) - return self - - def __radd__(self, other): - if isinstance(other,int) and other == 0: - # useful for merging many ParseResults using sum() builtin - return self.copy() - else: - # this may raise a TypeError - so be it - return other + self - - def __repr__( self ): - return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) ) - - def __str__( self ): - return '[' + ', '.join(_ustr(i) if isinstance(i, ParseResults) else repr(i) for i in self.__toklist) + ']' - - def _asStringList( self, sep='' ): - out = [] - for item in self.__toklist: - if out and sep: - out.append(sep) - if isinstance( item, ParseResults ): - out += item._asStringList() - else: - out.append( _ustr(item) ) - return out - - def asList( self ): - """ - Returns the parse results as a nested list of matching tokens, all converted to strings. - - Example:: - patt = OneOrMore(Word(alphas)) - result = patt.parseString("sldkj lsdkj sldkj") - # even though the result prints in string-like form, it is actually a pyparsing ParseResults - print(type(result), result) # -> <class 'pyparsing.ParseResults'> ['sldkj', 'lsdkj', 'sldkj'] - - # Use asList() to create an actual list - result_list = result.asList() - print(type(result_list), result_list) # -> <class 'list'> ['sldkj', 'lsdkj', 'sldkj'] - """ - return [res.asList() if isinstance(res,ParseResults) else res for res in self.__toklist] - - def asDict( self ): - """ - Returns the named parse results as a nested dictionary. - - Example:: - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - result = date_str.parseString('12/31/1999') - print(type(result), repr(result)) # -> <class 'pyparsing.ParseResults'> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]}) - - result_dict = result.asDict() - print(type(result_dict), repr(result_dict)) # -> <class 'dict'> {'day': '1999', 'year': '12', 'month': '31'} - - # even though a ParseResults supports dict-like access, sometime you just need to have a dict - import json - print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable - print(json.dumps(result.asDict())) # -> {"month": "31", "day": "1999", "year": "12"} - """ - if PY_3: - item_fn = self.items - else: - item_fn = self.iteritems - - def toItem(obj): - if isinstance(obj, ParseResults): - if obj.haskeys(): - return obj.asDict() - else: - return [toItem(v) for v in obj] - else: - return obj - - return dict((k,toItem(v)) for k,v in item_fn()) - - def copy( self ): - """ - Returns a new copy of a C{ParseResults} object. - """ - ret = ParseResults( self.__toklist ) - ret.__tokdict = self.__tokdict.copy() - ret.__parent = self.__parent - ret.__accumNames.update( self.__accumNames ) - ret.__name = self.__name - return ret - - def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ): - """ - (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names. - """ - nl = "\n" - out = [] - namedItems = dict((v[1],k) for (k,vlist) in self.__tokdict.items() - for v in vlist) - nextLevelIndent = indent + " " - - # collapse out indents if formatting is not desired - if not formatted: - indent = "" - nextLevelIndent = "" - nl = "" - - selfTag = None - if doctag is not None: - selfTag = doctag - else: - if self.__name: - selfTag = self.__name - - if not selfTag: - if namedItemsOnly: - return "" - else: - selfTag = "ITEM" - - out += [ nl, indent, "<", selfTag, ">" ] - - for i,res in enumerate(self.__toklist): - if isinstance(res,ParseResults): - if i in namedItems: - out += [ res.asXML(namedItems[i], - namedItemsOnly and doctag is None, - nextLevelIndent, - formatted)] - else: - out += [ res.asXML(None, - namedItemsOnly and doctag is None, - nextLevelIndent, - formatted)] - else: - # individual token, see if there is a name for it - resTag = None - if i in namedItems: - resTag = namedItems[i] - if not resTag: - if namedItemsOnly: - continue - else: - resTag = "ITEM" - xmlBodyText = _xml_escape(_ustr(res)) - out += [ nl, nextLevelIndent, "<", resTag, ">", - xmlBodyText, - "</", resTag, ">" ] - - out += [ nl, indent, "</", selfTag, ">" ] - return "".join(out) - - def __lookup(self,sub): - for k,vlist in self.__tokdict.items(): - for v,loc in vlist: - if sub is v: - return k - return None - - def getName(self): - r""" - Returns the results name for this token expression. Useful when several - different expressions might match at a particular location. - - Example:: - integer = Word(nums) - ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d") - house_number_expr = Suppress('#') + Word(nums, alphanums) - user_data = (Group(house_number_expr)("house_number") - | Group(ssn_expr)("ssn") - | Group(integer)("age")) - user_info = OneOrMore(user_data) - - result = user_info.parseString("22 111-22-3333 #221B") - for item in result: - print(item.getName(), ':', item[0]) - prints:: - age : 22 - ssn : 111-22-3333 - house_number : 221B - """ - if self.__name: - return self.__name - elif self.__parent: - par = self.__parent() - if par: - return par.__lookup(self) - else: - return None - elif (len(self) == 1 and - len(self.__tokdict) == 1 and - next(iter(self.__tokdict.values()))[0][1] in (0,-1)): - return next(iter(self.__tokdict.keys())) - else: - return None - - def dump(self, indent='', depth=0, full=True): - """ - Diagnostic method for listing out the contents of a C{ParseResults}. - Accepts an optional C{indent} argument so that this string can be embedded - in a nested display of other data. - - Example:: - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - result = date_str.parseString('12/31/1999') - print(result.dump()) - prints:: - ['12', '/', '31', '/', '1999'] - - day: 1999 - - month: 31 - - year: 12 - """ - out = [] - NL = '\n' - out.append( indent+_ustr(self.asList()) ) - if full: - if self.haskeys(): - items = sorted((str(k), v) for k,v in self.items()) - for k,v in items: - if out: - out.append(NL) - out.append( "%s%s- %s: " % (indent,(' '*depth), k) ) - if isinstance(v,ParseResults): - if v: - out.append( v.dump(indent,depth+1) ) - else: - out.append(_ustr(v)) - else: - out.append(repr(v)) - elif any(isinstance(vv,ParseResults) for vv in self): - v = self - for i,vv in enumerate(v): - if isinstance(vv,ParseResults): - out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),vv.dump(indent,depth+1) )) - else: - out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),_ustr(vv))) - - return "".join(out) - - def pprint(self, *args, **kwargs): - """ - Pretty-printer for parsed results as a list, using the C{pprint} module. - Accepts additional positional or keyword args as defined for the - C{pprint.pprint} method. (U{http://docs.python.org/3/library/pprint.html#pprint.pprint}) - - Example:: - ident = Word(alphas, alphanums) - num = Word(nums) - func = Forward() - term = ident | num | Group('(' + func + ')') - func <<= ident + Group(Optional(delimitedList(term))) - result = func.parseString("fna a,b,(fnb c,d,200),100") - result.pprint(width=40) - prints:: - ['fna', - ['a', - 'b', - ['(', 'fnb', ['c', 'd', '200'], ')'], - '100']] - """ - pprint.pprint(self.asList(), *args, **kwargs) - - # add support for pickle protocol - def __getstate__(self): - return ( self.__toklist, - ( self.__tokdict.copy(), - self.__parent is not None and self.__parent() or None, - self.__accumNames, - self.__name ) ) - - def __setstate__(self,state): - self.__toklist = state[0] - (self.__tokdict, - par, - inAccumNames, - self.__name) = state[1] - self.__accumNames = {} - self.__accumNames.update(inAccumNames) - if par is not None: - self.__parent = wkref(par) - else: - self.__parent = None - - def __getnewargs__(self): - return self.__toklist, self.__name, self.__asList, self.__modal - - def __dir__(self): - return (dir(type(self)) + list(self.keys())) - -MutableMapping.register(ParseResults) - -def col (loc,strg): - """Returns current column within a string, counting newlines as line separators. - The first column is number 1. - - Note: the default parsing behavior is to expand tabs in the input string - before starting the parsing process. See L{I{ParserElement.parseString}<ParserElement.parseString>} for more information - on parsing strings containing C{<TAB>}s, and suggested methods to maintain a - consistent view of the parsed string, the parse location, and line and column - positions within the parsed string. - """ - s = strg - return 1 if 0<loc<len(s) and s[loc-1] == '\n' else loc - s.rfind("\n", 0, loc) - -def lineno(loc,strg): - """Returns current line number within a string, counting newlines as line separators. - The first line is number 1. - - Note: the default parsing behavior is to expand tabs in the input string - before starting the parsing process. See L{I{ParserElement.parseString}<ParserElement.parseString>} for more information - on parsing strings containing C{<TAB>}s, and suggested methods to maintain a - consistent view of the parsed string, the parse location, and line and column - positions within the parsed string. - """ - return strg.count("\n",0,loc) + 1 - -def line( loc, strg ): - """Returns the line of text containing loc within a string, counting newlines as line separators. - """ - lastCR = strg.rfind("\n", 0, loc) - nextCR = strg.find("\n", loc) - if nextCR >= 0: - return strg[lastCR+1:nextCR] - else: - return strg[lastCR+1:] - -def _defaultStartDebugAction( instring, loc, expr ): - print (("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ))) - -def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ): - print ("Matched " + _ustr(expr) + " -> " + str(toks.asList())) - -def _defaultExceptionDebugAction( instring, loc, expr, exc ): - print ("Exception raised:" + _ustr(exc)) - -def nullDebugAction(*args): - """'Do-nothing' debug action, to suppress debugging output during parsing.""" - pass - -# Only works on Python 3.x - nonlocal is toxic to Python 2 installs -#~ 'decorator to trim function calls to match the arity of the target' -#~ def _trim_arity(func, maxargs=3): - #~ if func in singleArgBuiltins: - #~ return lambda s,l,t: func(t) - #~ limit = 0 - #~ foundArity = False - #~ def wrapper(*args): - #~ nonlocal limit,foundArity - #~ while 1: - #~ try: - #~ ret = func(*args[limit:]) - #~ foundArity = True - #~ return ret - #~ except TypeError: - #~ if limit == maxargs or foundArity: - #~ raise - #~ limit += 1 - #~ continue - #~ return wrapper - -# this version is Python 2.x-3.x cross-compatible -'decorator to trim function calls to match the arity of the target' -def _trim_arity(func, maxargs=2): - if func in singleArgBuiltins: - return lambda s,l,t: func(t) - limit = [0] - foundArity = [False] - - # traceback return data structure changed in Py3.5 - normalize back to plain tuples - if system_version[:2] >= (3,5): - def extract_stack(limit=0): - # special handling for Python 3.5.0 - extra deep call stack by 1 - offset = -3 if system_version == (3,5,0) else -2 - frame_summary = traceback.extract_stack(limit=-offset+limit-1)[offset] - return [frame_summary[:2]] - def extract_tb(tb, limit=0): - frames = traceback.extract_tb(tb, limit=limit) - frame_summary = frames[-1] - return [frame_summary[:2]] - else: - extract_stack = traceback.extract_stack - extract_tb = traceback.extract_tb - - # synthesize what would be returned by traceback.extract_stack at the call to - # user's parse action 'func', so that we don't incur call penalty at parse time - - LINE_DIFF = 6 - # IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND - # THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!! - this_line = extract_stack(limit=2)[-1] - pa_call_line_synth = (this_line[0], this_line[1]+LINE_DIFF) - - def wrapper(*args): - while 1: - try: - ret = func(*args[limit[0]:]) - foundArity[0] = True - return ret - except TypeError: - # re-raise TypeErrors if they did not come from our arity testing - if foundArity[0]: - raise - else: - try: - tb = sys.exc_info()[-1] - if not extract_tb(tb, limit=2)[-1][:2] == pa_call_line_synth: - raise - finally: - del tb - - if limit[0] <= maxargs: - limit[0] += 1 - continue - raise - - # copy func name to wrapper for sensible debug output - func_name = "<parse action>" - try: - func_name = getattr(func, '__name__', - getattr(func, '__class__').__name__) - except Exception: - func_name = str(func) - wrapper.__name__ = func_name - - return wrapper - -class ParserElement(object): - """Abstract base level parser element class.""" - DEFAULT_WHITE_CHARS = " \n\t\r" - verbose_stacktrace = False - - @staticmethod - def setDefaultWhitespaceChars( chars ): - r""" - Overrides the default whitespace chars - - Example:: - # default whitespace chars are space, <TAB> and newline - OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def', 'ghi', 'jkl'] - - # change to just treat newline as significant - ParserElement.setDefaultWhitespaceChars(" \t") - OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def'] - """ - ParserElement.DEFAULT_WHITE_CHARS = chars - - @staticmethod - def inlineLiteralsUsing(cls): - """ - Set class to be used for inclusion of string literals into a parser. - - Example:: - # default literal class used is Literal - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] - - - # change to Suppress - ParserElement.inlineLiteralsUsing(Suppress) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - date_str.parseString("1999/12/31") # -> ['1999', '12', '31'] - """ - ParserElement._literalStringClass = cls - - def __init__( self, savelist=False ): - self.parseAction = list() - self.failAction = None - #~ self.name = "<unknown>" # don't define self.name, let subclasses try/except upcall - self.strRepr = None - self.resultsName = None - self.saveAsList = savelist - self.skipWhitespace = True - self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS - self.copyDefaultWhiteChars = True - self.mayReturnEmpty = False # used when checking for left-recursion - self.keepTabs = False - self.ignoreExprs = list() - self.debug = False - self.streamlined = False - self.mayIndexError = True # used to optimize exception handling for subclasses that don't advance parse index - self.errmsg = "" - self.modalResults = True # used to mark results names as modal (report only last) or cumulative (list all) - self.debugActions = ( None, None, None ) #custom debug actions - self.re = None - self.callPreparse = True # used to avoid redundant calls to preParse - self.callDuringTry = False - - def copy( self ): - """ - Make a copy of this C{ParserElement}. Useful for defining different parse actions - for the same parsing pattern, using copies of the original parse element. - - Example:: - integer = Word(nums).setParseAction(lambda toks: int(toks[0])) - integerK = integer.copy().addParseAction(lambda toks: toks[0]*1024) + Suppress("K") - integerM = integer.copy().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") - - print(OneOrMore(integerK | integerM | integer).parseString("5K 100 640K 256M")) - prints:: - [5120, 100, 655360, 268435456] - Equivalent form of C{expr.copy()} is just C{expr()}:: - integerM = integer().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") - """ - cpy = copy.copy( self ) - cpy.parseAction = self.parseAction[:] - cpy.ignoreExprs = self.ignoreExprs[:] - if self.copyDefaultWhiteChars: - cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS - return cpy - - def setName( self, name ): - """ - Define name for this expression, makes debugging and exception messages clearer. - - Example:: - Word(nums).parseString("ABC") # -> Exception: Expected W:(0123...) (at char 0), (line:1, col:1) - Word(nums).setName("integer").parseString("ABC") # -> Exception: Expected integer (at char 0), (line:1, col:1) - """ - self.name = name - self.errmsg = "Expected " + self.name - if hasattr(self,"exception"): - self.exception.msg = self.errmsg - return self - - def setResultsName( self, name, listAllMatches=False ): - """ - Define name for referencing matching tokens as a nested attribute - of the returned parse results. - NOTE: this returns a *copy* of the original C{ParserElement} object; - this is so that the client can define a basic element, such as an - integer, and reference it in multiple places with different names. - - You can also set results names using the abbreviated syntax, - C{expr("name")} in place of C{expr.setResultsName("name")} - - see L{I{__call__}<__call__>}. - - Example:: - date_str = (integer.setResultsName("year") + '/' - + integer.setResultsName("month") + '/' - + integer.setResultsName("day")) - - # equivalent form: - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - """ - newself = self.copy() - if name.endswith("*"): - name = name[:-1] - listAllMatches=True - newself.resultsName = name - newself.modalResults = not listAllMatches - return newself - - def setBreak(self,breakFlag = True): - """Method to invoke the Python pdb debugger when this element is - about to be parsed. Set C{breakFlag} to True to enable, False to - disable. - """ - if breakFlag: - _parseMethod = self._parse - def breaker(instring, loc, doActions=True, callPreParse=True): - import pdb - pdb.set_trace() - return _parseMethod( instring, loc, doActions, callPreParse ) - breaker._originalParseMethod = _parseMethod - self._parse = breaker - else: - if hasattr(self._parse,"_originalParseMethod"): - self._parse = self._parse._originalParseMethod - return self - - def setParseAction( self, *fns, **kwargs ): - """ - Define one or more actions to perform when successfully matching parse element definition. - Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)}, - C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where: - - s = the original string being parsed (see note below) - - loc = the location of the matching substring - - toks = a list of the matched tokens, packaged as a C{L{ParseResults}} object - If the functions in fns modify the tokens, they can return them as the return - value from fn, and the modified list of tokens will replace the original. - Otherwise, fn does not need to return any value. - - Optional keyword arguments: - - callDuringTry = (default=C{False}) indicate if parse action should be run during lookaheads and alternate testing - - Note: the default parsing behavior is to expand tabs in the input string - before starting the parsing process. See L{I{parseString}<parseString>} for more information - on parsing strings containing C{<TAB>}s, and suggested methods to maintain a - consistent view of the parsed string, the parse location, and line and column - positions within the parsed string. - - Example:: - integer = Word(nums) - date_str = integer + '/' + integer + '/' + integer - - date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] - - # use parse action to convert to ints at parse time - integer = Word(nums).setParseAction(lambda toks: int(toks[0])) - date_str = integer + '/' + integer + '/' + integer - - # note that integer fields are now ints, not strings - date_str.parseString("1999/12/31") # -> [1999, '/', 12, '/', 31] - """ - self.parseAction = list(map(_trim_arity, list(fns))) - self.callDuringTry = kwargs.get("callDuringTry", False) - return self - - def addParseAction( self, *fns, **kwargs ): - """ - Add one or more parse actions to expression's list of parse actions. See L{I{setParseAction}<setParseAction>}. - - See examples in L{I{copy}<copy>}. - """ - self.parseAction += list(map(_trim_arity, list(fns))) - self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) - return self - - def addCondition(self, *fns, **kwargs): - """Add a boolean predicate function to expression's list of parse actions. See - L{I{setParseAction}<setParseAction>} for function call signatures. Unlike C{setParseAction}, - functions passed to C{addCondition} need to return boolean success/fail of the condition. - - Optional keyword arguments: - - message = define a custom message to be used in the raised exception - - fatal = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException - - Example:: - integer = Word(nums).setParseAction(lambda toks: int(toks[0])) - year_int = integer.copy() - year_int.addCondition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later") - date_str = year_int + '/' + integer + '/' + integer - - result = date_str.parseString("1999/12/31") # -> Exception: Only support years 2000 and later (at char 0), (line:1, col:1) - """ - msg = kwargs.get("message", "failed user-defined condition") - exc_type = ParseFatalException if kwargs.get("fatal", False) else ParseException - for fn in fns: - def pa(s,l,t): - if not bool(_trim_arity(fn)(s,l,t)): - raise exc_type(s,l,msg) - self.parseAction.append(pa) - self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) - return self - - def setFailAction( self, fn ): - """Define action to perform if parsing fails at this expression. - Fail acton fn is a callable function that takes the arguments - C{fn(s,loc,expr,err)} where: - - s = string being parsed - - loc = location where expression match was attempted and failed - - expr = the parse expression that failed - - err = the exception thrown - The function returns no value. It may throw C{L{ParseFatalException}} - if it is desired to stop parsing immediately.""" - self.failAction = fn - return self - - def _skipIgnorables( self, instring, loc ): - exprsFound = True - while exprsFound: - exprsFound = False - for e in self.ignoreExprs: - try: - while 1: - loc,dummy = e._parse( instring, loc ) - exprsFound = True - except ParseException: - pass - return loc - - def preParse( self, instring, loc ): - if self.ignoreExprs: - loc = self._skipIgnorables( instring, loc ) - - if self.skipWhitespace: - wt = self.whiteChars - instrlen = len(instring) - while loc < instrlen and instring[loc] in wt: - loc += 1 - - return loc - - def parseImpl( self, instring, loc, doActions=True ): - return loc, [] - - def postParse( self, instring, loc, tokenlist ): - return tokenlist - - #~ @profile - def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ): - debugging = ( self.debug ) #and doActions ) - - if debugging or self.failAction: - #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )) - if (self.debugActions[0] ): - self.debugActions[0]( instring, loc, self ) - if callPreParse and self.callPreparse: - preloc = self.preParse( instring, loc ) - else: - preloc = loc - tokensStart = preloc - try: - try: - loc,tokens = self.parseImpl( instring, preloc, doActions ) - except IndexError: - raise ParseException( instring, len(instring), self.errmsg, self ) - except ParseBaseException as err: - #~ print ("Exception raised:", err) - if self.debugActions[2]: - self.debugActions[2]( instring, tokensStart, self, err ) - if self.failAction: - self.failAction( instring, tokensStart, self, err ) - raise - else: - if callPreParse and self.callPreparse: - preloc = self.preParse( instring, loc ) - else: - preloc = loc - tokensStart = preloc - if self.mayIndexError or preloc >= len(instring): - try: - loc,tokens = self.parseImpl( instring, preloc, doActions ) - except IndexError: - raise ParseException( instring, len(instring), self.errmsg, self ) - else: - loc,tokens = self.parseImpl( instring, preloc, doActions ) - - tokens = self.postParse( instring, loc, tokens ) - - retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults ) - if self.parseAction and (doActions or self.callDuringTry): - if debugging: - try: - for fn in self.parseAction: - tokens = fn( instring, tokensStart, retTokens ) - if tokens is not None: - retTokens = ParseResults( tokens, - self.resultsName, - asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), - modal=self.modalResults ) - except ParseBaseException as err: - #~ print "Exception raised in user parse action:", err - if (self.debugActions[2] ): - self.debugActions[2]( instring, tokensStart, self, err ) - raise - else: - for fn in self.parseAction: - tokens = fn( instring, tokensStart, retTokens ) - if tokens is not None: - retTokens = ParseResults( tokens, - self.resultsName, - asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), - modal=self.modalResults ) - if debugging: - #~ print ("Matched",self,"->",retTokens.asList()) - if (self.debugActions[1] ): - self.debugActions[1]( instring, tokensStart, loc, self, retTokens ) - - return loc, retTokens - - def tryParse( self, instring, loc ): - try: - return self._parse( instring, loc, doActions=False )[0] - except ParseFatalException: - raise ParseException( instring, loc, self.errmsg, self) - - def canParseNext(self, instring, loc): - try: - self.tryParse(instring, loc) - except (ParseException, IndexError): - return False - else: - return True - - class _UnboundedCache(object): - def __init__(self): - cache = {} - self.not_in_cache = not_in_cache = object() - - def get(self, key): - return cache.get(key, not_in_cache) - - def set(self, key, value): - cache[key] = value - - def clear(self): - cache.clear() - - def cache_len(self): - return len(cache) - - self.get = types.MethodType(get, self) - self.set = types.MethodType(set, self) - self.clear = types.MethodType(clear, self) - self.__len__ = types.MethodType(cache_len, self) - - if _OrderedDict is not None: - class _FifoCache(object): - def __init__(self, size): - self.not_in_cache = not_in_cache = object() - - cache = _OrderedDict() - - def get(self, key): - return cache.get(key, not_in_cache) - - def set(self, key, value): - cache[key] = value - while len(cache) > size: - try: - cache.popitem(False) - except KeyError: - pass - - def clear(self): - cache.clear() - - def cache_len(self): - return len(cache) - - self.get = types.MethodType(get, self) - self.set = types.MethodType(set, self) - self.clear = types.MethodType(clear, self) - self.__len__ = types.MethodType(cache_len, self) - - else: - class _FifoCache(object): - def __init__(self, size): - self.not_in_cache = not_in_cache = object() - - cache = {} - key_fifo = collections.deque([], size) - - def get(self, key): - return cache.get(key, not_in_cache) - - def set(self, key, value): - cache[key] = value - while len(key_fifo) > size: - cache.pop(key_fifo.popleft(), None) - key_fifo.append(key) - - def clear(self): - cache.clear() - key_fifo.clear() - - def cache_len(self): - return len(cache) - - self.get = types.MethodType(get, self) - self.set = types.MethodType(set, self) - self.clear = types.MethodType(clear, self) - self.__len__ = types.MethodType(cache_len, self) - - # argument cache for optimizing repeated calls when backtracking through recursive expressions - packrat_cache = {} # this is set later by enabledPackrat(); this is here so that resetCache() doesn't fail - packrat_cache_lock = RLock() - packrat_cache_stats = [0, 0] - - # this method gets repeatedly called during backtracking with the same arguments - - # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression - def _parseCache( self, instring, loc, doActions=True, callPreParse=True ): - HIT, MISS = 0, 1 - lookup = (self, instring, loc, callPreParse, doActions) - with ParserElement.packrat_cache_lock: - cache = ParserElement.packrat_cache - value = cache.get(lookup) - if value is cache.not_in_cache: - ParserElement.packrat_cache_stats[MISS] += 1 - try: - value = self._parseNoCache(instring, loc, doActions, callPreParse) - except ParseBaseException as pe: - # cache a copy of the exception, without the traceback - cache.set(lookup, pe.__class__(*pe.args)) - raise - else: - cache.set(lookup, (value[0], value[1].copy())) - return value - else: - ParserElement.packrat_cache_stats[HIT] += 1 - if isinstance(value, Exception): - raise value - return (value[0], value[1].copy()) - - _parse = _parseNoCache - - @staticmethod - def resetCache(): - ParserElement.packrat_cache.clear() - ParserElement.packrat_cache_stats[:] = [0] * len(ParserElement.packrat_cache_stats) - - _packratEnabled = False - @staticmethod - def enablePackrat(cache_size_limit=128): - """Enables "packrat" parsing, which adds memoizing to the parsing logic. - Repeated parse attempts at the same string location (which happens - often in many complex grammars) can immediately return a cached value, - instead of re-executing parsing/validating code. Memoizing is done of - both valid results and parsing exceptions. - - Parameters: - - cache_size_limit - (default=C{128}) - if an integer value is provided - will limit the size of the packrat cache; if None is passed, then - the cache size will be unbounded; if 0 is passed, the cache will - be effectively disabled. - - This speedup may break existing programs that use parse actions that - have side-effects. For this reason, packrat parsing is disabled when - you first import pyparsing. To activate the packrat feature, your - program must call the class method C{ParserElement.enablePackrat()}. If - your program uses C{psyco} to "compile as you go", you must call - C{enablePackrat} before calling C{psyco.full()}. If you do not do this, - Python will crash. For best results, call C{enablePackrat()} immediately - after importing pyparsing. - - Example:: - import pyparsing - pyparsing.ParserElement.enablePackrat() - """ - if not ParserElement._packratEnabled: - ParserElement._packratEnabled = True - if cache_size_limit is None: - ParserElement.packrat_cache = ParserElement._UnboundedCache() - else: - ParserElement.packrat_cache = ParserElement._FifoCache(cache_size_limit) - ParserElement._parse = ParserElement._parseCache - - def parseString( self, instring, parseAll=False ): - """ - Execute the parse expression with the given string. - This is the main interface to the client code, once the complete - expression has been built. - - If you want the grammar to require that the entire input string be - successfully parsed, then set C{parseAll} to True (equivalent to ending - the grammar with C{L{StringEnd()}}). - - Note: C{parseString} implicitly calls C{expandtabs()} on the input string, - in order to report proper column numbers in parse actions. - If the input string contains tabs and - the grammar uses parse actions that use the C{loc} argument to index into the - string being parsed, you can ensure you have a consistent view of the input - string by: - - calling C{parseWithTabs} on your grammar before calling C{parseString} - (see L{I{parseWithTabs}<parseWithTabs>}) - - define your parse action using the full C{(s,loc,toks)} signature, and - reference the input string using the parse action's C{s} argument - - explictly expand the tabs in your input string before calling - C{parseString} - - Example:: - Word('a').parseString('aaaaabaaa') # -> ['aaaaa'] - Word('a').parseString('aaaaabaaa', parseAll=True) # -> Exception: Expected end of text - """ - ParserElement.resetCache() - if not self.streamlined: - self.streamline() - #~ self.saveAsList = True - for e in self.ignoreExprs: - e.streamline() - if not self.keepTabs: - instring = instring.expandtabs() - try: - loc, tokens = self._parse( instring, 0 ) - if parseAll: - loc = self.preParse( instring, loc ) - se = Empty() + StringEnd() - se._parse( instring, loc ) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - else: - return tokens - - def scanString( self, instring, maxMatches=_MAX_INT, overlap=False ): - """ - Scan the input string for expression matches. Each match will return the - matching tokens, start location, and end location. May be called with optional - C{maxMatches} argument, to clip scanning after 'n' matches are found. If - C{overlap} is specified, then overlapping matches will be reported. - - Note that the start and end locations are reported relative to the string - being parsed. See L{I{parseString}<parseString>} for more information on parsing - strings with embedded tabs. - - Example:: - source = "sldjf123lsdjjkf345sldkjf879lkjsfd987" - print(source) - for tokens,start,end in Word(alphas).scanString(source): - print(' '*start + '^'*(end-start)) - print(' '*start + tokens[0]) - - prints:: - - sldjf123lsdjjkf345sldkjf879lkjsfd987 - ^^^^^ - sldjf - ^^^^^^^ - lsdjjkf - ^^^^^^ - sldkjf - ^^^^^^ - lkjsfd - """ - if not self.streamlined: - self.streamline() - for e in self.ignoreExprs: - e.streamline() - - if not self.keepTabs: - instring = _ustr(instring).expandtabs() - instrlen = len(instring) - loc = 0 - preparseFn = self.preParse - parseFn = self._parse - ParserElement.resetCache() - matches = 0 - try: - while loc <= instrlen and matches < maxMatches: - try: - preloc = preparseFn( instring, loc ) - nextLoc,tokens = parseFn( instring, preloc, callPreParse=False ) - except ParseException: - loc = preloc+1 - else: - if nextLoc > loc: - matches += 1 - yield tokens, preloc, nextLoc - if overlap: - nextloc = preparseFn( instring, loc ) - if nextloc > loc: - loc = nextLoc - else: - loc += 1 - else: - loc = nextLoc - else: - loc = preloc+1 - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - - def transformString( self, instring ): - """ - Extension to C{L{scanString}}, to modify matching text with modified tokens that may - be returned from a parse action. To use C{transformString}, define a grammar and - attach a parse action to it that modifies the returned token list. - Invoking C{transformString()} on a target string will then scan for matches, - and replace the matched text patterns according to the logic in the parse - action. C{transformString()} returns the resulting transformed string. - - Example:: - wd = Word(alphas) - wd.setParseAction(lambda toks: toks[0].title()) - - print(wd.transformString("now is the winter of our discontent made glorious summer by this sun of york.")) - Prints:: - Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York. - """ - out = [] - lastE = 0 - # force preservation of <TAB>s, to minimize unwanted transformation of string, and to - # keep string locs straight between transformString and scanString - self.keepTabs = True - try: - for t,s,e in self.scanString( instring ): - out.append( instring[lastE:s] ) - if t: - if isinstance(t,ParseResults): - out += t.asList() - elif isinstance(t,list): - out += t - else: - out.append(t) - lastE = e - out.append(instring[lastE:]) - out = [o for o in out if o] - return "".join(map(_ustr,_flatten(out))) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - - def searchString( self, instring, maxMatches=_MAX_INT ): - """ - Another extension to C{L{scanString}}, simplifying the access to the tokens found - to match the given parse expression. May be called with optional - C{maxMatches} argument, to clip searching after 'n' matches are found. - - Example:: - # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters - cap_word = Word(alphas.upper(), alphas.lower()) - - print(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity")) - - # the sum() builtin can be used to merge results into a single ParseResults object - print(sum(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity"))) - prints:: - [['More'], ['Iron'], ['Lead'], ['Gold'], ['I'], ['Electricity']] - ['More', 'Iron', 'Lead', 'Gold', 'I', 'Electricity'] - """ - try: - return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ]) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - - def split(self, instring, maxsplit=_MAX_INT, includeSeparators=False): - """ - Generator method to split a string using the given expression as a separator. - May be called with optional C{maxsplit} argument, to limit the number of splits; - and the optional C{includeSeparators} argument (default=C{False}), if the separating - matching text should be included in the split results. - - Example:: - punc = oneOf(list(".,;:/-!?")) - print(list(punc.split("This, this?, this sentence, is badly punctuated!"))) - prints:: - ['This', ' this', '', ' this sentence', ' is badly punctuated', ''] - """ - splits = 0 - last = 0 - for t,s,e in self.scanString(instring, maxMatches=maxsplit): - yield instring[last:s] - if includeSeparators: - yield t[0] - last = e - yield instring[last:] - - def __add__(self, other ): - """ - Implementation of + operator - returns C{L{And}}. Adding strings to a ParserElement - converts them to L{Literal}s by default. - - Example:: - greet = Word(alphas) + "," + Word(alphas) + "!" - hello = "Hello, World!" - print (hello, "->", greet.parseString(hello)) - Prints:: - Hello, World! -> ['Hello', ',', 'World', '!'] - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return And( [ self, other ] ) - - def __radd__(self, other ): - """ - Implementation of + operator when left operand is not a C{L{ParserElement}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other + self - - def __sub__(self, other): - """ - Implementation of - operator, returns C{L{And}} with error stop - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return self + And._ErrorStop() + other - - def __rsub__(self, other ): - """ - Implementation of - operator when left operand is not a C{L{ParserElement}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other - self - - def __mul__(self,other): - """ - Implementation of * operator, allows use of C{expr * 3} in place of - C{expr + expr + expr}. Expressions may also me multiplied by a 2-integer - tuple, similar to C{{min,max}} multipliers in regular expressions. Tuples - may also include C{None} as in: - - C{expr*(n,None)} or C{expr*(n,)} is equivalent - to C{expr*n + L{ZeroOrMore}(expr)} - (read as "at least n instances of C{expr}") - - C{expr*(None,n)} is equivalent to C{expr*(0,n)} - (read as "0 to n instances of C{expr}") - - C{expr*(None,None)} is equivalent to C{L{ZeroOrMore}(expr)} - - C{expr*(1,None)} is equivalent to C{L{OneOrMore}(expr)} - - Note that C{expr*(None,n)} does not raise an exception if - more than n exprs exist in the input stream; that is, - C{expr*(None,n)} does not enforce a maximum number of expr - occurrences. If this behavior is desired, then write - C{expr*(None,n) + ~expr} - """ - if isinstance(other,int): - minElements, optElements = other,0 - elif isinstance(other,tuple): - other = (other + (None, None))[:2] - if other[0] is None: - other = (0, other[1]) - if isinstance(other[0],int) and other[1] is None: - if other[0] == 0: - return ZeroOrMore(self) - if other[0] == 1: - return OneOrMore(self) - else: - return self*other[0] + ZeroOrMore(self) - elif isinstance(other[0],int) and isinstance(other[1],int): - minElements, optElements = other - optElements -= minElements - else: - raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1])) - else: - raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other)) - - if minElements < 0: - raise ValueError("cannot multiply ParserElement by negative value") - if optElements < 0: - raise ValueError("second tuple value must be greater or equal to first tuple value") - if minElements == optElements == 0: - raise ValueError("cannot multiply ParserElement by 0 or (0,0)") - - if (optElements): - def makeOptionalList(n): - if n>1: - return Optional(self + makeOptionalList(n-1)) - else: - return Optional(self) - if minElements: - if minElements == 1: - ret = self + makeOptionalList(optElements) - else: - ret = And([self]*minElements) + makeOptionalList(optElements) - else: - ret = makeOptionalList(optElements) - else: - if minElements == 1: - ret = self - else: - ret = And([self]*minElements) - return ret - - def __rmul__(self, other): - return self.__mul__(other) - - def __or__(self, other ): - """ - Implementation of | operator - returns C{L{MatchFirst}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return MatchFirst( [ self, other ] ) - - def __ror__(self, other ): - """ - Implementation of | operator when left operand is not a C{L{ParserElement}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other | self - - def __xor__(self, other ): - """ - Implementation of ^ operator - returns C{L{Or}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return Or( [ self, other ] ) - - def __rxor__(self, other ): - """ - Implementation of ^ operator when left operand is not a C{L{ParserElement}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other ^ self - - def __and__(self, other ): - """ - Implementation of & operator - returns C{L{Each}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return Each( [ self, other ] ) - - def __rand__(self, other ): - """ - Implementation of & operator when left operand is not a C{L{ParserElement}} - """ - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - if not isinstance( other, ParserElement ): - warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), - SyntaxWarning, stacklevel=2) - return None - return other & self - - def __invert__( self ): - """ - Implementation of ~ operator - returns C{L{NotAny}} - """ - return NotAny( self ) - - def __call__(self, name=None): - """ - Shortcut for C{L{setResultsName}}, with C{listAllMatches=False}. - - If C{name} is given with a trailing C{'*'} character, then C{listAllMatches} will be - passed as C{True}. - - If C{name} is omitted, same as calling C{L{copy}}. - - Example:: - # these are equivalent - userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno") - userdata = Word(alphas)("name") + Word(nums+"-")("socsecno") - """ - if name is not None: - return self.setResultsName(name) - else: - return self.copy() - - def suppress( self ): - """ - Suppresses the output of this C{ParserElement}; useful to keep punctuation from - cluttering up returned output. - """ - return Suppress( self ) - - def leaveWhitespace( self ): - """ - Disables the skipping of whitespace before matching the characters in the - C{ParserElement}'s defined pattern. This is normally only used internally by - the pyparsing module, but may be needed in some whitespace-sensitive grammars. - """ - self.skipWhitespace = False - return self - - def setWhitespaceChars( self, chars ): - """ - Overrides the default whitespace chars - """ - self.skipWhitespace = True - self.whiteChars = chars - self.copyDefaultWhiteChars = False - return self - - def parseWithTabs( self ): - """ - Overrides default behavior to expand C{<TAB>}s to spaces before parsing the input string. - Must be called before C{parseString} when the input grammar contains elements that - match C{<TAB>} characters. - """ - self.keepTabs = True - return self - - def ignore( self, other ): - """ - Define expression to be ignored (e.g., comments) while doing pattern - matching; may be called repeatedly, to define multiple comment or other - ignorable patterns. - - Example:: - patt = OneOrMore(Word(alphas)) - patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj'] - - patt.ignore(cStyleComment) - patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd'] - """ - if isinstance(other, basestring): - other = Suppress(other) - - if isinstance( other, Suppress ): - if other not in self.ignoreExprs: - self.ignoreExprs.append(other) - else: - self.ignoreExprs.append( Suppress( other.copy() ) ) - return self - - def setDebugActions( self, startAction, successAction, exceptionAction ): - """ - Enable display of debugging messages while doing pattern matching. - """ - self.debugActions = (startAction or _defaultStartDebugAction, - successAction or _defaultSuccessDebugAction, - exceptionAction or _defaultExceptionDebugAction) - self.debug = True - return self - - def setDebug( self, flag=True ): - """ - Enable display of debugging messages while doing pattern matching. - Set C{flag} to True to enable, False to disable. - - Example:: - wd = Word(alphas).setName("alphaword") - integer = Word(nums).setName("numword") - term = wd | integer - - # turn on debugging for wd - wd.setDebug() - - OneOrMore(term).parseString("abc 123 xyz 890") - - prints:: - Match alphaword at loc 0(1,1) - Matched alphaword -> ['abc'] - Match alphaword at loc 3(1,4) - Exception raised:Expected alphaword (at char 4), (line:1, col:5) - Match alphaword at loc 7(1,8) - Matched alphaword -> ['xyz'] - Match alphaword at loc 11(1,12) - Exception raised:Expected alphaword (at char 12), (line:1, col:13) - Match alphaword at loc 15(1,16) - Exception raised:Expected alphaword (at char 15), (line:1, col:16) - - The output shown is that produced by the default debug actions - custom debug actions can be - specified using L{setDebugActions}. Prior to attempting - to match the C{wd} expression, the debugging message C{"Match <exprname> at loc <n>(<line>,<col>)"} - is shown. Then if the parse succeeds, a C{"Matched"} message is shown, or an C{"Exception raised"} - message is shown. Also note the use of L{setName} to assign a human-readable name to the expression, - which makes debugging and exception messages easier to understand - for instance, the default - name created for the C{Word} expression without calling C{setName} is C{"W:(ABCD...)"}. - """ - if flag: - self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction ) - else: - self.debug = False - return self - - def __str__( self ): - return self.name - - def __repr__( self ): - return _ustr(self) - - def streamline( self ): - self.streamlined = True - self.strRepr = None - return self - - def checkRecursion( self, parseElementList ): - pass - - def validate( self, validateTrace=[] ): - """ - Check defined expressions for valid structure, check for infinite recursive definitions. - """ - self.checkRecursion( [] ) - - def parseFile( self, file_or_filename, parseAll=False ): - """ - Execute the parse expression on the given file or filename. - If a filename is specified (instead of a file object), - the entire file is opened, read, and closed before parsing. - """ - try: - file_contents = file_or_filename.read() - except AttributeError: - with open(file_or_filename, "r") as f: - file_contents = f.read() - try: - return self.parseString(file_contents, parseAll) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc - - def __eq__(self,other): - if isinstance(other, ParserElement): - return self is other or vars(self) == vars(other) - elif isinstance(other, basestring): - return self.matches(other) - else: - return super(ParserElement,self)==other - - def __ne__(self,other): - return not (self == other) - - def __hash__(self): - return hash(id(self)) - - def __req__(self,other): - return self == other - - def __rne__(self,other): - return not (self == other) - - def matches(self, testString, parseAll=True): - """ - Method for quick testing of a parser against a test string. Good for simple - inline microtests of sub expressions while building up larger parser. - - Parameters: - - testString - to test against this expression for a match - - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests - - Example:: - expr = Word(nums) - assert expr.matches("100") - """ - try: - self.parseString(_ustr(testString), parseAll=parseAll) - return True - except ParseBaseException: - return False - - def runTests(self, tests, parseAll=True, comment='#', fullDump=True, printResults=True, failureTests=False): - """ - Execute the parse expression on a series of test strings, showing each - test, the parsed results or where the parse failed. Quick and easy way to - run a parse expression against a list of sample strings. - - Parameters: - - tests - a list of separate test strings, or a multiline string of test strings - - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests - - comment - (default=C{'#'}) - expression for indicating embedded comments in the test - string; pass None to disable comment filtering - - fullDump - (default=C{True}) - dump results as list followed by results names in nested outline; - if False, only dump nested list - - printResults - (default=C{True}) prints test output to stdout - - failureTests - (default=C{False}) indicates if these tests are expected to fail parsing - - Returns: a (success, results) tuple, where success indicates that all tests succeeded - (or failed if C{failureTests} is True), and the results contain a list of lines of each - test's output - - Example:: - number_expr = pyparsing_common.number.copy() - - result = number_expr.runTests(''' - # unsigned integer - 100 - # negative integer - -100 - # float with scientific notation - 6.02e23 - # integer with scientific notation - 1e-12 - ''') - print("Success" if result[0] else "Failed!") - - result = number_expr.runTests(''' - # stray character - 100Z - # missing leading digit before '.' - -.100 - # too many '.' - 3.14.159 - ''', failureTests=True) - print("Success" if result[0] else "Failed!") - prints:: - # unsigned integer - 100 - [100] - - # negative integer - -100 - [-100] - - # float with scientific notation - 6.02e23 - [6.02e+23] - - # integer with scientific notation - 1e-12 - [1e-12] - - Success - - # stray character - 100Z - ^ - FAIL: Expected end of text (at char 3), (line:1, col:4) - - # missing leading digit before '.' - -.100 - ^ - FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1) - - # too many '.' - 3.14.159 - ^ - FAIL: Expected end of text (at char 4), (line:1, col:5) - - Success - - Each test string must be on a single line. If you want to test a string that spans multiple - lines, create a test like this:: - - expr.runTest(r"this is a test\\n of strings that spans \\n 3 lines") - - (Note that this is a raw string literal, you must include the leading 'r'.) - """ - if isinstance(tests, basestring): - tests = list(map(str.strip, tests.rstrip().splitlines())) - if isinstance(comment, basestring): - comment = Literal(comment) - allResults = [] - comments = [] - success = True - for t in tests: - if comment is not None and comment.matches(t, False) or comments and not t: - comments.append(t) - continue - if not t: - continue - out = ['\n'.join(comments), t] - comments = [] - try: - t = t.replace(r'\n','\n') - result = self.parseString(t, parseAll=parseAll) - out.append(result.dump(full=fullDump)) - success = success and not failureTests - except ParseBaseException as pe: - fatal = "(FATAL)" if isinstance(pe, ParseFatalException) else "" - if '\n' in t: - out.append(line(pe.loc, t)) - out.append(' '*(col(pe.loc,t)-1) + '^' + fatal) - else: - out.append(' '*pe.loc + '^' + fatal) - out.append("FAIL: " + str(pe)) - success = success and failureTests - result = pe - except Exception as exc: - out.append("FAIL-EXCEPTION: " + str(exc)) - success = success and failureTests - result = exc - - if printResults: - if fullDump: - out.append('') - print('\n'.join(out)) - - allResults.append((t, result)) - - return success, allResults - - -class Token(ParserElement): - """ - Abstract C{ParserElement} subclass, for defining atomic matching patterns. - """ - def __init__( self ): - super(Token,self).__init__( savelist=False ) - - -class Empty(Token): - """ - An empty token, will always match. - """ - def __init__( self ): - super(Empty,self).__init__() - self.name = "Empty" - self.mayReturnEmpty = True - self.mayIndexError = False - - -class NoMatch(Token): - """ - A token that will never match. - """ - def __init__( self ): - super(NoMatch,self).__init__() - self.name = "NoMatch" - self.mayReturnEmpty = True - self.mayIndexError = False - self.errmsg = "Unmatchable token" - - def parseImpl( self, instring, loc, doActions=True ): - raise ParseException(instring, loc, self.errmsg, self) - - -class Literal(Token): - """ - Token to exactly match a specified string. - - Example:: - Literal('blah').parseString('blah') # -> ['blah'] - Literal('blah').parseString('blahfooblah') # -> ['blah'] - Literal('blah').parseString('bla') # -> Exception: Expected "blah" - - For case-insensitive matching, use L{CaselessLiteral}. - - For keyword matching (force word break before and after the matched string), - use L{Keyword} or L{CaselessKeyword}. - """ - def __init__( self, matchString ): - super(Literal,self).__init__() - self.match = matchString - self.matchLen = len(matchString) - try: - self.firstMatchChar = matchString[0] - except IndexError: - warnings.warn("null string passed to Literal; use Empty() instead", - SyntaxWarning, stacklevel=2) - self.__class__ = Empty - self.name = '"%s"' % _ustr(self.match) - self.errmsg = "Expected " + self.name - self.mayReturnEmpty = False - self.mayIndexError = False - - # Performance tuning: this routine gets called a *lot* - # if this is a single character match string and the first character matches, - # short-circuit as quickly as possible, and avoid calling startswith - #~ @profile - def parseImpl( self, instring, loc, doActions=True ): - if (instring[loc] == self.firstMatchChar and - (self.matchLen==1 or instring.startswith(self.match,loc)) ): - return loc+self.matchLen, self.match - raise ParseException(instring, loc, self.errmsg, self) -_L = Literal -ParserElement._literalStringClass = Literal - -class Keyword(Token): - """ - Token to exactly match a specified string as a keyword, that is, it must be - immediately followed by a non-keyword character. Compare with C{L{Literal}}: - - C{Literal("if")} will match the leading C{'if'} in C{'ifAndOnlyIf'}. - - C{Keyword("if")} will not; it will only match the leading C{'if'} in C{'if x=1'}, or C{'if(y==2)'} - Accepts two optional constructor arguments in addition to the keyword string: - - C{identChars} is a string of characters that would be valid identifier characters, - defaulting to all alphanumerics + "_" and "$" - - C{caseless} allows case-insensitive matching, default is C{False}. - - Example:: - Keyword("start").parseString("start") # -> ['start'] - Keyword("start").parseString("starting") # -> Exception - - For case-insensitive matching, use L{CaselessKeyword}. - """ - DEFAULT_KEYWORD_CHARS = alphanums+"_$" - - def __init__( self, matchString, identChars=None, caseless=False ): - super(Keyword,self).__init__() - if identChars is None: - identChars = Keyword.DEFAULT_KEYWORD_CHARS - self.match = matchString - self.matchLen = len(matchString) - try: - self.firstMatchChar = matchString[0] - except IndexError: - warnings.warn("null string passed to Keyword; use Empty() instead", - SyntaxWarning, stacklevel=2) - self.name = '"%s"' % self.match - self.errmsg = "Expected " + self.name - self.mayReturnEmpty = False - self.mayIndexError = False - self.caseless = caseless - if caseless: - self.caselessmatch = matchString.upper() - identChars = identChars.upper() - self.identChars = set(identChars) - - def parseImpl( self, instring, loc, doActions=True ): - if self.caseless: - if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and - (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and - (loc == 0 or instring[loc-1].upper() not in self.identChars) ): - return loc+self.matchLen, self.match - else: - if (instring[loc] == self.firstMatchChar and - (self.matchLen==1 or instring.startswith(self.match,loc)) and - (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and - (loc == 0 or instring[loc-1] not in self.identChars) ): - return loc+self.matchLen, self.match - raise ParseException(instring, loc, self.errmsg, self) - - def copy(self): - c = super(Keyword,self).copy() - c.identChars = Keyword.DEFAULT_KEYWORD_CHARS - return c - - @staticmethod - def setDefaultKeywordChars( chars ): - """Overrides the default Keyword chars - """ - Keyword.DEFAULT_KEYWORD_CHARS = chars - -class CaselessLiteral(Literal): - """ - Token to match a specified string, ignoring case of letters. - Note: the matched results will always be in the case of the given - match string, NOT the case of the input text. - - Example:: - OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD'] - - (Contrast with example for L{CaselessKeyword}.) - """ - def __init__( self, matchString ): - super(CaselessLiteral,self).__init__( matchString.upper() ) - # Preserve the defining literal. - self.returnString = matchString - self.name = "'%s'" % self.returnString - self.errmsg = "Expected " + self.name - - def parseImpl( self, instring, loc, doActions=True ): - if instring[ loc:loc+self.matchLen ].upper() == self.match: - return loc+self.matchLen, self.returnString - raise ParseException(instring, loc, self.errmsg, self) - -class CaselessKeyword(Keyword): - """ - Caseless version of L{Keyword}. - - Example:: - OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD'] - - (Contrast with example for L{CaselessLiteral}.) - """ - def __init__( self, matchString, identChars=None ): - super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True ) - - def parseImpl( self, instring, loc, doActions=True ): - if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and - (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ): - return loc+self.matchLen, self.match - raise ParseException(instring, loc, self.errmsg, self) - -class CloseMatch(Token): - """ - A variation on L{Literal} which matches "close" matches, that is, - strings with at most 'n' mismatching characters. C{CloseMatch} takes parameters: - - C{match_string} - string to be matched - - C{maxMismatches} - (C{default=1}) maximum number of mismatches allowed to count as a match - - The results from a successful parse will contain the matched text from the input string and the following named results: - - C{mismatches} - a list of the positions within the match_string where mismatches were found - - C{original} - the original match_string used to compare against the input string - - If C{mismatches} is an empty list, then the match was an exact match. - - Example:: - patt = CloseMatch("ATCATCGAATGGA") - patt.parseString("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']}) - patt.parseString("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1) - - # exact match - patt.parseString("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']}) - - # close match allowing up to 2 mismatches - patt = CloseMatch("ATCATCGAATGGA", maxMismatches=2) - patt.parseString("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']}) - """ - def __init__(self, match_string, maxMismatches=1): - super(CloseMatch,self).__init__() - self.name = match_string - self.match_string = match_string - self.maxMismatches = maxMismatches - self.errmsg = "Expected %r (with up to %d mismatches)" % (self.match_string, self.maxMismatches) - self.mayIndexError = False - self.mayReturnEmpty = False - - def parseImpl( self, instring, loc, doActions=True ): - start = loc - instrlen = len(instring) - maxloc = start + len(self.match_string) - - if maxloc <= instrlen: - match_string = self.match_string - match_stringloc = 0 - mismatches = [] - maxMismatches = self.maxMismatches - - for match_stringloc,s_m in enumerate(zip(instring[loc:maxloc], self.match_string)): - src,mat = s_m - if src != mat: - mismatches.append(match_stringloc) - if len(mismatches) > maxMismatches: - break - else: - loc = match_stringloc + 1 - results = ParseResults([instring[start:loc]]) - results['original'] = self.match_string - results['mismatches'] = mismatches - return loc, results - - raise ParseException(instring, loc, self.errmsg, self) - - -class Word(Token): - """ - Token for matching words composed of allowed character sets. - Defined with string containing all allowed initial characters, - an optional string containing allowed body characters (if omitted, - defaults to the initial character set), and an optional minimum, - maximum, and/or exact length. The default value for C{min} is 1 (a - minimum value < 1 is not valid); the default values for C{max} and C{exact} - are 0, meaning no maximum or exact length restriction. An optional - C{excludeChars} parameter can list characters that might be found in - the input C{bodyChars} string; useful to define a word of all printables - except for one or two characters, for instance. - - L{srange} is useful for defining custom character set strings for defining - C{Word} expressions, using range notation from regular expression character sets. - - A common mistake is to use C{Word} to match a specific literal string, as in - C{Word("Address")}. Remember that C{Word} uses the string argument to define - I{sets} of matchable characters. This expression would match "Add", "AAA", - "dAred", or any other word made up of the characters 'A', 'd', 'r', 'e', and 's'. - To match an exact literal string, use L{Literal} or L{Keyword}. - - pyparsing includes helper strings for building Words: - - L{alphas} - - L{nums} - - L{alphanums} - - L{hexnums} - - L{alphas8bit} (alphabetic characters in ASCII range 128-255 - accented, tilded, umlauted, etc.) - - L{punc8bit} (non-alphabetic characters in ASCII range 128-255 - currency, symbols, superscripts, diacriticals, etc.) - - L{printables} (any non-whitespace character) - - Example:: - # a word composed of digits - integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9")) - - # a word with a leading capital, and zero or more lowercase - capital_word = Word(alphas.upper(), alphas.lower()) - - # hostnames are alphanumeric, with leading alpha, and '-' - hostname = Word(alphas, alphanums+'-') - - # roman numeral (not a strict parser, accepts invalid mix of characters) - roman = Word("IVXLCDM") - - # any string of non-whitespace characters, except for ',' - csv_value = Word(printables, excludeChars=",") - """ - def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0, asKeyword=False, excludeChars=None ): - super(Word,self).__init__() - if excludeChars: - initChars = ''.join(c for c in initChars if c not in excludeChars) - if bodyChars: - bodyChars = ''.join(c for c in bodyChars if c not in excludeChars) - self.initCharsOrig = initChars - self.initChars = set(initChars) - if bodyChars : - self.bodyCharsOrig = bodyChars - self.bodyChars = set(bodyChars) - else: - self.bodyCharsOrig = initChars - self.bodyChars = set(initChars) - - self.maxSpecified = max > 0 - - if min < 1: - raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted") - - self.minLen = min - - if max > 0: - self.maxLen = max - else: - self.maxLen = _MAX_INT - - if exact > 0: - self.maxLen = exact - self.minLen = exact - - self.name = _ustr(self) - self.errmsg = "Expected " + self.name - self.mayIndexError = False - self.asKeyword = asKeyword - - if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0): - if self.bodyCharsOrig == self.initCharsOrig: - self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig) - elif len(self.initCharsOrig) == 1: - self.reString = "%s[%s]*" % \ - (re.escape(self.initCharsOrig), - _escapeRegexRangeChars(self.bodyCharsOrig),) - else: - self.reString = "[%s][%s]*" % \ - (_escapeRegexRangeChars(self.initCharsOrig), - _escapeRegexRangeChars(self.bodyCharsOrig),) - if self.asKeyword: - self.reString = r"\b"+self.reString+r"\b" - try: - self.re = re.compile( self.reString ) - except Exception: - self.re = None - - def parseImpl( self, instring, loc, doActions=True ): - if self.re: - result = self.re.match(instring,loc) - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - return loc, result.group() - - if not(instring[ loc ] in self.initChars): - raise ParseException(instring, loc, self.errmsg, self) - - start = loc - loc += 1 - instrlen = len(instring) - bodychars = self.bodyChars - maxloc = start + self.maxLen - maxloc = min( maxloc, instrlen ) - while loc < maxloc and instring[loc] in bodychars: - loc += 1 - - throwException = False - if loc - start < self.minLen: - throwException = True - if self.maxSpecified and loc < instrlen and instring[loc] in bodychars: - throwException = True - if self.asKeyword: - if (start>0 and instring[start-1] in bodychars) or (loc<instrlen and instring[loc] in bodychars): - throwException = True - - if throwException: - raise ParseException(instring, loc, self.errmsg, self) - - return loc, instring[start:loc] - - def __str__( self ): - try: - return super(Word,self).__str__() - except Exception: - pass - - - if self.strRepr is None: - - def charsAsStr(s): - if len(s)>4: - return s[:4]+"..." - else: - return s - - if ( self.initCharsOrig != self.bodyCharsOrig ): - self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) ) - else: - self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig) - - return self.strRepr - - -class Regex(Token): - r""" - Token for matching strings that match a given regular expression. - Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module. - If the given regex contains named groups (defined using C{(?P<name>...)}), these will be preserved as - named parse results. - - Example:: - realnum = Regex(r"[+-]?\d+\.\d*") - date = Regex(r'(?P<year>\d{4})-(?P<month>\d\d?)-(?P<day>\d\d?)') - # ref: http://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression - roman = Regex(r"M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})") - """ - compiledREtype = type(re.compile("[A-Z]")) - def __init__( self, pattern, flags=0): - """The parameters C{pattern} and C{flags} are passed to the C{re.compile()} function as-is. See the Python C{re} module for an explanation of the acceptable patterns and flags.""" - super(Regex,self).__init__() - - if isinstance(pattern, basestring): - if not pattern: - warnings.warn("null string passed to Regex; use Empty() instead", - SyntaxWarning, stacklevel=2) - - self.pattern = pattern - self.flags = flags - - try: - self.re = re.compile(self.pattern, self.flags) - self.reString = self.pattern - except sre_constants.error: - warnings.warn("invalid pattern (%s) passed to Regex" % pattern, - SyntaxWarning, stacklevel=2) - raise - - elif isinstance(pattern, Regex.compiledREtype): - self.re = pattern - self.pattern = \ - self.reString = str(pattern) - self.flags = flags - - else: - raise ValueError("Regex may only be constructed with a string or a compiled RE object") - - self.name = _ustr(self) - self.errmsg = "Expected " + self.name - self.mayIndexError = False - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - result = self.re.match(instring,loc) - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - d = result.groupdict() - ret = ParseResults(result.group()) - if d: - for k in d: - ret[k] = d[k] - return loc,ret - - def __str__( self ): - try: - return super(Regex,self).__str__() - except Exception: - pass - - if self.strRepr is None: - self.strRepr = "Re:(%s)" % repr(self.pattern) - - return self.strRepr - - -class QuotedString(Token): - r""" - Token for matching strings that are delimited by quoting characters. - - Defined with the following parameters: - - quoteChar - string of one or more characters defining the quote delimiting string - - escChar - character to escape quotes, typically backslash (default=C{None}) - - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=C{None}) - - multiline - boolean indicating whether quotes can span multiple lines (default=C{False}) - - unquoteResults - boolean indicating whether the matched text should be unquoted (default=C{True}) - - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=C{None} => same as quoteChar) - - convertWhitespaceEscapes - convert escaped whitespace (C{'\t'}, C{'\n'}, etc.) to actual whitespace (default=C{True}) - - Example:: - qs = QuotedString('"') - print(qs.searchString('lsjdf "This is the quote" sldjf')) - complex_qs = QuotedString('{{', endQuoteChar='}}') - print(complex_qs.searchString('lsjdf {{This is the "quote"}} sldjf')) - sql_qs = QuotedString('"', escQuote='""') - print(sql_qs.searchString('lsjdf "This is the quote with ""embedded"" quotes" sldjf')) - prints:: - [['This is the quote']] - [['This is the "quote"']] - [['This is the quote with "embedded" quotes']] - """ - def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None, convertWhitespaceEscapes=True): - super(QuotedString,self).__init__() - - # remove white space from quote chars - wont work anyway - quoteChar = quoteChar.strip() - if not quoteChar: - warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) - raise SyntaxError() - - if endQuoteChar is None: - endQuoteChar = quoteChar - else: - endQuoteChar = endQuoteChar.strip() - if not endQuoteChar: - warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) - raise SyntaxError() - - self.quoteChar = quoteChar - self.quoteCharLen = len(quoteChar) - self.firstQuoteChar = quoteChar[0] - self.endQuoteChar = endQuoteChar - self.endQuoteCharLen = len(endQuoteChar) - self.escChar = escChar - self.escQuote = escQuote - self.unquoteResults = unquoteResults - self.convertWhitespaceEscapes = convertWhitespaceEscapes - - if multiline: - self.flags = re.MULTILINE | re.DOTALL - self.pattern = r'%s(?:[^%s%s]' % \ - ( re.escape(self.quoteChar), - _escapeRegexRangeChars(self.endQuoteChar[0]), - (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) - else: - self.flags = 0 - self.pattern = r'%s(?:[^%s\n\r%s]' % \ - ( re.escape(self.quoteChar), - _escapeRegexRangeChars(self.endQuoteChar[0]), - (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) - if len(self.endQuoteChar) > 1: - self.pattern += ( - '|(?:' + ')|(?:'.join("%s[^%s]" % (re.escape(self.endQuoteChar[:i]), - _escapeRegexRangeChars(self.endQuoteChar[i])) - for i in range(len(self.endQuoteChar)-1,0,-1)) + ')' - ) - if escQuote: - self.pattern += (r'|(?:%s)' % re.escape(escQuote)) - if escChar: - self.pattern += (r'|(?:%s.)' % re.escape(escChar)) - self.escCharReplacePattern = re.escape(self.escChar)+"(.)" - self.pattern += (r')*%s' % re.escape(self.endQuoteChar)) - - try: - self.re = re.compile(self.pattern, self.flags) - self.reString = self.pattern - except sre_constants.error: - warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern, - SyntaxWarning, stacklevel=2) - raise - - self.name = _ustr(self) - self.errmsg = "Expected " + self.name - self.mayIndexError = False - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - ret = result.group() - - if self.unquoteResults: - - # strip off quotes - ret = ret[self.quoteCharLen:-self.endQuoteCharLen] - - if isinstance(ret,basestring): - # replace escaped whitespace - if '\\' in ret and self.convertWhitespaceEscapes: - ws_map = { - r'\t' : '\t', - r'\n' : '\n', - r'\f' : '\f', - r'\r' : '\r', - } - for wslit,wschar in ws_map.items(): - ret = ret.replace(wslit, wschar) - - # replace escaped characters - if self.escChar: - ret = re.sub(self.escCharReplacePattern, r"\g<1>", ret) - - # replace escaped quotes - if self.escQuote: - ret = ret.replace(self.escQuote, self.endQuoteChar) - - return loc, ret - - def __str__( self ): - try: - return super(QuotedString,self).__str__() - except Exception: - pass - - if self.strRepr is None: - self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar) - - return self.strRepr - - -class CharsNotIn(Token): - """ - Token for matching words composed of characters I{not} in a given set (will - include whitespace in matched characters if not listed in the provided exclusion set - see example). - Defined with string containing all disallowed characters, and an optional - minimum, maximum, and/or exact length. The default value for C{min} is 1 (a - minimum value < 1 is not valid); the default values for C{max} and C{exact} - are 0, meaning no maximum or exact length restriction. - - Example:: - # define a comma-separated-value as anything that is not a ',' - csv_value = CharsNotIn(',') - print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213")) - prints:: - ['dkls', 'lsdkjf', 's12 34', '@!#', '213'] - """ - def __init__( self, notChars, min=1, max=0, exact=0 ): - super(CharsNotIn,self).__init__() - self.skipWhitespace = False - self.notChars = notChars - - if min < 1: - raise ValueError("cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted") - - self.minLen = min - - if max > 0: - self.maxLen = max - else: - self.maxLen = _MAX_INT - - if exact > 0: - self.maxLen = exact - self.minLen = exact - - self.name = _ustr(self) - self.errmsg = "Expected " + self.name - self.mayReturnEmpty = ( self.minLen == 0 ) - self.mayIndexError = False - - def parseImpl( self, instring, loc, doActions=True ): - if instring[loc] in self.notChars: - raise ParseException(instring, loc, self.errmsg, self) - - start = loc - loc += 1 - notchars = self.notChars - maxlen = min( start+self.maxLen, len(instring) ) - while loc < maxlen and \ - (instring[loc] not in notchars): - loc += 1 - - if loc - start < self.minLen: - raise ParseException(instring, loc, self.errmsg, self) - - return loc, instring[start:loc] - - def __str__( self ): - try: - return super(CharsNotIn, self).__str__() - except Exception: - pass - - if self.strRepr is None: - if len(self.notChars) > 4: - self.strRepr = "!W:(%s...)" % self.notChars[:4] - else: - self.strRepr = "!W:(%s)" % self.notChars - - return self.strRepr - -class White(Token): - """ - Special matching class for matching whitespace. Normally, whitespace is ignored - by pyparsing grammars. This class is included when some whitespace structures - are significant. Define with a string containing the whitespace characters to be - matched; default is C{" \\t\\r\\n"}. Also takes optional C{min}, C{max}, and C{exact} arguments, - as defined for the C{L{Word}} class. - """ - whiteStrs = { - " " : "<SPC>", - "\t": "<TAB>", - "\n": "<LF>", - "\r": "<CR>", - "\f": "<FF>", - } - def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0): - super(White,self).__init__() - self.matchWhite = ws - self.setWhitespaceChars( "".join(c for c in self.whiteChars if c not in self.matchWhite) ) - #~ self.leaveWhitespace() - self.name = ("".join(White.whiteStrs[c] for c in self.matchWhite)) - self.mayReturnEmpty = True - self.errmsg = "Expected " + self.name - - self.minLen = min - - if max > 0: - self.maxLen = max - else: - self.maxLen = _MAX_INT - - if exact > 0: - self.maxLen = exact - self.minLen = exact - - def parseImpl( self, instring, loc, doActions=True ): - if not(instring[ loc ] in self.matchWhite): - raise ParseException(instring, loc, self.errmsg, self) - start = loc - loc += 1 - maxloc = start + self.maxLen - maxloc = min( maxloc, len(instring) ) - while loc < maxloc and instring[loc] in self.matchWhite: - loc += 1 - - if loc - start < self.minLen: - raise ParseException(instring, loc, self.errmsg, self) - - return loc, instring[start:loc] - - -class _PositionToken(Token): - def __init__( self ): - super(_PositionToken,self).__init__() - self.name=self.__class__.__name__ - self.mayReturnEmpty = True - self.mayIndexError = False - -class GoToColumn(_PositionToken): - """ - Token to advance to a specific column of input text; useful for tabular report scraping. - """ - def __init__( self, colno ): - super(GoToColumn,self).__init__() - self.col = colno - - def preParse( self, instring, loc ): - if col(loc,instring) != self.col: - instrlen = len(instring) - if self.ignoreExprs: - loc = self._skipIgnorables( instring, loc ) - while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col : - loc += 1 - return loc - - def parseImpl( self, instring, loc, doActions=True ): - thiscol = col( loc, instring ) - if thiscol > self.col: - raise ParseException( instring, loc, "Text not in expected column", self ) - newloc = loc + self.col - thiscol - ret = instring[ loc: newloc ] - return newloc, ret - - -class LineStart(_PositionToken): - """ - Matches if current position is at the beginning of a line within the parse string - - Example:: - - test = '''\ - AAA this line - AAA and this line - AAA but not this one - B AAA and definitely not this one - ''' - - for t in (LineStart() + 'AAA' + restOfLine).searchString(test): - print(t) - - Prints:: - ['AAA', ' this line'] - ['AAA', ' and this line'] - - """ - def __init__( self ): - super(LineStart,self).__init__() - self.errmsg = "Expected start of line" - - def parseImpl( self, instring, loc, doActions=True ): - if col(loc, instring) == 1: - return loc, [] - raise ParseException(instring, loc, self.errmsg, self) - -class LineEnd(_PositionToken): - """ - Matches if current position is at the end of a line within the parse string - """ - def __init__( self ): - super(LineEnd,self).__init__() - self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") ) - self.errmsg = "Expected end of line" - - def parseImpl( self, instring, loc, doActions=True ): - if loc<len(instring): - if instring[loc] == "\n": - return loc+1, "\n" - else: - raise ParseException(instring, loc, self.errmsg, self) - elif loc == len(instring): - return loc+1, [] - else: - raise ParseException(instring, loc, self.errmsg, self) - -class StringStart(_PositionToken): - """ - Matches if current position is at the beginning of the parse string - """ - def __init__( self ): - super(StringStart,self).__init__() - self.errmsg = "Expected start of text" - - def parseImpl( self, instring, loc, doActions=True ): - if loc != 0: - # see if entire string up to here is just whitespace and ignoreables - if loc != self.preParse( instring, 0 ): - raise ParseException(instring, loc, self.errmsg, self) - return loc, [] - -class StringEnd(_PositionToken): - """ - Matches if current position is at the end of the parse string - """ - def __init__( self ): - super(StringEnd,self).__init__() - self.errmsg = "Expected end of text" - - def parseImpl( self, instring, loc, doActions=True ): - if loc < len(instring): - raise ParseException(instring, loc, self.errmsg, self) - elif loc == len(instring): - return loc+1, [] - elif loc > len(instring): - return loc, [] - else: - raise ParseException(instring, loc, self.errmsg, self) - -class WordStart(_PositionToken): - """ - Matches if the current position is at the beginning of a Word, and - is not preceded by any character in a given set of C{wordChars} - (default=C{printables}). To emulate the C{\b} behavior of regular expressions, - use C{WordStart(alphanums)}. C{WordStart} will also match at the beginning of - the string being parsed, or at the beginning of a line. - """ - def __init__(self, wordChars = printables): - super(WordStart,self).__init__() - self.wordChars = set(wordChars) - self.errmsg = "Not at the start of a word" - - def parseImpl(self, instring, loc, doActions=True ): - if loc != 0: - if (instring[loc-1] in self.wordChars or - instring[loc] not in self.wordChars): - raise ParseException(instring, loc, self.errmsg, self) - return loc, [] - -class WordEnd(_PositionToken): - """ - Matches if the current position is at the end of a Word, and - is not followed by any character in a given set of C{wordChars} - (default=C{printables}). To emulate the C{\b} behavior of regular expressions, - use C{WordEnd(alphanums)}. C{WordEnd} will also match at the end of - the string being parsed, or at the end of a line. - """ - def __init__(self, wordChars = printables): - super(WordEnd,self).__init__() - self.wordChars = set(wordChars) - self.skipWhitespace = False - self.errmsg = "Not at the end of a word" - - def parseImpl(self, instring, loc, doActions=True ): - instrlen = len(instring) - if instrlen>0 and loc<instrlen: - if (instring[loc] in self.wordChars or - instring[loc-1] not in self.wordChars): - raise ParseException(instring, loc, self.errmsg, self) - return loc, [] - - -class ParseExpression(ParserElement): - """ - Abstract subclass of ParserElement, for combining and post-processing parsed tokens. - """ - def __init__( self, exprs, savelist = False ): - super(ParseExpression,self).__init__(savelist) - if isinstance( exprs, _generatorType ): - exprs = list(exprs) - - if isinstance( exprs, basestring ): - self.exprs = [ ParserElement._literalStringClass( exprs ) ] - elif isinstance( exprs, Iterable ): - exprs = list(exprs) - # if sequence of strings provided, wrap with Literal - if all(isinstance(expr, basestring) for expr in exprs): - exprs = map(ParserElement._literalStringClass, exprs) - self.exprs = list(exprs) - else: - try: - self.exprs = list( exprs ) - except TypeError: - self.exprs = [ exprs ] - self.callPreparse = False - - def __getitem__( self, i ): - return self.exprs[i] - - def append( self, other ): - self.exprs.append( other ) - self.strRepr = None - return self - - def leaveWhitespace( self ): - """Extends C{leaveWhitespace} defined in base class, and also invokes C{leaveWhitespace} on - all contained expressions.""" - self.skipWhitespace = False - self.exprs = [ e.copy() for e in self.exprs ] - for e in self.exprs: - e.leaveWhitespace() - return self - - def ignore( self, other ): - if isinstance( other, Suppress ): - if other not in self.ignoreExprs: - super( ParseExpression, self).ignore( other ) - for e in self.exprs: - e.ignore( self.ignoreExprs[-1] ) - else: - super( ParseExpression, self).ignore( other ) - for e in self.exprs: - e.ignore( self.ignoreExprs[-1] ) - return self - - def __str__( self ): - try: - return super(ParseExpression,self).__str__() - except Exception: - pass - - if self.strRepr is None: - self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.exprs) ) - return self.strRepr - - def streamline( self ): - super(ParseExpression,self).streamline() - - for e in self.exprs: - e.streamline() - - # collapse nested And's of the form And( And( And( a,b), c), d) to And( a,b,c,d ) - # but only if there are no parse actions or resultsNames on the nested And's - # (likewise for Or's and MatchFirst's) - if ( len(self.exprs) == 2 ): - other = self.exprs[0] - if ( isinstance( other, self.__class__ ) and - not(other.parseAction) and - other.resultsName is None and - not other.debug ): - self.exprs = other.exprs[:] + [ self.exprs[1] ] - self.strRepr = None - self.mayReturnEmpty |= other.mayReturnEmpty - self.mayIndexError |= other.mayIndexError - - other = self.exprs[-1] - if ( isinstance( other, self.__class__ ) and - not(other.parseAction) and - other.resultsName is None and - not other.debug ): - self.exprs = self.exprs[:-1] + other.exprs[:] - self.strRepr = None - self.mayReturnEmpty |= other.mayReturnEmpty - self.mayIndexError |= other.mayIndexError - - self.errmsg = "Expected " + _ustr(self) - - return self - - def setResultsName( self, name, listAllMatches=False ): - ret = super(ParseExpression,self).setResultsName(name,listAllMatches) - return ret - - def validate( self, validateTrace=[] ): - tmp = validateTrace[:]+[self] - for e in self.exprs: - e.validate(tmp) - self.checkRecursion( [] ) - - def copy(self): - ret = super(ParseExpression,self).copy() - ret.exprs = [e.copy() for e in self.exprs] - return ret - -class And(ParseExpression): - """ - Requires all given C{ParseExpression}s to be found in the given order. - Expressions may be separated by whitespace. - May be constructed using the C{'+'} operator. - May also be constructed using the C{'-'} operator, which will suppress backtracking. - - Example:: - integer = Word(nums) - name_expr = OneOrMore(Word(alphas)) - - expr = And([integer("id"),name_expr("name"),integer("age")]) - # more easily written as: - expr = integer("id") + name_expr("name") + integer("age") - """ - - class _ErrorStop(Empty): - def __init__(self, *args, **kwargs): - super(And._ErrorStop,self).__init__(*args, **kwargs) - self.name = '-' - self.leaveWhitespace() - - def __init__( self, exprs, savelist = True ): - super(And,self).__init__(exprs, savelist) - self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) - self.setWhitespaceChars( self.exprs[0].whiteChars ) - self.skipWhitespace = self.exprs[0].skipWhitespace - self.callPreparse = True - - def parseImpl( self, instring, loc, doActions=True ): - # pass False as last arg to _parse for first element, since we already - # pre-parsed the string as part of our And pre-parsing - loc, resultlist = self.exprs[0]._parse( instring, loc, doActions, callPreParse=False ) - errorStop = False - for e in self.exprs[1:]: - if isinstance(e, And._ErrorStop): - errorStop = True - continue - if errorStop: - try: - loc, exprtokens = e._parse( instring, loc, doActions ) - except ParseSyntaxException: - raise - except ParseBaseException as pe: - pe.__traceback__ = None - raise ParseSyntaxException._from_exception(pe) - except IndexError: - raise ParseSyntaxException(instring, len(instring), self.errmsg, self) - else: - loc, exprtokens = e._parse( instring, loc, doActions ) - if exprtokens or exprtokens.haskeys(): - resultlist += exprtokens - return loc, resultlist - - def __iadd__(self, other ): - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - return self.append( other ) #And( [ self, other ] ) - - def checkRecursion( self, parseElementList ): - subRecCheckList = parseElementList[:] + [ self ] - for e in self.exprs: - e.checkRecursion( subRecCheckList ) - if not e.mayReturnEmpty: - break - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + " ".join(_ustr(e) for e in self.exprs) + "}" - - return self.strRepr - - -class Or(ParseExpression): - """ - Requires that at least one C{ParseExpression} is found. - If two expressions match, the expression that matches the longest string will be used. - May be constructed using the C{'^'} operator. - - Example:: - # construct Or using '^' operator - - number = Word(nums) ^ Combine(Word(nums) + '.' + Word(nums)) - print(number.searchString("123 3.1416 789")) - prints:: - [['123'], ['3.1416'], ['789']] - """ - def __init__( self, exprs, savelist = False ): - super(Or,self).__init__(exprs, savelist) - if self.exprs: - self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) - else: - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - maxExcLoc = -1 - maxException = None - matches = [] - for e in self.exprs: - try: - loc2 = e.tryParse( instring, loc ) - except ParseException as err: - err.__traceback__ = None - if err.loc > maxExcLoc: - maxException = err - maxExcLoc = err.loc - except IndexError: - if len(instring) > maxExcLoc: - maxException = ParseException(instring,len(instring),e.errmsg,self) - maxExcLoc = len(instring) - else: - # save match among all matches, to retry longest to shortest - matches.append((loc2, e)) - - if matches: - matches.sort(key=lambda x: -x[0]) - for _,e in matches: - try: - return e._parse( instring, loc, doActions ) - except ParseException as err: - err.__traceback__ = None - if err.loc > maxExcLoc: - maxException = err - maxExcLoc = err.loc - - if maxException is not None: - maxException.msg = self.errmsg - raise maxException - else: - raise ParseException(instring, loc, "no defined alternatives to match", self) - - - def __ixor__(self, other ): - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - return self.append( other ) #Or( [ self, other ] ) - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + " ^ ".join(_ustr(e) for e in self.exprs) + "}" - - return self.strRepr - - def checkRecursion( self, parseElementList ): - subRecCheckList = parseElementList[:] + [ self ] - for e in self.exprs: - e.checkRecursion( subRecCheckList ) - - -class MatchFirst(ParseExpression): - """ - Requires that at least one C{ParseExpression} is found. - If two expressions match, the first one listed is the one that will match. - May be constructed using the C{'|'} operator. - - Example:: - # construct MatchFirst using '|' operator - - # watch the order of expressions to match - number = Word(nums) | Combine(Word(nums) + '.' + Word(nums)) - print(number.searchString("123 3.1416 789")) # Fail! -> [['123'], ['3'], ['1416'], ['789']] - - # put more selective expression first - number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums) - print(number.searchString("123 3.1416 789")) # Better -> [['123'], ['3.1416'], ['789']] - """ - def __init__( self, exprs, savelist = False ): - super(MatchFirst,self).__init__(exprs, savelist) - if self.exprs: - self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) - else: - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - maxExcLoc = -1 - maxException = None - for e in self.exprs: - try: - ret = e._parse( instring, loc, doActions ) - return ret - except ParseException as err: - if err.loc > maxExcLoc: - maxException = err - maxExcLoc = err.loc - except IndexError: - if len(instring) > maxExcLoc: - maxException = ParseException(instring,len(instring),e.errmsg,self) - maxExcLoc = len(instring) - - # only got here if no expression matched, raise exception for match that made it the furthest - else: - if maxException is not None: - maxException.msg = self.errmsg - raise maxException - else: - raise ParseException(instring, loc, "no defined alternatives to match", self) - - def __ior__(self, other ): - if isinstance( other, basestring ): - other = ParserElement._literalStringClass( other ) - return self.append( other ) #MatchFirst( [ self, other ] ) - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + " | ".join(_ustr(e) for e in self.exprs) + "}" - - return self.strRepr - - def checkRecursion( self, parseElementList ): - subRecCheckList = parseElementList[:] + [ self ] - for e in self.exprs: - e.checkRecursion( subRecCheckList ) - - -class Each(ParseExpression): - """ - Requires all given C{ParseExpression}s to be found, but in any order. - Expressions may be separated by whitespace. - May be constructed using the C{'&'} operator. - - Example:: - color = oneOf("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN") - shape_type = oneOf("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON") - integer = Word(nums) - shape_attr = "shape:" + shape_type("shape") - posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn") - color_attr = "color:" + color("color") - size_attr = "size:" + integer("size") - - # use Each (using operator '&') to accept attributes in any order - # (shape and posn are required, color and size are optional) - shape_spec = shape_attr & posn_attr & Optional(color_attr) & Optional(size_attr) - - shape_spec.runTests(''' - shape: SQUARE color: BLACK posn: 100, 120 - shape: CIRCLE size: 50 color: BLUE posn: 50,80 - color:GREEN size:20 shape:TRIANGLE posn:20,40 - ''' - ) - prints:: - shape: SQUARE color: BLACK posn: 100, 120 - ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']] - - color: BLACK - - posn: ['100', ',', '120'] - - x: 100 - - y: 120 - - shape: SQUARE - - - shape: CIRCLE size: 50 color: BLUE posn: 50,80 - ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']] - - color: BLUE - - posn: ['50', ',', '80'] - - x: 50 - - y: 80 - - shape: CIRCLE - - size: 50 - - - color: GREEN size: 20 shape: TRIANGLE posn: 20,40 - ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']] - - color: GREEN - - posn: ['20', ',', '40'] - - x: 20 - - y: 40 - - shape: TRIANGLE - - size: 20 - """ - def __init__( self, exprs, savelist = True ): - super(Each,self).__init__(exprs, savelist) - self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) - self.skipWhitespace = True - self.initExprGroups = True - - def parseImpl( self, instring, loc, doActions=True ): - if self.initExprGroups: - self.opt1map = dict((id(e.expr),e) for e in self.exprs if isinstance(e,Optional)) - opt1 = [ e.expr for e in self.exprs if isinstance(e,Optional) ] - opt2 = [ e for e in self.exprs if e.mayReturnEmpty and not isinstance(e,Optional)] - self.optionals = opt1 + opt2 - self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ] - self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ] - self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ] - self.required += self.multirequired - self.initExprGroups = False - tmpLoc = loc - tmpReqd = self.required[:] - tmpOpt = self.optionals[:] - matchOrder = [] - - keepMatching = True - while keepMatching: - tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired - failed = [] - for e in tmpExprs: - try: - tmpLoc = e.tryParse( instring, tmpLoc ) - except ParseException: - failed.append(e) - else: - matchOrder.append(self.opt1map.get(id(e),e)) - if e in tmpReqd: - tmpReqd.remove(e) - elif e in tmpOpt: - tmpOpt.remove(e) - if len(failed) == len(tmpExprs): - keepMatching = False - - if tmpReqd: - missing = ", ".join(_ustr(e) for e in tmpReqd) - raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing ) - - # add any unmatched Optionals, in case they have default values defined - matchOrder += [e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt] - - resultlist = [] - for e in matchOrder: - loc,results = e._parse(instring,loc,doActions) - resultlist.append(results) - - finalResults = sum(resultlist, ParseResults([])) - return loc, finalResults - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + " & ".join(_ustr(e) for e in self.exprs) + "}" - - return self.strRepr - - def checkRecursion( self, parseElementList ): - subRecCheckList = parseElementList[:] + [ self ] - for e in self.exprs: - e.checkRecursion( subRecCheckList ) - - -class ParseElementEnhance(ParserElement): - """ - Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens. - """ - def __init__( self, expr, savelist=False ): - super(ParseElementEnhance,self).__init__(savelist) - if isinstance( expr, basestring ): - if issubclass(ParserElement._literalStringClass, Token): - expr = ParserElement._literalStringClass(expr) - else: - expr = ParserElement._literalStringClass(Literal(expr)) - self.expr = expr - self.strRepr = None - if expr is not None: - self.mayIndexError = expr.mayIndexError - self.mayReturnEmpty = expr.mayReturnEmpty - self.setWhitespaceChars( expr.whiteChars ) - self.skipWhitespace = expr.skipWhitespace - self.saveAsList = expr.saveAsList - self.callPreparse = expr.callPreparse - self.ignoreExprs.extend(expr.ignoreExprs) - - def parseImpl( self, instring, loc, doActions=True ): - if self.expr is not None: - return self.expr._parse( instring, loc, doActions, callPreParse=False ) - else: - raise ParseException("",loc,self.errmsg,self) - - def leaveWhitespace( self ): - self.skipWhitespace = False - self.expr = self.expr.copy() - if self.expr is not None: - self.expr.leaveWhitespace() - return self - - def ignore( self, other ): - if isinstance( other, Suppress ): - if other not in self.ignoreExprs: - super( ParseElementEnhance, self).ignore( other ) - if self.expr is not None: - self.expr.ignore( self.ignoreExprs[-1] ) - else: - super( ParseElementEnhance, self).ignore( other ) - if self.expr is not None: - self.expr.ignore( self.ignoreExprs[-1] ) - return self - - def streamline( self ): - super(ParseElementEnhance,self).streamline() - if self.expr is not None: - self.expr.streamline() - return self - - def checkRecursion( self, parseElementList ): - if self in parseElementList: - raise RecursiveGrammarException( parseElementList+[self] ) - subRecCheckList = parseElementList[:] + [ self ] - if self.expr is not None: - self.expr.checkRecursion( subRecCheckList ) - - def validate( self, validateTrace=[] ): - tmp = validateTrace[:]+[self] - if self.expr is not None: - self.expr.validate(tmp) - self.checkRecursion( [] ) - - def __str__( self ): - try: - return super(ParseElementEnhance,self).__str__() - except Exception: - pass - - if self.strRepr is None and self.expr is not None: - self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) ) - return self.strRepr - - -class FollowedBy(ParseElementEnhance): - """ - Lookahead matching of the given parse expression. C{FollowedBy} - does I{not} advance the parsing position within the input string, it only - verifies that the specified parse expression matches at the current - position. C{FollowedBy} always returns a null token list. - - Example:: - # use FollowedBy to match a label only if it is followed by a ':' - data_word = Word(alphas) - label = data_word + FollowedBy(':') - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) - - OneOrMore(attr_expr).parseString("shape: SQUARE color: BLACK posn: upper left").pprint() - prints:: - [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']] - """ - def __init__( self, expr ): - super(FollowedBy,self).__init__(expr) - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - self.expr.tryParse( instring, loc ) - return loc, [] - - -class NotAny(ParseElementEnhance): - """ - Lookahead to disallow matching with the given parse expression. C{NotAny} - does I{not} advance the parsing position within the input string, it only - verifies that the specified parse expression does I{not} match at the current - position. Also, C{NotAny} does I{not} skip over leading whitespace. C{NotAny} - always returns a null token list. May be constructed using the '~' operator. - - Example:: - - """ - def __init__( self, expr ): - super(NotAny,self).__init__(expr) - #~ self.leaveWhitespace() - self.skipWhitespace = False # do NOT use self.leaveWhitespace(), don't want to propagate to exprs - self.mayReturnEmpty = True - self.errmsg = "Found unwanted token, "+_ustr(self.expr) - - def parseImpl( self, instring, loc, doActions=True ): - if self.expr.canParseNext(instring, loc): - raise ParseException(instring, loc, self.errmsg, self) - return loc, [] - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "~{" + _ustr(self.expr) + "}" - - return self.strRepr - -class _MultipleMatch(ParseElementEnhance): - def __init__( self, expr, stopOn=None): - super(_MultipleMatch, self).__init__(expr) - self.saveAsList = True - ender = stopOn - if isinstance(ender, basestring): - ender = ParserElement._literalStringClass(ender) - self.not_ender = ~ender if ender is not None else None - - def parseImpl( self, instring, loc, doActions=True ): - self_expr_parse = self.expr._parse - self_skip_ignorables = self._skipIgnorables - check_ender = self.not_ender is not None - if check_ender: - try_not_ender = self.not_ender.tryParse - - # must be at least one (but first see if we are the stopOn sentinel; - # if so, fail) - if check_ender: - try_not_ender(instring, loc) - loc, tokens = self_expr_parse( instring, loc, doActions, callPreParse=False ) - try: - hasIgnoreExprs = (not not self.ignoreExprs) - while 1: - if check_ender: - try_not_ender(instring, loc) - if hasIgnoreExprs: - preloc = self_skip_ignorables( instring, loc ) - else: - preloc = loc - loc, tmptokens = self_expr_parse( instring, preloc, doActions ) - if tmptokens or tmptokens.haskeys(): - tokens += tmptokens - except (ParseException,IndexError): - pass - - return loc, tokens - -class OneOrMore(_MultipleMatch): - """ - Repetition of one or more of the given expression. - - Parameters: - - expr - expression that must match one or more times - - stopOn - (default=C{None}) - expression for a terminating sentinel - (only required if the sentinel would ordinarily match the repetition - expression) - - Example:: - data_word = Word(alphas) - label = data_word + FollowedBy(':') - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) - - text = "shape: SQUARE posn: upper left color: BLACK" - OneOrMore(attr_expr).parseString(text).pprint() # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']] - - # use stopOn attribute for OneOrMore to avoid reading label string as part of the data - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) - OneOrMore(attr_expr).parseString(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']] - - # could also be written as - (attr_expr * (1,)).parseString(text).pprint() - """ - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "{" + _ustr(self.expr) + "}..." - - return self.strRepr - -class ZeroOrMore(_MultipleMatch): - """ - Optional repetition of zero or more of the given expression. - - Parameters: - - expr - expression that must match zero or more times - - stopOn - (default=C{None}) - expression for a terminating sentinel - (only required if the sentinel would ordinarily match the repetition - expression) - - Example: similar to L{OneOrMore} - """ - def __init__( self, expr, stopOn=None): - super(ZeroOrMore,self).__init__(expr, stopOn=stopOn) - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - try: - return super(ZeroOrMore, self).parseImpl(instring, loc, doActions) - except (ParseException,IndexError): - return loc, [] - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "[" + _ustr(self.expr) + "]..." - - return self.strRepr - -class _NullToken(object): - def __bool__(self): - return False - __nonzero__ = __bool__ - def __str__(self): - return "" - -_optionalNotMatched = _NullToken() -class Optional(ParseElementEnhance): - """ - Optional matching of the given expression. - - Parameters: - - expr - expression that must match zero or more times - - default (optional) - value to be returned if the optional expression is not found. - - Example:: - # US postal code can be a 5-digit zip, plus optional 4-digit qualifier - zip = Combine(Word(nums, exact=5) + Optional('-' + Word(nums, exact=4))) - zip.runTests(''' - # traditional ZIP code - 12345 - - # ZIP+4 form - 12101-0001 - - # invalid ZIP - 98765- - ''') - prints:: - # traditional ZIP code - 12345 - ['12345'] - - # ZIP+4 form - 12101-0001 - ['12101-0001'] - - # invalid ZIP - 98765- - ^ - FAIL: Expected end of text (at char 5), (line:1, col:6) - """ - def __init__( self, expr, default=_optionalNotMatched ): - super(Optional,self).__init__( expr, savelist=False ) - self.saveAsList = self.expr.saveAsList - self.defaultValue = default - self.mayReturnEmpty = True - - def parseImpl( self, instring, loc, doActions=True ): - try: - loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False ) - except (ParseException,IndexError): - if self.defaultValue is not _optionalNotMatched: - if self.expr.resultsName: - tokens = ParseResults([ self.defaultValue ]) - tokens[self.expr.resultsName] = self.defaultValue - else: - tokens = [ self.defaultValue ] - else: - tokens = [] - return loc, tokens - - def __str__( self ): - if hasattr(self,"name"): - return self.name - - if self.strRepr is None: - self.strRepr = "[" + _ustr(self.expr) + "]" - - return self.strRepr - -class SkipTo(ParseElementEnhance): - """ - Token for skipping over all undefined text until the matched expression is found. - - Parameters: - - expr - target expression marking the end of the data to be skipped - - include - (default=C{False}) if True, the target expression is also parsed - (the skipped text and target expression are returned as a 2-element list). - - ignore - (default=C{None}) used to define grammars (typically quoted strings and - comments) that might contain false matches to the target expression - - failOn - (default=C{None}) define expressions that are not allowed to be - included in the skipped test; if found before the target expression is found, - the SkipTo is not a match - - Example:: - report = ''' - Outstanding Issues Report - 1 Jan 2000 - - # | Severity | Description | Days Open - -----+----------+-------------------------------------------+----------- - 101 | Critical | Intermittent system crash | 6 - 94 | Cosmetic | Spelling error on Login ('log|n') | 14 - 79 | Minor | System slow when running too many reports | 47 - ''' - integer = Word(nums) - SEP = Suppress('|') - # use SkipTo to simply match everything up until the next SEP - # - ignore quoted strings, so that a '|' character inside a quoted string does not match - # - parse action will call token.strip() for each matched token, i.e., the description body - string_data = SkipTo(SEP, ignore=quotedString) - string_data.setParseAction(tokenMap(str.strip)) - ticket_expr = (integer("issue_num") + SEP - + string_data("sev") + SEP - + string_data("desc") + SEP - + integer("days_open")) - - for tkt in ticket_expr.searchString(report): - print tkt.dump() - prints:: - ['101', 'Critical', 'Intermittent system crash', '6'] - - days_open: 6 - - desc: Intermittent system crash - - issue_num: 101 - - sev: Critical - ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14'] - - days_open: 14 - - desc: Spelling error on Login ('log|n') - - issue_num: 94 - - sev: Cosmetic - ['79', 'Minor', 'System slow when running too many reports', '47'] - - days_open: 47 - - desc: System slow when running too many reports - - issue_num: 79 - - sev: Minor - """ - def __init__( self, other, include=False, ignore=None, failOn=None ): - super( SkipTo, self ).__init__( other ) - self.ignoreExpr = ignore - self.mayReturnEmpty = True - self.mayIndexError = False - self.includeMatch = include - self.asList = False - if isinstance(failOn, basestring): - self.failOn = ParserElement._literalStringClass(failOn) - else: - self.failOn = failOn - self.errmsg = "No match found for "+_ustr(self.expr) - - def parseImpl( self, instring, loc, doActions=True ): - startloc = loc - instrlen = len(instring) - expr = self.expr - expr_parse = self.expr._parse - self_failOn_canParseNext = self.failOn.canParseNext if self.failOn is not None else None - self_ignoreExpr_tryParse = self.ignoreExpr.tryParse if self.ignoreExpr is not None else None - - tmploc = loc - while tmploc <= instrlen: - if self_failOn_canParseNext is not None: - # break if failOn expression matches - if self_failOn_canParseNext(instring, tmploc): - break - - if self_ignoreExpr_tryParse is not None: - # advance past ignore expressions - while 1: - try: - tmploc = self_ignoreExpr_tryParse(instring, tmploc) - except ParseBaseException: - break - - try: - expr_parse(instring, tmploc, doActions=False, callPreParse=False) - except (ParseException, IndexError): - # no match, advance loc in string - tmploc += 1 - else: - # matched skipto expr, done - break - - else: - # ran off the end of the input string without matching skipto expr, fail - raise ParseException(instring, loc, self.errmsg, self) - - # build up return values - loc = tmploc - skiptext = instring[startloc:loc] - skipresult = ParseResults(skiptext) - - if self.includeMatch: - loc, mat = expr_parse(instring,loc,doActions,callPreParse=False) - skipresult += mat - - return loc, skipresult - -class Forward(ParseElementEnhance): - """ - Forward declaration of an expression to be defined later - - used for recursive grammars, such as algebraic infix notation. - When the expression is known, it is assigned to the C{Forward} variable using the '<<' operator. - - Note: take care when assigning to C{Forward} not to overlook precedence of operators. - Specifically, '|' has a lower precedence than '<<', so that:: - fwdExpr << a | b | c - will actually be evaluated as:: - (fwdExpr << a) | b | c - thereby leaving b and c out as parseable alternatives. It is recommended that you - explicitly group the values inserted into the C{Forward}:: - fwdExpr << (a | b | c) - Converting to use the '<<=' operator instead will avoid this problem. - - See L{ParseResults.pprint} for an example of a recursive parser created using - C{Forward}. - """ - def __init__( self, other=None ): - super(Forward,self).__init__( other, savelist=False ) - - def __lshift__( self, other ): - if isinstance( other, basestring ): - other = ParserElement._literalStringClass(other) - self.expr = other - self.strRepr = None - self.mayIndexError = self.expr.mayIndexError - self.mayReturnEmpty = self.expr.mayReturnEmpty - self.setWhitespaceChars( self.expr.whiteChars ) - self.skipWhitespace = self.expr.skipWhitespace - self.saveAsList = self.expr.saveAsList - self.ignoreExprs.extend(self.expr.ignoreExprs) - return self - - def __ilshift__(self, other): - return self << other - - def leaveWhitespace( self ): - self.skipWhitespace = False - return self - - def streamline( self ): - if not self.streamlined: - self.streamlined = True - if self.expr is not None: - self.expr.streamline() - return self - - def validate( self, validateTrace=[] ): - if self not in validateTrace: - tmp = validateTrace[:]+[self] - if self.expr is not None: - self.expr.validate(tmp) - self.checkRecursion([]) - - def __str__( self ): - if hasattr(self,"name"): - return self.name - return self.__class__.__name__ + ": ..." - - # stubbed out for now - creates awful memory and perf issues - self._revertClass = self.__class__ - self.__class__ = _ForwardNoRecurse - try: - if self.expr is not None: - retString = _ustr(self.expr) - else: - retString = "None" - finally: - self.__class__ = self._revertClass - return self.__class__.__name__ + ": " + retString - - def copy(self): - if self.expr is not None: - return super(Forward,self).copy() - else: - ret = Forward() - ret <<= self - return ret - -class _ForwardNoRecurse(Forward): - def __str__( self ): - return "..." - -class TokenConverter(ParseElementEnhance): - """ - Abstract subclass of C{ParseExpression}, for converting parsed results. - """ - def __init__( self, expr, savelist=False ): - super(TokenConverter,self).__init__( expr )#, savelist ) - self.saveAsList = False - -class Combine(TokenConverter): - """ - Converter to concatenate all matching tokens to a single string. - By default, the matching patterns must also be contiguous in the input string; - this can be disabled by specifying C{'adjacent=False'} in the constructor. - - Example:: - real = Word(nums) + '.' + Word(nums) - print(real.parseString('3.1416')) # -> ['3', '.', '1416'] - # will also erroneously match the following - print(real.parseString('3. 1416')) # -> ['3', '.', '1416'] - - real = Combine(Word(nums) + '.' + Word(nums)) - print(real.parseString('3.1416')) # -> ['3.1416'] - # no match when there are internal spaces - print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...) - """ - def __init__( self, expr, joinString="", adjacent=True ): - super(Combine,self).__init__( expr ) - # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself - if adjacent: - self.leaveWhitespace() - self.adjacent = adjacent - self.skipWhitespace = True - self.joinString = joinString - self.callPreparse = True - - def ignore( self, other ): - if self.adjacent: - ParserElement.ignore(self, other) - else: - super( Combine, self).ignore( other ) - return self - - def postParse( self, instring, loc, tokenlist ): - retToks = tokenlist.copy() - del retToks[:] - retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults) - - if self.resultsName and retToks.haskeys(): - return [ retToks ] - else: - return retToks - -class Group(TokenConverter): - """ - Converter to return the matched tokens as a list - useful for returning tokens of C{L{ZeroOrMore}} and C{L{OneOrMore}} expressions. - - Example:: - ident = Word(alphas) - num = Word(nums) - term = ident | num - func = ident + Optional(delimitedList(term)) - print(func.parseString("fn a,b,100")) # -> ['fn', 'a', 'b', '100'] - - func = ident + Group(Optional(delimitedList(term))) - print(func.parseString("fn a,b,100")) # -> ['fn', ['a', 'b', '100']] - """ - def __init__( self, expr ): - super(Group,self).__init__( expr ) - self.saveAsList = True - - def postParse( self, instring, loc, tokenlist ): - return [ tokenlist ] - -class Dict(TokenConverter): - """ - Converter to return a repetitive expression as a list, but also as a dictionary. - Each element can also be referenced using the first token in the expression as its key. - Useful for tabular report scraping when the first column can be used as a item key. - - Example:: - data_word = Word(alphas) - label = data_word + FollowedBy(':') - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) - - text = "shape: SQUARE posn: upper left color: light blue texture: burlap" - attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) - - # print attributes as plain groups - print(OneOrMore(attr_expr).parseString(text).dump()) - - # instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names - result = Dict(OneOrMore(Group(attr_expr))).parseString(text) - print(result.dump()) - - # access named fields as dict entries, or output as dict - print(result['shape']) - print(result.asDict()) - prints:: - ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap'] - - [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] - - color: light blue - - posn: upper left - - shape: SQUARE - - texture: burlap - SQUARE - {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'} - See more examples at L{ParseResults} of accessing fields by results name. - """ - def __init__( self, expr ): - super(Dict,self).__init__( expr ) - self.saveAsList = True - - def postParse( self, instring, loc, tokenlist ): - for i,tok in enumerate(tokenlist): - if len(tok) == 0: - continue - ikey = tok[0] - if isinstance(ikey,int): - ikey = _ustr(tok[0]).strip() - if len(tok)==1: - tokenlist[ikey] = _ParseResultsWithOffset("",i) - elif len(tok)==2 and not isinstance(tok[1],ParseResults): - tokenlist[ikey] = _ParseResultsWithOffset(tok[1],i) - else: - dictvalue = tok.copy() #ParseResults(i) - del dictvalue[0] - if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.haskeys()): - tokenlist[ikey] = _ParseResultsWithOffset(dictvalue,i) - else: - tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0],i) - - if self.resultsName: - return [ tokenlist ] - else: - return tokenlist - - -class Suppress(TokenConverter): - """ - Converter for ignoring the results of a parsed expression. - - Example:: - source = "a, b, c,d" - wd = Word(alphas) - wd_list1 = wd + ZeroOrMore(',' + wd) - print(wd_list1.parseString(source)) - - # often, delimiters that are useful during parsing are just in the - # way afterward - use Suppress to keep them out of the parsed output - wd_list2 = wd + ZeroOrMore(Suppress(',') + wd) - print(wd_list2.parseString(source)) - prints:: - ['a', ',', 'b', ',', 'c', ',', 'd'] - ['a', 'b', 'c', 'd'] - (See also L{delimitedList}.) - """ - def postParse( self, instring, loc, tokenlist ): - return [] - - def suppress( self ): - return self - - -class OnlyOnce(object): - """ - Wrapper for parse actions, to ensure they are only called once. - """ - def __init__(self, methodCall): - self.callable = _trim_arity(methodCall) - self.called = False - def __call__(self,s,l,t): - if not self.called: - results = self.callable(s,l,t) - self.called = True - return results - raise ParseException(s,l,"") - def reset(self): - self.called = False - -def traceParseAction(f): - """ - Decorator for debugging parse actions. - - When the parse action is called, this decorator will print C{">> entering I{method-name}(line:I{current_source_line}, I{parse_location}, I{matched_tokens})".} - When the parse action completes, the decorator will print C{"<<"} followed by the returned value, or any exception that the parse action raised. - - Example:: - wd = Word(alphas) - - @traceParseAction - def remove_duplicate_chars(tokens): - return ''.join(sorted(set(''.join(tokens)))) - - wds = OneOrMore(wd).setParseAction(remove_duplicate_chars) - print(wds.parseString("slkdjs sld sldd sdlf sdljf")) - prints:: - >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {})) - <<leaving remove_duplicate_chars (ret: 'dfjkls') - ['dfjkls'] - """ - f = _trim_arity(f) - def z(*paArgs): - thisFunc = f.__name__ - s,l,t = paArgs[-3:] - if len(paArgs)>3: - thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc - sys.stderr.write( ">>entering %s(line: '%s', %d, %r)\n" % (thisFunc,line(l,s),l,t) ) - try: - ret = f(*paArgs) - except Exception as exc: - sys.stderr.write( "<<leaving %s (exception: %s)\n" % (thisFunc,exc) ) - raise - sys.stderr.write( "<<leaving %s (ret: %r)\n" % (thisFunc,ret) ) - return ret - try: - z.__name__ = f.__name__ - except AttributeError: - pass - return z - -# -# global helpers -# -def delimitedList( expr, delim=",", combine=False ): - """ - Helper to define a delimited list of expressions - the delimiter defaults to ','. - By default, the list elements and delimiters can have intervening whitespace, and - comments, but this can be overridden by passing C{combine=True} in the constructor. - If C{combine} is set to C{True}, the matching tokens are returned as a single token - string, with the delimiters included; otherwise, the matching tokens are returned - as a list of tokens, with the delimiters suppressed. - - Example:: - delimitedList(Word(alphas)).parseString("aa,bb,cc") # -> ['aa', 'bb', 'cc'] - delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE'] - """ - dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..." - if combine: - return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName) - else: - return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName) - -def countedArray( expr, intExpr=None ): - """ - Helper to define a counted list of expressions. - This helper defines a pattern of the form:: - integer expr expr expr... - where the leading integer tells how many expr expressions follow. - The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed. - - If C{intExpr} is specified, it should be a pyparsing expression that produces an integer value. - - Example:: - countedArray(Word(alphas)).parseString('2 ab cd ef') # -> ['ab', 'cd'] - - # in this parser, the leading integer value is given in binary, - # '10' indicating that 2 values are in the array - binaryConstant = Word('01').setParseAction(lambda t: int(t[0], 2)) - countedArray(Word(alphas), intExpr=binaryConstant).parseString('10 ab cd ef') # -> ['ab', 'cd'] - """ - arrayExpr = Forward() - def countFieldParseAction(s,l,t): - n = t[0] - arrayExpr << (n and Group(And([expr]*n)) or Group(empty)) - return [] - if intExpr is None: - intExpr = Word(nums).setParseAction(lambda t:int(t[0])) - else: - intExpr = intExpr.copy() - intExpr.setName("arrayLen") - intExpr.addParseAction(countFieldParseAction, callDuringTry=True) - return ( intExpr + arrayExpr ).setName('(len) ' + _ustr(expr) + '...') - -def _flatten(L): - ret = [] - for i in L: - if isinstance(i,list): - ret.extend(_flatten(i)) - else: - ret.append(i) - return ret - -def matchPreviousLiteral(expr): - """ - Helper to define an expression that is indirectly defined from - the tokens matched in a previous expression, that is, it looks - for a 'repeat' of a previous expression. For example:: - first = Word(nums) - second = matchPreviousLiteral(first) - matchExpr = first + ":" + second - will match C{"1:1"}, but not C{"1:2"}. Because this matches a - previous literal, will also match the leading C{"1:1"} in C{"1:10"}. - If this is not desired, use C{matchPreviousExpr}. - Do I{not} use with packrat parsing enabled. - """ - rep = Forward() - def copyTokenToRepeater(s,l,t): - if t: - if len(t) == 1: - rep << t[0] - else: - # flatten t tokens - tflat = _flatten(t.asList()) - rep << And(Literal(tt) for tt in tflat) - else: - rep << Empty() - expr.addParseAction(copyTokenToRepeater, callDuringTry=True) - rep.setName('(prev) ' + _ustr(expr)) - return rep - -def matchPreviousExpr(expr): - """ - Helper to define an expression that is indirectly defined from - the tokens matched in a previous expression, that is, it looks - for a 'repeat' of a previous expression. For example:: - first = Word(nums) - second = matchPreviousExpr(first) - matchExpr = first + ":" + second - will match C{"1:1"}, but not C{"1:2"}. Because this matches by - expressions, will I{not} match the leading C{"1:1"} in C{"1:10"}; - the expressions are evaluated first, and then compared, so - C{"1"} is compared with C{"10"}. - Do I{not} use with packrat parsing enabled. - """ - rep = Forward() - e2 = expr.copy() - rep <<= e2 - def copyTokenToRepeater(s,l,t): - matchTokens = _flatten(t.asList()) - def mustMatchTheseTokens(s,l,t): - theseTokens = _flatten(t.asList()) - if theseTokens != matchTokens: - raise ParseException("",0,"") - rep.setParseAction( mustMatchTheseTokens, callDuringTry=True ) - expr.addParseAction(copyTokenToRepeater, callDuringTry=True) - rep.setName('(prev) ' + _ustr(expr)) - return rep - -def _escapeRegexRangeChars(s): - #~ escape these chars: ^-] - for c in r"\^-]": - s = s.replace(c,_bslash+c) - s = s.replace("\n",r"\n") - s = s.replace("\t",r"\t") - return _ustr(s) - -def oneOf( strs, caseless=False, useRegex=True ): - """ - Helper to quickly define a set of alternative Literals, and makes sure to do - longest-first testing when there is a conflict, regardless of the input order, - but returns a C{L{MatchFirst}} for best performance. - - Parameters: - - strs - a string of space-delimited literals, or a collection of string literals - - caseless - (default=C{False}) - treat all literals as caseless - - useRegex - (default=C{True}) - as an optimization, will generate a Regex - object; otherwise, will generate a C{MatchFirst} object (if C{caseless=True}, or - if creating a C{Regex} raises an exception) - - Example:: - comp_oper = oneOf("< = > <= >= !=") - var = Word(alphas) - number = Word(nums) - term = var | number - comparison_expr = term + comp_oper + term - print(comparison_expr.searchString("B = 12 AA=23 B<=AA AA>12")) - prints:: - [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']] - """ - if caseless: - isequal = ( lambda a,b: a.upper() == b.upper() ) - masks = ( lambda a,b: b.upper().startswith(a.upper()) ) - parseElementClass = CaselessLiteral - else: - isequal = ( lambda a,b: a == b ) - masks = ( lambda a,b: b.startswith(a) ) - parseElementClass = Literal - - symbols = [] - if isinstance(strs,basestring): - symbols = strs.split() - elif isinstance(strs, Iterable): - symbols = list(strs) - else: - warnings.warn("Invalid argument to oneOf, expected string or iterable", - SyntaxWarning, stacklevel=2) - if not symbols: - return NoMatch() - - i = 0 - while i < len(symbols)-1: - cur = symbols[i] - for j,other in enumerate(symbols[i+1:]): - if ( isequal(other, cur) ): - del symbols[i+j+1] - break - elif ( masks(cur, other) ): - del symbols[i+j+1] - symbols.insert(i,other) - cur = other - break - else: - i += 1 - - if not caseless and useRegex: - #~ print (strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] )) - try: - if len(symbols)==len("".join(symbols)): - return Regex( "[%s]" % "".join(_escapeRegexRangeChars(sym) for sym in symbols) ).setName(' | '.join(symbols)) - else: - return Regex( "|".join(re.escape(sym) for sym in symbols) ).setName(' | '.join(symbols)) - except Exception: - warnings.warn("Exception creating Regex for oneOf, building MatchFirst", - SyntaxWarning, stacklevel=2) - - - # last resort, just use MatchFirst - return MatchFirst(parseElementClass(sym) for sym in symbols).setName(' | '.join(symbols)) - -def dictOf( key, value ): - """ - Helper to easily and clearly define a dictionary by specifying the respective patterns - for the key and value. Takes care of defining the C{L{Dict}}, C{L{ZeroOrMore}}, and C{L{Group}} tokens - in the proper order. The key pattern can include delimiting markers or punctuation, - as long as they are suppressed, thereby leaving the significant key text. The value - pattern can include named results, so that the C{Dict} results can include named token - fields. - - Example:: - text = "shape: SQUARE posn: upper left color: light blue texture: burlap" - attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) - print(OneOrMore(attr_expr).parseString(text).dump()) - - attr_label = label - attr_value = Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join) - - # similar to Dict, but simpler call format - result = dictOf(attr_label, attr_value).parseString(text) - print(result.dump()) - print(result['shape']) - print(result.shape) # object attribute access works too - print(result.asDict()) - prints:: - [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] - - color: light blue - - posn: upper left - - shape: SQUARE - - texture: burlap - SQUARE - SQUARE - {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'} - """ - return Dict( ZeroOrMore( Group ( key + value ) ) ) - -def originalTextFor(expr, asString=True): - """ - Helper to return the original, untokenized text for a given expression. Useful to - restore the parsed fields of an HTML start tag into the raw tag text itself, or to - revert separate tokens with intervening whitespace back to the original matching - input text. By default, returns astring containing the original parsed text. - - If the optional C{asString} argument is passed as C{False}, then the return value is a - C{L{ParseResults}} containing any results names that were originally matched, and a - single token containing the original matched text from the input string. So if - the expression passed to C{L{originalTextFor}} contains expressions with defined - results names, you must set C{asString} to C{False} if you want to preserve those - results name values. - - Example:: - src = "this is test <b> bold <i>text</i> </b> normal text " - for tag in ("b","i"): - opener,closer = makeHTMLTags(tag) - patt = originalTextFor(opener + SkipTo(closer) + closer) - print(patt.searchString(src)[0]) - prints:: - ['<b> bold <i>text</i> </b>'] - ['<i>text</i>'] - """ - locMarker = Empty().setParseAction(lambda s,loc,t: loc) - endlocMarker = locMarker.copy() - endlocMarker.callPreparse = False - matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end") - if asString: - extractText = lambda s,l,t: s[t._original_start:t._original_end] - else: - def extractText(s,l,t): - t[:] = [s[t.pop('_original_start'):t.pop('_original_end')]] - matchExpr.setParseAction(extractText) - matchExpr.ignoreExprs = expr.ignoreExprs - return matchExpr - -def ungroup(expr): - """ - Helper to undo pyparsing's default grouping of And expressions, even - if all but one are non-empty. - """ - return TokenConverter(expr).setParseAction(lambda t:t[0]) - -def locatedExpr(expr): - """ - Helper to decorate a returned token with its starting and ending locations in the input string. - This helper adds the following results names: - - locn_start = location where matched expression begins - - locn_end = location where matched expression ends - - value = the actual parsed results - - Be careful if the input text contains C{<TAB>} characters, you may want to call - C{L{ParserElement.parseWithTabs}} - - Example:: - wd = Word(alphas) - for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"): - print(match) - prints:: - [[0, 'ljsdf', 5]] - [[8, 'lksdjjf', 15]] - [[18, 'lkkjj', 23]] - """ - locator = Empty().setParseAction(lambda s,l,t: l) - return Group(locator("locn_start") + expr("value") + locator.copy().leaveWhitespace()("locn_end")) - - -# convenience constants for positional expressions -empty = Empty().setName("empty") -lineStart = LineStart().setName("lineStart") -lineEnd = LineEnd().setName("lineEnd") -stringStart = StringStart().setName("stringStart") -stringEnd = StringEnd().setName("stringEnd") - -_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1]) -_escapedHexChar = Regex(r"\\0?[xX][0-9a-fA-F]+").setParseAction(lambda s,l,t:unichr(int(t[0].lstrip(r'\0x'),16))) -_escapedOctChar = Regex(r"\\0[0-7]+").setParseAction(lambda s,l,t:unichr(int(t[0][1:],8))) -_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | CharsNotIn(r'\]', exact=1) -_charRange = Group(_singleChar + Suppress("-") + _singleChar) -_reBracketExpr = Literal("[") + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]" - -def srange(s): - r""" - Helper to easily define string ranges for use in Word construction. Borrows - syntax from regexp '[]' string range definitions:: - srange("[0-9]") -> "0123456789" - srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz" - srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_" - The input string must be enclosed in []'s, and the returned string is the expanded - character set joined into a single string. - The values enclosed in the []'s may be: - - a single character - - an escaped character with a leading backslash (such as C{\-} or C{\]}) - - an escaped hex character with a leading C{'\x'} (C{\x21}, which is a C{'!'} character) - (C{\0x##} is also supported for backwards compatibility) - - an escaped octal character with a leading C{'\0'} (C{\041}, which is a C{'!'} character) - - a range of any of the above, separated by a dash (C{'a-z'}, etc.) - - any combination of the above (C{'aeiouy'}, C{'a-zA-Z0-9_$'}, etc.) - """ - _expanded = lambda p: p if not isinstance(p,ParseResults) else ''.join(unichr(c) for c in range(ord(p[0]),ord(p[1])+1)) - try: - return "".join(_expanded(part) for part in _reBracketExpr.parseString(s).body) - except Exception: - return "" - -def matchOnlyAtCol(n): - """ - Helper method for defining parse actions that require matching at a specific - column in the input text. - """ - def verifyCol(strg,locn,toks): - if col(locn,strg) != n: - raise ParseException(strg,locn,"matched token not at column %d" % n) - return verifyCol - -def replaceWith(replStr): - """ - Helper method for common parse actions that simply return a literal value. Especially - useful when used with C{L{transformString<ParserElement.transformString>}()}. - - Example:: - num = Word(nums).setParseAction(lambda toks: int(toks[0])) - na = oneOf("N/A NA").setParseAction(replaceWith(math.nan)) - term = na | num - - OneOrMore(term).parseString("324 234 N/A 234") # -> [324, 234, nan, 234] - """ - return lambda s,l,t: [replStr] - -def removeQuotes(s,l,t): - """ - Helper parse action for removing quotation marks from parsed quoted strings. - - Example:: - # by default, quotation marks are included in parsed results - quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"] - - # use removeQuotes to strip quotation marks from parsed results - quotedString.setParseAction(removeQuotes) - quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"] - """ - return t[0][1:-1] - -def tokenMap(func, *args): - """ - Helper to define a parse action by mapping a function to all elements of a ParseResults list.If any additional - args are passed, they are forwarded to the given function as additional arguments after - the token, as in C{hex_integer = Word(hexnums).setParseAction(tokenMap(int, 16))}, which will convert the - parsed data to an integer using base 16. - - Example (compare the last to example in L{ParserElement.transformString}:: - hex_ints = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16)) - hex_ints.runTests(''' - 00 11 22 aa FF 0a 0d 1a - ''') - - upperword = Word(alphas).setParseAction(tokenMap(str.upper)) - OneOrMore(upperword).runTests(''' - my kingdom for a horse - ''') - - wd = Word(alphas).setParseAction(tokenMap(str.title)) - OneOrMore(wd).setParseAction(' '.join).runTests(''' - now is the winter of our discontent made glorious summer by this sun of york - ''') - prints:: - 00 11 22 aa FF 0a 0d 1a - [0, 17, 34, 170, 255, 10, 13, 26] - - my kingdom for a horse - ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE'] - - now is the winter of our discontent made glorious summer by this sun of york - ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York'] - """ - def pa(s,l,t): - return [func(tokn, *args) for tokn in t] - - try: - func_name = getattr(func, '__name__', - getattr(func, '__class__').__name__) - except Exception: - func_name = str(func) - pa.__name__ = func_name - - return pa - -upcaseTokens = tokenMap(lambda t: _ustr(t).upper()) -"""(Deprecated) Helper parse action to convert tokens to upper case. Deprecated in favor of L{pyparsing_common.upcaseTokens}""" - -downcaseTokens = tokenMap(lambda t: _ustr(t).lower()) -"""(Deprecated) Helper parse action to convert tokens to lower case. Deprecated in favor of L{pyparsing_common.downcaseTokens}""" - -def _makeTags(tagStr, xml): - """Internal helper to construct opening and closing tag expressions, given a tag name""" - if isinstance(tagStr,basestring): - resname = tagStr - tagStr = Keyword(tagStr, caseless=not xml) - else: - resname = tagStr.name - - tagAttrName = Word(alphas,alphanums+"_-:") - if (xml): - tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes ) - openTag = Suppress("<") + tagStr("tag") + \ - Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \ - Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") - else: - printablesLessRAbrack = "".join(c for c in printables if c not in ">") - tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack) - openTag = Suppress("<") + tagStr("tag") + \ - Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \ - Optional( Suppress("=") + tagAttrValue ) ))) + \ - Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") - closeTag = Combine(_L("</") + tagStr + ">") - - openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % resname) - closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("</%s>" % resname) - openTag.tag = resname - closeTag.tag = resname - return openTag, closeTag - -def makeHTMLTags(tagStr): - """ - Helper to construct opening and closing tag expressions for HTML, given a tag name. Matches - tags in either upper or lower case, attributes with namespaces and with quoted or unquoted values. - - Example:: - text = '<td>More info at the <a href="http://pyparsing.wikispaces.com">pyparsing</a> wiki page</td>' - # makeHTMLTags returns pyparsing expressions for the opening and closing tags as a 2-tuple - a,a_end = makeHTMLTags("A") - link_expr = a + SkipTo(a_end)("link_text") + a_end - - for link in link_expr.searchString(text): - # attributes in the <A> tag (like "href" shown here) are also accessible as named results - print(link.link_text, '->', link.href) - prints:: - pyparsing -> http://pyparsing.wikispaces.com - """ - return _makeTags( tagStr, False ) - -def makeXMLTags(tagStr): - """ - Helper to construct opening and closing tag expressions for XML, given a tag name. Matches - tags only in the given upper/lower case. - - Example: similar to L{makeHTMLTags} - """ - return _makeTags( tagStr, True ) - -def withAttribute(*args,**attrDict): - """ - Helper to create a validating parse action to be used with start tags created - with C{L{makeXMLTags}} or C{L{makeHTMLTags}}. Use C{withAttribute} to qualify a starting tag - with a required attribute value, to avoid false matches on common tags such as - C{<TD>} or C{<DIV>}. - - Call C{withAttribute} with a series of attribute names and values. Specify the list - of filter attributes names and values as: - - keyword arguments, as in C{(align="right")}, or - - as an explicit dict with C{**} operator, when an attribute name is also a Python - reserved word, as in C{**{"class":"Customer", "align":"right"}} - - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) - For attribute names with a namespace prefix, you must use the second form. Attribute - names are matched insensitive to upper/lower case. - - If just testing for C{class} (with or without a namespace), use C{L{withClass}}. - - To verify that the attribute exists, but without specifying a value, pass - C{withAttribute.ANY_VALUE} as the value. - - Example:: - html = ''' - <div> - Some text - <div type="grid">1 4 0 1 0</div> - <div type="graph">1,3 2,3 1,1</div> - <div>this has no type</div> - </div> - - ''' - div,div_end = makeHTMLTags("div") - - # only match div tag having a type attribute with value "grid" - div_grid = div().setParseAction(withAttribute(type="grid")) - grid_expr = div_grid + SkipTo(div | div_end)("body") - for grid_header in grid_expr.searchString(html): - print(grid_header.body) - - # construct a match with any div tag having a type attribute, regardless of the value - div_any_type = div().setParseAction(withAttribute(type=withAttribute.ANY_VALUE)) - div_expr = div_any_type + SkipTo(div | div_end)("body") - for div_header in div_expr.searchString(html): - print(div_header.body) - prints:: - 1 4 0 1 0 - - 1 4 0 1 0 - 1,3 2,3 1,1 - """ - if args: - attrs = args[:] - else: - attrs = attrDict.items() - attrs = [(k,v) for k,v in attrs] - def pa(s,l,tokens): - for attrName,attrValue in attrs: - if attrName not in tokens: - raise ParseException(s,l,"no matching attribute " + attrName) - if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: - raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" % - (attrName, tokens[attrName], attrValue)) - return pa -withAttribute.ANY_VALUE = object() - -def withClass(classname, namespace=''): - """ - Simplified version of C{L{withAttribute}} when matching on a div class - made - difficult because C{class} is a reserved word in Python. - - Example:: - html = ''' - <div> - Some text - <div class="grid">1 4 0 1 0</div> - <div class="graph">1,3 2,3 1,1</div> - <div>this <div> has no class</div> - </div> - - ''' - div,div_end = makeHTMLTags("div") - div_grid = div().setParseAction(withClass("grid")) - - grid_expr = div_grid + SkipTo(div | div_end)("body") - for grid_header in grid_expr.searchString(html): - print(grid_header.body) - - div_any_type = div().setParseAction(withClass(withAttribute.ANY_VALUE)) - div_expr = div_any_type + SkipTo(div | div_end)("body") - for div_header in div_expr.searchString(html): - print(div_header.body) - prints:: - 1 4 0 1 0 - - 1 4 0 1 0 - 1,3 2,3 1,1 - """ - classattr = "%s:class" % namespace if namespace else "class" - return withAttribute(**{classattr : classname}) - -opAssoc = _Constants() -opAssoc.LEFT = object() -opAssoc.RIGHT = object() - -def infixNotation( baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')') ): - """ - Helper method for constructing grammars of expressions made up of - operators working in a precedence hierarchy. Operators may be unary or - binary, left- or right-associative. Parse actions can also be attached - to operator expressions. The generated parser will also recognize the use - of parentheses to override operator precedences (see example below). - - Note: if you define a deep operator list, you may see performance issues - when using infixNotation. See L{ParserElement.enablePackrat} for a - mechanism to potentially improve your parser performance. - - Parameters: - - baseExpr - expression representing the most basic element for the nested - - opList - list of tuples, one for each operator precedence level in the - expression grammar; each tuple is of the form - (opExpr, numTerms, rightLeftAssoc, parseAction), where: - - opExpr is the pyparsing expression for the operator; - may also be a string, which will be converted to a Literal; - if numTerms is 3, opExpr is a tuple of two expressions, for the - two operators separating the 3 terms - - numTerms is the number of terms for this operator (must - be 1, 2, or 3) - - rightLeftAssoc is the indicator whether the operator is - right or left associative, using the pyparsing-defined - constants C{opAssoc.RIGHT} and C{opAssoc.LEFT}. - - parseAction is the parse action to be associated with - expressions matching this operator expression (the - parse action tuple member may be omitted); if the parse action - is passed a tuple or list of functions, this is equivalent to - calling C{setParseAction(*fn)} (L{ParserElement.setParseAction}) - - lpar - expression for matching left-parentheses (default=C{Suppress('(')}) - - rpar - expression for matching right-parentheses (default=C{Suppress(')')}) - - Example:: - # simple example of four-function arithmetic with ints and variable names - integer = pyparsing_common.signed_integer - varname = pyparsing_common.identifier - - arith_expr = infixNotation(integer | varname, - [ - ('-', 1, opAssoc.RIGHT), - (oneOf('* /'), 2, opAssoc.LEFT), - (oneOf('+ -'), 2, opAssoc.LEFT), - ]) - - arith_expr.runTests(''' - 5+3*6 - (5+3)*6 - -2--11 - ''', fullDump=False) - prints:: - 5+3*6 - [[5, '+', [3, '*', 6]]] - - (5+3)*6 - [[[5, '+', 3], '*', 6]] - - -2--11 - [[['-', 2], '-', ['-', 11]]] - """ - ret = Forward() - lastExpr = baseExpr | ( lpar + ret + rpar ) - for i,operDef in enumerate(opList): - opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] - termName = "%s term" % opExpr if arity < 3 else "%s%s term" % opExpr - if arity == 3: - if opExpr is None or len(opExpr) != 2: - raise ValueError("if numterms=3, opExpr must be a tuple or list of two expressions") - opExpr1, opExpr2 = opExpr - thisExpr = Forward().setName(termName) - if rightLeftAssoc == opAssoc.LEFT: - if arity == 1: - matchExpr = FollowedBy(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) ) - elif arity == 2: - if opExpr is not None: - matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) - else: - matchExpr = FollowedBy(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) ) - elif arity == 3: - matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \ - Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr ) - else: - raise ValueError("operator must be unary (1), binary (2), or ternary (3)") - elif rightLeftAssoc == opAssoc.RIGHT: - if arity == 1: - # try to avoid LR with this extra test - if not isinstance(opExpr, Optional): - opExpr = Optional(opExpr) - matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) - elif arity == 2: - if opExpr is not None: - matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) - else: - matchExpr = FollowedBy(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) ) - elif arity == 3: - matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \ - Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr ) - else: - raise ValueError("operator must be unary (1), binary (2), or ternary (3)") - else: - raise ValueError("operator must indicate right or left associativity") - if pa: - if isinstance(pa, (tuple, list)): - matchExpr.setParseAction(*pa) - else: - matchExpr.setParseAction(pa) - thisExpr <<= ( matchExpr.setName(termName) | lastExpr ) - lastExpr = thisExpr - ret <<= lastExpr - return ret - -operatorPrecedence = infixNotation -"""(Deprecated) Former name of C{L{infixNotation}}, will be dropped in a future release.""" - -dblQuotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"').setName("string enclosed in double quotes") -sglQuotedString = Combine(Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("string enclosed in single quotes") -quotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"'| - Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("quotedString using single or double quotes") -unicodeString = Combine(_L('u') + quotedString.copy()).setName("unicode string literal") - -def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString.copy()): - """ - Helper method for defining nested lists enclosed in opening and closing - delimiters ("(" and ")" are the default). - - Parameters: - - opener - opening character for a nested list (default=C{"("}); can also be a pyparsing expression - - closer - closing character for a nested list (default=C{")"}); can also be a pyparsing expression - - content - expression for items within the nested lists (default=C{None}) - - ignoreExpr - expression for ignoring opening and closing delimiters (default=C{quotedString}) - - If an expression is not provided for the content argument, the nested - expression will capture all whitespace-delimited content between delimiters - as a list of separate values. - - Use the C{ignoreExpr} argument to define expressions that may contain - opening or closing characters that should not be treated as opening - or closing characters for nesting, such as quotedString or a comment - expression. Specify multiple expressions using an C{L{Or}} or C{L{MatchFirst}}. - The default is L{quotedString}, but if no expressions are to be ignored, - then pass C{None} for this argument. - - Example:: - data_type = oneOf("void int short long char float double") - decl_data_type = Combine(data_type + Optional(Word('*'))) - ident = Word(alphas+'_', alphanums+'_') - number = pyparsing_common.number - arg = Group(decl_data_type + ident) - LPAR,RPAR = map(Suppress, "()") - - code_body = nestedExpr('{', '}', ignoreExpr=(quotedString | cStyleComment)) - - c_function = (decl_data_type("type") - + ident("name") - + LPAR + Optional(delimitedList(arg), [])("args") + RPAR - + code_body("body")) - c_function.ignore(cStyleComment) - - source_code = ''' - int is_odd(int x) { - return (x%2); - } - - int dec_to_hex(char hchar) { - if (hchar >= '0' && hchar <= '9') { - return (ord(hchar)-ord('0')); - } else { - return (10+ord(hchar)-ord('A')); - } - } - ''' - for func in c_function.searchString(source_code): - print("%(name)s (%(type)s) args: %(args)s" % func) - - prints:: - is_odd (int) args: [['int', 'x']] - dec_to_hex (int) args: [['char', 'hchar']] - """ - if opener == closer: - raise ValueError("opening and closing strings cannot be the same") - if content is None: - if isinstance(opener,basestring) and isinstance(closer,basestring): - if len(opener) == 1 and len(closer)==1: - if ignoreExpr is not None: - content = (Combine(OneOrMore(~ignoreExpr + - CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS,exact=1)) - ).setParseAction(lambda t:t[0].strip())) - else: - content = (empty.copy()+CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS - ).setParseAction(lambda t:t[0].strip())) - else: - if ignoreExpr is not None: - content = (Combine(OneOrMore(~ignoreExpr + - ~Literal(opener) + ~Literal(closer) + - CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) - ).setParseAction(lambda t:t[0].strip())) - else: - content = (Combine(OneOrMore(~Literal(opener) + ~Literal(closer) + - CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) - ).setParseAction(lambda t:t[0].strip())) - else: - raise ValueError("opening and closing arguments must be strings if no content expression is given") - ret = Forward() - if ignoreExpr is not None: - ret <<= Group( Suppress(opener) + ZeroOrMore( ignoreExpr | ret | content ) + Suppress(closer) ) - else: - ret <<= Group( Suppress(opener) + ZeroOrMore( ret | content ) + Suppress(closer) ) - ret.setName('nested %s%s expression' % (opener,closer)) - return ret - -def indentedBlock(blockStatementExpr, indentStack, indent=True): - """ - Helper method for defining space-delimited indentation blocks, such as - those used to define block statements in Python source code. - - Parameters: - - blockStatementExpr - expression defining syntax of statement that - is repeated within the indented block - - indentStack - list created by caller to manage indentation stack - (multiple statementWithIndentedBlock expressions within a single grammar - should share a common indentStack) - - indent - boolean indicating whether block must be indented beyond the - the current level; set to False for block of left-most statements - (default=C{True}) - - A valid block must contain at least one C{blockStatement}. - - Example:: - data = ''' - def A(z): - A1 - B = 100 - G = A2 - A2 - A3 - B - def BB(a,b,c): - BB1 - def BBA(): - bba1 - bba2 - bba3 - C - D - def spam(x,y): - def eggs(z): - pass - ''' - - - indentStack = [1] - stmt = Forward() - - identifier = Word(alphas, alphanums) - funcDecl = ("def" + identifier + Group( "(" + Optional( delimitedList(identifier) ) + ")" ) + ":") - func_body = indentedBlock(stmt, indentStack) - funcDef = Group( funcDecl + func_body ) - - rvalue = Forward() - funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")") - rvalue << (funcCall | identifier | Word(nums)) - assignment = Group(identifier + "=" + rvalue) - stmt << ( funcDef | assignment | identifier ) - - module_body = OneOrMore(stmt) - - parseTree = module_body.parseString(data) - parseTree.pprint() - prints:: - [['def', - 'A', - ['(', 'z', ')'], - ':', - [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], - 'B', - ['def', - 'BB', - ['(', 'a', 'b', 'c', ')'], - ':', - [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], - 'C', - 'D', - ['def', - 'spam', - ['(', 'x', 'y', ')'], - ':', - [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] - """ - def checkPeerIndent(s,l,t): - if l >= len(s): return - curCol = col(l,s) - if curCol != indentStack[-1]: - if curCol > indentStack[-1]: - raise ParseFatalException(s,l,"illegal nesting") - raise ParseException(s,l,"not a peer entry") - - def checkSubIndent(s,l,t): - curCol = col(l,s) - if curCol > indentStack[-1]: - indentStack.append( curCol ) - else: - raise ParseException(s,l,"not a subentry") - - def checkUnindent(s,l,t): - if l >= len(s): return - curCol = col(l,s) - if not(indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]): - raise ParseException(s,l,"not an unindent") - indentStack.pop() - - NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress()) - INDENT = (Empty() + Empty().setParseAction(checkSubIndent)).setName('INDENT') - PEER = Empty().setParseAction(checkPeerIndent).setName('') - UNDENT = Empty().setParseAction(checkUnindent).setName('UNINDENT') - if indent: - smExpr = Group( Optional(NL) + - #~ FollowedBy(blockStatementExpr) + - INDENT + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) + UNDENT) - else: - smExpr = Group( Optional(NL) + - (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) ) - blockStatementExpr.ignore(_bslash + LineEnd()) - return smExpr.setName('indented block') - -alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]") -punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]") - -anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_:").setName('any tag')) -_htmlEntityMap = dict(zip("gt lt amp nbsp quot apos".split(),'><& "\'')) -commonHTMLEntity = Regex('&(?P<entity>' + '|'.join(_htmlEntityMap.keys()) +");").setName("common HTML entity") -def replaceHTMLEntity(t): - """Helper parser action to replace common HTML entities with their special characters""" - return _htmlEntityMap.get(t.entity) - -# it's easy to get these comment structures wrong - they're very common, so may as well make them available -cStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/').setName("C style comment") -"Comment of the form C{/* ... */}" - -htmlComment = Regex(r"<!--[\s\S]*?-->").setName("HTML comment") -"Comment of the form C{<!-- ... -->}" - -restOfLine = Regex(r".*").leaveWhitespace().setName("rest of line") -dblSlashComment = Regex(r"//(?:\\\n|[^\n])*").setName("// comment") -"Comment of the form C{// ... (to end of line)}" - -cppStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/'| dblSlashComment).setName("C++ style comment") -"Comment of either form C{L{cStyleComment}} or C{L{dblSlashComment}}" - -javaStyleComment = cppStyleComment -"Same as C{L{cppStyleComment}}" - -pythonStyleComment = Regex(r"#.*").setName("Python style comment") -"Comment of the form C{# ... (to end of line)}" - -_commasepitem = Combine(OneOrMore(Word(printables, excludeChars=',') + - Optional( Word(" \t") + - ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem") -commaSeparatedList = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("commaSeparatedList") -"""(Deprecated) Predefined expression of 1 or more printable words or quoted strings, separated by commas. - This expression is deprecated in favor of L{pyparsing_common.comma_separated_list}.""" - -# some other useful expressions - using lower-case class name since we are really using this as a namespace -class pyparsing_common: - """ - Here are some common low-level expressions that may be useful in jump-starting parser development: - - numeric forms (L{integers<integer>}, L{reals<real>}, L{scientific notation<sci_real>}) - - common L{programming identifiers<identifier>} - - network addresses (L{MAC<mac_address>}, L{IPv4<ipv4_address>}, L{IPv6<ipv6_address>}) - - ISO8601 L{dates<iso8601_date>} and L{datetime<iso8601_datetime>} - - L{UUID<uuid>} - - L{comma-separated list<comma_separated_list>} - Parse actions: - - C{L{convertToInteger}} - - C{L{convertToFloat}} - - C{L{convertToDate}} - - C{L{convertToDatetime}} - - C{L{stripHTMLTags}} - - C{L{upcaseTokens}} - - C{L{downcaseTokens}} - - Example:: - pyparsing_common.number.runTests(''' - # any int or real number, returned as the appropriate type - 100 - -100 - +100 - 3.14159 - 6.02e23 - 1e-12 - ''') - - pyparsing_common.fnumber.runTests(''' - # any int or real number, returned as float - 100 - -100 - +100 - 3.14159 - 6.02e23 - 1e-12 - ''') - - pyparsing_common.hex_integer.runTests(''' - # hex numbers - 100 - FF - ''') - - pyparsing_common.fraction.runTests(''' - # fractions - 1/2 - -3/4 - ''') - - pyparsing_common.mixed_integer.runTests(''' - # mixed fractions - 1 - 1/2 - -3/4 - 1-3/4 - ''') - - import uuid - pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) - pyparsing_common.uuid.runTests(''' - # uuid - 12345678-1234-5678-1234-567812345678 - ''') - prints:: - # any int or real number, returned as the appropriate type - 100 - [100] - - -100 - [-100] - - +100 - [100] - - 3.14159 - [3.14159] - - 6.02e23 - [6.02e+23] - - 1e-12 - [1e-12] - - # any int or real number, returned as float - 100 - [100.0] - - -100 - [-100.0] - - +100 - [100.0] - - 3.14159 - [3.14159] - - 6.02e23 - [6.02e+23] - - 1e-12 - [1e-12] - - # hex numbers - 100 - [256] - - FF - [255] - - # fractions - 1/2 - [0.5] - - -3/4 - [-0.75] - - # mixed fractions - 1 - [1] - - 1/2 - [0.5] - - -3/4 - [-0.75] - - 1-3/4 - [1.75] - - # uuid - 12345678-1234-5678-1234-567812345678 - [UUID('12345678-1234-5678-1234-567812345678')] - """ - - convertToInteger = tokenMap(int) - """ - Parse action for converting parsed integers to Python int - """ - - convertToFloat = tokenMap(float) - """ - Parse action for converting parsed numbers to Python float - """ - - integer = Word(nums).setName("integer").setParseAction(convertToInteger) - """expression that parses an unsigned integer, returns an int""" - - hex_integer = Word(hexnums).setName("hex integer").setParseAction(tokenMap(int,16)) - """expression that parses a hexadecimal integer, returns an int""" - - signed_integer = Regex(r'[+-]?\d+').setName("signed integer").setParseAction(convertToInteger) - """expression that parses an integer with optional leading sign, returns an int""" - - fraction = (signed_integer().setParseAction(convertToFloat) + '/' + signed_integer().setParseAction(convertToFloat)).setName("fraction") - """fractional expression of an integer divided by an integer, returns a float""" - fraction.addParseAction(lambda t: t[0]/t[-1]) - - mixed_integer = (fraction | signed_integer + Optional(Optional('-').suppress() + fraction)).setName("fraction or mixed integer-fraction") - """mixed integer of the form 'integer - fraction', with optional leading integer, returns float""" - mixed_integer.addParseAction(sum) - - real = Regex(r'[+-]?\d+\.\d*').setName("real number").setParseAction(convertToFloat) - """expression that parses a floating point number and returns a float""" - - sci_real = Regex(r'[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)').setName("real number with scientific notation").setParseAction(convertToFloat) - """expression that parses a floating point number with optional scientific notation and returns a float""" - - # streamlining this expression makes the docs nicer-looking - number = (sci_real | real | signed_integer).streamline() - """any numeric expression, returns the corresponding Python type""" - - fnumber = Regex(r'[+-]?\d+\.?\d*([eE][+-]?\d+)?').setName("fnumber").setParseAction(convertToFloat) - """any int or real number, returned as float""" - - identifier = Word(alphas+'_', alphanums+'_').setName("identifier") - """typical code identifier (leading alpha or '_', followed by 0 or more alphas, nums, or '_')""" - - ipv4_address = Regex(r'(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}').setName("IPv4 address") - "IPv4 address (C{0.0.0.0 - 255.255.255.255})" - - _ipv6_part = Regex(r'[0-9a-fA-F]{1,4}').setName("hex_integer") - _full_ipv6_address = (_ipv6_part + (':' + _ipv6_part)*7).setName("full IPv6 address") - _short_ipv6_address = (Optional(_ipv6_part + (':' + _ipv6_part)*(0,6)) + "::" + Optional(_ipv6_part + (':' + _ipv6_part)*(0,6))).setName("short IPv6 address") - _short_ipv6_address.addCondition(lambda t: sum(1 for tt in t if pyparsing_common._ipv6_part.matches(tt)) < 8) - _mixed_ipv6_address = ("::ffff:" + ipv4_address).setName("mixed IPv6 address") - ipv6_address = Combine((_full_ipv6_address | _mixed_ipv6_address | _short_ipv6_address).setName("IPv6 address")).setName("IPv6 address") - "IPv6 address (long, short, or mixed form)" - - mac_address = Regex(r'[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}').setName("MAC address") - "MAC address xx:xx:xx:xx:xx (may also have '-' or '.' delimiters)" - - @staticmethod - def convertToDate(fmt="%Y-%m-%d"): - """ - Helper to create a parse action for converting parsed date string to Python datetime.date - - Params - - - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%d"}) - - Example:: - date_expr = pyparsing_common.iso8601_date.copy() - date_expr.setParseAction(pyparsing_common.convertToDate()) - print(date_expr.parseString("1999-12-31")) - prints:: - [datetime.date(1999, 12, 31)] - """ - def cvt_fn(s,l,t): - try: - return datetime.strptime(t[0], fmt).date() - except ValueError as ve: - raise ParseException(s, l, str(ve)) - return cvt_fn - - @staticmethod - def convertToDatetime(fmt="%Y-%m-%dT%H:%M:%S.%f"): - """ - Helper to create a parse action for converting parsed datetime string to Python datetime.datetime - - Params - - - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%dT%H:%M:%S.%f"}) - - Example:: - dt_expr = pyparsing_common.iso8601_datetime.copy() - dt_expr.setParseAction(pyparsing_common.convertToDatetime()) - print(dt_expr.parseString("1999-12-31T23:59:59.999")) - prints:: - [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] - """ - def cvt_fn(s,l,t): - try: - return datetime.strptime(t[0], fmt) - except ValueError as ve: - raise ParseException(s, l, str(ve)) - return cvt_fn - - iso8601_date = Regex(r'(?P<year>\d{4})(?:-(?P<month>\d\d)(?:-(?P<day>\d\d))?)?').setName("ISO8601 date") - "ISO8601 date (C{yyyy-mm-dd})" - - iso8601_datetime = Regex(r'(?P<year>\d{4})-(?P<month>\d\d)-(?P<day>\d\d)[T ](?P<hour>\d\d):(?P<minute>\d\d)(:(?P<second>\d\d(\.\d*)?)?)?(?P<tz>Z|[+-]\d\d:?\d\d)?').setName("ISO8601 datetime") - "ISO8601 datetime (C{yyyy-mm-ddThh:mm:ss.s(Z|+-00:00)}) - trailing seconds, milliseconds, and timezone optional; accepts separating C{'T'} or C{' '}" - - uuid = Regex(r'[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}').setName("UUID") - "UUID (C{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx})" - - _html_stripper = anyOpenTag.suppress() | anyCloseTag.suppress() - @staticmethod - def stripHTMLTags(s, l, tokens): - """ - Parse action to remove HTML tags from web page HTML source - - Example:: - # strip HTML links from normal text - text = '<td>More info at the <a href="http://pyparsing.wikispaces.com">pyparsing</a> wiki page</td>' - td,td_end = makeHTMLTags("TD") - table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end - - print(table_text.parseString(text).body) # -> 'More info at the pyparsing wiki page' - """ - return pyparsing_common._html_stripper.transformString(tokens[0]) - - _commasepitem = Combine(OneOrMore(~Literal(",") + ~LineEnd() + Word(printables, excludeChars=',') - + Optional( White(" \t") ) ) ).streamline().setName("commaItem") - comma_separated_list = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("comma separated list") - """Predefined expression of 1 or more printable words or quoted strings, separated by commas.""" - - upcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).upper())) - """Parse action to convert tokens to upper case.""" - - downcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).lower())) - """Parse action to convert tokens to lower case.""" - - -if __name__ == "__main__": - - selectToken = CaselessLiteral("select") - fromToken = CaselessLiteral("from") - - ident = Word(alphas, alphanums + "_$") - - columnName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) - columnNameList = Group(delimitedList(columnName)).setName("columns") - columnSpec = ('*' | columnNameList) - - tableName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) - tableNameList = Group(delimitedList(tableName)).setName("tables") - - simpleSQL = selectToken("command") + columnSpec("columns") + fromToken + tableNameList("tables") - - # demo runTests method, including embedded comments in test string - simpleSQL.runTests(""" - # '*' as column list and dotted table name - select * from SYS.XYZZY - - # caseless match on "SELECT", and casts back to "select" - SELECT * from XYZZY, ABC - - # list of column names, and mixed case SELECT keyword - Select AA,BB,CC from Sys.dual - - # multiple tables - Select A, B, C from Sys.dual, Table2 - - # invalid SELECT keyword - should fail - Xelect A, B, C from Sys.dual - - # incomplete command - should fail - Select - - # invalid column name - should fail - Select ^^^ frox Sys.dual - - """) - - pyparsing_common.number.runTests(""" - 100 - -100 - +100 - 3.14159 - 6.02e23 - 1e-12 - """) - - # any int or real number, returned as float - pyparsing_common.fnumber.runTests(""" - 100 - -100 - +100 - 3.14159 - 6.02e23 - 1e-12 - """) - - pyparsing_common.hex_integer.runTests(""" - 100 - FF - """) - - import uuid - pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) - pyparsing_common.uuid.runTests(""" - 12345678-1234-5678-1234-567812345678 - """) diff --git a/venv2/lib/python2.7/site-packages/setuptools/_vendor/six.py b/venv2/lib/python2.7/site-packages/setuptools/_vendor/six.py deleted file mode 100644 index 190c023..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/_vendor/six.py +++ /dev/null @@ -1,868 +0,0 @@ -"""Utilities for writing code that runs on Python 2 and 3""" - -# Copyright (c) 2010-2015 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. - -from __future__ import absolute_import - -import functools -import itertools -import operator -import sys -import types - -__author__ = "Benjamin Peterson <benjamin@python.org>" -__version__ = "1.10.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("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_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("email_mime_base", "email.MIMEBase", "email.mime.base"), - 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("urlencode", "urllib", "urllib.parse"), - MovedAttribute("splitquery", "urllib", "urllib.parse"), - MovedAttribute("splittag", "urllib", "urllib.parse"), - MovedAttribute("splituser", "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"), -] -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): - if value is None: - value = tp() - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - -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): - raise tp, value, tb -""") - - -if sys.version_info[:2] == (3, 2): - exec_("""def raise_from(value, from_value): - if from_value is None: - raise value - raise value from from_value -""") -elif sys.version_info[:2] > (3, 2): - exec_("""def raise_from(value, from_value): - raise value from from_value -""") -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(meta): - - def __new__(cls, name, this_bases, d): - return meta(name, bases, d) - 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) - return metaclass(cls.__name__, cls.__bases__, orig_vars) - return wrapper - - -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) diff --git a/venv2/lib/python2.7/site-packages/setuptools/archive_util.py b/venv2/lib/python2.7/site-packages/setuptools/archive_util.py deleted file mode 100644 index 8143604..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/archive_util.py +++ /dev/null @@ -1,173 +0,0 @@ -"""Utilities for extracting common archive formats""" - -import zipfile -import tarfile -import os -import shutil -import posixpath -import contextlib -from distutils.errors import DistutilsError - -from pkg_resources import ensure_directory - -__all__ = [ - "unpack_archive", "unpack_zipfile", "unpack_tarfile", "default_filter", - "UnrecognizedFormat", "extraction_drivers", "unpack_directory", -] - - -class UnrecognizedFormat(DistutilsError): - """Couldn't recognize the archive type""" - - -def default_filter(src, dst): - """The default progress/filter callback; returns True for all files""" - return dst - - -def unpack_archive(filename, extract_dir, progress_filter=default_filter, - drivers=None): - """Unpack `filename` to `extract_dir`, or raise ``UnrecognizedFormat`` - - `progress_filter` is a function taking two arguments: a source path - internal to the archive ('/'-separated), and a filesystem path where it - will be extracted. The callback must return the desired extract path - (which may be the same as the one passed in), or else ``None`` to skip - that file or directory. The callback can thus be used to report on the - progress of the extraction, as well as to filter the items extracted or - alter their extraction paths. - - `drivers`, if supplied, must be a non-empty sequence of functions with the - same signature as this function (minus the `drivers` argument), that raise - ``UnrecognizedFormat`` if they do not support extracting the designated - archive type. The `drivers` are tried in sequence until one is found that - does not raise an error, or until all are exhausted (in which case - ``UnrecognizedFormat`` is raised). If you do not supply a sequence of - drivers, the module's ``extraction_drivers`` constant will be used, which - means that ``unpack_zipfile`` and ``unpack_tarfile`` will be tried, in that - order. - """ - for driver in drivers or extraction_drivers: - try: - driver(filename, extract_dir, progress_filter) - except UnrecognizedFormat: - continue - else: - return - else: - raise UnrecognizedFormat( - "Not a recognized archive type: %s" % filename - ) - - -def unpack_directory(filename, extract_dir, progress_filter=default_filter): - """"Unpack" a directory, using the same interface as for archives - - Raises ``UnrecognizedFormat`` if `filename` is not a directory - """ - if not os.path.isdir(filename): - raise UnrecognizedFormat("%s is not a directory" % filename) - - paths = { - filename: ('', extract_dir), - } - for base, dirs, files in os.walk(filename): - src, dst = paths[base] - for d in dirs: - paths[os.path.join(base, d)] = src + d + '/', os.path.join(dst, d) - for f in files: - target = os.path.join(dst, f) - target = progress_filter(src + f, target) - if not target: - # skip non-files - continue - ensure_directory(target) - f = os.path.join(base, f) - shutil.copyfile(f, target) - shutil.copystat(f, target) - - -def unpack_zipfile(filename, extract_dir, progress_filter=default_filter): - """Unpack zip `filename` to `extract_dir` - - Raises ``UnrecognizedFormat`` if `filename` is not a zipfile (as determined - by ``zipfile.is_zipfile()``). See ``unpack_archive()`` for an explanation - of the `progress_filter` argument. - """ - - if not zipfile.is_zipfile(filename): - raise UnrecognizedFormat("%s is not a zip file" % (filename,)) - - with zipfile.ZipFile(filename) as z: - for info in z.infolist(): - name = info.filename - - # don't extract absolute paths or ones with .. in them - if name.startswith('/') or '..' in name.split('/'): - continue - - target = os.path.join(extract_dir, *name.split('/')) - target = progress_filter(name, target) - if not target: - continue - if name.endswith('/'): - # directory - ensure_directory(target) - else: - # file - ensure_directory(target) - data = z.read(info.filename) - with open(target, 'wb') as f: - f.write(data) - unix_attributes = info.external_attr >> 16 - if unix_attributes: - os.chmod(target, unix_attributes) - - -def unpack_tarfile(filename, extract_dir, progress_filter=default_filter): - """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir` - - Raises ``UnrecognizedFormat`` if `filename` is not a tarfile (as determined - by ``tarfile.open()``). See ``unpack_archive()`` for an explanation - of the `progress_filter` argument. - """ - try: - tarobj = tarfile.open(filename) - except tarfile.TarError: - raise UnrecognizedFormat( - "%s is not a compressed or uncompressed tar file" % (filename,) - ) - with contextlib.closing(tarobj): - # don't do any chowning! - tarobj.chown = lambda *args: None - for member in tarobj: - name = member.name - # don't extract absolute paths or ones with .. in them - if not name.startswith('/') and '..' not in name.split('/'): - prelim_dst = os.path.join(extract_dir, *name.split('/')) - - # resolve any links and to extract the link targets as normal - # files - while member is not None and (member.islnk() or member.issym()): - linkpath = member.linkname - if member.issym(): - base = posixpath.dirname(member.name) - linkpath = posixpath.join(base, linkpath) - linkpath = posixpath.normpath(linkpath) - member = tarobj._getmember(linkpath) - - if member is not None and (member.isfile() or member.isdir()): - final_dst = progress_filter(name, prelim_dst) - if final_dst: - if final_dst.endswith(os.sep): - final_dst = final_dst[:-1] - try: - # XXX Ugh - tarobj._extract_member(member, final_dst) - except tarfile.ExtractError: - # chown/chmod/mkfifo/mknode/makedev failed - pass - return True - - -extraction_drivers = unpack_directory, unpack_zipfile, unpack_tarfile diff --git a/venv2/lib/python2.7/site-packages/setuptools/build_meta.py b/venv2/lib/python2.7/site-packages/setuptools/build_meta.py deleted file mode 100644 index e40904a..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/build_meta.py +++ /dev/null @@ -1,254 +0,0 @@ -"""A PEP 517 interface to setuptools - -Previously, when a user or a command line tool (let's call it a "frontend") -needed to make a request of setuptools to take a certain action, for -example, generating a list of installation requirements, the frontend would -would call "setup.py egg_info" or "setup.py bdist_wheel" on the command line. - -PEP 517 defines a different method of interfacing with setuptools. Rather -than calling "setup.py" directly, the frontend should: - - 1. Set the current directory to the directory with a setup.py file - 2. Import this module into a safe python interpreter (one in which - setuptools can potentially set global variables or crash hard). - 3. Call one of the functions defined in PEP 517. - -What each function does is defined in PEP 517. However, here is a "casual" -definition of the functions (this definition should not be relied on for -bug reports or API stability): - - - `build_wheel`: build a wheel in the folder and return the basename - - `get_requires_for_build_wheel`: get the `setup_requires` to build - - `prepare_metadata_for_build_wheel`: get the `install_requires` - - `build_sdist`: build an sdist in the folder and return the basename - - `get_requires_for_build_sdist`: get the `setup_requires` to build - -Again, this is not a formal definition! Just a "taste" of the module. -""" - -import io -import os -import sys -import tokenize -import shutil -import contextlib - -import setuptools -import distutils -from setuptools.py31compat import TemporaryDirectory - -from pkg_resources import parse_requirements - -__all__ = ['get_requires_for_build_sdist', - 'get_requires_for_build_wheel', - 'prepare_metadata_for_build_wheel', - 'build_wheel', - 'build_sdist', - '__legacy__', - 'SetupRequirementsError'] - -class SetupRequirementsError(BaseException): - def __init__(self, specifiers): - self.specifiers = specifiers - - -class Distribution(setuptools.dist.Distribution): - def fetch_build_eggs(self, specifiers): - specifier_list = list(map(str, parse_requirements(specifiers))) - - raise SetupRequirementsError(specifier_list) - - @classmethod - @contextlib.contextmanager - def patch(cls): - """ - Replace - distutils.dist.Distribution with this class - for the duration of this context. - """ - orig = distutils.core.Distribution - distutils.core.Distribution = cls - try: - yield - finally: - distutils.core.Distribution = orig - - -def _to_str(s): - """ - Convert a filename to a string (on Python 2, explicitly - a byte string, not Unicode) as distutils checks for the - exact type str. - """ - if sys.version_info[0] == 2 and not isinstance(s, str): - # Assume it's Unicode, as that's what the PEP says - # should be provided. - return s.encode(sys.getfilesystemencoding()) - return s - - -def _get_immediate_subdirectories(a_dir): - return [name for name in os.listdir(a_dir) - if os.path.isdir(os.path.join(a_dir, name))] - - -def _file_with_extension(directory, extension): - matching = ( - f for f in os.listdir(directory) - if f.endswith(extension) - ) - file, = matching - return file - - -def _open_setup_script(setup_script): - if not os.path.exists(setup_script): - # Supply a default setup.py - return io.StringIO(u"from setuptools import setup; setup()") - - return getattr(tokenize, 'open', open)(setup_script) - - -class _BuildMetaBackend(object): - - def _fix_config(self, config_settings): - config_settings = config_settings or {} - config_settings.setdefault('--global-option', []) - return config_settings - - def _get_build_requires(self, config_settings, requirements): - config_settings = self._fix_config(config_settings) - - sys.argv = sys.argv[:1] + ['egg_info'] + \ - config_settings["--global-option"] - try: - with Distribution.patch(): - self.run_setup() - except SetupRequirementsError as e: - requirements += e.specifiers - - return requirements - - def run_setup(self, setup_script='setup.py'): - # Note that we can reuse our build directory between calls - # Correctness comes first, then optimization later - __file__ = setup_script - __name__ = '__main__' - - with _open_setup_script(__file__) as f: - code = f.read().replace(r'\r\n', r'\n') - - exec(compile(code, __file__, 'exec'), locals()) - - def get_requires_for_build_wheel(self, config_settings=None): - config_settings = self._fix_config(config_settings) - return self._get_build_requires(config_settings, requirements=['wheel']) - - def get_requires_for_build_sdist(self, config_settings=None): - config_settings = self._fix_config(config_settings) - return self._get_build_requires(config_settings, requirements=[]) - - def prepare_metadata_for_build_wheel(self, metadata_directory, - config_settings=None): - sys.argv = sys.argv[:1] + ['dist_info', '--egg-base', - _to_str(metadata_directory)] - self.run_setup() - - dist_info_directory = metadata_directory - while True: - dist_infos = [f for f in os.listdir(dist_info_directory) - if f.endswith('.dist-info')] - - if (len(dist_infos) == 0 and - len(_get_immediate_subdirectories(dist_info_directory)) == 1): - - dist_info_directory = os.path.join( - dist_info_directory, os.listdir(dist_info_directory)[0]) - continue - - assert len(dist_infos) == 1 - break - - # PEP 517 requires that the .dist-info directory be placed in the - # metadata_directory. To comply, we MUST copy the directory to the root - if dist_info_directory != metadata_directory: - shutil.move( - os.path.join(dist_info_directory, dist_infos[0]), - metadata_directory) - shutil.rmtree(dist_info_directory, ignore_errors=True) - - return dist_infos[0] - - def build_wheel(self, wheel_directory, config_settings=None, - metadata_directory=None): - config_settings = self._fix_config(config_settings) - wheel_directory = os.path.abspath(wheel_directory) - - # Build the wheel in a temporary directory, then copy to the target - with TemporaryDirectory(dir=wheel_directory) as tmp_dist_dir: - sys.argv = (sys.argv[:1] + - ['bdist_wheel', '--dist-dir', tmp_dist_dir] + - config_settings["--global-option"]) - self.run_setup() - - wheel_basename = _file_with_extension(tmp_dist_dir, '.whl') - wheel_path = os.path.join(wheel_directory, wheel_basename) - if os.path.exists(wheel_path): - # os.rename will fail overwriting on non-unix env - os.remove(wheel_path) - os.rename(os.path.join(tmp_dist_dir, wheel_basename), wheel_path) - - return wheel_basename - - def build_sdist(self, sdist_directory, config_settings=None): - config_settings = self._fix_config(config_settings) - sdist_directory = os.path.abspath(sdist_directory) - sys.argv = sys.argv[:1] + ['sdist', '--formats', 'gztar'] + \ - config_settings["--global-option"] + \ - ["--dist-dir", sdist_directory] - self.run_setup() - - return _file_with_extension(sdist_directory, '.tar.gz') - - -class _BuildMetaLegacyBackend(_BuildMetaBackend): - """Compatibility backend for setuptools - - This is a version of setuptools.build_meta that endeavors to maintain backwards - compatibility with pre-PEP 517 modes of invocation. It exists as a temporary - bridge between the old packaging mechanism and the new packaging mechanism, - and will eventually be removed. - """ - def run_setup(self, setup_script='setup.py'): - # In order to maintain compatibility with scripts assuming that - # the setup.py script is in a directory on the PYTHONPATH, inject - # '' into sys.path. (pypa/setuptools#1642) - sys_path = list(sys.path) # Save the original path - - script_dir = os.path.dirname(os.path.abspath(setup_script)) - if script_dir not in sys.path: - sys.path.insert(0, script_dir) - - try: - super(_BuildMetaLegacyBackend, - self).run_setup(setup_script=setup_script) - finally: - # While PEP 517 frontends should be calling each hook in a fresh - # subprocess according to the standard (and thus it should not be - # strictly necessary to restore the old sys.path), we'll restore - # the original path so that the path manipulation does not persist - # within the hook after run_setup is called. - sys.path[:] = sys_path - -# The primary backend -_BACKEND = _BuildMetaBackend() - -get_requires_for_build_wheel = _BACKEND.get_requires_for_build_wheel -get_requires_for_build_sdist = _BACKEND.get_requires_for_build_sdist -prepare_metadata_for_build_wheel = _BACKEND.prepare_metadata_for_build_wheel -build_wheel = _BACKEND.build_wheel -build_sdist = _BACKEND.build_sdist - - -# The legacy backend -__legacy__ = _BuildMetaLegacyBackend() diff --git a/venv2/lib/python2.7/site-packages/setuptools/cli-32.exe b/venv2/lib/python2.7/site-packages/setuptools/cli-32.exe deleted file mode 100644 index b1487b7819e7286577a043c7726fbe0ca1543083..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65536 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[c}i<OXTz6k>I#RErv3nvcIClH@!{vM)zJ_weD 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 diff --git a/venv2/lib/python2.7/site-packages/setuptools/cli-64.exe b/venv2/lib/python2.7/site-packages/setuptools/cli-64.exe deleted file mode 100644 index 675e6bf3743f3d3011c238657e7128ee9960ef7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74752 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 &sjKl@1{;unAiW2w^OujNoW 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 diff --git a/venv2/lib/python2.7/site-packages/setuptools/cli.exe b/venv2/lib/python2.7/site-packages/setuptools/cli.exe deleted file mode 100644 index b1487b7819e7286577a043c7726fbe0ca1543083..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65536 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[c}i<OXTz6k>I#RErv3nvcIClH@!{vM)zJ_weD zu_-L8NU*G<xQC7$Bg`f~d>lC{d0L!!VW10^+~>qmNB~Y8H+F}!P8_d(PpvjzMJQmr z)F<LB!IdzF`7%cck^aLb_J<@DD#CfB0B$E^bzV@-Vr`q!&`=<s^68_Wa_GZ_v^?aY zU=VZGXAzm5x{LcyVkUd8JxnNsqtS!3fw-nje@5tui@0AmI$b-*P5O7)s<z9AVj!{a zusK!aLirXkGmKBs9|=}}+<^)RB1ao<^{^>kX;2B~<|3JfJeWv@IXo~nTtp$}Gjie> zs8UDG*kid(%i5QCBp~MA;#I186PI-nZ&k7!k8BiLJSuR>h7ArSYHD~<iO|JiNP|OD zR=9Lm@@Ua+Eq87EAwAZBPGrH*)zP)xEF>B0I<PUu3WRluor4HwG59U@*GT3C4#)*> z=T6L{zqglekt0JjG5z&|GWb4?+B5+{p^fgTufl_KesA{@I&g7rNq==^SGc5GcM%$N zDBG2)qExz*Z;jGN_-iD-y8i2BCq)p}2lKcspLg>w-;qwg(()HXrZa3jd!}spuwBVX zwmX!iwU<Qo&ds@10tJ4pnneT?LI)M|HS1v7YY$x9Bv-SsJ$Cl+xPAV;6Eqk-srxG9 z{LT5_#k!V#{GO}ibh%Xvw5jxHs@yzGY~@?`(yJD$GqsX;X$pypI5DT^o5eVu9#Z@z zw!tumU}_j8#vZXTB&Vb!;K(WYBw))aIfHo=I@urFFfxYS9PyXWVFQN5U;5Dw%tIz$ zw`nTQR_c;mZr;Y5QwPf3_^KR#GvcZKkFXD~jQGWdi~_bGh!>?#7uoQnunw|OlU~+c z^L5Ak3zWhaA4B^FhMMboO0k*O2GL)lD9_<$5b>czbCvKcSt+u*gA*=%dH>Q-Bc11h zzO7jbXN)&5mBf=w2anK6P$YcJZQoWa2#E!v{hFKxxm7Fc)Fc9iC35{|Lp7bIDjrhC zgMiGf4r2yquH{U7WdMio;XS4Y%Ry{q7#kv#gZ07i`7eo#MMh_o68E*Fd_#nrri^4b zX+slbsv>+8pmck%oLDU<yTk`c&RTk8mVQAOK~qMQ#2raos*zaqlvJZo>L()8NRJ#Z z8DReF_eq2zsjEXGs)yS{k}ykS1B!ZrY0f6O65^lslJv3g&wfpDg-&EwF8wrc=hSwm zPlV&n%%yE_@onOwK?)`GNJ6MQ0drMuBYWCH5dkD)uErh@*k}#GcFl<-;;TN+5vb|b zctkCv;*zL7f)A;QuO%(81r0)&aUz4EQu;kA!k@7i8RZ)koMaWW`5cC6n@{w!!J$5d zx}l)4VP4xL=BKi&c^{n_Qi`q@G{vimblcVR53b#<Dz&@nl0LRIeY=p^I1%{g=J)$y zJ4tny{}tcKG0i7qLLJtU;jl;LnJu8bQak(kB&;UDjom{#=dp=&3s}YXYz3C()*?Ie zpOr>*X$FUOQFm!A8JKahNSiBdY+x3bJZfD8n{--FLUM4+Mx@{vM<W!B9QJEa7>_ep zkk)U=K8R(rhU(X_faI*ZO}cn`5t*O}lx^j8|0rt-)o=Axn^DGcQTi!#7hxLTq?|HQ zB;T6(nrsCeYK0_o%)IO+CP{n#+|;w1ZmvD2c-J{i88bp63RjyKOE!B!D3U{RCs*Zh z&^%65VM(J34230U4bHS}M@SYS9TEK}c%)2<$h1|T;##zRtjRt@#1T%J=kAhOiw+Z% z7DpyWVK@6%9K^uVD9LDKj)dR^aZK6$@Lt)l;sj@`QSzBm{TlLG{JKM_^60Zr2w~nr zr>P-BaV8OjjWm?hQ3$ZCx+lyD%q`~4iNF9xWKi$t&pzBhwN9Dq-o^v9@=abLR#|<P zZAhQVQAqt{KX8b!o72`jV*h~V{I<6~6`|CSYi!tcFRq-OP_ri!l#8;keBk$FyRh37 zh-vx<nho1V<uSlQEH;(ry7_afSZop_PK$8boQKoq+i)shoyMOs4}aFK<j<xGJnq14 zb2)CC*WtE#b4An68qy4#ciQ16Pbjcq3r`~(syir#2qbbvYtKWddcXwdfk_9bi9C9n ze)1pT^3siP-~5MsCpR}_o2eh^LneJBm*p>KZqkLal4YCRR9VNhIM|rBqmzzcImvcx z66fD`zj4}M-A;gyA17cSC-oI$`q?*q&8~)Qv|C#(aSFd|hYbf}FFVB?n3Q?Svt+Td z#AW4x=9X}?aizE|`r{}3l-H&b6-{_j#STR!lD001vu;K>KT;*^ChCevBwCMFpg{JI zv``4YsjK1&142Pl%%A#u3rbGso1<_fngd1`+}!pMu@z5Me_5UFxiPYKqFL4_`WXmY zeWJrZUKzrrMuBcHupOq4Wr12sE*T-*CXh;FA=)Q+BMN(?DJ!kq?%Ww`xlG3e;lz2t zY?tl;i?gHO_79VwJ_cThq^>FqRUPlqS?IuI+CfSbNkv_1l~7eGaCwRmuOF|ic1ac2 z9ldo$TN~LhX~J01P75nyi&d8=Y@QNZ5e<=6v_R3rM}nN}5ae`^LV&sAD<=;*z=!~` zvJ0@i!orMuT*5kyXNzJnxfU!+#FTW(syy@yj7XX8#zD_9TWBSg(;KZ25VO;is;-&R zf(29n3U}agkC`j4sjX{=`D1EkCC@enOA~v{GOLYQKAdPN6+?W+QE4fLMhrW4RG<SI z@?qI-KY>bH5^K(rm4T}`=ra<6GP2}cRBE9K8^r(O+ZvKpJDL~qNguPmwQZp-8m7V@ zN^KFU8@Q*E7UJswZD=OYtct4KqA&NDKSOfc-#M>@o#)4;YLqtENdFS^3K9&dFBr|M z*loqE3X2sMmi8hv#7H5<kgna*Z>rqGc_y=ShEbHT^m7S`?4d%B+(-6dYGI-*t5E+< z^P3gqvBIHjFQNKiDKj-p;Y*MmMAXOK^8{gVhrBn?Un}%9(JqaGPiann?Ll$aX-{n1 z!AnT<v!xN*zo+dH+)yR$d)}fNUUOcJ)Xz$%vH5mur0%L;@p((;IW$raH52Q@7``Z{ z?rO>WyjwZ7y=hrziEYVZVX)-}D^!8a+Bc<5#*3h1xvWqS7I$WL>iwNNvp;P<;TX`| zOF6ZibFB4T(YJC~mj~?Ev*ln|9sgYVFTcLiEi{YE;!ZWj>X*aK9|va;HulW-D`RH9 zw=O#R&of(j+rwMS%oCi;+oFskQ}@q2q4x)O3<fKs&%WtzzFD};-G{Hxx)V?F$WHWF z7(*i07&g=2&}`P4G>k5e6yDx`kLvQs@M`+D)vGA+`X6%Dl9YOA?Qrurfg>XqT9E@^ zgWxOT&hX+yo>7=HCb!3BO$p54I3{j@qbN!+nu>Ti*O~vw`5RU!f_JXS+*x#-zFp@m zr}GGVhgT1=p-TFp#dtAVjM3QdpDoi{l*z?1s=d~(E;Fkn=*i8+oB<M)E&5W?I^M)M zknOw+hdKDcP%Q}tuai)WoEa!7&-Iumsf3KA>cJ3Ib?Vh+rZWNZ$pO`dl8LcBv_cAA zc18lYB|rc<0u%wEdTGEup|%_S`L>@ui4LTkvnNApm<q=y*er!iCv8V>#>+b4WIF<} z^J}=w7L&$J%unXCb|Wy{z3WVlMDNhz3o7S-3)6oqjx)7WX0HTEH<C-Do)>{-=9>q+ zXXtoVPHKfVJMk8bt&h;MII}u~0l79^#`5CdW6Ef!eb|E&Q{UJ$n$yP;^Jd)qhw~ej zB?c~nN*%0zm%$}MD%|<q*x?^2$-sGY)_qDIsjoQeKH{k^*%_~Mm`JG>VZuS8W+Qtf zS+Uu?;oSPL<h#s;p3UgxZ3c;@9(LZhh9?&RH`z;Ufi?^GL|RbrQ|i$u#k>L}G`jMH zn3`(J{6K%B(Gykos(!d}z)Wr!%sjC6=V@s)qG1MJN~uoVlq{jeI#XKPMI;@L^`RBZ z<X%K$e<C_&9&p~HQ%fuI$-p5?U{jDsR}QoVqzzw}E77mP5v&U`27f1F&0F8zlxE2) ze=M@fh-;2;q_!ewec2frY%fKQkh6Y#Ck=~JBu;z6vOFXzd7O1mkt`yaC)8Gn>0Fhm zEI{|uQr0z1gk4W{mj*%4Z*00DBL5ko{4X}2{Dl0wAi#aSmq_r~FBHL|;}P&0k>OU! zhx64h5vSKwffV0W4JQs2dFBrfQx(B{AK=BGc`U!}S&BFnE6QSvw?`~m^}8j(4$IzQ z_WzjR?fD!VI8Aa=N;O96$f<JeDN}@@k24)dnpa7nV{o~|y480HWd%qi09M-w5HA7H z5t)dJA9OeU2(Ddz+nofIxgaM#sfN{v)}n+p872aEFyGb(<(TUTpJ(1Bv9RRP<lWbe zn*X9W;yA^EqlAv1#u2Gg|1wrNw~{@z1W#o_GFNuVYLs|BsZ*hkg_h`Il0YDiCHm+W zmS~Y0wwCC%sMd>IWzW@IV2KtfOm4MwFVU~FM5pwL+-yY-+$4mvEEjvjP+5JUm8n(w zTE>U0(q9W!VAi2soP~_07HUw%Pt_tTYxD^79a6Fw-(PjP4xwLxv3Ycv!%RV}m`xvC zX`nx*(H@IF+EJ)392Ul)-t@Oj>L>VGb7%C~V}eWde6yYkCcYR2>L5_BFiz*D#3I_* zY)|v0XvW#xv=Y0=d;t!!=&NUW2H8t2>2H>>rUwQga=@Hd8s$Z+x+rNk0%K7J*cGvn za#2GFTwHgcx}(hY&AoeJJ>OtvvdouZfGLkWz?5@JX6KrhfDJ0`xz(qU+f2hY)2ykx zl5dMrs#`m^OO;aljpVNpXHI7j?NBazjFr-P<5NZ{lysyym6ILI!i}auR#r=s8-sHH zo|F}x&aDr!mLdRfA3dBON<#lrL!uSm7=o9syd*hDuX`F0HkX``(5Ixonj|KOyUg3^ zQc-Q1zi|oXoEJ7t`z@l)r8HbVnV=3@R147(4T%Z?MF>|u+vhb+dmd}f?PMV8SW8Om zNGeF;<~ukE61hiT7Fejt`7XmU^|R{ev+p#`i$*Qly)%e2TjDu=LV)p<*h6u5gyTBv zF2X}pxW+%<Fj!P}AZas9RZ`k$Jvv1owwn8%W?{}x!+bkqQCghlz9l!;d?w_cXMXg@ z&=}JPT7tF@L2ahnMB72@q!wG|Y3@>;eRIVAvq#45Tg=WlQSFR|)0f>5G`p(9xM7}| zFKtPEbWZkN=1qLjD*3c&W=C5QZ78nOyIt7^bEIKqkTQs5B8y0Tx?-c7F3RU`pPOs` z_?hl<U&@p~CMd0Mfz5AN1#S&Vwsi0NvWloHbK|_KEOMjJm}q8E=E&9JuvOv6IZ8ov zcoQ8$o#cQM?=kPAi}LePW480inT%^k+4bRRjjowT_3NF_?RV~cwfUrD02;pIjR9GK zQO@U%q%4cq2SOIu>A-(AYe*|k@#n%-mt4P66m+?M)nmWXqWP-^>As_PEzQPQQFQR8 z8-h3Q39C3Q91oVz2*#A-KL%2bY;8!cmJ9uHA`|<v{z~0`eQ`+GHZb5=o_|mCd#>C8 z$NX`>3!Xc-34zzMQ(s0p^HbkPL0@}t>MK)QkhQHnsYONA8Y3sjLq95yD8o_vXX;;L z>_rtUVz~Yrx{&>y!BX_$%=h%m(WLsmNbc^@hvIY`rx=`G3p{Y^ZC06YKwy@l-|)Hh zU=6u>PjJFvP!kJ(Tc+sbM_EIjrY|G=W}4NvvWB>k^nM4`K&TNt=8t0byviN1Lph6= zm_yLKL?eam;`vUGWXllNQpvgH+$3sPb_yL=Bg|EjmK*vv&mK-$JqW8%=|ASK>2#&P z_Hr|Y5Dkgu7#^X*C_?v-?p6bh!n7?WmSW!JeSwnSm}M7T5((zV1Sgd@d05#6N@`iq zIof-m%Wyrh&Os_zmvwFpf)UBIy{<8BeDtovo%NaL&_|tBV$bJ-C;E$apFPY)zG1$1 z&owMVml>CDJKAdL5zE6EYkt$pYmLfF?wDG0`I8N*#DQu4-A7E6KcN`U27=18Fz;s6 zgRIKZJ=&bE;>8osoUL9Ryh=TbC>SSDx$a_ae4Sb3Y{(ciQKVJ&x*C=an(TMl4xLH2 zXX$$5{C?<{&`X7#bw|C!?@WU>(wf=M60Egk4C)t`yyBd`(C=(qFld4VoFf6R4+pHN zK8Ll6cJ>?zJRuIOK|)?8A%{uGgm6egv3W?S%i_2=V{%GzdHk`#X)(c}lhxAXtow#+ zFHp)}cHUdTEBD@=-@HTIVx!PQ#~t7^T8*<#^hS~|xc9~6%di^At;m{`IHO;U1JyJ& z?$6LV#Y%45gWjnIu3a5-`VNydN5;meS;L)mKjUK-hMMbbbJA&Cbq9~|S=gw!q$wS} z<Z(t^y7;u%;xGk;LG3lcOw_zt$NHvB?!ZTuJIo+vtIY)W*7UDg7nZYhgoJ`|`U@?# zf&SRW>>!$M`UNJWuIMmgl*gmkLk_ZS(?`c%lMZ(&XFK8NP#)0^vSl6vFEG>}Yt=qY z>WCarV-#iQR(@uObO3d9Zj~Ae<}6f(n;Hky?Oz`=r|lj-I0#^gmZN5;ee)19uN-uf zbLW7xnioz$Qqpv@afoy00q1WU<dahvrqv*^Tb#kb-RY_O47=@EAgz1AjGqJEU%$BD z#{P{%{LcENgC^i$Gs0h&&6#v8aM9Ug50ykMQMk~#qpD^cswS=IIHD-)jLMD@Eu?Zl zXzx^j#tYp#^O##HK)x^gH2Y8oBzw6P^DLtqvNE>|&pEgH8343To6masFPXZZ+i2fw zw(TOJh6NWV1zH#tgBTU7eP2E-U^0`E%lVvRweM3##v6R|Hc)r2ZWu6UP8uu_SKF^7 z5Ei+b&tX|(bW>KeN_C)b7q?VhC2@*pFT<#gaK20zQb%f_ppm8Xf&=AdHBgp?2g=0N zzUt06{THYVS>0fh!O|&%MP5GTWr9DpB_rmtxWJV%cw()<Th-`+9pNw^epR)x<&H5y zNn}p<5E>yvDADh1(g)ek#K;gD6diD^_G>B>y~3*2ri=>?y@k#|fr6r^y=jEkKl3E7 z4M}aqf+KgXac<4$1&vT`xA250AV##H0=5ek@I!)vK3Iwme$0oDmHS)WNy*wIdYTYj zZRu7LFxIS58JMfP!&x-K4>+HK()5vW=nSz9Me#w3T`4{giqU44ixK<NS-`KgQcF~+ z$)Xx~#$%3oPu5N7C1^%ShRb#_>rd!tunBaOeaO;`@Gg0VSi}FyYeUlc*jfuoTFFEd zOR8Z4RTBHrnM_v=qLS_KTIyGvYt1|?i!+C4y??`sV=b9MS0Ju6Q)C6T`W3;Z%o85d ziENh~l0#_RtCgzGELP8JHB9M!#^AHfT3W1T^h?P+q1$V+gEe9y%{FPzuSsRs@Ay-r z&&$%MWa*cg*GZ8R;SHL@d5gHczoSYe+a|;+l&uAZooROH4pP=g`GeNXPLfFzb`#S1 z2_-JE19Kg4B`^wb`OGw9drEbu!t~n%qeIJiU}$Ld55)5#)skz}?aZlPlQ8z#UJ#-| zYO^vmzd2P;V*j5ETWQQ}A;NIjCB|%xCEmF;jXrG6JdLv!xSAK@X@Sdl!B-26nk^;Q zowGGGn&>N2cRRN_tq77S`L(hZ^0u`V19Af$;OpSM*@-NJvG_<B4C7r?o87^iy*8Wb zMrpq6c67@_sMBrzt2>@@hy5J^v<IIiJ1y|!Q!YK$isdqQoTPDML_TG>d5CVZ8v5tF zwQ7lkRx1I6-#=R@`m)Md`q#Na+?08k)vz7fn~b?P7;2Kt8t}>IiMVUrKGxYujGZWb zLanz`MzcgG7IDuLahiX|7e$b)I}hh9p%{<(HOiH54&kp~Ytv~>ArTCn#S8~^$oQ)X zh^?`%yGTMs6NUtL_ntBL;MAmDP#8v#36b}%i_U$y`ln#i)B;*>S*Pvjco$ClL? z%=q~elnuXpj0WVh4c6?B5^b?x@W;C;BYJ#|yQV(-^BV8xS@qdyP_7}XGtF%KKWAjn zLectNCDB|O$s?N`pgU^fn(!runKLO{ZL*IDdN#goZ=z)9FDy|a4b+7tIf&rq{hz40 z&UP~#62@?Yv#|LPJJk&HQ3e)?F*x^tH_b5TT8Z=h%QKll3XntrekU{W1ucz%R_!vl zu6JTwtI@B2wku%k4*@aLHLf+aS<jd)!%M#cTQ)o{<ty6y;vrvlB!}@s{CO0_`ltZs z3fJ>dHs*_rgZ{Wh2W%`KXEPa`u}qU^8Nd`Gtzm`f-1-zBi0iySJ$H?3COIw5Sts}8 z<+Vm%m)h*yTBpLCW?Q^x1F!Vd+Cd-yYm=~2?%cW>C+BZ7&rJ<xIqNRtBg?sU36IuH zGk8uOY8JK)$4P80(iq7HrP*8qcI&NRs5o4XL)iMFv+i5c$~Hy3oMB$wp_-Th?yNKL zAangr28eU(Pbpw+wfW(1ey17vQuDUsxUj8DIfV^QQ0G0jGyEy5^P3)CLis=cawvai z-5gx4GVHJ%DF#_>{WkI2`jH<!Izhz8W}oAaF^s~#^M*_X2XtOm#D*kvo)l8G*-}>+ z<t5PsS#I^dD)cT0YpM^@RaIwOUV(>b9w~ZgNut<T7H`U!4Nfz|w82YY^r-kX#J6>( zRG;4bHiKMr_Jpiv$aIiF9yPwvac%awnv<K8gmQS^5Q443>2~cp8C&!2=C}j(2#tMi zjAaHm5bPpSUwa%RYp-#*{ngfz;(tXArj2S*S=&8{L(57D#>Sy>ye}&aBu|6{WXYoR zJy=+9jhe&f&&Pd^I=}K3&D!?hXM~&KKNL|-rI@I}J}9IBm%CT4Pr(h2lA`RU!W}#z zTt1O71J@X3uEEEm16dpYC#BMwiUd{3p3PQWl4fnzvSl_Q9@M}hNeE;-!hE}nWGGc1 zPd%s4GDneKLvjGcS1HB`9XaviNE~IJ5)rQKQ@w;(FbQa{p*Dyv{NvkHXAi;5a-v(C z`r^gH3Wfzd%G^(xROzgOnu~kNc%v|Y{{$u`D4$wu6mDT|WDAsPz{x$PmVRmi?cZF+ z-U3yHJ4XL3ya%Jx{3B1Os@RU`W_KkhwTO`EP<`_mS~KR8U+7dTIE{Ja&Tt#Gon$nl zE(dWJp-%nLFGR6dIAy<_TXIXDnE(n>ay2-K8OIy5nAx_qmLyOgtQ6Fj%*-=qe@HKi z0nCq$syuW4!}7)5RiQ;?m+>J6id0FQbux>KbU4=#b?)3Fg%G{}A@pSk=NYO@J@Gx( z+{gD5$inzGt&2vIBM=9%&Ys$We)D#=;$X>?T(d~*H3&8|nSsg$L4-o()4BCDnT9d8 zE_0<UD}u4Lw;fd;UFHK1Sw-$AMSfUDn)r(v5hd^Sk`)Y2*Ymsk6l$eaD9LZJB+_ZC z?#wseq9VdWMx##Wq_ehmu!z%RL@#$oFo~*F_DyBDl?uh~G*>`&P_=OS)^ylwt2<5* zvwCk}v{^^0RD(Mo4Ce-R%T811{Z?J%>mVhkZSqsZUab`AH#ms$5NI#mLjx`}s<cDr zd(bT?x#j~c4Ean`t;tA{$e7DliznxUyYchy8+U-d7c;x*N+iTJseQy>ob@d<%w|L( zocFxQ+iwIN$`Lbg(^wA>sk1CDaCHq1dn;88aoAtv)vqavty0V_rw}n1A$&%RTW^fp zY)}2T(vF=bG5SC~B*4=@Q8ksK&3H(1Umvsi=+-mqUO_!8b(bJ>RT_kck`^w4=oz2- zwmQq2dD6<s{fq(TOjQ^`MAUW8j=)Q)pKZQtBiUBnNhi3h<-*+j`^bGNgVvX9{sEGR zNO&hvNz2S>)<X=Yal0`ZAdBD?=G#SKJjZ;G*RVweNW@0_IHN=HbIvdd$%?KtCDDXl zS-puTv{HE}Vwupja?ML6W68l~ZcsT0fl8=k*}`^H<U@)jw_TZWQdA3@6ACGl0(xdK zv6O82hzlWrpNr9j5G_^2VwJ3Rizru3uw+-GLsw+ulN!^ZTID%+Zm>hOs(rtPvK;BG z{Y=ms-NO?H{RW<b%v>f<@R!l@1ap~PGv8k0k3-q__{PCC@7C5Fh^ikPxV*RPmYM_6 z0kfvSzBw?k$ERj&%~qlI8?ow$vto~Q!31rW=wT=8P}xDGS$oy?u<(xFOYiHeWgsP# zT)aFG=O0)ID^^KfcN36{h|5_lk9ol<i^Xs#!VJ1=)5TyRo4{4=Mm$HcD9|-JJ&<fh zkv<f^_enN#g)O(Tku&Sh7?;YX7>2Erhw1%VG`GJQ^J0PAl8jr?Yx*E!U4=K2it(Ud zQ6rhrtZtLI1dW*3;fTHQ-7(GY#w6b|7=sK8vsi6UF!k;QP1I`7T{{)D%r}j9f6JY_ z`axh=-H>^}`P?qy;<rl2GrJD5de^xKlln23Oy<F+EPK<&BrJD#Zc35s&LNx|Ji}&J zXm_K>er7j3=la1cXR(2P^}~G5U@)^Y9R^W~(Yf&ei6pNG>XS)n>Z@{y@SU?&+x_PP zwi4TIm{g4?h9h`GI^_u<CDQ?3teJ-(%{L@AWgch0dr;Ksu;h1GD-v@Vd?KD%8=f^m z;~-ZoK9U+x<NkT(4r1pAmLrJ72_nawwuDKdgr0<*Fp4!2$;P1$QjoiH>ccL{tvDS( zC7i=<#ERSNqK5joFl%3Dof%|KBvEU5qQ@ea%d`kN0xVuIHgfZRyPgfKsk;4%Cssd! zRZy@kcG~O{Xfb=dB)TDUpTCpV$~J|+y5e-hioLf6Tpsh<?=bFK?P5~WABz$q<20L1 zgK^Njk^zL6F8vdO>o_n_hSP(E;qsV|s#j?^8BAB(5Hf@{N#z(eFM>tMXu;~1uk&K# zE;Rzpm%)M=;(^<h1j!5clYZyCd5BydPFZnUI5nru$8oe_LALrZ21JRzsDzD_MOjK( zk00E|rj4;t{uou#?P7|O!p$-N?LHWDp|9zbIyggai<?WN4itPete-Y-G=orT;ji9@ zLZ=ymGJHhw=e8|l=poY$b}_LL$-0_PXX|5f%|!A;LiZHb1)@|=P1CS_a;kCA%$JSh zxHn`U3rtF09;IJZvp#yJae2*p+iYVjBMKEb-&RqNfxq_i50rAjaJMzrB+u3l!Dye9 ziMZoyHmr2-3XD;W@iY-=yLLglF9DNcS7U9=rn>O${@GT2SY*Q<WH6{6fu7s|*TK2< zT3P#Nn0GR%^BYE+f1!axn_2WK8jB`q6;Wudt(Y3NX71&$7WkD1)-24lgPvS-^RHD$ z_24>}7pOi8US|%YNHQuI9Dx}gPKACg9BY2xSRbtn$9iuY9oSBsmKgV3c(wEn=%-nK zD|%o2NhvE{vveJc2sn-K3I^M)_Ob0-oNJyT-AUD_7&*4H{_58PGyIvmsB7>#GLE9O zM_%Yt+6~?L-bud7E~=~mV~m!R6?=_4{MCo0O}Rex{k}23X2mR8`5ssCbIoY$sMFI9 zV=R9en4=k(1bGJ`JxbOSr0X_SY1>&{IxnuM;$(R1rZhlZsNjrRzXB)?&li~var z?B}%klDLWDf^4)nO#Q>nX4L#{frSueKHj{6e&Bw?L>`d{`ZHFsWS3ZmQoc`R>p!Zt z)MWNo*@Q0+(@KUAHQ#)n2!1ZmKjktmg>5tXOlEwvo@l;@bE{CFH1qfBRZ%~VD0^FK zYxkW_5R7B$+uR~XI@m1DA|0`t2h;L9#E9HeM)1wN?ybHta2K0&yD%+>v34#tOPGE6 z`4T2CtnhJRUgKcr&fU(Poo6zxgN->hy>T#X%%RSme-YWd)|AY6<Q>vM0lNYNQ&yn% zUR-P#5K5nU)Yx-dWQHOQ5Jo1y$g%9Mk}!8IeeMr47nESfX>;2=StXRpPm!JqVOg!O zss1JtXWbeChf1w%MT>HGxYweE6iHzp10k|K23P|lvUm(HB!wrCOfHOAC+sN2t35LB zOh)u5<f*#!IgOW4DXvp=1(w6XCDf~{2e47@U+w>B9syRTR=6tT`Fqj2nANt5guo2m zFRo1DZ{oTuaTy*M?|e>p@X=?|N4fNYq|h*m3`rtjb3S)K(tr~W*Ak!p*pjtM&|QE` z1g;w|3YQ_Trwmq5RfH^6ge+BrELDUoRfH^6gsiVr1gXj)W9({XO@BJWxitVf8QE40 zLOB<V*u~}OEb%~M+|m&GzUoKm-f$<4BQ9%Yue(_y!71{a^buyY_Xq#|XDDPs%>2Ws z#?1K7`D%?yj@5<1AMJ1LLKc%*@PGU7yMNKNXMh&qIPd`w1JXJYm<B8WRsu!9-9SC? zFz__+B5(jW4s-yHF5&^nKrT=M+zs3V+z<Q!*a;j0jsd5DGl2bbjG6(Xfr&seun_n< zPy*Z!JPqsx{seRYgCIwZ1g-=!fTchQPzP)SegOOo_$_c4I0bY7age!&1CxR40S|CH zPzG!S?gbtLegW(T4g>E39l%IX`-wm@a3j$7_kLoU_KWm1ZQ4y~+M(s#*}g5UJIHUI zPSYM7*7F_qSY1$D>MeBZ<?cJYy4$<HSa+`~FZ8-sSC+4FS5%g-@>W$%;b7krZdIkX zK=(%axhGU<{MY7`8>NNrvT{ksyGmSfD<~6()x~9nZqEk2sJu*h8hXL)rCx%Nv^H*R zh4Ps~G%44(vEA{?E4*bY)KyihDvK-hDHR(epUO-M>aj|vX=}79ZIxE8Rcc=TP0<Rq zQvT7GTA603_bVh>ZDN^GT57!tV<JYH(52a8w3uj@Ju@@2pZumLX&x2Wo$Og2>(H)C zO3L#<8gjb@-_RT@i&pZ}wDlG1`8fyy(bwVN;ozTqYEO+#*R)Fkeo@gjd%u`iNB_71 z@dF1rU4t(gk}&k*OA?0-A2D*&=rQiGmyR1h;j+soUUB85$yZIeI_a8gr%szb<GSRO znW?j8U;nkV^c&`6WX_$JHUGw&7Gy76<XOBVXDJptm*;=|=37?WdfUo^+gBBOSKm=o zTykgWnzHhWyDF=6W9_>28}9zb#_CO*6`47+OuE!lUR<VoD=E`WTBf!{Tgcx9+EndY zS}cRN1**Im-riy7mR8NJ^m;X(IbJ=tpwv+B^CI5UOH0dFN#shSOfO#Jb$cr-%PZZQ zHjvI;x?oXGj^!esTF(51^CCXAj78b$^B4BGESZrsb=ttV^fGrrMMY`xssg>3AyZUP z<z7?3uq?n`*S%{hbQ!Xx<pm7gBCmUnJDhiE@$Hobl^fi})VZ?KyGk$JFeT1Y>Mf}9 zGO)|^f>p#MMnvkDSGlW<ii+||e7pr~+^Z@4n(|67Y4Ey6m0*f0Jmr`2O&u6_l{>ws z7zSx)=geOaF>~~y;wpDRRh4(m?WG&sg+^s@*&XgOl3FXppd!U(#d>i;Y4P1E`M9ML zo;e~F_7c;5yKx8K?hWNeWn@{WxaaF`g03mA(%q%ScX~-(s#EE$GD>xK`D*v7g3?mS zjFyrzUA3xwO@*4`6R%!XT6u+gwNbW8wW*rn1wDl-tI{itRXUaDzw*o|EzK?{E>m@v zdS5H`R@1wz+_<C2T~$%Aij{)k41fZrb3}thw%0X%+N-<nUaRw#EVbHOFQU-pWvjeX zzIuB|K2o+M$zu*FN%?v*C=B^un=JlDnOb!iIXxlVMc#r6tF)wZ?R8&L$92UK5mmqS z#G7%!cvX7gm&BVc@hS{P+uGtv-6$yS=^*Jzm4TFtIdOruzpcDXmhGz<II?=Hg|)j} z*Q7|io_eeGlzC89PInc0*A}nx_Jj?!k#~Is^M*}9TBc`as&>9cwU0rLp)hM0cEx%T zdqSa%f;;<$zi_*RA{7?s1r%YR)#VY>Qce0w?_GwsN(v*Rd`W15p#xdT))X_L7<AI# zGTe<aqe>cZUBTaR%G35qstwOO?!9I7T6x(TZ<$UVB&=$~^M);`yu*-yRjR=yteQ`& zS;TaiuobdCcdtZ}ge-4fHG(xQyLeS)c~$vp-JM&kYB^`pr0(`uU@dwqPg)%FVak*# z+AQ|&J1SYt$_iMKjj}t-%GZ@$PalSwFjLm(v2k&1q7rPTTO#x0<g^R2zWR;gT^RfF zdm!SyiFdUb;*JiC?svpDyWh7(yu<A4cIU1@_xpDu-eYQN?y0G*VMDgvQ*+OjnuLD+ z*patx-AaLyl4?9P^_oMQczLoXuZI1WP1)nACwuqAn)(`IX>7|yMMVxr?D~p|brlu8 z_G7&NzyG<lzW*kIA6ftU`ke1O3ry+D{?%z;{MS2tt=97|O8aX6B2(C+_56#5xcycB zh2y*bzwdwT3;pj#!{h(q5fD||{SSfXuk;J|pggxk_56#D`fC5e@y|D=|6^`{Z3akA z3H%G^C|^DAE)ntm5B&Ou|7x}E3FXpy-mSN&D47H`wOf33TkrX1eM6)F-llKex9!{a zf9Jd3d*J&IKJ@TEJo1k}_~E15AKUTx6Hor=sUQE3pFI83pZ(J_KmWxqfA#Fn=bnGz z*S~r3rQiN;SM%;Ydw<{3x^Mr1mk<8o&?|?Jyn6JtKfeCPu{Ym(`}jZq>75fN-+k}Y zzx?@qv+Z94r~mDP58FTb_m4Y1Idiu2)4zPy#pTGq`9O5x1J74F5dCM@|35qbzq$SY z+JW@K{^~&bpI!f~teI=p%&Zd9gjUFJvOAlfTV6Ks)3UR#E-bv77k-{>O-lzj6LXGJ zM`vwe`P%OHMVywzImcVUk<<#1Zrov1>6&(<QL56o5nNf)O0TFa7MetMLFK9<o^!po zR~j5t#qY*~GWAM6lD<Z|lBPylk`7QtybY3u#Fw}dN6RVDjmkniB)!UF^|rLgsH_UP z<#`LsyrGY!pwZ%-U0$YqbBxflK$o~0@if9~gp)8D{u+n;5RD~|qiOlN99<oH#C=(n zw{p?#C7cuH_Z*Ui;(_0Sf+{_oGv-=I4i!d)a<jgzWVCE(N(Fa#Zzx}%t}V;STr&0A zDH#hOKaeL`QvwP?c_<b&wAzO%Q*#=CcAz<E6&i;&qN!*xX*hm!7A;(~Z0UGy3TIyV z4%3sS+^&+reNCZqzlFRuaH?3dq`X`*;Fo1R{+IsNT$HXIhC^v1_TlT;X^TN)A3A?h zkaeNtX&N+m^$dT%0qstH;qQHY{9hc`+y7vM|Bol6X)git3&+1V!hhEEG%XE?^zWPh zdoz3cAC8DG@qV7#+dndY@lTy?`OAAO@8NRv&1cv3R=5lKfBdxz`;SUb(^3HWT`2xl z^LqRDE$3%9_V({vzB?Cwx&Kc+J#~9A;{8~k_9|b}6Yd)k?|t)|p5Hsa$aLQRdYbkj zAir>ZBmJ+sIZe9;i1gppryTXS_V$nL*F@;USBGfC;q?2K?~0NO$CrF(miG4V8~^$Z zz5OHem-q{7zuf=oExrBw_UHKT_4e<Z{!8Ega{r~<d;9k-|I1JG_U}6{zx^Z2U*q?O zCwuz5Z#fqHtamzn{fl<@_U~KI0SD5wrJs^X=r>3MojVc!>izt0p32|GQ&|!<&s*lL zgt#=vqLj_iD@!xiLc4)ag`Y0mhdDx04|5>O?0E&n`rPu$94I-ZUTbI6zNgJmypm8b zw#R?6K}3&8G^?PjuoMj96G=6@ywE81&V^XJ5Sk64-_kOLVn3%6QZdB99CllX;qZc@ z7kCTSdcWZQm!4Ftg!43Ql0B!?3odbKG&x8?(hCbA7K8uvi;85TR7l)8<!jbZq6Nie zWZy1jwbFsHBXz%C(#X*ZEk}505=Y9rbVG$#n`QYHK*g*Oq##}U9hg(8msadkf$Qu` z!_>R(7W^M7e*=<zSs3Zivh2&sic|{~X0Bfal11&wPBAgY*eTrwy<d->UzOp7hJJ^) z(nEEn>)w|f1UFHnFHL(gIt%)yVs2=UsdtN!af>R6N2;LxK6<|NfDkslh4af`eF+6m z)0!jQ!9K$7ITAO0jz`lHq%{_0X3P5tN(1MlxKNE5FdyxD`_j@X0$BW%S@IR)qI^x> zyE!eh<x3T@LwX~k^goMeuceCoIv?ET`}REAT8$y?O!NZihau7+qv_X_ImC15+au{^ zg*g?)WmY%e6eSsE_E0u+bm3l9rE9w+&o6pt3oZ~NPph-%6&HHv6cto1EzcH8@eLbv zueSUA=`dO!SN&kk8ci#(=UOyz)dKmp#fG<XgU4H`xH7N_RC$>_CDPVQi&xzl8mB*r zXq(Ugqj7T7_*7`$Qn*y<Rchq&raf$1qL(f!TL+S>{aBS?iP!3mTf-#?^-i5iIkYIy zvkydkGkwAIZ-|;(YE%_T+BX=hS9>d&X@8DhFekg9!fHo)VvMc3EtZyt8%Q%FL(vv# z)_jt-m-$7!IlWy7(<b>ZP|O!=%4zS*IFa1D*?m7zHOeWzo6==yb4tsryrBtvuQggi z>ruM)a71ku8G41G%jkWeSExKKMrK~bDzG86%1Nf!ErdI}rlO$I+g;n--Y%5-n3OSM z9OV{N77Jr0UArlB$->M9oCgX^IV_dgmcUk!bT#ddR-D2`tF7<Lq%A_7EAtph04cpH zgwBAy-GGlqoBj9i|LzvpB?|HQ$<v}xh05y+JtH0nS_#&3!JqgG{P*v_Ti~m<z`{SL z{pRPxewXpD<I>dFDt#B-`T)nMV2ubY{4f4woL&rs$D}RvZs(Z@^aBP0$f0Qcfmk3O zaD<-XCf`y7@e`h0*iX`xxbj3Rhsr~yi?|I2E((F<Jr)r6>41EvhrZ{8zFFW^oFyUm zoY0eHTBV=QQ}SjxR_Uza=>}MEkw-%21CX*xJ)}G}fRwp5^xVQz{C$A<*8x%<xd3<t z@Pp9zcAiqc#{tRjM}UNT4v;z>0>u9fK>QPF6ltGuoAKJcHblus#4r3Eeullm-+iBb z{ri6ZweT1652y2A@9DbW&#J5Yg1`S7ZE<0ygjK%_6UF~))L&|G!66XZ$uBqr-2Zjj zfSUY2J`{?Ef`>)h9gnkNt=zI<%h*uoJo%3Gvi%9`S^L8iUGkQ;sYX4YB7F0Xw|2NK z?=SqVMfO#GX`$z{Uom`oDEv;szw+3r$A)YF@|gM9%~oO&f4kG)v|Ysz-BF9*y7eu$ zcH3JeZ(SP^(t52udhAappr>84$%<L}Zx-!tPAFt}4gW&KztLga@bq3O{H@<o&c0<8 zd)47zQ6Nog|1eFf_$W=QADON_Nd6LDp3>KX=g3d?)=o1`;TQ*b%AWlwPua^IJY^Ce ze?Lv_#ZU7T9HXA+5T3X26r5%}&tW{f{+y-_=ed{X2%h)y6kMT@=V+c8Jjd`n@h@qb zo99zJ$MSsURGP91=Hj`YZ;j^$9_{a?X?OEH!BYm?ah^e*2YDWXzWY^x;iK><NmuF= zT9h<tpA!21!H?6l?*iL^dx3hO4yXav0~J6Ka0}o8vVd7YGB6ED0wx0!f$@MF7zrc- z34jZT2kb!Sztbmx2}t-8JdXi~fxW<sz%#((z@xw;z&2nbPyzI}_w>2+=@jadL7(4y z#b1Zbp`VPADB?+6d4_+|PVRo+k#0QiPsT~)ucpF^-~N%s&+_Cfjr9Hxzk4$Nw)lss zmkZ@sGN!|sN4^W6LqL8q7E^(*12QhY4?GLJ27C+*reTtRg@9a?3CEd<Up}x7cmVhn sa1{7=KrVY;4P*nQ!2j#Nzb3L0-REZu{lfJw?Z8eMa0{>$=sSM?C)~1m4*&oF diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/__init__.py b/venv2/lib/python2.7/site-packages/setuptools/command/__init__.py deleted file mode 100644 index fe619e2..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -__all__ = [ - 'alias', 'bdist_egg', 'bdist_rpm', 'build_ext', 'build_py', 'develop', - 'easy_install', 'egg_info', 'install', 'install_lib', 'rotate', 'saveopts', - 'sdist', 'setopt', 'test', 'install_egg_info', 'install_scripts', - 'register', 'bdist_wininst', 'upload_docs', 'upload', 'build_clib', - 'dist_info', -] - -from distutils.command.bdist import bdist -import sys - -from setuptools.command import install_scripts - -if 'egg' not in bdist.format_commands: - bdist.format_command['egg'] = ('bdist_egg', "Python .egg file") - bdist.format_commands.append('egg') - -del bdist, sys diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/alias.py b/venv2/lib/python2.7/site-packages/setuptools/command/alias.py deleted file mode 100644 index 4532b1c..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/alias.py +++ /dev/null @@ -1,80 +0,0 @@ -from distutils.errors import DistutilsOptionError - -from setuptools.extern.six.moves import map - -from setuptools.command.setopt import edit_config, option_base, config_file - - -def shquote(arg): - """Quote an argument for later parsing by shlex.split()""" - for c in '"', "'", "\\", "#": - if c in arg: - return repr(arg) - if arg.split() != [arg]: - return repr(arg) - return arg - - -class alias(option_base): - """Define a shortcut that invokes one or more commands""" - - description = "define a shortcut to invoke one or more commands" - command_consumes_arguments = True - - user_options = [ - ('remove', 'r', 'remove (unset) the alias'), - ] + option_base.user_options - - boolean_options = option_base.boolean_options + ['remove'] - - def initialize_options(self): - option_base.initialize_options(self) - self.args = None - self.remove = None - - def finalize_options(self): - option_base.finalize_options(self) - if self.remove and len(self.args) != 1: - raise DistutilsOptionError( - "Must specify exactly one argument (the alias name) when " - "using --remove" - ) - - def run(self): - aliases = self.distribution.get_option_dict('aliases') - - if not self.args: - print("Command Aliases") - print("---------------") - for alias in aliases: - print("setup.py alias", format_alias(alias, aliases)) - return - - elif len(self.args) == 1: - alias, = self.args - if self.remove: - command = None - elif alias in aliases: - print("setup.py alias", format_alias(alias, aliases)) - return - else: - print("No alias definition found for %r" % alias) - return - else: - alias = self.args[0] - command = ' '.join(map(shquote, self.args[1:])) - - edit_config(self.filename, {'aliases': {alias: command}}, self.dry_run) - - -def format_alias(name, aliases): - source, command = aliases[name] - if source == config_file('global'): - source = '--global-config ' - elif source == config_file('user'): - source = '--user-config ' - elif source == config_file('local'): - source = '' - else: - source = '--filename=%r' % source - return source + name + ' ' + command diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/bdist_egg.py b/venv2/lib/python2.7/site-packages/setuptools/command/bdist_egg.py deleted file mode 100644 index 9f8df91..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/bdist_egg.py +++ /dev/null @@ -1,502 +0,0 @@ -"""setuptools.command.bdist_egg - -Build .egg distributions""" - -from distutils.errors import DistutilsSetupError -from distutils.dir_util import remove_tree, mkpath -from distutils import log -from types import CodeType -import sys -import os -import re -import textwrap -import marshal - -from setuptools.extern import six - -from pkg_resources import get_build_platform, Distribution, ensure_directory -from pkg_resources import EntryPoint -from setuptools.extension import Library -from setuptools import Command - -try: - # Python 2.7 or >=3.2 - from sysconfig import get_path, get_python_version - - def _get_purelib(): - return get_path("purelib") -except ImportError: - from distutils.sysconfig import get_python_lib, get_python_version - - def _get_purelib(): - return get_python_lib(False) - - -def strip_module(filename): - if '.' in filename: - filename = os.path.splitext(filename)[0] - if filename.endswith('module'): - filename = filename[:-6] - return filename - - -def sorted_walk(dir): - """Do os.walk in a reproducible way, - independent of indeterministic filesystem readdir order - """ - for base, dirs, files in os.walk(dir): - dirs.sort() - files.sort() - yield base, dirs, files - - -def write_stub(resource, pyfile): - _stub_template = textwrap.dedent(""" - def __bootstrap__(): - global __bootstrap__, __loader__, __file__ - import sys, pkg_resources, imp - __file__ = pkg_resources.resource_filename(__name__, %r) - __loader__ = None; del __bootstrap__, __loader__ - imp.load_dynamic(__name__,__file__) - __bootstrap__() - """).lstrip() - with open(pyfile, 'w') as f: - f.write(_stub_template % resource) - - -class bdist_egg(Command): - description = "create an \"egg\" distribution" - - user_options = [ - ('bdist-dir=', 'b', - "temporary directory for creating the distribution"), - ('plat-name=', 'p', "platform name to embed in generated filenames " - "(default: %s)" % get_build_platform()), - ('exclude-source-files', None, - "remove all .py files from the generated egg"), - ('keep-temp', 'k', - "keep the pseudo-installation tree around after " + - "creating the distribution archive"), - ('dist-dir=', 'd', - "directory to put final built distributions in"), - ('skip-build', None, - "skip rebuilding everything (for testing/debugging)"), - ] - - boolean_options = [ - 'keep-temp', 'skip-build', 'exclude-source-files' - ] - - def initialize_options(self): - self.bdist_dir = None - self.plat_name = None - self.keep_temp = 0 - self.dist_dir = None - self.skip_build = 0 - self.egg_output = None - self.exclude_source_files = None - - def finalize_options(self): - ei_cmd = self.ei_cmd = self.get_finalized_command("egg_info") - self.egg_info = ei_cmd.egg_info - - if self.bdist_dir is None: - bdist_base = self.get_finalized_command('bdist').bdist_base - self.bdist_dir = os.path.join(bdist_base, 'egg') - - if self.plat_name is None: - self.plat_name = get_build_platform() - - self.set_undefined_options('bdist', ('dist_dir', 'dist_dir')) - - if self.egg_output is None: - - # Compute filename of the output egg - basename = Distribution( - None, None, ei_cmd.egg_name, ei_cmd.egg_version, - get_python_version(), - self.distribution.has_ext_modules() and self.plat_name - ).egg_name() - - self.egg_output = os.path.join(self.dist_dir, basename + '.egg') - - def do_install_data(self): - # Hack for packages that install data to install's --install-lib - self.get_finalized_command('install').install_lib = self.bdist_dir - - site_packages = os.path.normcase(os.path.realpath(_get_purelib())) - old, self.distribution.data_files = self.distribution.data_files, [] - - for item in old: - if isinstance(item, tuple) and len(item) == 2: - if os.path.isabs(item[0]): - realpath = os.path.realpath(item[0]) - normalized = os.path.normcase(realpath) - if normalized == site_packages or normalized.startswith( - site_packages + os.sep - ): - item = realpath[len(site_packages) + 1:], item[1] - # XXX else: raise ??? - self.distribution.data_files.append(item) - - try: - log.info("installing package data to %s", self.bdist_dir) - self.call_command('install_data', force=0, root=None) - finally: - self.distribution.data_files = old - - def get_outputs(self): - return [self.egg_output] - - def call_command(self, cmdname, **kw): - """Invoke reinitialized command `cmdname` with keyword args""" - for dirname in INSTALL_DIRECTORY_ATTRS: - kw.setdefault(dirname, self.bdist_dir) - kw.setdefault('skip_build', self.skip_build) - kw.setdefault('dry_run', self.dry_run) - cmd = self.reinitialize_command(cmdname, **kw) - self.run_command(cmdname) - return cmd - - def run(self): - # Generate metadata first - self.run_command("egg_info") - # We run install_lib before install_data, because some data hacks - # pull their data path from the install_lib command. - log.info("installing library code to %s", self.bdist_dir) - instcmd = self.get_finalized_command('install') - old_root = instcmd.root - instcmd.root = None - if self.distribution.has_c_libraries() and not self.skip_build: - self.run_command('build_clib') - cmd = self.call_command('install_lib', warn_dir=0) - instcmd.root = old_root - - all_outputs, ext_outputs = self.get_ext_outputs() - self.stubs = [] - to_compile = [] - for (p, ext_name) in enumerate(ext_outputs): - filename, ext = os.path.splitext(ext_name) - pyfile = os.path.join(self.bdist_dir, strip_module(filename) + - '.py') - self.stubs.append(pyfile) - log.info("creating stub loader for %s", ext_name) - if not self.dry_run: - write_stub(os.path.basename(ext_name), pyfile) - to_compile.append(pyfile) - ext_outputs[p] = ext_name.replace(os.sep, '/') - - if to_compile: - cmd.byte_compile(to_compile) - if self.distribution.data_files: - self.do_install_data() - - # Make the EGG-INFO directory - archive_root = self.bdist_dir - egg_info = os.path.join(archive_root, 'EGG-INFO') - self.mkpath(egg_info) - if self.distribution.scripts: - script_dir = os.path.join(egg_info, 'scripts') - log.info("installing scripts to %s", script_dir) - self.call_command('install_scripts', install_dir=script_dir, - no_ep=1) - - self.copy_metadata_to(egg_info) - native_libs = os.path.join(egg_info, "native_libs.txt") - if all_outputs: - log.info("writing %s", native_libs) - if not self.dry_run: - ensure_directory(native_libs) - libs_file = open(native_libs, 'wt') - libs_file.write('\n'.join(all_outputs)) - libs_file.write('\n') - libs_file.close() - elif os.path.isfile(native_libs): - log.info("removing %s", native_libs) - if not self.dry_run: - os.unlink(native_libs) - - write_safety_flag( - os.path.join(archive_root, 'EGG-INFO'), self.zip_safe() - ) - - if os.path.exists(os.path.join(self.egg_info, 'depends.txt')): - log.warn( - "WARNING: 'depends.txt' will not be used by setuptools 0.6!\n" - "Use the install_requires/extras_require setup() args instead." - ) - - if self.exclude_source_files: - self.zap_pyfiles() - - # Make the archive - make_zipfile(self.egg_output, archive_root, verbose=self.verbose, - dry_run=self.dry_run, mode=self.gen_header()) - if not self.keep_temp: - remove_tree(self.bdist_dir, dry_run=self.dry_run) - - # Add to 'Distribution.dist_files' so that the "upload" command works - getattr(self.distribution, 'dist_files', []).append( - ('bdist_egg', get_python_version(), self.egg_output)) - - def zap_pyfiles(self): - log.info("Removing .py files from temporary directory") - for base, dirs, files in walk_egg(self.bdist_dir): - for name in files: - path = os.path.join(base, name) - - if name.endswith('.py'): - log.debug("Deleting %s", path) - os.unlink(path) - - if base.endswith('__pycache__'): - path_old = path - - pattern = r'(?P<name>.+)\.(?P<magic>[^.]+)\.pyc' - m = re.match(pattern, name) - path_new = os.path.join( - base, os.pardir, m.group('name') + '.pyc') - log.info( - "Renaming file from [%s] to [%s]" - % (path_old, path_new)) - try: - os.remove(path_new) - except OSError: - pass - os.rename(path_old, path_new) - - def zip_safe(self): - safe = getattr(self.distribution, 'zip_safe', None) - if safe is not None: - return safe - log.warn("zip_safe flag not set; analyzing archive contents...") - return analyze_egg(self.bdist_dir, self.stubs) - - def gen_header(self): - epm = EntryPoint.parse_map(self.distribution.entry_points or '') - ep = epm.get('setuptools.installation', {}).get('eggsecutable') - if ep is None: - return 'w' # not an eggsecutable, do it the usual way. - - if not ep.attrs or ep.extras: - raise DistutilsSetupError( - "eggsecutable entry point (%r) cannot have 'extras' " - "or refer to a module" % (ep,) - ) - - pyver = sys.version[:3] - pkg = ep.module_name - full = '.'.join(ep.attrs) - base = ep.attrs[0] - basename = os.path.basename(self.egg_output) - - header = ( - "#!/bin/sh\n" - 'if [ `basename $0` = "%(basename)s" ]\n' - 'then exec python%(pyver)s -c "' - "import sys, os; sys.path.insert(0, os.path.abspath('$0')); " - "from %(pkg)s import %(base)s; sys.exit(%(full)s())" - '" "$@"\n' - 'else\n' - ' echo $0 is not the correct name for this egg file.\n' - ' echo Please rename it back to %(basename)s and try again.\n' - ' exec false\n' - 'fi\n' - ) % locals() - - if not self.dry_run: - mkpath(os.path.dirname(self.egg_output), dry_run=self.dry_run) - f = open(self.egg_output, 'w') - f.write(header) - f.close() - return 'a' - - def copy_metadata_to(self, target_dir): - "Copy metadata (egg info) to the target_dir" - # normalize the path (so that a forward-slash in egg_info will - # match using startswith below) - norm_egg_info = os.path.normpath(self.egg_info) - prefix = os.path.join(norm_egg_info, '') - for path in self.ei_cmd.filelist.files: - if path.startswith(prefix): - target = os.path.join(target_dir, path[len(prefix):]) - ensure_directory(target) - self.copy_file(path, target) - - def get_ext_outputs(self): - """Get a list of relative paths to C extensions in the output distro""" - - all_outputs = [] - ext_outputs = [] - - paths = {self.bdist_dir: ''} - for base, dirs, files in sorted_walk(self.bdist_dir): - for filename in files: - if os.path.splitext(filename)[1].lower() in NATIVE_EXTENSIONS: - all_outputs.append(paths[base] + filename) - for filename in dirs: - paths[os.path.join(base, filename)] = (paths[base] + - filename + '/') - - if self.distribution.has_ext_modules(): - build_cmd = self.get_finalized_command('build_ext') - for ext in build_cmd.extensions: - if isinstance(ext, Library): - continue - fullname = build_cmd.get_ext_fullname(ext.name) - filename = build_cmd.get_ext_filename(fullname) - if not os.path.basename(filename).startswith('dl-'): - if os.path.exists(os.path.join(self.bdist_dir, filename)): - ext_outputs.append(filename) - - return all_outputs, ext_outputs - - -NATIVE_EXTENSIONS = dict.fromkeys('.dll .so .dylib .pyd'.split()) - - -def walk_egg(egg_dir): - """Walk an unpacked egg's contents, skipping the metadata directory""" - walker = sorted_walk(egg_dir) - base, dirs, files = next(walker) - if 'EGG-INFO' in dirs: - dirs.remove('EGG-INFO') - yield base, dirs, files - for bdf in walker: - yield bdf - - -def analyze_egg(egg_dir, stubs): - # check for existing flag in EGG-INFO - for flag, fn in safety_flags.items(): - if os.path.exists(os.path.join(egg_dir, 'EGG-INFO', fn)): - return flag - if not can_scan(): - return False - safe = True - for base, dirs, files in walk_egg(egg_dir): - for name in files: - if name.endswith('.py') or name.endswith('.pyw'): - continue - elif name.endswith('.pyc') or name.endswith('.pyo'): - # always scan, even if we already know we're not safe - safe = scan_module(egg_dir, base, name, stubs) and safe - return safe - - -def write_safety_flag(egg_dir, safe): - # Write or remove zip safety flag file(s) - for flag, fn in safety_flags.items(): - fn = os.path.join(egg_dir, fn) - if os.path.exists(fn): - if safe is None or bool(safe) != flag: - os.unlink(fn) - elif safe is not None and bool(safe) == flag: - f = open(fn, 'wt') - f.write('\n') - f.close() - - -safety_flags = { - True: 'zip-safe', - False: 'not-zip-safe', -} - - -def scan_module(egg_dir, base, name, stubs): - """Check whether module possibly uses unsafe-for-zipfile stuff""" - - filename = os.path.join(base, name) - if filename[:-1] in stubs: - return True # Extension module - pkg = base[len(egg_dir) + 1:].replace(os.sep, '.') - module = pkg + (pkg and '.' or '') + os.path.splitext(name)[0] - if six.PY2: - skip = 8 # skip magic & date - elif sys.version_info < (3, 7): - skip = 12 # skip magic & date & file size - else: - skip = 16 # skip magic & reserved? & date & file size - f = open(filename, 'rb') - f.read(skip) - code = marshal.load(f) - f.close() - safe = True - symbols = dict.fromkeys(iter_symbols(code)) - for bad in ['__file__', '__path__']: - if bad in symbols: - log.warn("%s: module references %s", module, bad) - safe = False - if 'inspect' in symbols: - for bad in [ - 'getsource', 'getabsfile', 'getsourcefile', 'getfile' - 'getsourcelines', 'findsource', 'getcomments', 'getframeinfo', - 'getinnerframes', 'getouterframes', 'stack', 'trace' - ]: - if bad in symbols: - log.warn("%s: module MAY be using inspect.%s", module, bad) - safe = False - return safe - - -def iter_symbols(code): - """Yield names and strings used by `code` and its nested code objects""" - for name in code.co_names: - yield name - for const in code.co_consts: - if isinstance(const, six.string_types): - yield const - elif isinstance(const, CodeType): - for name in iter_symbols(const): - yield name - - -def can_scan(): - if not sys.platform.startswith('java') and sys.platform != 'cli': - # CPython, PyPy, etc. - return True - log.warn("Unable to analyze compiled code on this platform.") - log.warn("Please ask the author to include a 'zip_safe'" - " setting (either True or False) in the package's setup.py") - - -# Attribute names of options for commands that might need to be convinced to -# install to the egg build directory - -INSTALL_DIRECTORY_ATTRS = [ - 'install_lib', 'install_dir', 'install_data', 'install_base' -] - - -def make_zipfile(zip_filename, base_dir, verbose=0, dry_run=0, compress=True, - mode='w'): - """Create a zip file from all the files under 'base_dir'. The output - zip file will be named 'base_dir' + ".zip". Uses either the "zipfile" - Python module (if available) or the InfoZIP "zip" utility (if installed - and found on the default search path). If neither tool is available, - raises DistutilsExecError. Returns the name of the output zip file. - """ - import zipfile - - mkpath(os.path.dirname(zip_filename), dry_run=dry_run) - log.info("creating '%s' and adding '%s' to it", zip_filename, base_dir) - - def visit(z, dirname, names): - for name in names: - path = os.path.normpath(os.path.join(dirname, name)) - if os.path.isfile(path): - p = path[len(base_dir) + 1:] - if not dry_run: - z.write(path, p) - log.debug("adding '%s'", p) - - compression = zipfile.ZIP_DEFLATED if compress else zipfile.ZIP_STORED - if not dry_run: - z = zipfile.ZipFile(zip_filename, mode, compression=compression) - for dirname, dirs, files in sorted_walk(base_dir): - visit(z, dirname, files) - z.close() - else: - for dirname, dirs, files in sorted_walk(base_dir): - visit(None, dirname, files) - return zip_filename diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/bdist_rpm.py b/venv2/lib/python2.7/site-packages/setuptools/command/bdist_rpm.py deleted file mode 100644 index 7073092..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/bdist_rpm.py +++ /dev/null @@ -1,43 +0,0 @@ -import distutils.command.bdist_rpm as orig - - -class bdist_rpm(orig.bdist_rpm): - """ - Override the default bdist_rpm behavior to do the following: - - 1. Run egg_info to ensure the name and version are properly calculated. - 2. Always run 'install' using --single-version-externally-managed to - disable eggs in RPM distributions. - 3. Replace dash with underscore in the version numbers for better RPM - compatibility. - """ - - def run(self): - # ensure distro name is up-to-date - self.run_command('egg_info') - - orig.bdist_rpm.run(self) - - def _make_spec_file(self): - version = self.distribution.get_version() - rpmversion = version.replace('-', '_') - spec = orig.bdist_rpm._make_spec_file(self) - line23 = '%define version ' + version - line24 = '%define version ' + rpmversion - spec = [ - line.replace( - "Source0: %{name}-%{version}.tar", - "Source0: %{name}-%{unmangled_version}.tar" - ).replace( - "setup.py install ", - "setup.py install --single-version-externally-managed " - ).replace( - "%setup", - "%setup -n %{name}-%{unmangled_version}" - ).replace(line23, line24) - for line in spec - ] - insert_loc = spec.index(line24) + 1 - unmangled_version = "%define unmangled_version " + version - spec.insert(insert_loc, unmangled_version) - return spec diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/bdist_wininst.py b/venv2/lib/python2.7/site-packages/setuptools/command/bdist_wininst.py deleted file mode 100644 index 073de97..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/bdist_wininst.py +++ /dev/null @@ -1,21 +0,0 @@ -import distutils.command.bdist_wininst as orig - - -class bdist_wininst(orig.bdist_wininst): - def reinitialize_command(self, command, reinit_subcommands=0): - """ - Supplement reinitialize_command to work around - http://bugs.python.org/issue20819 - """ - cmd = self.distribution.reinitialize_command( - command, reinit_subcommands) - if command in ('install', 'install_lib'): - cmd.install_lib = None - return cmd - - def run(self): - self._is_running = True - try: - orig.bdist_wininst.run(self) - finally: - self._is_running = False diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/build_clib.py b/venv2/lib/python2.7/site-packages/setuptools/command/build_clib.py deleted file mode 100644 index 09caff6..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/build_clib.py +++ /dev/null @@ -1,98 +0,0 @@ -import distutils.command.build_clib as orig -from distutils.errors import DistutilsSetupError -from distutils import log -from setuptools.dep_util import newer_pairwise_group - - -class build_clib(orig.build_clib): - """ - Override the default build_clib behaviour to do the following: - - 1. Implement a rudimentary timestamp-based dependency system - so 'compile()' doesn't run every time. - 2. Add more keys to the 'build_info' dictionary: - * obj_deps - specify dependencies for each object compiled. - this should be a dictionary mapping a key - with the source filename to a list of - dependencies. Use an empty string for global - dependencies. - * cflags - specify a list of additional flags to pass to - the compiler. - """ - - def build_libraries(self, libraries): - for (lib_name, build_info) in libraries: - sources = build_info.get('sources') - if sources is None or not isinstance(sources, (list, tuple)): - raise DistutilsSetupError( - "in 'libraries' option (library '%s'), " - "'sources' must be present and must be " - "a list of source filenames" % lib_name) - sources = list(sources) - - log.info("building '%s' library", lib_name) - - # Make sure everything is the correct type. - # obj_deps should be a dictionary of keys as sources - # and a list/tuple of files that are its dependencies. - obj_deps = build_info.get('obj_deps', dict()) - if not isinstance(obj_deps, dict): - raise DistutilsSetupError( - "in 'libraries' option (library '%s'), " - "'obj_deps' must be a dictionary of " - "type 'source: list'" % lib_name) - dependencies = [] - - # Get the global dependencies that are specified by the '' key. - # These will go into every source's dependency list. - global_deps = obj_deps.get('', list()) - if not isinstance(global_deps, (list, tuple)): - raise DistutilsSetupError( - "in 'libraries' option (library '%s'), " - "'obj_deps' must be a dictionary of " - "type 'source: list'" % lib_name) - - # Build the list to be used by newer_pairwise_group - # each source will be auto-added to its dependencies. - for source in sources: - src_deps = [source] - src_deps.extend(global_deps) - extra_deps = obj_deps.get(source, list()) - if not isinstance(extra_deps, (list, tuple)): - raise DistutilsSetupError( - "in 'libraries' option (library '%s'), " - "'obj_deps' must be a dictionary of " - "type 'source: list'" % lib_name) - src_deps.extend(extra_deps) - dependencies.append(src_deps) - - expected_objects = self.compiler.object_filenames( - sources, - output_dir=self.build_temp - ) - - if newer_pairwise_group(dependencies, expected_objects) != ([], []): - # First, compile the source code to object files in the library - # directory. (This should probably change to putting object - # files in a temporary build directory.) - macros = build_info.get('macros') - include_dirs = build_info.get('include_dirs') - cflags = build_info.get('cflags') - objects = self.compiler.compile( - sources, - output_dir=self.build_temp, - macros=macros, - include_dirs=include_dirs, - extra_postargs=cflags, - debug=self.debug - ) - - # Now "link" the object files together into a static library. - # (On Unix at least, this isn't really linking -- it just - # builds an archive. Whatever.) - self.compiler.create_static_lib( - expected_objects, - lib_name, - output_dir=self.build_clib, - debug=self.debug - ) diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/build_ext.py b/venv2/lib/python2.7/site-packages/setuptools/command/build_ext.py deleted file mode 100644 index 60a8a32..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/build_ext.py +++ /dev/null @@ -1,321 +0,0 @@ -import os -import sys -import itertools -import imp -from distutils.command.build_ext import build_ext as _du_build_ext -from distutils.file_util import copy_file -from distutils.ccompiler import new_compiler -from distutils.sysconfig import customize_compiler, get_config_var -from distutils.errors import DistutilsError -from distutils import log - -from setuptools.extension import Library -from setuptools.extern import six - -try: - # Attempt to use Cython for building extensions, if available - from Cython.Distutils.build_ext import build_ext as _build_ext - # Additionally, assert that the compiler module will load - # also. Ref #1229. - __import__('Cython.Compiler.Main') -except ImportError: - _build_ext = _du_build_ext - -# make sure _config_vars is initialized -get_config_var("LDSHARED") -from distutils.sysconfig import _config_vars as _CONFIG_VARS - - -def _customize_compiler_for_shlib(compiler): - if sys.platform == "darwin": - # building .dylib requires additional compiler flags on OSX; here we - # temporarily substitute the pyconfig.h variables so that distutils' - # 'customize_compiler' uses them before we build the shared libraries. - tmp = _CONFIG_VARS.copy() - try: - # XXX Help! I don't have any idea whether these are right... - _CONFIG_VARS['LDSHARED'] = ( - "gcc -Wl,-x -dynamiclib -undefined dynamic_lookup") - _CONFIG_VARS['CCSHARED'] = " -dynamiclib" - _CONFIG_VARS['SO'] = ".dylib" - customize_compiler(compiler) - finally: - _CONFIG_VARS.clear() - _CONFIG_VARS.update(tmp) - else: - customize_compiler(compiler) - - -have_rtld = False -use_stubs = False -libtype = 'shared' - -if sys.platform == "darwin": - use_stubs = True -elif os.name != 'nt': - try: - import dl - use_stubs = have_rtld = hasattr(dl, 'RTLD_NOW') - except ImportError: - pass - -if_dl = lambda s: s if have_rtld else '' - - -def get_abi3_suffix(): - """Return the file extension for an abi3-compliant Extension()""" - for suffix, _, _ in (s for s in imp.get_suffixes() if s[2] == imp.C_EXTENSION): - if '.abi3' in suffix: # Unix - return suffix - elif suffix == '.pyd': # Windows - return suffix - - -class build_ext(_build_ext): - def run(self): - """Build extensions in build directory, then copy if --inplace""" - old_inplace, self.inplace = self.inplace, 0 - _build_ext.run(self) - self.inplace = old_inplace - if old_inplace: - self.copy_extensions_to_source() - - def copy_extensions_to_source(self): - build_py = self.get_finalized_command('build_py') - for ext in self.extensions: - fullname = self.get_ext_fullname(ext.name) - filename = self.get_ext_filename(fullname) - modpath = fullname.split('.') - package = '.'.join(modpath[:-1]) - package_dir = build_py.get_package_dir(package) - dest_filename = os.path.join(package_dir, - os.path.basename(filename)) - src_filename = os.path.join(self.build_lib, filename) - - # Always copy, even if source is older than destination, to ensure - # that the right extensions for the current Python/platform are - # used. - copy_file( - src_filename, dest_filename, verbose=self.verbose, - dry_run=self.dry_run - ) - if ext._needs_stub: - self.write_stub(package_dir or os.curdir, ext, True) - - def get_ext_filename(self, fullname): - filename = _build_ext.get_ext_filename(self, fullname) - if fullname in self.ext_map: - ext = self.ext_map[fullname] - use_abi3 = ( - six.PY3 - and getattr(ext, 'py_limited_api') - and get_abi3_suffix() - ) - if use_abi3: - so_ext = get_config_var('EXT_SUFFIX') - filename = filename[:-len(so_ext)] - filename = filename + get_abi3_suffix() - if isinstance(ext, Library): - fn, ext = os.path.splitext(filename) - return self.shlib_compiler.library_filename(fn, libtype) - elif use_stubs and ext._links_to_dynamic: - d, fn = os.path.split(filename) - return os.path.join(d, 'dl-' + fn) - return filename - - def initialize_options(self): - _build_ext.initialize_options(self) - self.shlib_compiler = None - self.shlibs = [] - self.ext_map = {} - - def finalize_options(self): - _build_ext.finalize_options(self) - self.extensions = self.extensions or [] - self.check_extensions_list(self.extensions) - self.shlibs = [ext for ext in self.extensions - if isinstance(ext, Library)] - if self.shlibs: - self.setup_shlib_compiler() - for ext in self.extensions: - ext._full_name = self.get_ext_fullname(ext.name) - for ext in self.extensions: - fullname = ext._full_name - self.ext_map[fullname] = ext - - # distutils 3.1 will also ask for module names - # XXX what to do with conflicts? - self.ext_map[fullname.split('.')[-1]] = ext - - ltd = self.shlibs and self.links_to_dynamic(ext) or False - ns = ltd and use_stubs and not isinstance(ext, Library) - ext._links_to_dynamic = ltd - ext._needs_stub = ns - filename = ext._file_name = self.get_ext_filename(fullname) - libdir = os.path.dirname(os.path.join(self.build_lib, filename)) - if ltd and libdir not in ext.library_dirs: - ext.library_dirs.append(libdir) - if ltd and use_stubs and os.curdir not in ext.runtime_library_dirs: - ext.runtime_library_dirs.append(os.curdir) - - def setup_shlib_compiler(self): - compiler = self.shlib_compiler = new_compiler( - compiler=self.compiler, dry_run=self.dry_run, force=self.force - ) - _customize_compiler_for_shlib(compiler) - - if self.include_dirs is not None: - compiler.set_include_dirs(self.include_dirs) - if self.define is not None: - # 'define' option is a list of (name,value) tuples - for (name, value) in self.define: - compiler.define_macro(name, value) - if self.undef is not None: - for macro in self.undef: - compiler.undefine_macro(macro) - if self.libraries is not None: - compiler.set_libraries(self.libraries) - if self.library_dirs is not None: - compiler.set_library_dirs(self.library_dirs) - if self.rpath is not None: - compiler.set_runtime_library_dirs(self.rpath) - if self.link_objects is not None: - compiler.set_link_objects(self.link_objects) - - # hack so distutils' build_extension() builds a library instead - compiler.link_shared_object = link_shared_object.__get__(compiler) - - def get_export_symbols(self, ext): - if isinstance(ext, Library): - return ext.export_symbols - return _build_ext.get_export_symbols(self, ext) - - def build_extension(self, ext): - ext._convert_pyx_sources_to_lang() - _compiler = self.compiler - try: - if isinstance(ext, Library): - self.compiler = self.shlib_compiler - _build_ext.build_extension(self, ext) - if ext._needs_stub: - cmd = self.get_finalized_command('build_py').build_lib - self.write_stub(cmd, ext) - finally: - self.compiler = _compiler - - def links_to_dynamic(self, ext): - """Return true if 'ext' links to a dynamic lib in the same package""" - # XXX this should check to ensure the lib is actually being built - # XXX as dynamic, and not just using a locally-found version or a - # XXX static-compiled version - libnames = dict.fromkeys([lib._full_name for lib in self.shlibs]) - pkg = '.'.join(ext._full_name.split('.')[:-1] + ['']) - return any(pkg + libname in libnames for libname in ext.libraries) - - def get_outputs(self): - return _build_ext.get_outputs(self) + self.__get_stubs_outputs() - - def __get_stubs_outputs(self): - # assemble the base name for each extension that needs a stub - ns_ext_bases = ( - os.path.join(self.build_lib, *ext._full_name.split('.')) - for ext in self.extensions - if ext._needs_stub - ) - # pair each base with the extension - pairs = itertools.product(ns_ext_bases, self.__get_output_extensions()) - return list(base + fnext for base, fnext in pairs) - - def __get_output_extensions(self): - yield '.py' - yield '.pyc' - if self.get_finalized_command('build_py').optimize: - yield '.pyo' - - def write_stub(self, output_dir, ext, compile=False): - log.info("writing stub loader for %s to %s", ext._full_name, - output_dir) - stub_file = (os.path.join(output_dir, *ext._full_name.split('.')) + - '.py') - if compile and os.path.exists(stub_file): - raise DistutilsError(stub_file + " already exists! Please delete.") - if not self.dry_run: - f = open(stub_file, 'w') - f.write( - '\n'.join([ - "def __bootstrap__():", - " global __bootstrap__, __file__, __loader__", - " import sys, os, pkg_resources, imp" + if_dl(", dl"), - " __file__ = pkg_resources.resource_filename" - "(__name__,%r)" - % os.path.basename(ext._file_name), - " del __bootstrap__", - " if '__loader__' in globals():", - " del __loader__", - if_dl(" old_flags = sys.getdlopenflags()"), - " old_dir = os.getcwd()", - " try:", - " os.chdir(os.path.dirname(__file__))", - if_dl(" sys.setdlopenflags(dl.RTLD_NOW)"), - " imp.load_dynamic(__name__,__file__)", - " finally:", - if_dl(" sys.setdlopenflags(old_flags)"), - " os.chdir(old_dir)", - "__bootstrap__()", - "" # terminal \n - ]) - ) - f.close() - if compile: - from distutils.util import byte_compile - - byte_compile([stub_file], optimize=0, - force=True, dry_run=self.dry_run) - optimize = self.get_finalized_command('install_lib').optimize - if optimize > 0: - byte_compile([stub_file], optimize=optimize, - force=True, dry_run=self.dry_run) - if os.path.exists(stub_file) and not self.dry_run: - os.unlink(stub_file) - - -if use_stubs or os.name == 'nt': - # Build shared libraries - # - def link_shared_object( - self, objects, output_libname, output_dir=None, libraries=None, - library_dirs=None, runtime_library_dirs=None, export_symbols=None, - debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, - target_lang=None): - self.link( - self.SHARED_LIBRARY, objects, output_libname, - output_dir, libraries, library_dirs, runtime_library_dirs, - export_symbols, debug, extra_preargs, extra_postargs, - build_temp, target_lang - ) -else: - # Build static libraries everywhere else - libtype = 'static' - - def link_shared_object( - self, objects, output_libname, output_dir=None, libraries=None, - library_dirs=None, runtime_library_dirs=None, export_symbols=None, - debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, - target_lang=None): - # XXX we need to either disallow these attrs on Library instances, - # or warn/abort here if set, or something... - # libraries=None, library_dirs=None, runtime_library_dirs=None, - # export_symbols=None, extra_preargs=None, extra_postargs=None, - # build_temp=None - - assert output_dir is None # distutils build_ext doesn't pass this - output_dir, filename = os.path.split(output_libname) - basename, ext = os.path.splitext(filename) - if self.library_filename("x").startswith('lib'): - # strip 'lib' prefix; this is kludgy if some platform uses - # a different prefix - basename = basename[3:] - - self.create_static_lib( - objects, basename, output_dir, debug, target_lang - ) diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/build_py.py b/venv2/lib/python2.7/site-packages/setuptools/command/build_py.py deleted file mode 100644 index b0314fd..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/build_py.py +++ /dev/null @@ -1,270 +0,0 @@ -from glob import glob -from distutils.util import convert_path -import distutils.command.build_py as orig -import os -import fnmatch -import textwrap -import io -import distutils.errors -import itertools - -from setuptools.extern import six -from setuptools.extern.six.moves import map, filter, filterfalse - -try: - from setuptools.lib2to3_ex import Mixin2to3 -except ImportError: - - class Mixin2to3: - def run_2to3(self, files, doctests=True): - "do nothing" - - -class build_py(orig.build_py, Mixin2to3): - """Enhanced 'build_py' command that includes data files with packages - - The data files are specified via a 'package_data' argument to 'setup()'. - See 'setuptools.dist.Distribution' for more details. - - Also, this version of the 'build_py' command allows you to specify both - 'py_modules' and 'packages' in the same setup operation. - """ - - def finalize_options(self): - orig.build_py.finalize_options(self) - self.package_data = self.distribution.package_data - self.exclude_package_data = (self.distribution.exclude_package_data or - {}) - if 'data_files' in self.__dict__: - del self.__dict__['data_files'] - self.__updated_files = [] - self.__doctests_2to3 = [] - - def run(self): - """Build modules, packages, and copy data files to build directory""" - if not self.py_modules and not self.packages: - return - - if self.py_modules: - self.build_modules() - - if self.packages: - self.build_packages() - self.build_package_data() - - self.run_2to3(self.__updated_files, False) - self.run_2to3(self.__updated_files, True) - self.run_2to3(self.__doctests_2to3, True) - - # Only compile actual .py files, using our base class' idea of what our - # output files are. - self.byte_compile(orig.build_py.get_outputs(self, include_bytecode=0)) - - def __getattr__(self, attr): - "lazily compute data files" - if attr == 'data_files': - self.data_files = self._get_data_files() - return self.data_files - return orig.build_py.__getattr__(self, attr) - - def build_module(self, module, module_file, package): - if six.PY2 and isinstance(package, six.string_types): - # avoid errors on Python 2 when unicode is passed (#190) - package = package.split('.') - outfile, copied = orig.build_py.build_module(self, module, module_file, - package) - if copied: - self.__updated_files.append(outfile) - return outfile, copied - - def _get_data_files(self): - """Generate list of '(package,src_dir,build_dir,filenames)' tuples""" - self.analyze_manifest() - return list(map(self._get_pkg_data_files, self.packages or ())) - - def _get_pkg_data_files(self, package): - # Locate package source directory - src_dir = self.get_package_dir(package) - - # Compute package build directory - build_dir = os.path.join(*([self.build_lib] + package.split('.'))) - - # Strip directory from globbed filenames - filenames = [ - os.path.relpath(file, src_dir) - for file in self.find_data_files(package, src_dir) - ] - return package, src_dir, build_dir, filenames - - def find_data_files(self, package, src_dir): - """Return filenames for package's data files in 'src_dir'""" - patterns = self._get_platform_patterns( - self.package_data, - package, - src_dir, - ) - globs_expanded = map(glob, patterns) - # flatten the expanded globs into an iterable of matches - globs_matches = itertools.chain.from_iterable(globs_expanded) - glob_files = filter(os.path.isfile, globs_matches) - files = itertools.chain( - self.manifest_files.get(package, []), - glob_files, - ) - return self.exclude_data_files(package, src_dir, files) - - def build_package_data(self): - """Copy data files into build directory""" - for package, src_dir, build_dir, filenames in self.data_files: - for filename in filenames: - target = os.path.join(build_dir, filename) - self.mkpath(os.path.dirname(target)) - srcfile = os.path.join(src_dir, filename) - outf, copied = self.copy_file(srcfile, target) - srcfile = os.path.abspath(srcfile) - if (copied and - srcfile in self.distribution.convert_2to3_doctests): - self.__doctests_2to3.append(outf) - - def analyze_manifest(self): - self.manifest_files = mf = {} - if not self.distribution.include_package_data: - return - src_dirs = {} - for package in self.packages or (): - # Locate package source directory - src_dirs[assert_relative(self.get_package_dir(package))] = package - - self.run_command('egg_info') - ei_cmd = self.get_finalized_command('egg_info') - for path in ei_cmd.filelist.files: - d, f = os.path.split(assert_relative(path)) - prev = None - oldf = f - while d and d != prev and d not in src_dirs: - prev = d - d, df = os.path.split(d) - f = os.path.join(df, f) - if d in src_dirs: - if path.endswith('.py') and f == oldf: - continue # it's a module, not data - mf.setdefault(src_dirs[d], []).append(path) - - def get_data_files(self): - pass # Lazily compute data files in _get_data_files() function. - - def check_package(self, package, package_dir): - """Check namespace packages' __init__ for declare_namespace""" - try: - return self.packages_checked[package] - except KeyError: - pass - - init_py = orig.build_py.check_package(self, package, package_dir) - self.packages_checked[package] = init_py - - if not init_py or not self.distribution.namespace_packages: - return init_py - - for pkg in self.distribution.namespace_packages: - if pkg == package or pkg.startswith(package + '.'): - break - else: - return init_py - - with io.open(init_py, 'rb') as f: - contents = f.read() - if b'declare_namespace' not in contents: - raise distutils.errors.DistutilsError( - "Namespace package problem: %s is a namespace package, but " - "its\n__init__.py does not call declare_namespace()! Please " - 'fix it.\n(See the setuptools manual under ' - '"Namespace Packages" for details.)\n"' % (package,) - ) - return init_py - - def initialize_options(self): - self.packages_checked = {} - orig.build_py.initialize_options(self) - - def get_package_dir(self, package): - res = orig.build_py.get_package_dir(self, package) - if self.distribution.src_root is not None: - return os.path.join(self.distribution.src_root, res) - return res - - def exclude_data_files(self, package, src_dir, files): - """Filter filenames for package's data files in 'src_dir'""" - files = list(files) - patterns = self._get_platform_patterns( - self.exclude_package_data, - package, - src_dir, - ) - match_groups = ( - fnmatch.filter(files, pattern) - for pattern in patterns - ) - # flatten the groups of matches into an iterable of matches - matches = itertools.chain.from_iterable(match_groups) - bad = set(matches) - keepers = ( - fn - for fn in files - if fn not in bad - ) - # ditch dupes - return list(_unique_everseen(keepers)) - - @staticmethod - def _get_platform_patterns(spec, package, src_dir): - """ - yield platform-specific path patterns (suitable for glob - or fn_match) from a glob-based spec (such as - self.package_data or self.exclude_package_data) - matching package in src_dir. - """ - raw_patterns = itertools.chain( - spec.get('', []), - spec.get(package, []), - ) - return ( - # Each pattern has to be converted to a platform-specific path - os.path.join(src_dir, convert_path(pattern)) - for pattern in raw_patterns - ) - - -# from Python docs -def _unique_everseen(iterable, key=None): - "List unique elements, preserving order. Remember all elements ever seen." - # unique_everseen('AAAABBBCCDAABBB') --> A B C D - # unique_everseen('ABBCcAD', str.lower) --> A B C D - seen = set() - seen_add = seen.add - if key is None: - for element in filterfalse(seen.__contains__, iterable): - seen_add(element) - yield element - else: - for element in iterable: - k = key(element) - if k not in seen: - seen_add(k) - yield element - - -def assert_relative(path): - if not os.path.isabs(path): - return path - from distutils.errors import DistutilsSetupError - - msg = textwrap.dedent(""" - Error: setup script specifies an absolute path: - - %s - - setup() arguments must *always* be /-separated paths relative to the - setup.py directory, *never* absolute paths. - """).lstrip() % path - raise DistutilsSetupError(msg) diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/develop.py b/venv2/lib/python2.7/site-packages/setuptools/command/develop.py deleted file mode 100644 index 009e4f9..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/develop.py +++ /dev/null @@ -1,221 +0,0 @@ -from distutils.util import convert_path -from distutils import log -from distutils.errors import DistutilsError, DistutilsOptionError -import os -import glob -import io - -from setuptools.extern import six - -import pkg_resources -from setuptools.command.easy_install import easy_install -from setuptools import namespaces -import setuptools - -__metaclass__ = type - - -class develop(namespaces.DevelopInstaller, easy_install): - """Set up package for development""" - - description = "install package in 'development mode'" - - user_options = easy_install.user_options + [ - ("uninstall", "u", "Uninstall this source package"), - ("egg-path=", None, "Set the path to be used in the .egg-link file"), - ] - - boolean_options = easy_install.boolean_options + ['uninstall'] - - command_consumes_arguments = False # override base - - def run(self): - if self.uninstall: - self.multi_version = True - self.uninstall_link() - self.uninstall_namespaces() - else: - self.install_for_development() - self.warn_deprecated_options() - - def initialize_options(self): - self.uninstall = None - self.egg_path = None - easy_install.initialize_options(self) - self.setup_path = None - self.always_copy_from = '.' # always copy eggs installed in curdir - - def finalize_options(self): - ei = self.get_finalized_command("egg_info") - if ei.broken_egg_info: - template = "Please rename %r to %r before using 'develop'" - args = ei.egg_info, ei.broken_egg_info - raise DistutilsError(template % args) - self.args = [ei.egg_name] - - easy_install.finalize_options(self) - self.expand_basedirs() - self.expand_dirs() - # pick up setup-dir .egg files only: no .egg-info - self.package_index.scan(glob.glob('*.egg')) - - egg_link_fn = ei.egg_name + '.egg-link' - self.egg_link = os.path.join(self.install_dir, egg_link_fn) - self.egg_base = ei.egg_base - if self.egg_path is None: - self.egg_path = os.path.abspath(ei.egg_base) - - target = pkg_resources.normalize_path(self.egg_base) - egg_path = pkg_resources.normalize_path( - os.path.join(self.install_dir, self.egg_path)) - if egg_path != target: - raise DistutilsOptionError( - "--egg-path must be a relative path from the install" - " directory to " + target - ) - - # Make a distribution for the package's source - self.dist = pkg_resources.Distribution( - target, - pkg_resources.PathMetadata(target, os.path.abspath(ei.egg_info)), - project_name=ei.egg_name - ) - - self.setup_path = self._resolve_setup_path( - self.egg_base, - self.install_dir, - self.egg_path, - ) - - @staticmethod - def _resolve_setup_path(egg_base, install_dir, egg_path): - """ - Generate a path from egg_base back to '.' where the - setup script resides and ensure that path points to the - setup path from $install_dir/$egg_path. - """ - path_to_setup = egg_base.replace(os.sep, '/').rstrip('/') - if path_to_setup != os.curdir: - path_to_setup = '../' * (path_to_setup.count('/') + 1) - resolved = pkg_resources.normalize_path( - os.path.join(install_dir, egg_path, path_to_setup) - ) - if resolved != pkg_resources.normalize_path(os.curdir): - raise DistutilsOptionError( - "Can't get a consistent path to setup script from" - " installation directory", resolved, - pkg_resources.normalize_path(os.curdir)) - return path_to_setup - - def install_for_development(self): - if six.PY3 and getattr(self.distribution, 'use_2to3', False): - # If we run 2to3 we can not do this inplace: - - # Ensure metadata is up-to-date - self.reinitialize_command('build_py', inplace=0) - self.run_command('build_py') - bpy_cmd = self.get_finalized_command("build_py") - build_path = pkg_resources.normalize_path(bpy_cmd.build_lib) - - # Build extensions - self.reinitialize_command('egg_info', egg_base=build_path) - self.run_command('egg_info') - - self.reinitialize_command('build_ext', inplace=0) - self.run_command('build_ext') - - # Fixup egg-link and easy-install.pth - ei_cmd = self.get_finalized_command("egg_info") - self.egg_path = build_path - self.dist.location = build_path - # XXX - self.dist._provider = pkg_resources.PathMetadata( - build_path, ei_cmd.egg_info) - else: - # Without 2to3 inplace works fine: - self.run_command('egg_info') - - # Build extensions in-place - self.reinitialize_command('build_ext', inplace=1) - self.run_command('build_ext') - - self.install_site_py() # ensure that target dir is site-safe - if setuptools.bootstrap_install_from: - self.easy_install(setuptools.bootstrap_install_from) - setuptools.bootstrap_install_from = None - - self.install_namespaces() - - # create an .egg-link in the installation dir, pointing to our egg - log.info("Creating %s (link to %s)", self.egg_link, self.egg_base) - if not self.dry_run: - with open(self.egg_link, "w") as f: - f.write(self.egg_path + "\n" + self.setup_path) - # postprocess the installed distro, fixing up .pth, installing scripts, - # and handling requirements - self.process_distribution(None, self.dist, not self.no_deps) - - def uninstall_link(self): - if os.path.exists(self.egg_link): - log.info("Removing %s (link to %s)", self.egg_link, self.egg_base) - egg_link_file = open(self.egg_link) - contents = [line.rstrip() for line in egg_link_file] - egg_link_file.close() - if contents not in ([self.egg_path], - [self.egg_path, self.setup_path]): - log.warn("Link points to %s: uninstall aborted", contents) - return - if not self.dry_run: - os.unlink(self.egg_link) - if not self.dry_run: - self.update_pth(self.dist) # remove any .pth link to us - if self.distribution.scripts: - # XXX should also check for entry point scripts! - log.warn("Note: you must uninstall or replace scripts manually!") - - def install_egg_scripts(self, dist): - if dist is not self.dist: - # Installing a dependency, so fall back to normal behavior - return easy_install.install_egg_scripts(self, dist) - - # create wrapper scripts in the script dir, pointing to dist.scripts - - # new-style... - self.install_wrapper_scripts(dist) - - # ...and old-style - for script_name in self.distribution.scripts or []: - script_path = os.path.abspath(convert_path(script_name)) - script_name = os.path.basename(script_path) - with io.open(script_path) as strm: - script_text = strm.read() - self.install_script(dist, script_name, script_text, script_path) - - def install_wrapper_scripts(self, dist): - dist = VersionlessRequirement(dist) - return easy_install.install_wrapper_scripts(self, dist) - - -class VersionlessRequirement: - """ - Adapt a pkg_resources.Distribution to simply return the project - name as the 'requirement' so that scripts will work across - multiple versions. - - >>> from pkg_resources import Distribution - >>> dist = Distribution(project_name='foo', version='1.0') - >>> str(dist.as_requirement()) - 'foo==1.0' - >>> adapted_dist = VersionlessRequirement(dist) - >>> str(adapted_dist.as_requirement()) - 'foo' - """ - - def __init__(self, dist): - self.__dist = dist - - def __getattr__(self, name): - return getattr(self.__dist, name) - - def as_requirement(self): - return self.project_name diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/dist_info.py b/venv2/lib/python2.7/site-packages/setuptools/command/dist_info.py deleted file mode 100644 index c45258f..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/dist_info.py +++ /dev/null @@ -1,36 +0,0 @@ -""" -Create a dist_info directory -As defined in the wheel specification -""" - -import os - -from distutils.core import Command -from distutils import log - - -class dist_info(Command): - - description = 'create a .dist-info directory' - - user_options = [ - ('egg-base=', 'e', "directory containing .egg-info directories" - " (default: top of the source tree)"), - ] - - def initialize_options(self): - self.egg_base = None - - def finalize_options(self): - pass - - def run(self): - egg_info = self.get_finalized_command('egg_info') - egg_info.egg_base = self.egg_base - egg_info.finalize_options() - egg_info.run() - dist_info_dir = egg_info.egg_info[:-len('.egg-info')] + '.dist-info' - log.info("creating '{}'".format(os.path.abspath(dist_info_dir))) - - bdist_wheel = self.get_finalized_command('bdist_wheel') - bdist_wheel.egg2dist(egg_info.egg_info, dist_info_dir) diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/easy_install.py b/venv2/lib/python2.7/site-packages/setuptools/command/easy_install.py deleted file mode 100644 index 06c9827..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/easy_install.py +++ /dev/null @@ -1,2342 +0,0 @@ -#!/usr/bin/env python -""" -Easy Install ------------- - -A tool for doing automatic download/extract/build of distutils-based Python -packages. For detailed documentation, see the accompanying EasyInstall.txt -file, or visit the `EasyInstall home page`__. - -__ https://setuptools.readthedocs.io/en/latest/easy_install.html - -""" - -from glob import glob -from distutils.util import get_platform -from distutils.util import convert_path, subst_vars -from distutils.errors import ( - DistutilsArgError, DistutilsOptionError, - DistutilsError, DistutilsPlatformError, -) -from distutils.command.install import INSTALL_SCHEMES, SCHEME_KEYS -from distutils import log, dir_util -from distutils.command.build_scripts import first_line_re -from distutils.spawn import find_executable -import sys -import os -import zipimport -import shutil -import tempfile -import zipfile -import re -import stat -import random -import textwrap -import warnings -import site -import struct -import contextlib -import subprocess -import shlex -import io - - -from sysconfig import get_config_vars, get_path - -from setuptools import SetuptoolsDeprecationWarning - -from setuptools.extern import six -from setuptools.extern.six.moves import configparser, map - -from setuptools import Command -from setuptools.sandbox import run_setup -from setuptools.py27compat import rmtree_safe -from setuptools.command import setopt -from setuptools.archive_util import unpack_archive -from setuptools.package_index import ( - PackageIndex, parse_requirement_arg, URL_SCHEME, -) -from setuptools.command import bdist_egg, egg_info -from setuptools.wheel import Wheel -from pkg_resources import ( - yield_lines, normalize_path, resource_string, ensure_directory, - get_distribution, find_distributions, Environment, Requirement, - Distribution, PathMetadata, EggMetadata, WorkingSet, DistributionNotFound, - VersionConflict, DEVELOP_DIST, -) -import pkg_resources.py31compat - -__metaclass__ = type - -# Turn on PEP440Warnings -warnings.filterwarnings("default", category=pkg_resources.PEP440Warning) - -__all__ = [ - 'samefile', 'easy_install', 'PthDistributions', 'extract_wininst_cfg', - 'main', 'get_exe_prefixes', -] - - -def is_64bit(): - return struct.calcsize("P") == 8 - - -def samefile(p1, p2): - """ - Determine if two paths reference the same file. - - Augments os.path.samefile to work on Windows and - suppresses errors if the path doesn't exist. - """ - both_exist = os.path.exists(p1) and os.path.exists(p2) - use_samefile = hasattr(os.path, 'samefile') and both_exist - if use_samefile: - return os.path.samefile(p1, p2) - norm_p1 = os.path.normpath(os.path.normcase(p1)) - norm_p2 = os.path.normpath(os.path.normcase(p2)) - return norm_p1 == norm_p2 - - -if six.PY2: - - def _to_bytes(s): - return s - - def isascii(s): - try: - six.text_type(s, 'ascii') - return True - except UnicodeError: - return False -else: - - def _to_bytes(s): - return s.encode('utf8') - - def isascii(s): - try: - s.encode('ascii') - return True - except UnicodeError: - return False - - -_one_liner = lambda text: textwrap.dedent(text).strip().replace('\n', '; ') - - -class easy_install(Command): - """Manage a download/build/install process""" - description = "Find/get/install Python packages" - command_consumes_arguments = True - - user_options = [ - ('prefix=', None, "installation prefix"), - ("zip-ok", "z", "install package as a zipfile"), - ("multi-version", "m", "make apps have to require() a version"), - ("upgrade", "U", "force upgrade (searches PyPI for latest versions)"), - ("install-dir=", "d", "install package to DIR"), - ("script-dir=", "s", "install scripts to DIR"), - ("exclude-scripts", "x", "Don't install scripts"), - ("always-copy", "a", "Copy all needed packages to install dir"), - ("index-url=", "i", "base URL of Python Package Index"), - ("find-links=", "f", "additional URL(s) to search for packages"), - ("build-directory=", "b", - "download/extract/build in DIR; keep the results"), - ('optimize=', 'O', - "also compile with optimization: -O1 for \"python -O\", " - "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"), - ('record=', None, - "filename in which to record list of installed files"), - ('always-unzip', 'Z', "don't install as a zipfile, no matter what"), - ('site-dirs=', 'S', "list of directories where .pth files work"), - ('editable', 'e', "Install specified packages in editable form"), - ('no-deps', 'N', "don't install dependencies"), - ('allow-hosts=', 'H', "pattern(s) that hostnames must match"), - ('local-snapshots-ok', 'l', - "allow building eggs from local checkouts"), - ('version', None, "print version information and exit"), - ('no-find-links', None, - "Don't load find-links defined in packages being installed") - ] - boolean_options = [ - 'zip-ok', 'multi-version', 'exclude-scripts', 'upgrade', 'always-copy', - 'editable', - 'no-deps', 'local-snapshots-ok', 'version' - ] - - if site.ENABLE_USER_SITE: - help_msg = "install in user site-package '%s'" % site.USER_SITE - user_options.append(('user', None, help_msg)) - boolean_options.append('user') - - negative_opt = {'always-unzip': 'zip-ok'} - create_index = PackageIndex - - def initialize_options(self): - # the --user option seems to be an opt-in one, - # so the default should be False. - self.user = 0 - self.zip_ok = self.local_snapshots_ok = None - self.install_dir = self.script_dir = self.exclude_scripts = None - self.index_url = None - self.find_links = None - self.build_directory = None - self.args = None - self.optimize = self.record = None - self.upgrade = self.always_copy = self.multi_version = None - self.editable = self.no_deps = self.allow_hosts = None - self.root = self.prefix = self.no_report = None - self.version = None - self.install_purelib = None # for pure module distributions - self.install_platlib = None # non-pure (dists w/ extensions) - self.install_headers = None # for C/C++ headers - self.install_lib = None # set to either purelib or platlib - self.install_scripts = None - self.install_data = None - self.install_base = None - self.install_platbase = None - if site.ENABLE_USER_SITE: - self.install_userbase = site.USER_BASE - self.install_usersite = site.USER_SITE - else: - self.install_userbase = None - self.install_usersite = None - self.no_find_links = None - - # Options not specifiable via command line - self.package_index = None - self.pth_file = self.always_copy_from = None - self.site_dirs = None - self.installed_projects = {} - self.sitepy_installed = False - # Always read easy_install options, even if we are subclassed, or have - # an independent instance created. This ensures that defaults will - # always come from the standard configuration file(s)' "easy_install" - # section, even if this is a "develop" or "install" command, or some - # other embedding. - self._dry_run = None - self.verbose = self.distribution.verbose - self.distribution._set_command_options( - self, self.distribution.get_option_dict('easy_install') - ) - - def delete_blockers(self, blockers): - extant_blockers = ( - filename for filename in blockers - if os.path.exists(filename) or os.path.islink(filename) - ) - list(map(self._delete_path, extant_blockers)) - - def _delete_path(self, path): - log.info("Deleting %s", path) - if self.dry_run: - return - - is_tree = os.path.isdir(path) and not os.path.islink(path) - remover = rmtree if is_tree else os.unlink - remover(path) - - @staticmethod - def _render_version(): - """ - Render the Setuptools version and installation details, then exit. - """ - ver = sys.version[:3] - dist = get_distribution('setuptools') - tmpl = 'setuptools {dist.version} from {dist.location} (Python {ver})' - print(tmpl.format(**locals())) - raise SystemExit() - - def finalize_options(self): - self.version and self._render_version() - - py_version = sys.version.split()[0] - prefix, exec_prefix = get_config_vars('prefix', 'exec_prefix') - - self.config_vars = { - 'dist_name': self.distribution.get_name(), - 'dist_version': self.distribution.get_version(), - 'dist_fullname': self.distribution.get_fullname(), - 'py_version': py_version, - 'py_version_short': py_version[0:3], - 'py_version_nodot': py_version[0] + py_version[2], - 'sys_prefix': prefix, - 'prefix': prefix, - 'sys_exec_prefix': exec_prefix, - 'exec_prefix': exec_prefix, - # Only python 3.2+ has abiflags - 'abiflags': getattr(sys, 'abiflags', ''), - } - - if site.ENABLE_USER_SITE: - self.config_vars['userbase'] = self.install_userbase - self.config_vars['usersite'] = self.install_usersite - - self._fix_install_dir_for_user_site() - - self.expand_basedirs() - self.expand_dirs() - - self._expand( - 'install_dir', 'script_dir', 'build_directory', - 'site_dirs', - ) - # If a non-default installation directory was specified, default the - # script directory to match it. - if self.script_dir is None: - self.script_dir = self.install_dir - - if self.no_find_links is None: - self.no_find_links = False - - # Let install_dir get set by install_lib command, which in turn - # gets its info from the install command, and takes into account - # --prefix and --home and all that other crud. - self.set_undefined_options( - 'install_lib', ('install_dir', 'install_dir') - ) - # Likewise, set default script_dir from 'install_scripts.install_dir' - self.set_undefined_options( - 'install_scripts', ('install_dir', 'script_dir') - ) - - if self.user and self.install_purelib: - self.install_dir = self.install_purelib - self.script_dir = self.install_scripts - # default --record from the install command - self.set_undefined_options('install', ('record', 'record')) - # Should this be moved to the if statement below? It's not used - # elsewhere - normpath = map(normalize_path, sys.path) - self.all_site_dirs = get_site_dirs() - if self.site_dirs is not None: - site_dirs = [ - os.path.expanduser(s.strip()) for s in - self.site_dirs.split(',') - ] - for d in site_dirs: - if not os.path.isdir(d): - log.warn("%s (in --site-dirs) does not exist", d) - elif normalize_path(d) not in normpath: - raise DistutilsOptionError( - d + " (in --site-dirs) is not on sys.path" - ) - else: - self.all_site_dirs.append(normalize_path(d)) - if not self.editable: - self.check_site_dir() - self.index_url = self.index_url or "https://pypi.org/simple/" - self.shadow_path = self.all_site_dirs[:] - for path_item in self.install_dir, normalize_path(self.script_dir): - if path_item not in self.shadow_path: - self.shadow_path.insert(0, path_item) - - if self.allow_hosts is not None: - hosts = [s.strip() for s in self.allow_hosts.split(',')] - else: - hosts = ['*'] - if self.package_index is None: - self.package_index = self.create_index( - self.index_url, search_path=self.shadow_path, hosts=hosts, - ) - self.local_index = Environment(self.shadow_path + sys.path) - - if self.find_links is not None: - if isinstance(self.find_links, six.string_types): - self.find_links = self.find_links.split() - else: - self.find_links = [] - if self.local_snapshots_ok: - self.package_index.scan_egg_links(self.shadow_path + sys.path) - if not self.no_find_links: - self.package_index.add_find_links(self.find_links) - self.set_undefined_options('install_lib', ('optimize', 'optimize')) - if not isinstance(self.optimize, int): - try: - self.optimize = int(self.optimize) - if not (0 <= self.optimize <= 2): - raise ValueError - except ValueError: - raise DistutilsOptionError("--optimize must be 0, 1, or 2") - - if self.editable and not self.build_directory: - raise DistutilsArgError( - "Must specify a build directory (-b) when using --editable" - ) - if not self.args: - raise DistutilsArgError( - "No urls, filenames, or requirements specified (see --help)") - - self.outputs = [] - - def _fix_install_dir_for_user_site(self): - """ - Fix the install_dir if "--user" was used. - """ - if not self.user or not site.ENABLE_USER_SITE: - return - - self.create_home_path() - if self.install_userbase is None: - msg = "User base directory is not specified" - raise DistutilsPlatformError(msg) - self.install_base = self.install_platbase = self.install_userbase - scheme_name = os.name.replace('posix', 'unix') + '_user' - self.select_scheme(scheme_name) - - def _expand_attrs(self, attrs): - for attr in attrs: - val = getattr(self, attr) - if val is not None: - if os.name == 'posix' or os.name == 'nt': - val = os.path.expanduser(val) - val = subst_vars(val, self.config_vars) - setattr(self, attr, val) - - def expand_basedirs(self): - """Calls `os.path.expanduser` on install_base, install_platbase and - root.""" - self._expand_attrs(['install_base', 'install_platbase', 'root']) - - def expand_dirs(self): - """Calls `os.path.expanduser` on install dirs.""" - dirs = [ - 'install_purelib', - 'install_platlib', - 'install_lib', - 'install_headers', - 'install_scripts', - 'install_data', - ] - self._expand_attrs(dirs) - - def run(self): - if self.verbose != self.distribution.verbose: - log.set_verbosity(self.verbose) - try: - for spec in self.args: - self.easy_install(spec, not self.no_deps) - if self.record: - outputs = self.outputs - if self.root: # strip any package prefix - root_len = len(self.root) - for counter in range(len(outputs)): - outputs[counter] = outputs[counter][root_len:] - from distutils import file_util - - self.execute( - file_util.write_file, (self.record, outputs), - "writing list of installed files to '%s'" % - self.record - ) - self.warn_deprecated_options() - finally: - log.set_verbosity(self.distribution.verbose) - - def pseudo_tempname(self): - """Return a pseudo-tempname base in the install directory. - This code is intentionally naive; if a malicious party can write to - the target directory you're already in deep doodoo. - """ - try: - pid = os.getpid() - except Exception: - pid = random.randint(0, sys.maxsize) - return os.path.join(self.install_dir, "test-easy-install-%s" % pid) - - def warn_deprecated_options(self): - pass - - def check_site_dir(self): - """Verify that self.install_dir is .pth-capable dir, if needed""" - - instdir = normalize_path(self.install_dir) - pth_file = os.path.join(instdir, 'easy-install.pth') - - # Is it a configured, PYTHONPATH, implicit, or explicit site dir? - is_site_dir = instdir in self.all_site_dirs - - if not is_site_dir and not self.multi_version: - # No? Then directly test whether it does .pth file processing - is_site_dir = self.check_pth_processing() - else: - # make sure we can write to target dir - testfile = self.pseudo_tempname() + '.write-test' - test_exists = os.path.exists(testfile) - try: - if test_exists: - os.unlink(testfile) - open(testfile, 'w').close() - os.unlink(testfile) - except (OSError, IOError): - self.cant_write_to_target() - - if not is_site_dir and not self.multi_version: - # Can't install non-multi to non-site dir - raise DistutilsError(self.no_default_version_msg()) - - if is_site_dir: - if self.pth_file is None: - self.pth_file = PthDistributions(pth_file, self.all_site_dirs) - else: - self.pth_file = None - - if instdir not in map(normalize_path, _pythonpath()): - # only PYTHONPATH dirs need a site.py, so pretend it's there - self.sitepy_installed = True - elif self.multi_version and not os.path.exists(pth_file): - self.sitepy_installed = True # don't need site.py in this case - self.pth_file = None # and don't create a .pth file - self.install_dir = instdir - - __cant_write_msg = textwrap.dedent(""" - can't create or remove files in install directory - - The following error occurred while trying to add or remove files in the - installation directory: - - %s - - The installation directory you specified (via --install-dir, --prefix, or - the distutils default setting) was: - - %s - """).lstrip() - - __not_exists_id = textwrap.dedent(""" - This directory does not currently exist. Please create it and try again, or - choose a different installation directory (using the -d or --install-dir - option). - """).lstrip() - - __access_msg = textwrap.dedent(""" - Perhaps your account does not have write access to this directory? If the - installation directory is a system-owned directory, you may need to sign in - as the administrator or "root" account. If you do not have administrative - access to this machine, you may wish to choose a different installation - directory, preferably one that is listed in your PYTHONPATH environment - variable. - - For information on other options, you may wish to consult the - documentation at: - - https://setuptools.readthedocs.io/en/latest/easy_install.html - - Please make the appropriate changes for your system and try again. - """).lstrip() - - def cant_write_to_target(self): - msg = self.__cant_write_msg % (sys.exc_info()[1], self.install_dir,) - - if not os.path.exists(self.install_dir): - msg += '\n' + self.__not_exists_id - else: - msg += '\n' + self.__access_msg - raise DistutilsError(msg) - - def check_pth_processing(self): - """Empirically verify whether .pth files are supported in inst. dir""" - instdir = self.install_dir - log.info("Checking .pth file support in %s", instdir) - pth_file = self.pseudo_tempname() + ".pth" - ok_file = pth_file + '.ok' - ok_exists = os.path.exists(ok_file) - tmpl = _one_liner(""" - import os - f = open({ok_file!r}, 'w') - f.write('OK') - f.close() - """) + '\n' - try: - if ok_exists: - os.unlink(ok_file) - dirname = os.path.dirname(ok_file) - pkg_resources.py31compat.makedirs(dirname, exist_ok=True) - f = open(pth_file, 'w') - except (OSError, IOError): - self.cant_write_to_target() - else: - try: - f.write(tmpl.format(**locals())) - f.close() - f = None - executable = sys.executable - if os.name == 'nt': - dirname, basename = os.path.split(executable) - alt = os.path.join(dirname, 'pythonw.exe') - use_alt = ( - basename.lower() == 'python.exe' and - os.path.exists(alt) - ) - if use_alt: - # use pythonw.exe to avoid opening a console window - executable = alt - - from distutils.spawn import spawn - - spawn([executable, '-E', '-c', 'pass'], 0) - - if os.path.exists(ok_file): - log.info( - "TEST PASSED: %s appears to support .pth files", - instdir - ) - return True - finally: - if f: - f.close() - if os.path.exists(ok_file): - os.unlink(ok_file) - if os.path.exists(pth_file): - os.unlink(pth_file) - if not self.multi_version: - log.warn("TEST FAILED: %s does NOT support .pth files", instdir) - return False - - def install_egg_scripts(self, dist): - """Write all the scripts for `dist`, unless scripts are excluded""" - if not self.exclude_scripts and dist.metadata_isdir('scripts'): - for script_name in dist.metadata_listdir('scripts'): - if dist.metadata_isdir('scripts/' + script_name): - # The "script" is a directory, likely a Python 3 - # __pycache__ directory, so skip it. - continue - self.install_script( - dist, script_name, - dist.get_metadata('scripts/' + script_name) - ) - self.install_wrapper_scripts(dist) - - def add_output(self, path): - if os.path.isdir(path): - for base, dirs, files in os.walk(path): - for filename in files: - self.outputs.append(os.path.join(base, filename)) - else: - self.outputs.append(path) - - def not_editable(self, spec): - if self.editable: - raise DistutilsArgError( - "Invalid argument %r: you can't use filenames or URLs " - "with --editable (except via the --find-links option)." - % (spec,) - ) - - def check_editable(self, spec): - if not self.editable: - return - - if os.path.exists(os.path.join(self.build_directory, spec.key)): - raise DistutilsArgError( - "%r already exists in %s; can't do a checkout there" % - (spec.key, self.build_directory) - ) - - @contextlib.contextmanager - def _tmpdir(self): - tmpdir = tempfile.mkdtemp(prefix=u"easy_install-") - try: - # cast to str as workaround for #709 and #710 and #712 - yield str(tmpdir) - finally: - os.path.exists(tmpdir) and rmtree(rmtree_safe(tmpdir)) - - def easy_install(self, spec, deps=False): - if not self.editable: - self.install_site_py() - - with self._tmpdir() as tmpdir: - if not isinstance(spec, Requirement): - if URL_SCHEME(spec): - # It's a url, download it to tmpdir and process - self.not_editable(spec) - dl = self.package_index.download(spec, tmpdir) - return self.install_item(None, dl, tmpdir, deps, True) - - elif os.path.exists(spec): - # Existing file or directory, just process it directly - self.not_editable(spec) - return self.install_item(None, spec, tmpdir, deps, True) - else: - spec = parse_requirement_arg(spec) - - self.check_editable(spec) - dist = self.package_index.fetch_distribution( - spec, tmpdir, self.upgrade, self.editable, - not self.always_copy, self.local_index - ) - if dist is None: - msg = "Could not find suitable distribution for %r" % spec - if self.always_copy: - msg += " (--always-copy skips system and development eggs)" - raise DistutilsError(msg) - elif dist.precedence == DEVELOP_DIST: - # .egg-info dists don't need installing, just process deps - self.process_distribution(spec, dist, deps, "Using") - return dist - else: - return self.install_item(spec, dist.location, tmpdir, deps) - - def install_item(self, spec, download, tmpdir, deps, install_needed=False): - - # Installation is also needed if file in tmpdir or is not an egg - install_needed = install_needed or self.always_copy - install_needed = install_needed or os.path.dirname(download) == tmpdir - install_needed = install_needed or not download.endswith('.egg') - install_needed = install_needed or ( - self.always_copy_from is not None and - os.path.dirname(normalize_path(download)) == - normalize_path(self.always_copy_from) - ) - - if spec and not install_needed: - # at this point, we know it's a local .egg, we just don't know if - # it's already installed. - for dist in self.local_index[spec.project_name]: - if dist.location == download: - break - else: - install_needed = True # it's not in the local index - - log.info("Processing %s", os.path.basename(download)) - - if install_needed: - dists = self.install_eggs(spec, download, tmpdir) - for dist in dists: - self.process_distribution(spec, dist, deps) - else: - dists = [self.egg_distribution(download)] - self.process_distribution(spec, dists[0], deps, "Using") - - if spec is not None: - for dist in dists: - if dist in spec: - return dist - - def select_scheme(self, name): - """Sets the install directories by applying the install schemes.""" - # it's the caller's problem if they supply a bad name! - scheme = INSTALL_SCHEMES[name] - for key in SCHEME_KEYS: - attrname = 'install_' + key - if getattr(self, attrname) is None: - setattr(self, attrname, scheme[key]) - - def process_distribution(self, requirement, dist, deps=True, *info): - self.update_pth(dist) - self.package_index.add(dist) - if dist in self.local_index[dist.key]: - self.local_index.remove(dist) - self.local_index.add(dist) - self.install_egg_scripts(dist) - self.installed_projects[dist.key] = dist - log.info(self.installation_report(requirement, dist, *info)) - if (dist.has_metadata('dependency_links.txt') and - not self.no_find_links): - self.package_index.add_find_links( - dist.get_metadata_lines('dependency_links.txt') - ) - if not deps and not self.always_copy: - return - elif requirement is not None and dist.key != requirement.key: - log.warn("Skipping dependencies for %s", dist) - return # XXX this is not the distribution we were looking for - elif requirement is None or dist not in requirement: - # if we wound up with a different version, resolve what we've got - distreq = dist.as_requirement() - requirement = Requirement(str(distreq)) - log.info("Processing dependencies for %s", requirement) - try: - distros = WorkingSet([]).resolve( - [requirement], self.local_index, self.easy_install - ) - except DistributionNotFound as e: - raise DistutilsError(str(e)) - except VersionConflict as e: - raise DistutilsError(e.report()) - if self.always_copy or self.always_copy_from: - # Force all the relevant distros to be copied or activated - for dist in distros: - if dist.key not in self.installed_projects: - self.easy_install(dist.as_requirement()) - log.info("Finished processing dependencies for %s", requirement) - - def should_unzip(self, dist): - if self.zip_ok is not None: - return not self.zip_ok - if dist.has_metadata('not-zip-safe'): - return True - if not dist.has_metadata('zip-safe'): - return True - return False - - def maybe_move(self, spec, dist_filename, setup_base): - dst = os.path.join(self.build_directory, spec.key) - if os.path.exists(dst): - msg = ( - "%r already exists in %s; build directory %s will not be kept" - ) - log.warn(msg, spec.key, self.build_directory, setup_base) - return setup_base - if os.path.isdir(dist_filename): - setup_base = dist_filename - else: - if os.path.dirname(dist_filename) == setup_base: - os.unlink(dist_filename) # get it out of the tmp dir - contents = os.listdir(setup_base) - if len(contents) == 1: - dist_filename = os.path.join(setup_base, contents[0]) - if os.path.isdir(dist_filename): - # if the only thing there is a directory, move it instead - setup_base = dist_filename - ensure_directory(dst) - shutil.move(setup_base, dst) - return dst - - def install_wrapper_scripts(self, dist): - if self.exclude_scripts: - return - for args in ScriptWriter.best().get_args(dist): - self.write_script(*args) - - def install_script(self, dist, script_name, script_text, dev_path=None): - """Generate a legacy script wrapper and install it""" - spec = str(dist.as_requirement()) - is_script = is_python_script(script_text, script_name) - - if is_script: - body = self._load_template(dev_path) % locals() - script_text = ScriptWriter.get_header(script_text) + body - self.write_script(script_name, _to_bytes(script_text), 'b') - - @staticmethod - def _load_template(dev_path): - """ - There are a couple of template scripts in the package. This - function loads one of them and prepares it for use. - """ - # See https://github.com/pypa/setuptools/issues/134 for info - # on script file naming and downstream issues with SVR4 - name = 'script.tmpl' - if dev_path: - name = name.replace('.tmpl', ' (dev).tmpl') - - raw_bytes = resource_string('setuptools', name) - return raw_bytes.decode('utf-8') - - def write_script(self, script_name, contents, mode="t", blockers=()): - """Write an executable file to the scripts directory""" - self.delete_blockers( # clean up old .py/.pyw w/o a script - [os.path.join(self.script_dir, x) for x in blockers] - ) - log.info("Installing %s script to %s", script_name, self.script_dir) - target = os.path.join(self.script_dir, script_name) - self.add_output(target) - - if self.dry_run: - return - - mask = current_umask() - ensure_directory(target) - if os.path.exists(target): - os.unlink(target) - with open(target, "w" + mode) as f: - f.write(contents) - chmod(target, 0o777 - mask) - - def install_eggs(self, spec, dist_filename, tmpdir): - # .egg dirs or files are already built, so just return them - if dist_filename.lower().endswith('.egg'): - return [self.install_egg(dist_filename, tmpdir)] - elif dist_filename.lower().endswith('.exe'): - return [self.install_exe(dist_filename, tmpdir)] - elif dist_filename.lower().endswith('.whl'): - return [self.install_wheel(dist_filename, tmpdir)] - - # Anything else, try to extract and build - setup_base = tmpdir - if os.path.isfile(dist_filename) and not dist_filename.endswith('.py'): - unpack_archive(dist_filename, tmpdir, self.unpack_progress) - elif os.path.isdir(dist_filename): - setup_base = os.path.abspath(dist_filename) - - if (setup_base.startswith(tmpdir) # something we downloaded - and self.build_directory and spec is not None): - setup_base = self.maybe_move(spec, dist_filename, setup_base) - - # Find the setup.py file - setup_script = os.path.join(setup_base, 'setup.py') - - if not os.path.exists(setup_script): - setups = glob(os.path.join(setup_base, '*', 'setup.py')) - if not setups: - raise DistutilsError( - "Couldn't find a setup script in %s" % - os.path.abspath(dist_filename) - ) - if len(setups) > 1: - raise DistutilsError( - "Multiple setup scripts in %s" % - os.path.abspath(dist_filename) - ) - setup_script = setups[0] - - # Now run it, and return the result - if self.editable: - log.info(self.report_editable(spec, setup_script)) - return [] - else: - return self.build_and_install(setup_script, setup_base) - - def egg_distribution(self, egg_path): - if os.path.isdir(egg_path): - metadata = PathMetadata(egg_path, os.path.join(egg_path, - 'EGG-INFO')) - else: - metadata = EggMetadata(zipimport.zipimporter(egg_path)) - return Distribution.from_filename(egg_path, metadata=metadata) - - def install_egg(self, egg_path, tmpdir): - destination = os.path.join( - self.install_dir, - os.path.basename(egg_path), - ) - destination = os.path.abspath(destination) - if not self.dry_run: - ensure_directory(destination) - - dist = self.egg_distribution(egg_path) - if not samefile(egg_path, destination): - if os.path.isdir(destination) and not os.path.islink(destination): - dir_util.remove_tree(destination, dry_run=self.dry_run) - elif os.path.exists(destination): - self.execute( - os.unlink, - (destination,), - "Removing " + destination, - ) - try: - new_dist_is_zipped = False - if os.path.isdir(egg_path): - if egg_path.startswith(tmpdir): - f, m = shutil.move, "Moving" - else: - f, m = shutil.copytree, "Copying" - elif self.should_unzip(dist): - self.mkpath(destination) - f, m = self.unpack_and_compile, "Extracting" - else: - new_dist_is_zipped = True - if egg_path.startswith(tmpdir): - f, m = shutil.move, "Moving" - else: - f, m = shutil.copy2, "Copying" - self.execute( - f, - (egg_path, destination), - (m + " %s to %s") % ( - os.path.basename(egg_path), - os.path.dirname(destination) - ), - ) - update_dist_caches( - destination, - fix_zipimporter_caches=new_dist_is_zipped, - ) - except Exception: - update_dist_caches(destination, fix_zipimporter_caches=False) - raise - - self.add_output(destination) - return self.egg_distribution(destination) - - def install_exe(self, dist_filename, tmpdir): - # See if it's valid, get data - cfg = extract_wininst_cfg(dist_filename) - if cfg is None: - raise DistutilsError( - "%s is not a valid distutils Windows .exe" % dist_filename - ) - # Create a dummy distribution object until we build the real distro - dist = Distribution( - None, - project_name=cfg.get('metadata', 'name'), - version=cfg.get('metadata', 'version'), platform=get_platform(), - ) - - # Convert the .exe to an unpacked egg - egg_path = os.path.join(tmpdir, dist.egg_name() + '.egg') - dist.location = egg_path - egg_tmp = egg_path + '.tmp' - _egg_info = os.path.join(egg_tmp, 'EGG-INFO') - pkg_inf = os.path.join(_egg_info, 'PKG-INFO') - ensure_directory(pkg_inf) # make sure EGG-INFO dir exists - dist._provider = PathMetadata(egg_tmp, _egg_info) # XXX - self.exe_to_egg(dist_filename, egg_tmp) - - # Write EGG-INFO/PKG-INFO - if not os.path.exists(pkg_inf): - f = open(pkg_inf, 'w') - f.write('Metadata-Version: 1.0\n') - for k, v in cfg.items('metadata'): - if k != 'target_version': - f.write('%s: %s\n' % (k.replace('_', '-').title(), v)) - f.close() - script_dir = os.path.join(_egg_info, 'scripts') - # delete entry-point scripts to avoid duping - self.delete_blockers([ - os.path.join(script_dir, args[0]) - for args in ScriptWriter.get_args(dist) - ]) - # Build .egg file from tmpdir - bdist_egg.make_zipfile( - egg_path, egg_tmp, verbose=self.verbose, dry_run=self.dry_run, - ) - # install the .egg - return self.install_egg(egg_path, tmpdir) - - def exe_to_egg(self, dist_filename, egg_tmp): - """Extract a bdist_wininst to the directories an egg would use""" - # Check for .pth file and set up prefix translations - prefixes = get_exe_prefixes(dist_filename) - to_compile = [] - native_libs = [] - top_level = {} - - def process(src, dst): - s = src.lower() - for old, new in prefixes: - if s.startswith(old): - src = new + src[len(old):] - parts = src.split('/') - dst = os.path.join(egg_tmp, *parts) - dl = dst.lower() - if dl.endswith('.pyd') or dl.endswith('.dll'): - parts[-1] = bdist_egg.strip_module(parts[-1]) - top_level[os.path.splitext(parts[0])[0]] = 1 - native_libs.append(src) - elif dl.endswith('.py') and old != 'SCRIPTS/': - top_level[os.path.splitext(parts[0])[0]] = 1 - to_compile.append(dst) - return dst - if not src.endswith('.pth'): - log.warn("WARNING: can't process %s", src) - return None - - # extract, tracking .pyd/.dll->native_libs and .py -> to_compile - unpack_archive(dist_filename, egg_tmp, process) - stubs = [] - for res in native_libs: - if res.lower().endswith('.pyd'): # create stubs for .pyd's - parts = res.split('/') - resource = parts[-1] - parts[-1] = bdist_egg.strip_module(parts[-1]) + '.py' - pyfile = os.path.join(egg_tmp, *parts) - to_compile.append(pyfile) - stubs.append(pyfile) - bdist_egg.write_stub(resource, pyfile) - self.byte_compile(to_compile) # compile .py's - bdist_egg.write_safety_flag( - os.path.join(egg_tmp, 'EGG-INFO'), - bdist_egg.analyze_egg(egg_tmp, stubs)) # write zip-safety flag - - for name in 'top_level', 'native_libs': - if locals()[name]: - txt = os.path.join(egg_tmp, 'EGG-INFO', name + '.txt') - if not os.path.exists(txt): - f = open(txt, 'w') - f.write('\n'.join(locals()[name]) + '\n') - f.close() - - def install_wheel(self, wheel_path, tmpdir): - wheel = Wheel(wheel_path) - assert wheel.is_compatible() - destination = os.path.join(self.install_dir, wheel.egg_name()) - destination = os.path.abspath(destination) - if not self.dry_run: - ensure_directory(destination) - if os.path.isdir(destination) and not os.path.islink(destination): - dir_util.remove_tree(destination, dry_run=self.dry_run) - elif os.path.exists(destination): - self.execute( - os.unlink, - (destination,), - "Removing " + destination, - ) - try: - self.execute( - wheel.install_as_egg, - (destination,), - ("Installing %s to %s") % ( - os.path.basename(wheel_path), - os.path.dirname(destination) - ), - ) - finally: - update_dist_caches(destination, fix_zipimporter_caches=False) - self.add_output(destination) - return self.egg_distribution(destination) - - __mv_warning = textwrap.dedent(""" - Because this distribution was installed --multi-version, before you can - import modules from this package in an application, you will need to - 'import pkg_resources' and then use a 'require()' call similar to one of - these examples, in order to select the desired version: - - pkg_resources.require("%(name)s") # latest installed version - pkg_resources.require("%(name)s==%(version)s") # this exact version - pkg_resources.require("%(name)s>=%(version)s") # this version or higher - """).lstrip() - - __id_warning = textwrap.dedent(""" - Note also that the installation directory must be on sys.path at runtime for - this to work. (e.g. by being the application's script directory, by being on - PYTHONPATH, or by being added to sys.path by your code.) - """) - - def installation_report(self, req, dist, what="Installed"): - """Helpful installation message for display to package users""" - msg = "\n%(what)s %(eggloc)s%(extras)s" - if self.multi_version and not self.no_report: - msg += '\n' + self.__mv_warning - if self.install_dir not in map(normalize_path, sys.path): - msg += '\n' + self.__id_warning - - eggloc = dist.location - name = dist.project_name - version = dist.version - extras = '' # TODO: self.report_extras(req, dist) - return msg % locals() - - __editable_msg = textwrap.dedent(""" - Extracted editable version of %(spec)s to %(dirname)s - - If it uses setuptools in its setup script, you can activate it in - "development" mode by going to that directory and running:: - - %(python)s setup.py develop - - See the setuptools documentation for the "develop" command for more info. - """).lstrip() - - def report_editable(self, spec, setup_script): - dirname = os.path.dirname(setup_script) - python = sys.executable - return '\n' + self.__editable_msg % locals() - - def run_setup(self, setup_script, setup_base, args): - sys.modules.setdefault('distutils.command.bdist_egg', bdist_egg) - sys.modules.setdefault('distutils.command.egg_info', egg_info) - - args = list(args) - if self.verbose > 2: - v = 'v' * (self.verbose - 1) - args.insert(0, '-' + v) - elif self.verbose < 2: - args.insert(0, '-q') - if self.dry_run: - args.insert(0, '-n') - log.info( - "Running %s %s", setup_script[len(setup_base) + 1:], ' '.join(args) - ) - try: - run_setup(setup_script, args) - except SystemExit as v: - raise DistutilsError("Setup script exited with %s" % (v.args[0],)) - - def build_and_install(self, setup_script, setup_base): - args = ['bdist_egg', '--dist-dir'] - - dist_dir = tempfile.mkdtemp( - prefix='egg-dist-tmp-', dir=os.path.dirname(setup_script) - ) - try: - self._set_fetcher_options(os.path.dirname(setup_script)) - args.append(dist_dir) - - self.run_setup(setup_script, setup_base, args) - all_eggs = Environment([dist_dir]) - eggs = [] - for key in all_eggs: - for dist in all_eggs[key]: - eggs.append(self.install_egg(dist.location, setup_base)) - if not eggs and not self.dry_run: - log.warn("No eggs found in %s (setup script problem?)", - dist_dir) - return eggs - finally: - rmtree(dist_dir) - log.set_verbosity(self.verbose) # restore our log verbosity - - def _set_fetcher_options(self, base): - """ - When easy_install is about to run bdist_egg on a source dist, that - source dist might have 'setup_requires' directives, requiring - additional fetching. Ensure the fetcher options given to easy_install - are available to that command as well. - """ - # find the fetch options from easy_install and write them out - # to the setup.cfg file. - ei_opts = self.distribution.get_option_dict('easy_install').copy() - fetch_directives = ( - 'find_links', 'site_dirs', 'index_url', 'optimize', - 'site_dirs', 'allow_hosts', - ) - fetch_options = {} - for key, val in ei_opts.items(): - if key not in fetch_directives: - continue - fetch_options[key.replace('_', '-')] = val[1] - # create a settings dictionary suitable for `edit_config` - settings = dict(easy_install=fetch_options) - cfg_filename = os.path.join(base, 'setup.cfg') - setopt.edit_config(cfg_filename, settings) - - def update_pth(self, dist): - if self.pth_file is None: - return - - for d in self.pth_file[dist.key]: # drop old entries - if self.multi_version or d.location != dist.location: - log.info("Removing %s from easy-install.pth file", d) - self.pth_file.remove(d) - if d.location in self.shadow_path: - self.shadow_path.remove(d.location) - - if not self.multi_version: - if dist.location in self.pth_file.paths: - log.info( - "%s is already the active version in easy-install.pth", - dist, - ) - else: - log.info("Adding %s to easy-install.pth file", dist) - self.pth_file.add(dist) # add new entry - if dist.location not in self.shadow_path: - self.shadow_path.append(dist.location) - - if not self.dry_run: - - self.pth_file.save() - - if dist.key == 'setuptools': - # Ensure that setuptools itself never becomes unavailable! - # XXX should this check for latest version? - filename = os.path.join(self.install_dir, 'setuptools.pth') - if os.path.islink(filename): - os.unlink(filename) - f = open(filename, 'wt') - f.write(self.pth_file.make_relative(dist.location) + '\n') - f.close() - - def unpack_progress(self, src, dst): - # Progress filter for unpacking - log.debug("Unpacking %s to %s", src, dst) - return dst # only unpack-and-compile skips files for dry run - - def unpack_and_compile(self, egg_path, destination): - to_compile = [] - to_chmod = [] - - def pf(src, dst): - if dst.endswith('.py') and not src.startswith('EGG-INFO/'): - to_compile.append(dst) - elif dst.endswith('.dll') or dst.endswith('.so'): - to_chmod.append(dst) - self.unpack_progress(src, dst) - return not self.dry_run and dst or None - - unpack_archive(egg_path, destination, pf) - self.byte_compile(to_compile) - if not self.dry_run: - for f in to_chmod: - mode = ((os.stat(f)[stat.ST_MODE]) | 0o555) & 0o7755 - chmod(f, mode) - - def byte_compile(self, to_compile): - if sys.dont_write_bytecode: - return - - from distutils.util import byte_compile - - try: - # try to make the byte compile messages quieter - log.set_verbosity(self.verbose - 1) - - byte_compile(to_compile, optimize=0, force=1, dry_run=self.dry_run) - if self.optimize: - byte_compile( - to_compile, optimize=self.optimize, force=1, - dry_run=self.dry_run, - ) - finally: - log.set_verbosity(self.verbose) # restore original verbosity - - __no_default_msg = textwrap.dedent(""" - bad install directory or PYTHONPATH - - You are attempting to install a package to a directory that is not - on PYTHONPATH and which Python does not read ".pth" files from. The - installation directory you specified (via --install-dir, --prefix, or - the distutils default setting) was: - - %s - - and your PYTHONPATH environment variable currently contains: - - %r - - Here are some of your options for correcting the problem: - - * You can choose a different installation directory, i.e., one that is - on PYTHONPATH or supports .pth files - - * You can add the installation directory to the PYTHONPATH environment - variable. (It must then also be on PYTHONPATH whenever you run - Python and want to use the package(s) you are installing.) - - * You can set up the installation directory to support ".pth" files by - using one of the approaches described here: - - https://setuptools.readthedocs.io/en/latest/easy_install.html#custom-installation-locations - - - Please make the appropriate changes for your system and try again.""").lstrip() - - def no_default_version_msg(self): - template = self.__no_default_msg - return template % (self.install_dir, os.environ.get('PYTHONPATH', '')) - - def install_site_py(self): - """Make sure there's a site.py in the target dir, if needed""" - - if self.sitepy_installed: - return # already did it, or don't need to - - sitepy = os.path.join(self.install_dir, "site.py") - source = resource_string("setuptools", "site-patch.py") - source = source.decode('utf-8') - current = "" - - if os.path.exists(sitepy): - log.debug("Checking existing site.py in %s", self.install_dir) - with io.open(sitepy) as strm: - current = strm.read() - - if not current.startswith('def __boot():'): - raise DistutilsError( - "%s is not a setuptools-generated site.py; please" - " remove it." % sitepy - ) - - if current != source: - log.info("Creating %s", sitepy) - if not self.dry_run: - ensure_directory(sitepy) - with io.open(sitepy, 'w', encoding='utf-8') as strm: - strm.write(source) - self.byte_compile([sitepy]) - - self.sitepy_installed = True - - def create_home_path(self): - """Create directories under ~.""" - if not self.user: - return - home = convert_path(os.path.expanduser("~")) - for name, path in six.iteritems(self.config_vars): - if path.startswith(home) and not os.path.isdir(path): - self.debug_print("os.makedirs('%s', 0o700)" % path) - os.makedirs(path, 0o700) - - INSTALL_SCHEMES = dict( - posix=dict( - install_dir='$base/lib/python$py_version_short/site-packages', - script_dir='$base/bin', - ), - ) - - DEFAULT_SCHEME = dict( - install_dir='$base/Lib/site-packages', - script_dir='$base/Scripts', - ) - - def _expand(self, *attrs): - config_vars = self.get_finalized_command('install').config_vars - - if self.prefix: - # Set default install_dir/scripts from --prefix - config_vars = config_vars.copy() - config_vars['base'] = self.prefix - scheme = self.INSTALL_SCHEMES.get(os.name, self.DEFAULT_SCHEME) - for attr, val in scheme.items(): - if getattr(self, attr, None) is None: - setattr(self, attr, val) - - from distutils.util import subst_vars - - for attr in attrs: - val = getattr(self, attr) - if val is not None: - val = subst_vars(val, config_vars) - if os.name == 'posix': - val = os.path.expanduser(val) - setattr(self, attr, val) - - -def _pythonpath(): - items = os.environ.get('PYTHONPATH', '').split(os.pathsep) - return filter(None, items) - - -def get_site_dirs(): - """ - Return a list of 'site' dirs - """ - - sitedirs = [] - - # start with PYTHONPATH - sitedirs.extend(_pythonpath()) - - prefixes = [sys.prefix] - if sys.exec_prefix != sys.prefix: - prefixes.append(sys.exec_prefix) - for prefix in prefixes: - if prefix: - if sys.platform in ('os2emx', 'riscos'): - sitedirs.append(os.path.join(prefix, "Lib", "site-packages")) - elif os.sep == '/': - sitedirs.extend([ - os.path.join( - prefix, - "lib", - "python" + sys.version[:3], - "site-packages", - ), - os.path.join(prefix, "lib", "site-python"), - ]) - else: - sitedirs.extend([ - prefix, - os.path.join(prefix, "lib", "site-packages"), - ]) - if sys.platform == 'darwin': - # for framework builds *only* we add the standard Apple - # locations. Currently only per-user, but /Library and - # /Network/Library could be added too - if 'Python.framework' in prefix: - home = os.environ.get('HOME') - if home: - home_sp = os.path.join( - home, - 'Library', - 'Python', - sys.version[:3], - 'site-packages', - ) - sitedirs.append(home_sp) - lib_paths = get_path('purelib'), get_path('platlib') - for site_lib in lib_paths: - if site_lib not in sitedirs: - sitedirs.append(site_lib) - - if site.ENABLE_USER_SITE: - sitedirs.append(site.USER_SITE) - - try: - sitedirs.extend(site.getsitepackages()) - except AttributeError: - pass - - sitedirs = list(map(normalize_path, sitedirs)) - - return sitedirs - - -def expand_paths(inputs): - """Yield sys.path directories that might contain "old-style" packages""" - - seen = {} - - for dirname in inputs: - dirname = normalize_path(dirname) - if dirname in seen: - continue - - seen[dirname] = 1 - if not os.path.isdir(dirname): - continue - - files = os.listdir(dirname) - yield dirname, files - - for name in files: - if not name.endswith('.pth'): - # We only care about the .pth files - continue - if name in ('easy-install.pth', 'setuptools.pth'): - # Ignore .pth files that we control - continue - - # Read the .pth file - f = open(os.path.join(dirname, name)) - lines = list(yield_lines(f)) - f.close() - - # Yield existing non-dupe, non-import directory lines from it - for line in lines: - if not line.startswith("import"): - line = normalize_path(line.rstrip()) - if line not in seen: - seen[line] = 1 - if not os.path.isdir(line): - continue - yield line, os.listdir(line) - - -def extract_wininst_cfg(dist_filename): - """Extract configuration data from a bdist_wininst .exe - - Returns a configparser.RawConfigParser, or None - """ - f = open(dist_filename, 'rb') - try: - endrec = zipfile._EndRecData(f) - if endrec is None: - return None - - prepended = (endrec[9] - endrec[5]) - endrec[6] - if prepended < 12: # no wininst data here - return None - f.seek(prepended - 12) - - tag, cfglen, bmlen = struct.unpack("<iii", f.read(12)) - if tag not in (0x1234567A, 0x1234567B): - return None # not a valid tag - - f.seek(prepended - (12 + cfglen)) - init = {'version': '', 'target_version': ''} - cfg = configparser.RawConfigParser(init) - try: - part = f.read(cfglen) - # Read up to the first null byte. - config = part.split(b'\0', 1)[0] - # Now the config is in bytes, but for RawConfigParser, it should - # be text, so decode it. - config = config.decode(sys.getfilesystemencoding()) - cfg.readfp(six.StringIO(config)) - except configparser.Error: - return None - if not cfg.has_section('metadata') or not cfg.has_section('Setup'): - return None - return cfg - - finally: - f.close() - - -def get_exe_prefixes(exe_filename): - """Get exe->egg path translations for a given .exe file""" - - prefixes = [ - ('PURELIB/', ''), - ('PLATLIB/pywin32_system32', ''), - ('PLATLIB/', ''), - ('SCRIPTS/', 'EGG-INFO/scripts/'), - ('DATA/lib/site-packages', ''), - ] - z = zipfile.ZipFile(exe_filename) - try: - for info in z.infolist(): - name = info.filename - parts = name.split('/') - if len(parts) == 3 and parts[2] == 'PKG-INFO': - if parts[1].endswith('.egg-info'): - prefixes.insert(0, ('/'.join(parts[:2]), 'EGG-INFO/')) - break - if len(parts) != 2 or not name.endswith('.pth'): - continue - if name.endswith('-nspkg.pth'): - continue - if parts[0].upper() in ('PURELIB', 'PLATLIB'): - contents = z.read(name) - if six.PY3: - contents = contents.decode() - for pth in yield_lines(contents): - pth = pth.strip().replace('\\', '/') - if not pth.startswith('import'): - prefixes.append((('%s/%s/' % (parts[0], pth)), '')) - finally: - z.close() - prefixes = [(x.lower(), y) for x, y in prefixes] - prefixes.sort() - prefixes.reverse() - return prefixes - - -class PthDistributions(Environment): - """A .pth file with Distribution paths in it""" - - dirty = False - - def __init__(self, filename, sitedirs=()): - self.filename = filename - self.sitedirs = list(map(normalize_path, sitedirs)) - self.basedir = normalize_path(os.path.dirname(self.filename)) - self._load() - Environment.__init__(self, [], None, None) - for path in yield_lines(self.paths): - list(map(self.add, find_distributions(path, True))) - - def _load(self): - self.paths = [] - saw_import = False - seen = dict.fromkeys(self.sitedirs) - if os.path.isfile(self.filename): - f = open(self.filename, 'rt') - for line in f: - if line.startswith('import'): - saw_import = True - continue - path = line.rstrip() - self.paths.append(path) - if not path.strip() or path.strip().startswith('#'): - continue - # skip non-existent paths, in case somebody deleted a package - # manually, and duplicate paths as well - path = self.paths[-1] = normalize_path( - os.path.join(self.basedir, path) - ) - if not os.path.exists(path) or path in seen: - self.paths.pop() # skip it - self.dirty = True # we cleaned up, so we're dirty now :) - continue - seen[path] = 1 - f.close() - - if self.paths and not saw_import: - self.dirty = True # ensure anything we touch has import wrappers - while self.paths and not self.paths[-1].strip(): - self.paths.pop() - - def save(self): - """Write changed .pth file back to disk""" - if not self.dirty: - return - - rel_paths = list(map(self.make_relative, self.paths)) - if rel_paths: - log.debug("Saving %s", self.filename) - lines = self._wrap_lines(rel_paths) - data = '\n'.join(lines) + '\n' - - if os.path.islink(self.filename): - os.unlink(self.filename) - with open(self.filename, 'wt') as f: - f.write(data) - - elif os.path.exists(self.filename): - log.debug("Deleting empty %s", self.filename) - os.unlink(self.filename) - - self.dirty = False - - @staticmethod - def _wrap_lines(lines): - return lines - - def add(self, dist): - """Add `dist` to the distribution map""" - new_path = ( - dist.location not in self.paths and ( - dist.location not in self.sitedirs or - # account for '.' being in PYTHONPATH - dist.location == os.getcwd() - ) - ) - if new_path: - self.paths.append(dist.location) - self.dirty = True - Environment.add(self, dist) - - def remove(self, dist): - """Remove `dist` from the distribution map""" - while dist.location in self.paths: - self.paths.remove(dist.location) - self.dirty = True - Environment.remove(self, dist) - - def make_relative(self, path): - npath, last = os.path.split(normalize_path(path)) - baselen = len(self.basedir) - parts = [last] - sep = os.altsep == '/' and '/' or os.sep - while len(npath) >= baselen: - if npath == self.basedir: - parts.append(os.curdir) - parts.reverse() - return sep.join(parts) - npath, last = os.path.split(npath) - parts.append(last) - else: - return path - - -class RewritePthDistributions(PthDistributions): - @classmethod - def _wrap_lines(cls, lines): - yield cls.prelude - for line in lines: - yield line - yield cls.postlude - - prelude = _one_liner(""" - import sys - sys.__plen = len(sys.path) - """) - postlude = _one_liner(""" - import sys - new = sys.path[sys.__plen:] - del sys.path[sys.__plen:] - p = getattr(sys, '__egginsert', 0) - sys.path[p:p] = new - sys.__egginsert = p + len(new) - """) - - -if os.environ.get('SETUPTOOLS_SYS_PATH_TECHNIQUE', 'raw') == 'rewrite': - PthDistributions = RewritePthDistributions - - -def _first_line_re(): - """ - Return a regular expression based on first_line_re suitable for matching - strings. - """ - if isinstance(first_line_re.pattern, str): - return first_line_re - - # first_line_re in Python >=3.1.4 and >=3.2.1 is a bytes pattern. - return re.compile(first_line_re.pattern.decode()) - - -def auto_chmod(func, arg, exc): - if func in [os.unlink, os.remove] and os.name == 'nt': - chmod(arg, stat.S_IWRITE) - return func(arg) - et, ev, _ = sys.exc_info() - six.reraise(et, (ev[0], ev[1] + (" %s %s" % (func, arg)))) - - -def update_dist_caches(dist_path, fix_zipimporter_caches): - """ - Fix any globally cached `dist_path` related data - - `dist_path` should be a path of a newly installed egg distribution (zipped - or unzipped). - - sys.path_importer_cache contains finder objects that have been cached when - importing data from the original distribution. Any such finders need to be - cleared since the replacement distribution might be packaged differently, - e.g. a zipped egg distribution might get replaced with an unzipped egg - folder or vice versa. Having the old finders cached may then cause Python - to attempt loading modules from the replacement distribution using an - incorrect loader. - - zipimport.zipimporter objects are Python loaders charged with importing - data packaged inside zip archives. If stale loaders referencing the - original distribution, are left behind, they can fail to load modules from - the replacement distribution. E.g. if an old zipimport.zipimporter instance - is used to load data from a new zipped egg archive, it may cause the - operation to attempt to locate the requested data in the wrong location - - one indicated by the original distribution's zip archive directory - information. Such an operation may then fail outright, e.g. report having - read a 'bad local file header', or even worse, it may fail silently & - return invalid data. - - zipimport._zip_directory_cache contains cached zip archive directory - information for all existing zipimport.zipimporter instances and all such - instances connected to the same archive share the same cached directory - information. - - If asked, and the underlying Python implementation allows it, we can fix - all existing zipimport.zipimporter instances instead of having to track - them down and remove them one by one, by updating their shared cached zip - archive directory information. This, of course, assumes that the - replacement distribution is packaged as a zipped egg. - - If not asked to fix existing zipimport.zipimporter instances, we still do - our best to clear any remaining zipimport.zipimporter related cached data - that might somehow later get used when attempting to load data from the new - distribution and thus cause such load operations to fail. Note that when - tracking down such remaining stale data, we can not catch every conceivable - usage from here, and we clear only those that we know of and have found to - cause problems if left alive. Any remaining caches should be updated by - whomever is in charge of maintaining them, i.e. they should be ready to - handle us replacing their zip archives with new distributions at runtime. - - """ - # There are several other known sources of stale zipimport.zipimporter - # instances that we do not clear here, but might if ever given a reason to - # do so: - # * Global setuptools pkg_resources.working_set (a.k.a. 'master working - # set') may contain distributions which may in turn contain their - # zipimport.zipimporter loaders. - # * Several zipimport.zipimporter loaders held by local variables further - # up the function call stack when running the setuptools installation. - # * Already loaded modules may have their __loader__ attribute set to the - # exact loader instance used when importing them. Python 3.4 docs state - # that this information is intended mostly for introspection and so is - # not expected to cause us problems. - normalized_path = normalize_path(dist_path) - _uncache(normalized_path, sys.path_importer_cache) - if fix_zipimporter_caches: - _replace_zip_directory_cache_data(normalized_path) - else: - # Here, even though we do not want to fix existing and now stale - # zipimporter cache information, we still want to remove it. Related to - # Python's zip archive directory information cache, we clear each of - # its stale entries in two phases: - # 1. Clear the entry so attempting to access zip archive information - # via any existing stale zipimport.zipimporter instances fails. - # 2. Remove the entry from the cache so any newly constructed - # zipimport.zipimporter instances do not end up using old stale - # zip archive directory information. - # This whole stale data removal step does not seem strictly necessary, - # but has been left in because it was done before we started replacing - # the zip archive directory information cache content if possible, and - # there are no relevant unit tests that we can depend on to tell us if - # this is really needed. - _remove_and_clear_zip_directory_cache_data(normalized_path) - - -def _collect_zipimporter_cache_entries(normalized_path, cache): - """ - Return zipimporter cache entry keys related to a given normalized path. - - Alternative path spellings (e.g. those using different character case or - those using alternative path separators) related to the same path are - included. Any sub-path entries are included as well, i.e. those - corresponding to zip archives embedded in other zip archives. - - """ - result = [] - prefix_len = len(normalized_path) - for p in cache: - np = normalize_path(p) - if (np.startswith(normalized_path) and - np[prefix_len:prefix_len + 1] in (os.sep, '')): - result.append(p) - return result - - -def _update_zipimporter_cache(normalized_path, cache, updater=None): - """ - Update zipimporter cache data for a given normalized path. - - Any sub-path entries are processed as well, i.e. those corresponding to zip - archives embedded in other zip archives. - - Given updater is a callable taking a cache entry key and the original entry - (after already removing the entry from the cache), and expected to update - the entry and possibly return a new one to be inserted in its place. - Returning None indicates that the entry should not be replaced with a new - one. If no updater is given, the cache entries are simply removed without - any additional processing, the same as if the updater simply returned None. - - """ - for p in _collect_zipimporter_cache_entries(normalized_path, cache): - # N.B. pypy's custom zipimport._zip_directory_cache implementation does - # not support the complete dict interface: - # * Does not support item assignment, thus not allowing this function - # to be used only for removing existing cache entries. - # * Does not support the dict.pop() method, forcing us to use the - # get/del patterns instead. For more detailed information see the - # following links: - # https://github.com/pypa/setuptools/issues/202#issuecomment-202913420 - # http://bit.ly/2h9itJX - old_entry = cache[p] - del cache[p] - new_entry = updater and updater(p, old_entry) - if new_entry is not None: - cache[p] = new_entry - - -def _uncache(normalized_path, cache): - _update_zipimporter_cache(normalized_path, cache) - - -def _remove_and_clear_zip_directory_cache_data(normalized_path): - def clear_and_remove_cached_zip_archive_directory_data(path, old_entry): - old_entry.clear() - - _update_zipimporter_cache( - normalized_path, zipimport._zip_directory_cache, - updater=clear_and_remove_cached_zip_archive_directory_data) - - -# PyPy Python implementation does not allow directly writing to the -# zipimport._zip_directory_cache and so prevents us from attempting to correct -# its content. The best we can do there is clear the problematic cache content -# and have PyPy repopulate it as needed. The downside is that if there are any -# stale zipimport.zipimporter instances laying around, attempting to use them -# will fail due to not having its zip archive directory information available -# instead of being automatically corrected to use the new correct zip archive -# directory information. -if '__pypy__' in sys.builtin_module_names: - _replace_zip_directory_cache_data = \ - _remove_and_clear_zip_directory_cache_data -else: - - def _replace_zip_directory_cache_data(normalized_path): - def replace_cached_zip_archive_directory_data(path, old_entry): - # N.B. In theory, we could load the zip directory information just - # once for all updated path spellings, and then copy it locally and - # update its contained path strings to contain the correct - # spelling, but that seems like a way too invasive move (this cache - # structure is not officially documented anywhere and could in - # theory change with new Python releases) for no significant - # benefit. - old_entry.clear() - zipimport.zipimporter(path) - old_entry.update(zipimport._zip_directory_cache[path]) - return old_entry - - _update_zipimporter_cache( - normalized_path, zipimport._zip_directory_cache, - updater=replace_cached_zip_archive_directory_data) - - -def is_python(text, filename='<string>'): - "Is this string a valid Python script?" - try: - compile(text, filename, 'exec') - except (SyntaxError, TypeError): - return False - else: - return True - - -def is_sh(executable): - """Determine if the specified executable is a .sh (contains a #! line)""" - try: - with io.open(executable, encoding='latin-1') as fp: - magic = fp.read(2) - except (OSError, IOError): - return executable - return magic == '#!' - - -def nt_quote_arg(arg): - """Quote a command line argument according to Windows parsing rules""" - return subprocess.list2cmdline([arg]) - - -def is_python_script(script_text, filename): - """Is this text, as a whole, a Python script? (as opposed to shell/bat/etc. - """ - if filename.endswith('.py') or filename.endswith('.pyw'): - return True # extension says it's Python - if is_python(script_text, filename): - return True # it's syntactically valid Python - if script_text.startswith('#!'): - # It begins with a '#!' line, so check if 'python' is in it somewhere - return 'python' in script_text.splitlines()[0].lower() - - return False # Not any Python I can recognize - - -try: - from os import chmod as _chmod -except ImportError: - # Jython compatibility - def _chmod(*args): - pass - - -def chmod(path, mode): - log.debug("changing mode of %s to %o", path, mode) - try: - _chmod(path, mode) - except os.error as e: - log.debug("chmod failed: %s", e) - - -class CommandSpec(list): - """ - A command spec for a #! header, specified as a list of arguments akin to - those passed to Popen. - """ - - options = [] - split_args = dict() - - @classmethod - def best(cls): - """ - Choose the best CommandSpec class based on environmental conditions. - """ - return cls - - @classmethod - def _sys_executable(cls): - _default = os.path.normpath(sys.executable) - return os.environ.get('__PYVENV_LAUNCHER__', _default) - - @classmethod - def from_param(cls, param): - """ - Construct a CommandSpec from a parameter to build_scripts, which may - be None. - """ - if isinstance(param, cls): - return param - if isinstance(param, list): - return cls(param) - if param is None: - return cls.from_environment() - # otherwise, assume it's a string. - return cls.from_string(param) - - @classmethod - def from_environment(cls): - return cls([cls._sys_executable()]) - - @classmethod - def from_string(cls, string): - """ - Construct a command spec from a simple string representing a command - line parseable by shlex.split. - """ - items = shlex.split(string, **cls.split_args) - return cls(items) - - def install_options(self, script_text): - self.options = shlex.split(self._extract_options(script_text)) - cmdline = subprocess.list2cmdline(self) - if not isascii(cmdline): - self.options[:0] = ['-x'] - - @staticmethod - def _extract_options(orig_script): - """ - Extract any options from the first line of the script. - """ - first = (orig_script + '\n').splitlines()[0] - match = _first_line_re().match(first) - options = match.group(1) or '' if match else '' - return options.strip() - - def as_header(self): - return self._render(self + list(self.options)) - - @staticmethod - def _strip_quotes(item): - _QUOTES = '"\'' - for q in _QUOTES: - if item.startswith(q) and item.endswith(q): - return item[1:-1] - return item - - @staticmethod - def _render(items): - cmdline = subprocess.list2cmdline( - CommandSpec._strip_quotes(item.strip()) for item in items) - return '#!' + cmdline + '\n' - - -# For pbr compat; will be removed in a future version. -sys_executable = CommandSpec._sys_executable() - - -class WindowsCommandSpec(CommandSpec): - split_args = dict(posix=False) - - -class ScriptWriter: - """ - Encapsulates behavior around writing entry point scripts for console and - gui apps. - """ - - template = textwrap.dedent(r""" - # EASY-INSTALL-ENTRY-SCRIPT: %(spec)r,%(group)r,%(name)r - __requires__ = %(spec)r - import re - import sys - from pkg_resources import load_entry_point - - if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) - sys.exit( - load_entry_point(%(spec)r, %(group)r, %(name)r)() - ) - """).lstrip() - - command_spec_class = CommandSpec - - @classmethod - def get_script_args(cls, dist, executable=None, wininst=False): - # for backward compatibility - warnings.warn("Use get_args", EasyInstallDeprecationWarning) - writer = (WindowsScriptWriter if wininst else ScriptWriter).best() - header = cls.get_script_header("", executable, wininst) - return writer.get_args(dist, header) - - @classmethod - def get_script_header(cls, script_text, executable=None, wininst=False): - # for backward compatibility - warnings.warn("Use get_header", EasyInstallDeprecationWarning, stacklevel=2) - if wininst: - executable = "python.exe" - return cls.get_header(script_text, executable) - - @classmethod - def get_args(cls, dist, header=None): - """ - Yield write_script() argument tuples for a distribution's - console_scripts and gui_scripts entry points. - """ - if header is None: - header = cls.get_header() - spec = str(dist.as_requirement()) - for type_ in 'console', 'gui': - group = type_ + '_scripts' - for name, ep in dist.get_entry_map(group).items(): - cls._ensure_safe_name(name) - script_text = cls.template % locals() - args = cls._get_script_args(type_, name, header, script_text) - for res in args: - yield res - - @staticmethod - def _ensure_safe_name(name): - """ - Prevent paths in *_scripts entry point names. - """ - has_path_sep = re.search(r'[\\/]', name) - if has_path_sep: - raise ValueError("Path separators not allowed in script names") - - @classmethod - def get_writer(cls, force_windows): - # for backward compatibility - warnings.warn("Use best", EasyInstallDeprecationWarning) - return WindowsScriptWriter.best() if force_windows else cls.best() - - @classmethod - def best(cls): - """ - Select the best ScriptWriter for this environment. - """ - if sys.platform == 'win32' or (os.name == 'java' and os._name == 'nt'): - return WindowsScriptWriter.best() - else: - return cls - - @classmethod - def _get_script_args(cls, type_, name, header, script_text): - # Simply write the stub with no extension. - yield (name, header + script_text) - - @classmethod - def get_header(cls, script_text="", executable=None): - """Create a #! line, getting options (if any) from script_text""" - cmd = cls.command_spec_class.best().from_param(executable) - cmd.install_options(script_text) - return cmd.as_header() - - -class WindowsScriptWriter(ScriptWriter): - command_spec_class = WindowsCommandSpec - - @classmethod - def get_writer(cls): - # for backward compatibility - warnings.warn("Use best", EasyInstallDeprecationWarning) - return cls.best() - - @classmethod - def best(cls): - """ - Select the best ScriptWriter suitable for Windows - """ - writer_lookup = dict( - executable=WindowsExecutableLauncherWriter, - natural=cls, - ) - # for compatibility, use the executable launcher by default - launcher = os.environ.get('SETUPTOOLS_LAUNCHER', 'executable') - return writer_lookup[launcher] - - @classmethod - def _get_script_args(cls, type_, name, header, script_text): - "For Windows, add a .py extension" - ext = dict(console='.pya', gui='.pyw')[type_] - if ext not in os.environ['PATHEXT'].lower().split(';'): - msg = ( - "{ext} not listed in PATHEXT; scripts will not be " - "recognized as executables." - ).format(**locals()) - warnings.warn(msg, UserWarning) - old = ['.pya', '.py', '-script.py', '.pyc', '.pyo', '.pyw', '.exe'] - old.remove(ext) - header = cls._adjust_header(type_, header) - blockers = [name + x for x in old] - yield name + ext, header + script_text, 't', blockers - - @classmethod - def _adjust_header(cls, type_, orig_header): - """ - Make sure 'pythonw' is used for gui and and 'python' is used for - console (regardless of what sys.executable is). - """ - pattern = 'pythonw.exe' - repl = 'python.exe' - if type_ == 'gui': - pattern, repl = repl, pattern - pattern_ob = re.compile(re.escape(pattern), re.IGNORECASE) - new_header = pattern_ob.sub(string=orig_header, repl=repl) - return new_header if cls._use_header(new_header) else orig_header - - @staticmethod - def _use_header(new_header): - """ - Should _adjust_header use the replaced header? - - On non-windows systems, always use. On - Windows systems, only use the replaced header if it resolves - to an executable on the system. - """ - clean_header = new_header[2:-1].strip('"') - return sys.platform != 'win32' or find_executable(clean_header) - - -class WindowsExecutableLauncherWriter(WindowsScriptWriter): - @classmethod - def _get_script_args(cls, type_, name, header, script_text): - """ - For Windows, add a .py extension and an .exe launcher - """ - if type_ == 'gui': - launcher_type = 'gui' - ext = '-script.pyw' - old = ['.pyw'] - else: - launcher_type = 'cli' - ext = '-script.py' - old = ['.py', '.pyc', '.pyo'] - hdr = cls._adjust_header(type_, header) - blockers = [name + x for x in old] - yield (name + ext, hdr + script_text, 't', blockers) - yield ( - name + '.exe', get_win_launcher(launcher_type), - 'b' # write in binary mode - ) - if not is_64bit(): - # install a manifest for the launcher to prevent Windows - # from detecting it as an installer (which it will for - # launchers like easy_install.exe). Consider only - # adding a manifest for launchers detected as installers. - # See Distribute #143 for details. - m_name = name + '.exe.manifest' - yield (m_name, load_launcher_manifest(name), 't') - - -# for backward-compatibility -get_script_args = ScriptWriter.get_script_args -get_script_header = ScriptWriter.get_script_header - - -def get_win_launcher(type): - """ - Load the Windows launcher (executable) suitable for launching a script. - - `type` should be either 'cli' or 'gui' - - Returns the executable as a byte string. - """ - launcher_fn = '%s.exe' % type - if is_64bit(): - launcher_fn = launcher_fn.replace(".", "-64.") - else: - launcher_fn = launcher_fn.replace(".", "-32.") - return resource_string('setuptools', launcher_fn) - - -def load_launcher_manifest(name): - manifest = pkg_resources.resource_string(__name__, 'launcher manifest.xml') - if six.PY2: - return manifest % vars() - else: - return manifest.decode('utf-8') % vars() - - -def rmtree(path, ignore_errors=False, onerror=auto_chmod): - return shutil.rmtree(path, ignore_errors, onerror) - - -def current_umask(): - tmp = os.umask(0o022) - os.umask(tmp) - return tmp - - -def bootstrap(): - # This function is called when setuptools*.egg is run using /bin/sh - import setuptools - - argv0 = os.path.dirname(setuptools.__path__[0]) - sys.argv[0] = argv0 - sys.argv.append(argv0) - main() - - -def main(argv=None, **kw): - from setuptools import setup - from setuptools.dist import Distribution - - class DistributionWithoutHelpCommands(Distribution): - common_usage = "" - - def _show_help(self, *args, **kw): - with _patch_usage(): - Distribution._show_help(self, *args, **kw) - - if argv is None: - argv = sys.argv[1:] - - with _patch_usage(): - setup( - script_args=['-q', 'easy_install', '-v'] + argv, - script_name=sys.argv[0] or 'easy_install', - distclass=DistributionWithoutHelpCommands, - **kw - ) - - -@contextlib.contextmanager -def _patch_usage(): - import distutils.core - USAGE = textwrap.dedent(""" - usage: %(script)s [options] requirement_or_url ... - or: %(script)s --help - """).lstrip() - - def gen_usage(script_name): - return USAGE % dict( - script=os.path.basename(script_name), - ) - - saved = distutils.core.gen_usage - distutils.core.gen_usage = gen_usage - try: - yield - finally: - distutils.core.gen_usage = saved - -class EasyInstallDeprecationWarning(SetuptoolsDeprecationWarning): - """Class for warning about deprecations in EasyInstall in SetupTools. Not ignored by default, unlike DeprecationWarning.""" - diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/egg_info.py b/venv2/lib/python2.7/site-packages/setuptools/command/egg_info.py deleted file mode 100644 index 5d8f451..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/egg_info.py +++ /dev/null @@ -1,717 +0,0 @@ -"""setuptools.command.egg_info - -Create a distribution's .egg-info directory and contents""" - -from distutils.filelist import FileList as _FileList -from distutils.errors import DistutilsInternalError -from distutils.util import convert_path -from distutils import log -import distutils.errors -import distutils.filelist -import os -import re -import sys -import io -import warnings -import time -import collections - -from setuptools.extern import six -from setuptools.extern.six.moves import map - -from setuptools import Command -from setuptools.command.sdist import sdist -from setuptools.command.sdist import walk_revctrl -from setuptools.command.setopt import edit_config -from setuptools.command import bdist_egg -from pkg_resources import ( - parse_requirements, safe_name, parse_version, - safe_version, yield_lines, EntryPoint, iter_entry_points, to_filename) -import setuptools.unicode_utils as unicode_utils -from setuptools.glob import glob - -from setuptools.extern import packaging -from setuptools import SetuptoolsDeprecationWarning - -def translate_pattern(glob): - """ - Translate a file path glob like '*.txt' in to a regular expression. - This differs from fnmatch.translate which allows wildcards to match - directory separators. It also knows about '**/' which matches any number of - directories. - """ - pat = '' - - # This will split on '/' within [character classes]. This is deliberate. - chunks = glob.split(os.path.sep) - - sep = re.escape(os.sep) - valid_char = '[^%s]' % (sep,) - - for c, chunk in enumerate(chunks): - last_chunk = c == len(chunks) - 1 - - # Chunks that are a literal ** are globstars. They match anything. - if chunk == '**': - if last_chunk: - # Match anything if this is the last component - pat += '.*' - else: - # Match '(name/)*' - pat += '(?:%s+%s)*' % (valid_char, sep) - continue # Break here as the whole path component has been handled - - # Find any special characters in the remainder - i = 0 - chunk_len = len(chunk) - while i < chunk_len: - char = chunk[i] - if char == '*': - # Match any number of name characters - pat += valid_char + '*' - elif char == '?': - # Match a name character - pat += valid_char - elif char == '[': - # Character class - inner_i = i + 1 - # Skip initial !/] chars - if inner_i < chunk_len and chunk[inner_i] == '!': - inner_i = inner_i + 1 - if inner_i < chunk_len and chunk[inner_i] == ']': - inner_i = inner_i + 1 - - # Loop till the closing ] is found - while inner_i < chunk_len and chunk[inner_i] != ']': - inner_i = inner_i + 1 - - if inner_i >= chunk_len: - # Got to the end of the string without finding a closing ] - # Do not treat this as a matching group, but as a literal [ - pat += re.escape(char) - else: - # Grab the insides of the [brackets] - inner = chunk[i + 1:inner_i] - char_class = '' - - # Class negation - if inner[0] == '!': - char_class = '^' - inner = inner[1:] - - char_class += re.escape(inner) - pat += '[%s]' % (char_class,) - - # Skip to the end ] - i = inner_i - else: - pat += re.escape(char) - i += 1 - - # Join each chunk with the dir separator - if not last_chunk: - pat += sep - - pat += r'\Z' - return re.compile(pat, flags=re.MULTILINE|re.DOTALL) - - -class InfoCommon: - tag_build = None - tag_date = None - - @property - def name(self): - return safe_name(self.distribution.get_name()) - - def tagged_version(self): - version = self.distribution.get_version() - # egg_info may be called more than once for a distribution, - # in which case the version string already contains all tags. - if self.vtags and version.endswith(self.vtags): - return safe_version(version) - return safe_version(version + self.vtags) - - def tags(self): - version = '' - if self.tag_build: - version += self.tag_build - if self.tag_date: - version += time.strftime("-%Y%m%d") - return version - vtags = property(tags) - - -class egg_info(InfoCommon, Command): - description = "create a distribution's .egg-info directory" - - user_options = [ - ('egg-base=', 'e', "directory containing .egg-info directories" - " (default: top of the source tree)"), - ('tag-date', 'd', "Add date stamp (e.g. 20050528) to version number"), - ('tag-build=', 'b', "Specify explicit tag to add to version number"), - ('no-date', 'D', "Don't include date stamp [default]"), - ] - - boolean_options = ['tag-date'] - negative_opt = { - 'no-date': 'tag-date', - } - - def initialize_options(self): - self.egg_base = None - self.egg_name = None - self.egg_info = None - self.egg_version = None - self.broken_egg_info = False - - #################################### - # allow the 'tag_svn_revision' to be detected and - # set, supporting sdists built on older Setuptools. - @property - def tag_svn_revision(self): - pass - - @tag_svn_revision.setter - def tag_svn_revision(self, value): - pass - #################################### - - def save_version_info(self, filename): - """ - Materialize the value of date into the - build tag. Install build keys in a deterministic order - to avoid arbitrary reordering on subsequent builds. - """ - egg_info = collections.OrderedDict() - # follow the order these keys would have been added - # when PYTHONHASHSEED=0 - egg_info['tag_build'] = self.tags() - egg_info['tag_date'] = 0 - edit_config(filename, dict(egg_info=egg_info)) - - def finalize_options(self): - # Note: we need to capture the current value returned - # by `self.tagged_version()`, so we can later update - # `self.distribution.metadata.version` without - # repercussions. - self.egg_name = self.name - self.egg_version = self.tagged_version() - parsed_version = parse_version(self.egg_version) - - try: - is_version = isinstance(parsed_version, packaging.version.Version) - spec = ( - "%s==%s" if is_version else "%s===%s" - ) - list( - parse_requirements(spec % (self.egg_name, self.egg_version)) - ) - except ValueError: - raise distutils.errors.DistutilsOptionError( - "Invalid distribution name or version syntax: %s-%s" % - (self.egg_name, self.egg_version) - ) - - if self.egg_base is None: - dirs = self.distribution.package_dir - self.egg_base = (dirs or {}).get('', os.curdir) - - self.ensure_dirname('egg_base') - self.egg_info = to_filename(self.egg_name) + '.egg-info' - if self.egg_base != os.curdir: - self.egg_info = os.path.join(self.egg_base, self.egg_info) - if '-' in self.egg_name: - self.check_broken_egg_info() - - # Set package version for the benefit of dumber commands - # (e.g. sdist, bdist_wininst, etc.) - # - self.distribution.metadata.version = self.egg_version - - # If we bootstrapped around the lack of a PKG-INFO, as might be the - # case in a fresh checkout, make sure that any special tags get added - # to the version info - # - pd = self.distribution._patched_dist - if pd is not None and pd.key == self.egg_name.lower(): - pd._version = self.egg_version - pd._parsed_version = parse_version(self.egg_version) - self.distribution._patched_dist = None - - def write_or_delete_file(self, what, filename, data, force=False): - """Write `data` to `filename` or delete if empty - - If `data` is non-empty, this routine is the same as ``write_file()``. - If `data` is empty but not ``None``, this is the same as calling - ``delete_file(filename)`. If `data` is ``None``, then this is a no-op - unless `filename` exists, in which case a warning is issued about the - orphaned file (if `force` is false), or deleted (if `force` is true). - """ - if data: - self.write_file(what, filename, data) - elif os.path.exists(filename): - if data is None and not force: - log.warn( - "%s not set in setup(), but %s exists", what, filename - ) - return - else: - self.delete_file(filename) - - def write_file(self, what, filename, data): - """Write `data` to `filename` (if not a dry run) after announcing it - - `what` is used in a log message to identify what is being written - to the file. - """ - log.info("writing %s to %s", what, filename) - if six.PY3: - data = data.encode("utf-8") - if not self.dry_run: - f = open(filename, 'wb') - f.write(data) - f.close() - - def delete_file(self, filename): - """Delete `filename` (if not a dry run) after announcing it""" - log.info("deleting %s", filename) - if not self.dry_run: - os.unlink(filename) - - def run(self): - self.mkpath(self.egg_info) - os.utime(self.egg_info, None) - installer = self.distribution.fetch_build_egg - for ep in iter_entry_points('egg_info.writers'): - ep.require(installer=installer) - writer = ep.resolve() - writer(self, ep.name, os.path.join(self.egg_info, ep.name)) - - # Get rid of native_libs.txt if it was put there by older bdist_egg - nl = os.path.join(self.egg_info, "native_libs.txt") - if os.path.exists(nl): - self.delete_file(nl) - - self.find_sources() - - def find_sources(self): - """Generate SOURCES.txt manifest file""" - manifest_filename = os.path.join(self.egg_info, "SOURCES.txt") - mm = manifest_maker(self.distribution) - mm.manifest = manifest_filename - mm.run() - self.filelist = mm.filelist - - def check_broken_egg_info(self): - bei = self.egg_name + '.egg-info' - if self.egg_base != os.curdir: - bei = os.path.join(self.egg_base, bei) - if os.path.exists(bei): - log.warn( - "-" * 78 + '\n' - "Note: Your current .egg-info directory has a '-' in its name;" - '\nthis will not work correctly with "setup.py develop".\n\n' - 'Please rename %s to %s to correct this problem.\n' + '-' * 78, - bei, self.egg_info - ) - self.broken_egg_info = self.egg_info - self.egg_info = bei # make it work for now - - -class FileList(_FileList): - # Implementations of the various MANIFEST.in commands - - def process_template_line(self, line): - # 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 (dir_pattern). - (action, patterns, dir, dir_pattern) = self._parse_template_line(line) - - # 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': - self.debug_print("include " + ' '.join(patterns)) - for pattern in patterns: - if not self.include(pattern): - log.warn("warning: no files found matching '%s'", pattern) - - elif action == 'exclude': - self.debug_print("exclude " + ' '.join(patterns)) - for pattern in patterns: - if not self.exclude(pattern): - log.warn(("warning: no previously-included files " - "found matching '%s'"), pattern) - - elif action == 'global-include': - self.debug_print("global-include " + ' '.join(patterns)) - for pattern in patterns: - if not self.global_include(pattern): - log.warn(("warning: no files found matching '%s' " - "anywhere in distribution"), pattern) - - elif action == 'global-exclude': - self.debug_print("global-exclude " + ' '.join(patterns)) - for pattern in patterns: - if not self.global_exclude(pattern): - log.warn(("warning: no previously-included files matching " - "'%s' found anywhere in distribution"), - pattern) - - elif action == 'recursive-include': - self.debug_print("recursive-include %s %s" % - (dir, ' '.join(patterns))) - for pattern in patterns: - if not self.recursive_include(dir, pattern): - log.warn(("warning: no files found matching '%s' " - "under directory '%s'"), - pattern, dir) - - elif action == 'recursive-exclude': - self.debug_print("recursive-exclude %s %s" % - (dir, ' '.join(patterns))) - for pattern in patterns: - if not self.recursive_exclude(dir, pattern): - log.warn(("warning: no previously-included files matching " - "'%s' found under directory '%s'"), - pattern, dir) - - elif action == 'graft': - self.debug_print("graft " + dir_pattern) - if not self.graft(dir_pattern): - log.warn("warning: no directories found matching '%s'", - dir_pattern) - - elif action == 'prune': - self.debug_print("prune " + dir_pattern) - if not self.prune(dir_pattern): - log.warn(("no previously-included directories found " - "matching '%s'"), dir_pattern) - - else: - raise DistutilsInternalError( - "this cannot happen: invalid action '%s'" % action) - - def _remove_files(self, predicate): - """ - Remove all files from the file list that match the predicate. - Return True if any matching files were removed - """ - found = False - for i in range(len(self.files) - 1, -1, -1): - if predicate(self.files[i]): - self.debug_print(" removing " + self.files[i]) - del self.files[i] - found = True - return found - - def include(self, pattern): - """Include files that match 'pattern'.""" - found = [f for f in glob(pattern) if not os.path.isdir(f)] - self.extend(found) - return bool(found) - - def exclude(self, pattern): - """Exclude files that match 'pattern'.""" - match = translate_pattern(pattern) - return self._remove_files(match.match) - - def recursive_include(self, dir, pattern): - """ - Include all files anywhere in 'dir/' that match the pattern. - """ - full_pattern = os.path.join(dir, '**', pattern) - found = [f for f in glob(full_pattern, recursive=True) - if not os.path.isdir(f)] - self.extend(found) - return bool(found) - - def recursive_exclude(self, dir, pattern): - """ - Exclude any file anywhere in 'dir/' that match the pattern. - """ - match = translate_pattern(os.path.join(dir, '**', pattern)) - return self._remove_files(match.match) - - def graft(self, dir): - """Include all files from 'dir/'.""" - found = [ - item - for match_dir in glob(dir) - for item in distutils.filelist.findall(match_dir) - ] - self.extend(found) - return bool(found) - - def prune(self, dir): - """Filter out files from 'dir/'.""" - match = translate_pattern(os.path.join(dir, '**')) - return self._remove_files(match.match) - - def global_include(self, pattern): - """ - Include all files anywhere in the current directory that match the - pattern. This is very inefficient on large file trees. - """ - if self.allfiles is None: - self.findall() - match = translate_pattern(os.path.join('**', pattern)) - found = [f for f in self.allfiles if match.match(f)] - self.extend(found) - return bool(found) - - def global_exclude(self, pattern): - """ - Exclude all files anywhere that match the pattern. - """ - match = translate_pattern(os.path.join('**', pattern)) - return self._remove_files(match.match) - - def append(self, item): - if item.endswith('\r'): # Fix older sdists built on Windows - item = item[:-1] - path = convert_path(item) - - if self._safe_path(path): - self.files.append(path) - - def extend(self, paths): - self.files.extend(filter(self._safe_path, paths)) - - def _repair(self): - """ - Replace self.files with only safe paths - - Because some owners of FileList manipulate the underlying - ``files`` attribute directly, this method must be called to - repair those paths. - """ - self.files = list(filter(self._safe_path, self.files)) - - def _safe_path(self, path): - enc_warn = "'%s' not %s encodable -- skipping" - - # To avoid accidental trans-codings errors, first to unicode - u_path = unicode_utils.filesys_decode(path) - if u_path is None: - log.warn("'%s' in unexpected encoding -- skipping" % path) - return False - - # Must ensure utf-8 encodability - utf8_path = unicode_utils.try_encode(u_path, "utf-8") - if utf8_path is None: - log.warn(enc_warn, path, 'utf-8') - return False - - try: - # accept is either way checks out - if os.path.exists(u_path) or os.path.exists(utf8_path): - return True - # this will catch any encode errors decoding u_path - except UnicodeEncodeError: - log.warn(enc_warn, path, sys.getfilesystemencoding()) - - -class manifest_maker(sdist): - template = "MANIFEST.in" - - def initialize_options(self): - self.use_defaults = 1 - self.prune = 1 - self.manifest_only = 1 - self.force_manifest = 1 - - def finalize_options(self): - pass - - def run(self): - self.filelist = FileList() - if not os.path.exists(self.manifest): - self.write_manifest() # it must exist so it'll get in the list - self.add_defaults() - if os.path.exists(self.template): - self.read_template() - self.prune_file_list() - self.filelist.sort() - self.filelist.remove_duplicates() - self.write_manifest() - - def _manifest_normalize(self, path): - path = unicode_utils.filesys_decode(path) - return path.replace(os.sep, '/') - - def write_manifest(self): - """ - Write the file list in 'self.filelist' to the manifest file - named by 'self.manifest'. - """ - self.filelist._repair() - - # Now _repairs should encodability, but not unicode - files = [self._manifest_normalize(f) for f in self.filelist.files] - msg = "writing manifest file '%s'" % self.manifest - self.execute(write_file, (self.manifest, files), msg) - - def warn(self, msg): - if not self._should_suppress_warning(msg): - sdist.warn(self, msg) - - @staticmethod - def _should_suppress_warning(msg): - """ - suppress missing-file warnings from sdist - """ - return re.match(r"standard file .*not found", msg) - - def add_defaults(self): - sdist.add_defaults(self) - self.check_license() - self.filelist.append(self.template) - self.filelist.append(self.manifest) - rcfiles = list(walk_revctrl()) - if rcfiles: - self.filelist.extend(rcfiles) - elif os.path.exists(self.manifest): - self.read_manifest() - - if os.path.exists("setup.py"): - # setup.py should be included by default, even if it's not - # the script called to create the sdist - self.filelist.append("setup.py") - - ei_cmd = self.get_finalized_command('egg_info') - self.filelist.graft(ei_cmd.egg_info) - - def prune_file_list(self): - build = self.get_finalized_command('build') - base_dir = self.distribution.get_fullname() - self.filelist.prune(build.build_base) - self.filelist.prune(base_dir) - sep = re.escape(os.sep) - self.filelist.exclude_pattern(r'(^|' + sep + r')(RCS|CVS|\.svn)' + sep, - is_regex=1) - - -def write_file(filename, contents): - """Create a file with the specified name and write 'contents' (a - sequence of strings without line terminators) to it. - """ - contents = "\n".join(contents) - - # assuming the contents has been vetted for utf-8 encoding - contents = contents.encode("utf-8") - - with open(filename, "wb") as f: # always write POSIX-style manifest - f.write(contents) - - -def write_pkg_info(cmd, basename, filename): - log.info("writing %s", filename) - if not cmd.dry_run: - metadata = cmd.distribution.metadata - metadata.version, oldver = cmd.egg_version, metadata.version - metadata.name, oldname = cmd.egg_name, metadata.name - - try: - # write unescaped data to PKG-INFO, so older pkg_resources - # can still parse it - metadata.write_pkg_info(cmd.egg_info) - finally: - metadata.name, metadata.version = oldname, oldver - - safe = getattr(cmd.distribution, 'zip_safe', None) - - bdist_egg.write_safety_flag(cmd.egg_info, safe) - - -def warn_depends_obsolete(cmd, basename, filename): - if os.path.exists(filename): - log.warn( - "WARNING: 'depends.txt' is not used by setuptools 0.6!\n" - "Use the install_requires/extras_require setup() args instead." - ) - - -def _write_requirements(stream, reqs): - lines = yield_lines(reqs or ()) - append_cr = lambda line: line + '\n' - lines = map(append_cr, lines) - stream.writelines(lines) - - -def write_requirements(cmd, basename, filename): - dist = cmd.distribution - data = six.StringIO() - _write_requirements(data, dist.install_requires) - extras_require = dist.extras_require or {} - for extra in sorted(extras_require): - data.write('\n[{extra}]\n'.format(**vars())) - _write_requirements(data, extras_require[extra]) - cmd.write_or_delete_file("requirements", filename, data.getvalue()) - - -def write_setup_requirements(cmd, basename, filename): - data = io.StringIO() - _write_requirements(data, cmd.distribution.setup_requires) - cmd.write_or_delete_file("setup-requirements", filename, data.getvalue()) - - -def write_toplevel_names(cmd, basename, filename): - pkgs = dict.fromkeys( - [ - k.split('.', 1)[0] - for k in cmd.distribution.iter_distribution_names() - ] - ) - cmd.write_file("top-level names", filename, '\n'.join(sorted(pkgs)) + '\n') - - -def overwrite_arg(cmd, basename, filename): - write_arg(cmd, basename, filename, True) - - -def write_arg(cmd, basename, filename, force=False): - argname = os.path.splitext(basename)[0] - value = getattr(cmd.distribution, argname, None) - if value is not None: - value = '\n'.join(value) + '\n' - cmd.write_or_delete_file(argname, filename, value, force) - - -def write_entries(cmd, basename, filename): - ep = cmd.distribution.entry_points - - if isinstance(ep, six.string_types) or ep is None: - data = ep - elif ep is not None: - data = [] - for section, contents in sorted(ep.items()): - if not isinstance(contents, six.string_types): - contents = EntryPoint.parse_group(section, contents) - contents = '\n'.join(sorted(map(str, contents.values()))) - data.append('[%s]\n%s\n\n' % (section, contents)) - data = ''.join(data) - - cmd.write_or_delete_file('entry points', filename, data, True) - - -def get_pkg_info_revision(): - """ - Get a -r### off of PKG-INFO Version in case this is an sdist of - a subversion revision. - """ - warnings.warn("get_pkg_info_revision is deprecated.", EggInfoDeprecationWarning) - if os.path.exists('PKG-INFO'): - with io.open('PKG-INFO') as f: - for line in f: - match = re.match(r"Version:.*-r(\d+)\s*$", line) - if match: - return int(match.group(1)) - return 0 - - -class EggInfoDeprecationWarning(SetuptoolsDeprecationWarning): - """Class for warning about deprecations in eggInfo in setupTools. Not ignored by default, unlike DeprecationWarning.""" diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/install.py b/venv2/lib/python2.7/site-packages/setuptools/command/install.py deleted file mode 100644 index 31a5ddb..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/install.py +++ /dev/null @@ -1,125 +0,0 @@ -from distutils.errors import DistutilsArgError -import inspect -import glob -import warnings -import platform -import distutils.command.install as orig - -import setuptools - -# Prior to numpy 1.9, NumPy relies on the '_install' name, so provide it for -# now. See https://github.com/pypa/setuptools/issues/199/ -_install = orig.install - - -class install(orig.install): - """Use easy_install to install the package, w/dependencies""" - - user_options = orig.install.user_options + [ - ('old-and-unmanageable', None, "Try not to use this!"), - ('single-version-externally-managed', None, - "used by system package builders to create 'flat' eggs"), - ] - boolean_options = orig.install.boolean_options + [ - 'old-and-unmanageable', 'single-version-externally-managed', - ] - new_commands = [ - ('install_egg_info', lambda self: True), - ('install_scripts', lambda self: True), - ] - _nc = dict(new_commands) - - def initialize_options(self): - orig.install.initialize_options(self) - self.old_and_unmanageable = None - self.single_version_externally_managed = None - - def finalize_options(self): - orig.install.finalize_options(self) - if self.root: - self.single_version_externally_managed = True - elif self.single_version_externally_managed: - if not self.root and not self.record: - raise DistutilsArgError( - "You must specify --record or --root when building system" - " packages" - ) - - def handle_extra_path(self): - if self.root or self.single_version_externally_managed: - # explicit backward-compatibility mode, allow extra_path to work - return orig.install.handle_extra_path(self) - - # Ignore extra_path when installing an egg (or being run by another - # command without --root or --single-version-externally-managed - self.path_file = None - self.extra_dirs = '' - - def run(self): - # Explicit request for old-style install? Just do it - if self.old_and_unmanageable or self.single_version_externally_managed: - return orig.install.run(self) - - if not self._called_from_setup(inspect.currentframe()): - # Run in backward-compatibility mode to support bdist_* commands. - orig.install.run(self) - else: - self.do_egg_install() - - @staticmethod - def _called_from_setup(run_frame): - """ - Attempt to detect whether run() was called from setup() or by another - command. If called by setup(), the parent caller will be the - 'run_command' method in 'distutils.dist', and *its* caller will be - the 'run_commands' method. If called any other way, the - immediate caller *might* be 'run_command', but it won't have been - called by 'run_commands'. Return True in that case or if a call stack - is unavailable. Return False otherwise. - """ - if run_frame is None: - msg = "Call stack not available. bdist_* commands may fail." - warnings.warn(msg) - if platform.python_implementation() == 'IronPython': - msg = "For best results, pass -X:Frames to enable call stack." - warnings.warn(msg) - return True - res = inspect.getouterframes(run_frame)[2] - caller, = res[:1] - info = inspect.getframeinfo(caller) - caller_module = caller.f_globals.get('__name__', '') - return ( - caller_module == 'distutils.dist' - and info.function == 'run_commands' - ) - - def do_egg_install(self): - - easy_install = self.distribution.get_command_class('easy_install') - - cmd = easy_install( - self.distribution, args="x", root=self.root, record=self.record, - ) - cmd.ensure_finalized() # finalize before bdist_egg munges install cmd - cmd.always_copy_from = '.' # make sure local-dir eggs get installed - - # pick up setup-dir .egg files only: no .egg-info - cmd.package_index.scan(glob.glob('*.egg')) - - self.run_command('bdist_egg') - args = [self.distribution.get_command_obj('bdist_egg').egg_output] - - if setuptools.bootstrap_install_from: - # Bootstrap self-installation of setuptools - args.insert(0, setuptools.bootstrap_install_from) - - cmd.args = args - cmd.run() - setuptools.bootstrap_install_from = None - - -# XXX Python 3.1 doesn't see _nc if this is inside the class -install.sub_commands = ( - [cmd for cmd in orig.install.sub_commands if cmd[0] not in install._nc] + - install.new_commands -) diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/install_egg_info.py b/venv2/lib/python2.7/site-packages/setuptools/command/install_egg_info.py deleted file mode 100644 index edc4718..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/install_egg_info.py +++ /dev/null @@ -1,62 +0,0 @@ -from distutils import log, dir_util -import os - -from setuptools import Command -from setuptools import namespaces -from setuptools.archive_util import unpack_archive -import pkg_resources - - -class install_egg_info(namespaces.Installer, Command): - """Install an .egg-info directory for the package""" - - description = "Install an .egg-info directory for the package" - - user_options = [ - ('install-dir=', 'd', "directory to install to"), - ] - - def initialize_options(self): - self.install_dir = None - - def finalize_options(self): - self.set_undefined_options('install_lib', - ('install_dir', 'install_dir')) - ei_cmd = self.get_finalized_command("egg_info") - basename = pkg_resources.Distribution( - None, None, ei_cmd.egg_name, ei_cmd.egg_version - ).egg_name() + '.egg-info' - self.source = ei_cmd.egg_info - self.target = os.path.join(self.install_dir, basename) - self.outputs = [] - - def run(self): - self.run_command('egg_info') - if os.path.isdir(self.target) and not os.path.islink(self.target): - dir_util.remove_tree(self.target, dry_run=self.dry_run) - elif os.path.exists(self.target): - self.execute(os.unlink, (self.target,), "Removing " + self.target) - if not self.dry_run: - pkg_resources.ensure_directory(self.target) - self.execute( - self.copytree, (), "Copying %s to %s" % (self.source, self.target) - ) - self.install_namespaces() - - def get_outputs(self): - return self.outputs - - def copytree(self): - # Copy the .egg-info tree to site-packages - def skimmer(src, dst): - # filter out source-control directories; note that 'src' is always - # a '/'-separated path, regardless of platform. 'dst' is a - # platform-specific path. - for skip in '.svn/', 'CVS/': - if src.startswith(skip) or '/' + skip in src: - return None - self.outputs.append(dst) - log.debug("Copying %s to %s", src, dst) - return dst - - unpack_archive(self.source, self.target, skimmer) diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/install_lib.py b/venv2/lib/python2.7/site-packages/setuptools/command/install_lib.py deleted file mode 100644 index 2b31c3e..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/install_lib.py +++ /dev/null @@ -1,121 +0,0 @@ -import os -import imp -from itertools import product, starmap -import distutils.command.install_lib as orig - - -class install_lib(orig.install_lib): - """Don't add compiled flags to filenames of non-Python files""" - - def run(self): - self.build() - outfiles = self.install() - if outfiles is not None: - # always compile, in case we have any extension stubs to deal with - self.byte_compile(outfiles) - - def get_exclusions(self): - """ - Return a collections.Sized collections.Container of paths to be - excluded for single_version_externally_managed installations. - """ - all_packages = ( - pkg - for ns_pkg in self._get_SVEM_NSPs() - for pkg in self._all_packages(ns_pkg) - ) - - excl_specs = product(all_packages, self._gen_exclusion_paths()) - return set(starmap(self._exclude_pkg_path, excl_specs)) - - def _exclude_pkg_path(self, pkg, exclusion_path): - """ - Given a package name and exclusion path within that package, - compute the full exclusion path. - """ - parts = pkg.split('.') + [exclusion_path] - return os.path.join(self.install_dir, *parts) - - @staticmethod - def _all_packages(pkg_name): - """ - >>> list(install_lib._all_packages('foo.bar.baz')) - ['foo.bar.baz', 'foo.bar', 'foo'] - """ - while pkg_name: - yield pkg_name - pkg_name, sep, child = pkg_name.rpartition('.') - - def _get_SVEM_NSPs(self): - """ - Get namespace packages (list) but only for - single_version_externally_managed installations and empty otherwise. - """ - # TODO: is it necessary to short-circuit here? i.e. what's the cost - # if get_finalized_command is called even when namespace_packages is - # False? - if not self.distribution.namespace_packages: - return [] - - install_cmd = self.get_finalized_command('install') - svem = install_cmd.single_version_externally_managed - - return self.distribution.namespace_packages if svem else [] - - @staticmethod - def _gen_exclusion_paths(): - """ - Generate file paths to be excluded for namespace packages (bytecode - cache files). - """ - # always exclude the package module itself - yield '__init__.py' - - yield '__init__.pyc' - yield '__init__.pyo' - - if not hasattr(imp, 'get_tag'): - return - - base = os.path.join('__pycache__', '__init__.' + imp.get_tag()) - yield base + '.pyc' - yield base + '.pyo' - yield base + '.opt-1.pyc' - yield base + '.opt-2.pyc' - - def copy_tree( - self, infile, outfile, - preserve_mode=1, preserve_times=1, preserve_symlinks=0, level=1 - ): - assert preserve_mode and preserve_times and not preserve_symlinks - exclude = self.get_exclusions() - - if not exclude: - return orig.install_lib.copy_tree(self, infile, outfile) - - # Exclude namespace package __init__.py* files from the output - - from setuptools.archive_util import unpack_directory - from distutils import log - - outfiles = [] - - def pf(src, dst): - if dst in exclude: - log.warn("Skipping installation of %s (namespace package)", - dst) - return False - - log.info("copying %s -> %s", src, os.path.dirname(dst)) - outfiles.append(dst) - return dst - - unpack_directory(infile, outfile, pf) - return outfiles - - def get_outputs(self): - outputs = orig.install_lib.get_outputs(self) - exclude = self.get_exclusions() - if exclude: - return [f for f in outputs if f not in exclude] - return outputs diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/install_scripts.py b/venv2/lib/python2.7/site-packages/setuptools/command/install_scripts.py deleted file mode 100644 index 1623427..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/install_scripts.py +++ /dev/null @@ -1,65 +0,0 @@ -from distutils import log -import distutils.command.install_scripts as orig -import os -import sys - -from pkg_resources import Distribution, PathMetadata, ensure_directory - - -class install_scripts(orig.install_scripts): - """Do normal script install, plus any egg_info wrapper scripts""" - - def initialize_options(self): - orig.install_scripts.initialize_options(self) - self.no_ep = False - - def run(self): - import setuptools.command.easy_install as ei - - self.run_command("egg_info") - if self.distribution.scripts: - orig.install_scripts.run(self) # run first to set up self.outfiles - else: - self.outfiles = [] - if self.no_ep: - # don't install entry point scripts into .egg file! - return - - ei_cmd = self.get_finalized_command("egg_info") - dist = Distribution( - ei_cmd.egg_base, PathMetadata(ei_cmd.egg_base, ei_cmd.egg_info), - ei_cmd.egg_name, ei_cmd.egg_version, - ) - bs_cmd = self.get_finalized_command('build_scripts') - exec_param = getattr(bs_cmd, 'executable', None) - bw_cmd = self.get_finalized_command("bdist_wininst") - is_wininst = getattr(bw_cmd, '_is_running', False) - writer = ei.ScriptWriter - if is_wininst: - exec_param = "python.exe" - writer = ei.WindowsScriptWriter - if exec_param == sys.executable: - # In case the path to the Python executable contains a space, wrap - # it so it's not split up. - exec_param = [exec_param] - # resolve the writer to the environment - writer = writer.best() - cmd = writer.command_spec_class.best().from_param(exec_param) - for args in writer.get_args(dist, cmd.as_header()): - self.write_script(*args) - - def write_script(self, script_name, contents, mode="t", *ignored): - """Write an executable file to the scripts directory""" - from setuptools.command.easy_install import chmod, current_umask - - log.info("Installing %s script to %s", script_name, self.install_dir) - target = os.path.join(self.install_dir, script_name) - self.outfiles.append(target) - - mask = current_umask() - if not self.dry_run: - ensure_directory(target) - f = open(target, "w" + mode) - f.write(contents) - f.close() - chmod(target, 0o777 - mask) diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/launcher manifest.xml b/venv2/lib/python2.7/site-packages/setuptools/command/launcher manifest.xml deleted file mode 100644 index 5972a96..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/launcher manifest.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> - <assemblyIdentity version="1.0.0.0" - processorArchitecture="X86" - name="%(name)s" - type="win32"/> - <!-- Identify the application security requirements. --> - <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> - <security> - <requestedPrivileges> - <requestedExecutionLevel level="asInvoker" uiAccess="false"/> - </requestedPrivileges> - </security> - </trustInfo> -</assembly> diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/py36compat.py b/venv2/lib/python2.7/site-packages/setuptools/command/py36compat.py deleted file mode 100644 index 61063e7..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/py36compat.py +++ /dev/null @@ -1,136 +0,0 @@ -import os -from glob import glob -from distutils.util import convert_path -from distutils.command import sdist - -from setuptools.extern.six.moves import filter - - -class sdist_add_defaults: - """ - Mix-in providing forward-compatibility for functionality as found in - distutils on Python 3.7. - - Do not edit the code in this class except to update functionality - as implemented in distutils. Instead, override in the subclass. - """ - - def add_defaults(self): - """Add all the default files to self.filelist: - - README or README.txt - - setup.py - - test/test*.py - - all pure Python modules mentioned in setup script - - all files pointed by package_data (build_py) - - all files defined in data_files. - - all files defined as scripts. - - all C sources listed as part of extensions or C libraries - in the setup script (doesn't catch C headers!) - Warns if (README or README.txt) or setup.py are missing; everything - else is optional. - """ - self._add_defaults_standards() - self._add_defaults_optional() - self._add_defaults_python() - self._add_defaults_data_files() - self._add_defaults_ext() - self._add_defaults_c_libs() - self._add_defaults_scripts() - - @staticmethod - def _cs_path_exists(fspath): - """ - Case-sensitive path existence check - - >>> sdist_add_defaults._cs_path_exists(__file__) - True - >>> sdist_add_defaults._cs_path_exists(__file__.upper()) - False - """ - if not os.path.exists(fspath): - return False - # make absolute so we always have a directory - abspath = os.path.abspath(fspath) - directory, filename = os.path.split(abspath) - return filename in os.listdir(directory) - - def _add_defaults_standards(self): - standards = [self.READMES, self.distribution.script_name] - for fn in standards: - if isinstance(fn, tuple): - alts = fn - got_it = False - for fn in alts: - if self._cs_path_exists(fn): - got_it = True - self.filelist.append(fn) - break - - if not got_it: - self.warn("standard file not found: should have one of " + - ', '.join(alts)) - else: - if self._cs_path_exists(fn): - self.filelist.append(fn) - else: - self.warn("standard file '%s' not found" % fn) - - def _add_defaults_optional(self): - optional = ['test/test*.py', 'setup.cfg'] - for pattern in optional: - files = filter(os.path.isfile, glob(pattern)) - self.filelist.extend(files) - - def _add_defaults_python(self): - # build_py is used to get: - # - python modules - # - files defined in package_data - build_py = self.get_finalized_command('build_py') - - # getting python files - if self.distribution.has_pure_modules(): - self.filelist.extend(build_py.get_source_files()) - - # getting package_data files - # (computed in build_py.data_files by build_py.finalize_options) - for pkg, src_dir, build_dir, filenames in build_py.data_files: - for filename in filenames: - self.filelist.append(os.path.join(src_dir, filename)) - - def _add_defaults_data_files(self): - # getting distribution.data_files - if self.distribution.has_data_files(): - for item in self.distribution.data_files: - if isinstance(item, str): - # plain file - item = convert_path(item) - if os.path.isfile(item): - self.filelist.append(item) - else: - # a (dirname, filenames) tuple - dirname, filenames = item - for f in filenames: - f = convert_path(f) - if os.path.isfile(f): - self.filelist.append(f) - - def _add_defaults_ext(self): - if self.distribution.has_ext_modules(): - build_ext = self.get_finalized_command('build_ext') - self.filelist.extend(build_ext.get_source_files()) - - def _add_defaults_c_libs(self): - if self.distribution.has_c_libraries(): - build_clib = self.get_finalized_command('build_clib') - self.filelist.extend(build_clib.get_source_files()) - - def _add_defaults_scripts(self): - if self.distribution.has_scripts(): - build_scripts = self.get_finalized_command('build_scripts') - self.filelist.extend(build_scripts.get_source_files()) - - -if hasattr(sdist.sdist, '_add_defaults_standards'): - # disable the functionality already available upstream - class sdist_add_defaults: - pass diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/register.py b/venv2/lib/python2.7/site-packages/setuptools/command/register.py deleted file mode 100644 index 98bc015..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/register.py +++ /dev/null @@ -1,18 +0,0 @@ -from distutils import log -import distutils.command.register as orig - - -class register(orig.register): - __doc__ = orig.register.__doc__ - - def run(self): - try: - # Make sure that we are using valid current name/version info - self.run_command('egg_info') - orig.register.run(self) - finally: - self.announce( - "WARNING: Registering is deprecated, use twine to " - "upload instead (https://pypi.org/p/twine/)", - log.WARN - ) diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/rotate.py b/venv2/lib/python2.7/site-packages/setuptools/command/rotate.py deleted file mode 100644 index b89353f..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/rotate.py +++ /dev/null @@ -1,66 +0,0 @@ -from distutils.util import convert_path -from distutils import log -from distutils.errors import DistutilsOptionError -import os -import shutil - -from setuptools.extern import six - -from setuptools import Command - - -class rotate(Command): - """Delete older distributions""" - - description = "delete older distributions, keeping N newest files" - user_options = [ - ('match=', 'm', "patterns to match (required)"), - ('dist-dir=', 'd', "directory where the distributions are"), - ('keep=', 'k', "number of matching distributions to keep"), - ] - - boolean_options = [] - - def initialize_options(self): - self.match = None - self.dist_dir = None - self.keep = None - - def finalize_options(self): - if self.match is None: - raise DistutilsOptionError( - "Must specify one or more (comma-separated) match patterns " - "(e.g. '.zip' or '.egg')" - ) - if self.keep is None: - raise DistutilsOptionError("Must specify number of files to keep") - try: - self.keep = int(self.keep) - except ValueError: - raise DistutilsOptionError("--keep must be an integer") - if isinstance(self.match, six.string_types): - self.match = [ - convert_path(p.strip()) for p in self.match.split(',') - ] - self.set_undefined_options('bdist', ('dist_dir', 'dist_dir')) - - def run(self): - self.run_command("egg_info") - from glob import glob - - for pattern in self.match: - pattern = self.distribution.get_name() + '*' + pattern - files = glob(os.path.join(self.dist_dir, pattern)) - files = [(os.path.getmtime(f), f) for f in files] - files.sort() - files.reverse() - - log.info("%d file(s) matching %s", len(files), pattern) - files = files[self.keep:] - for (t, f) in files: - log.info("Deleting %s", f) - if not self.dry_run: - if os.path.isdir(f): - shutil.rmtree(f) - else: - os.unlink(f) diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/saveopts.py b/venv2/lib/python2.7/site-packages/setuptools/command/saveopts.py deleted file mode 100644 index 611cec5..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/saveopts.py +++ /dev/null @@ -1,22 +0,0 @@ -from setuptools.command.setopt import edit_config, option_base - - -class saveopts(option_base): - """Save command-line options to a file""" - - description = "save supplied options to setup.cfg or other config file" - - def run(self): - dist = self.distribution - settings = {} - - for cmd in dist.command_options: - - if cmd == 'saveopts': - continue # don't save our own options! - - for opt, (src, val) in dist.get_option_dict(cmd).items(): - if src == "command line": - settings.setdefault(cmd, {})[opt] = val - - edit_config(self.filename, settings, self.dry_run) diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/sdist.py b/venv2/lib/python2.7/site-packages/setuptools/command/sdist.py deleted file mode 100644 index dc25398..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/sdist.py +++ /dev/null @@ -1,221 +0,0 @@ -from distutils import log -import distutils.command.sdist as orig -import os -import sys -import io -import contextlib - -from setuptools.extern import six - -from .py36compat import sdist_add_defaults - -import pkg_resources - -_default_revctrl = list - - -def walk_revctrl(dirname=''): - """Find all files under revision control""" - for ep in pkg_resources.iter_entry_points('setuptools.file_finders'): - for item in ep.load()(dirname): - yield item - - -class sdist(sdist_add_defaults, orig.sdist): - """Smart sdist that finds anything supported by revision control""" - - user_options = [ - ('formats=', None, - "formats for source distribution (comma-separated list)"), - ('keep-temp', 'k', - "keep the distribution tree around after creating " + - "archive file(s)"), - ('dist-dir=', 'd', - "directory to put the source distribution archive(s) in " - "[default: dist]"), - ] - - negative_opt = {} - - README_EXTENSIONS = ['', '.rst', '.txt', '.md'] - READMES = tuple('README{0}'.format(ext) for ext in README_EXTENSIONS) - - def run(self): - self.run_command('egg_info') - ei_cmd = self.get_finalized_command('egg_info') - self.filelist = ei_cmd.filelist - self.filelist.append(os.path.join(ei_cmd.egg_info, 'SOURCES.txt')) - self.check_readme() - - # Run sub commands - for cmd_name in self.get_sub_commands(): - self.run_command(cmd_name) - - self.make_distribution() - - dist_files = getattr(self.distribution, 'dist_files', []) - for file in self.archive_files: - data = ('sdist', '', file) - if data not in dist_files: - dist_files.append(data) - - def initialize_options(self): - orig.sdist.initialize_options(self) - - self._default_to_gztar() - - def _default_to_gztar(self): - # only needed on Python prior to 3.6. - if sys.version_info >= (3, 6, 0, 'beta', 1): - return - self.formats = ['gztar'] - - def make_distribution(self): - """ - Workaround for #516 - """ - with self._remove_os_link(): - orig.sdist.make_distribution(self) - - @staticmethod - @contextlib.contextmanager - def _remove_os_link(): - """ - In a context, remove and restore os.link if it exists - """ - - class NoValue: - pass - - orig_val = getattr(os, 'link', NoValue) - try: - del os.link - except Exception: - pass - try: - yield - finally: - if orig_val is not NoValue: - setattr(os, 'link', orig_val) - - def __read_template_hack(self): - # This grody hack closes the template file (MANIFEST.in) if an - # exception occurs during read_template. - # Doing so prevents an error when easy_install attempts to delete the - # file. - try: - orig.sdist.read_template(self) - except Exception: - _, _, tb = sys.exc_info() - tb.tb_next.tb_frame.f_locals['template'].close() - raise - - # Beginning with Python 2.7.2, 3.1.4, and 3.2.1, this leaky file handle - # has been fixed, so only override the method if we're using an earlier - # Python. - has_leaky_handle = ( - sys.version_info < (2, 7, 2) - or (3, 0) <= sys.version_info < (3, 1, 4) - or (3, 2) <= sys.version_info < (3, 2, 1) - ) - if has_leaky_handle: - read_template = __read_template_hack - - def _add_defaults_python(self): - """getting python files""" - if self.distribution.has_pure_modules(): - build_py = self.get_finalized_command('build_py') - self.filelist.extend(build_py.get_source_files()) - # This functionality is incompatible with include_package_data, and - # will in fact create an infinite recursion if include_package_data - # is True. Use of include_package_data will imply that - # distutils-style automatic handling of package_data is disabled - if not self.distribution.include_package_data: - for _, src_dir, _, filenames in build_py.data_files: - self.filelist.extend([os.path.join(src_dir, filename) - for filename in filenames]) - - def _add_defaults_data_files(self): - try: - if six.PY2: - sdist_add_defaults._add_defaults_data_files(self) - else: - super()._add_defaults_data_files() - except TypeError: - log.warn("data_files contains unexpected objects") - - def check_readme(self): - for f in self.READMES: - if os.path.exists(f): - return - else: - self.warn( - "standard file not found: should have one of " + - ', '.join(self.READMES) - ) - - def make_release_tree(self, base_dir, files): - orig.sdist.make_release_tree(self, base_dir, files) - - # Save any egg_info command line options used to create this sdist - dest = os.path.join(base_dir, 'setup.cfg') - if hasattr(os, 'link') and os.path.exists(dest): - # unlink and re-copy, since it might be hard-linked, and - # we don't want to change the source version - os.unlink(dest) - self.copy_file('setup.cfg', dest) - - self.get_finalized_command('egg_info').save_version_info(dest) - - def _manifest_is_not_generated(self): - # check for special comment used in 2.7.1 and higher - if not os.path.isfile(self.manifest): - return False - - with io.open(self.manifest, 'rb') as fp: - first_line = fp.readline() - return (first_line != - '# file GENERATED by distutils, do NOT edit\n'.encode()) - - def read_manifest(self): - """Read the manifest file (named by 'self.manifest') and use it to - fill in 'self.filelist', the list of files to include in the source - distribution. - """ - log.info("reading manifest file '%s'", self.manifest) - manifest = open(self.manifest, 'rb') - for line in manifest: - # The manifest must contain UTF-8. See #303. - if six.PY3: - try: - line = line.decode('UTF-8') - except UnicodeDecodeError: - log.warn("%r not UTF-8 decodable -- skipping" % line) - continue - # ignore comments and blank lines - line = line.strip() - if line.startswith('#') or not line: - continue - self.filelist.append(line) - manifest.close() - - def check_license(self): - """Checks if license_file' is configured and adds it to - 'self.filelist' if the value contains a valid path. - """ - - opts = self.distribution.get_option_dict('metadata') - - # ignore the source of the value - _, license_file = opts.get('license_file', (None, None)) - - if license_file is None: - log.debug("'license_file' option was not specified") - return - - if not os.path.exists(license_file): - log.warn("warning: Failed to find the configured license file '%s'", - license_file) - return - - self.filelist.append(license_file) diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/setopt.py b/venv2/lib/python2.7/site-packages/setuptools/command/setopt.py deleted file mode 100644 index 7e57cc0..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/setopt.py +++ /dev/null @@ -1,149 +0,0 @@ -from distutils.util import convert_path -from distutils import log -from distutils.errors import DistutilsOptionError -import distutils -import os - -from setuptools.extern.six.moves import configparser - -from setuptools import Command - -__all__ = ['config_file', 'edit_config', 'option_base', 'setopt'] - - -def config_file(kind="local"): - """Get the filename of the distutils, local, global, or per-user config - - `kind` must be one of "local", "global", or "user" - """ - if kind == 'local': - return 'setup.cfg' - if kind == 'global': - return os.path.join( - os.path.dirname(distutils.__file__), 'distutils.cfg' - ) - if kind == 'user': - dot = os.name == 'posix' and '.' or '' - return os.path.expanduser(convert_path("~/%spydistutils.cfg" % dot)) - raise ValueError( - "config_file() type must be 'local', 'global', or 'user'", kind - ) - - -def edit_config(filename, settings, dry_run=False): - """Edit a configuration file to include `settings` - - `settings` is a dictionary of dictionaries or ``None`` values, keyed by - command/section name. A ``None`` value means to delete the entire section, - while a dictionary lists settings to be changed or deleted in that section. - A setting of ``None`` means to delete that setting. - """ - log.debug("Reading configuration from %s", filename) - opts = configparser.RawConfigParser() - opts.read([filename]) - for section, options in settings.items(): - if options is None: - log.info("Deleting section [%s] from %s", section, filename) - opts.remove_section(section) - else: - if not opts.has_section(section): - log.debug("Adding new section [%s] to %s", section, filename) - opts.add_section(section) - for option, value in options.items(): - if value is None: - log.debug( - "Deleting %s.%s from %s", - section, option, filename - ) - opts.remove_option(section, option) - if not opts.options(section): - log.info("Deleting empty [%s] section from %s", - section, filename) - opts.remove_section(section) - else: - log.debug( - "Setting %s.%s to %r in %s", - section, option, value, filename - ) - opts.set(section, option, value) - - log.info("Writing %s", filename) - if not dry_run: - with open(filename, 'w') as f: - opts.write(f) - - -class option_base(Command): - """Abstract base class for commands that mess with config files""" - - user_options = [ - ('global-config', 'g', - "save options to the site-wide distutils.cfg file"), - ('user-config', 'u', - "save options to the current user's pydistutils.cfg file"), - ('filename=', 'f', - "configuration file to use (default=setup.cfg)"), - ] - - boolean_options = [ - 'global-config', 'user-config', - ] - - def initialize_options(self): - self.global_config = None - self.user_config = None - self.filename = None - - def finalize_options(self): - filenames = [] - if self.global_config: - filenames.append(config_file('global')) - if self.user_config: - filenames.append(config_file('user')) - if self.filename is not None: - filenames.append(self.filename) - if not filenames: - filenames.append(config_file('local')) - if len(filenames) > 1: - raise DistutilsOptionError( - "Must specify only one configuration file option", - filenames - ) - self.filename, = filenames - - -class setopt(option_base): - """Save command-line options to a file""" - - description = "set an option in setup.cfg or another config file" - - user_options = [ - ('command=', 'c', 'command to set an option for'), - ('option=', 'o', 'option to set'), - ('set-value=', 's', 'value of the option'), - ('remove', 'r', 'remove (unset) the value'), - ] + option_base.user_options - - boolean_options = option_base.boolean_options + ['remove'] - - def initialize_options(self): - option_base.initialize_options(self) - self.command = None - self.option = None - self.set_value = None - self.remove = None - - def finalize_options(self): - option_base.finalize_options(self) - if self.command is None or self.option is None: - raise DistutilsOptionError("Must specify --command *and* --option") - if self.set_value is None and not self.remove: - raise DistutilsOptionError("Must specify --set-value or --remove") - - def run(self): - edit_config( - self.filename, { - self.command: {self.option.replace('-', '_'): self.set_value} - }, - self.dry_run - ) diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/test.py b/venv2/lib/python2.7/site-packages/setuptools/command/test.py deleted file mode 100644 index 973e4eb..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/test.py +++ /dev/null @@ -1,271 +0,0 @@ -import os -import operator -import sys -import contextlib -import itertools -import unittest -from distutils.errors import DistutilsError, DistutilsOptionError -from distutils import log -from unittest import TestLoader - -from setuptools.extern import six -from setuptools.extern.six.moves import map, filter - -from pkg_resources import (resource_listdir, resource_exists, normalize_path, - working_set, _namespace_packages, evaluate_marker, - add_activation_listener, require, EntryPoint) -from setuptools import Command -from .build_py import _unique_everseen - -__metaclass__ = type - - -class ScanningLoader(TestLoader): - - def __init__(self): - TestLoader.__init__(self) - self._visited = set() - - def loadTestsFromModule(self, module, pattern=None): - """Return a suite of all tests cases contained in the given module - - If the module is a package, load tests from all the modules in it. - If the module has an ``additional_tests`` function, call it and add - the return value to the tests. - """ - if module in self._visited: - return None - self._visited.add(module) - - tests = [] - tests.append(TestLoader.loadTestsFromModule(self, module)) - - if hasattr(module, "additional_tests"): - tests.append(module.additional_tests()) - - if hasattr(module, '__path__'): - for file in resource_listdir(module.__name__, ''): - if file.endswith('.py') and file != '__init__.py': - submodule = module.__name__ + '.' + file[:-3] - else: - if resource_exists(module.__name__, file + '/__init__.py'): - submodule = module.__name__ + '.' + file - else: - continue - tests.append(self.loadTestsFromName(submodule)) - - if len(tests) != 1: - return self.suiteClass(tests) - else: - return tests[0] # don't create a nested suite for only one return - - -# adapted from jaraco.classes.properties:NonDataProperty -class NonDataProperty: - def __init__(self, fget): - self.fget = fget - - def __get__(self, obj, objtype=None): - if obj is None: - return self - return self.fget(obj) - - -class test(Command): - """Command to run unit tests after in-place build""" - - description = "run unit tests after in-place build" - - user_options = [ - ('test-module=', 'm', "Run 'test_suite' in specified module"), - ('test-suite=', 's', - "Run single test, case or suite (e.g. 'module.test_suite')"), - ('test-runner=', 'r', "Test runner to use"), - ] - - def initialize_options(self): - self.test_suite = None - self.test_module = None - self.test_loader = None - self.test_runner = None - - def finalize_options(self): - - if self.test_suite and self.test_module: - msg = "You may specify a module or a suite, but not both" - raise DistutilsOptionError(msg) - - if self.test_suite is None: - if self.test_module is None: - self.test_suite = self.distribution.test_suite - else: - self.test_suite = self.test_module + ".test_suite" - - if self.test_loader is None: - self.test_loader = getattr(self.distribution, 'test_loader', None) - if self.test_loader is None: - self.test_loader = "setuptools.command.test:ScanningLoader" - if self.test_runner is None: - self.test_runner = getattr(self.distribution, 'test_runner', None) - - @NonDataProperty - def test_args(self): - return list(self._test_args()) - - def _test_args(self): - if not self.test_suite and sys.version_info >= (2, 7): - yield 'discover' - if self.verbose: - yield '--verbose' - if self.test_suite: - yield self.test_suite - - def with_project_on_sys_path(self, func): - """ - Backward compatibility for project_on_sys_path context. - """ - with self.project_on_sys_path(): - func() - - @contextlib.contextmanager - def project_on_sys_path(self, include_dists=[]): - with_2to3 = six.PY3 and getattr(self.distribution, 'use_2to3', False) - - if with_2to3: - # If we run 2to3 we can not do this inplace: - - # Ensure metadata is up-to-date - self.reinitialize_command('build_py', inplace=0) - self.run_command('build_py') - bpy_cmd = self.get_finalized_command("build_py") - build_path = normalize_path(bpy_cmd.build_lib) - - # Build extensions - self.reinitialize_command('egg_info', egg_base=build_path) - self.run_command('egg_info') - - self.reinitialize_command('build_ext', inplace=0) - self.run_command('build_ext') - else: - # Without 2to3 inplace works fine: - self.run_command('egg_info') - - # Build extensions in-place - self.reinitialize_command('build_ext', inplace=1) - self.run_command('build_ext') - - ei_cmd = self.get_finalized_command("egg_info") - - old_path = sys.path[:] - old_modules = sys.modules.copy() - - try: - project_path = normalize_path(ei_cmd.egg_base) - sys.path.insert(0, project_path) - working_set.__init__() - add_activation_listener(lambda dist: dist.activate()) - require('%s==%s' % (ei_cmd.egg_name, ei_cmd.egg_version)) - with self.paths_on_pythonpath([project_path]): - yield - finally: - sys.path[:] = old_path - sys.modules.clear() - sys.modules.update(old_modules) - working_set.__init__() - - @staticmethod - @contextlib.contextmanager - def paths_on_pythonpath(paths): - """ - Add the indicated paths to the head of the PYTHONPATH environment - variable so that subprocesses will also see the packages at - these paths. - - Do this in a context that restores the value on exit. - """ - nothing = object() - orig_pythonpath = os.environ.get('PYTHONPATH', nothing) - current_pythonpath = os.environ.get('PYTHONPATH', '') - try: - prefix = os.pathsep.join(_unique_everseen(paths)) - to_join = filter(None, [prefix, current_pythonpath]) - new_path = os.pathsep.join(to_join) - if new_path: - os.environ['PYTHONPATH'] = new_path - yield - finally: - if orig_pythonpath is nothing: - os.environ.pop('PYTHONPATH', None) - else: - os.environ['PYTHONPATH'] = orig_pythonpath - - @staticmethod - def install_dists(dist): - """ - Install the requirements indicated by self.distribution and - return an iterable of the dists that were built. - """ - ir_d = dist.fetch_build_eggs(dist.install_requires) - tr_d = dist.fetch_build_eggs(dist.tests_require or []) - er_d = dist.fetch_build_eggs( - v for k, v in dist.extras_require.items() - if k.startswith(':') and evaluate_marker(k[1:]) - ) - return itertools.chain(ir_d, tr_d, er_d) - - def run(self): - installed_dists = self.install_dists(self.distribution) - - cmd = ' '.join(self._argv) - if self.dry_run: - self.announce('skipping "%s" (dry run)' % cmd) - return - - self.announce('running "%s"' % cmd) - - paths = map(operator.attrgetter('location'), installed_dists) - with self.paths_on_pythonpath(paths): - with self.project_on_sys_path(): - self.run_tests() - - def run_tests(self): - # Purge modules under test from sys.modules. The test loader will - # re-import them from the build location. Required when 2to3 is used - # with namespace packages. - if six.PY3 and getattr(self.distribution, 'use_2to3', False): - module = self.test_suite.split('.')[0] - if module in _namespace_packages: - del_modules = [] - if module in sys.modules: - del_modules.append(module) - module += '.' - for name in sys.modules: - if name.startswith(module): - del_modules.append(name) - list(map(sys.modules.__delitem__, del_modules)) - - test = unittest.main( - None, None, self._argv, - testLoader=self._resolve_as_ep(self.test_loader), - testRunner=self._resolve_as_ep(self.test_runner), - exit=False, - ) - if not test.result.wasSuccessful(): - msg = 'Test failed: %s' % test.result - self.announce(msg, log.ERROR) - raise DistutilsError(msg) - - @property - def _argv(self): - return ['unittest'] + self.test_args - - @staticmethod - def _resolve_as_ep(val): - """ - Load the indicated attribute value, called, as a as if it were - specified as an entry point. - """ - if val is None: - return - parsed = EntryPoint.parse("x=" + val) - return parsed.resolve()() diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/upload.py b/venv2/lib/python2.7/site-packages/setuptools/command/upload.py deleted file mode 100644 index 6db8888..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/upload.py +++ /dev/null @@ -1,196 +0,0 @@ -import io -import os -import hashlib -import getpass - -from base64 import standard_b64encode - -from distutils import log -from distutils.command import upload as orig -from distutils.spawn import spawn - -from distutils.errors import DistutilsError - -from setuptools.extern.six.moves.urllib.request import urlopen, Request -from setuptools.extern.six.moves.urllib.error import HTTPError -from setuptools.extern.six.moves.urllib.parse import urlparse - - -class upload(orig.upload): - """ - Override default upload behavior to obtain password - in a variety of different ways. - """ - def run(self): - try: - orig.upload.run(self) - finally: - self.announce( - "WARNING: Uploading via this command is deprecated, use twine " - "to upload instead (https://pypi.org/p/twine/)", - log.WARN - ) - - def finalize_options(self): - orig.upload.finalize_options(self) - self.username = ( - self.username or - getpass.getuser() - ) - # Attempt to obtain password. Short circuit evaluation at the first - # sign of success. - self.password = ( - self.password or - self._load_password_from_keyring() or - self._prompt_for_password() - ) - - def upload_file(self, command, pyversion, filename): - # Makes sure the repository URL is compliant - schema, netloc, url, params, query, fragments = \ - urlparse(self.repository) - if params or query or fragments: - raise AssertionError("Incompatible url %s" % self.repository) - - if schema not in ('http', 'https'): - raise AssertionError("unsupported schema " + schema) - - # Sign if requested - if self.sign: - gpg_args = ["gpg", "--detach-sign", "-a", filename] - if self.identity: - gpg_args[2:2] = ["--local-user", self.identity] - spawn(gpg_args, - dry_run=self.dry_run) - - # Fill in the data - send all the meta-data in case we need to - # register a new release - with open(filename, 'rb') as f: - content = f.read() - - meta = self.distribution.metadata - - data = { - # action - ':action': 'file_upload', - 'protocol_version': '1', - - # identify release - 'name': meta.get_name(), - 'version': meta.get_version(), - - # file content - 'content': (os.path.basename(filename), content), - 'filetype': command, - 'pyversion': pyversion, - 'md5_digest': hashlib.md5(content).hexdigest(), - - # additional meta-data - 'metadata_version': str(meta.get_metadata_version()), - 'summary': meta.get_description(), - 'home_page': meta.get_url(), - 'author': meta.get_contact(), - 'author_email': meta.get_contact_email(), - 'license': meta.get_licence(), - 'description': meta.get_long_description(), - 'keywords': meta.get_keywords(), - 'platform': meta.get_platforms(), - 'classifiers': meta.get_classifiers(), - 'download_url': meta.get_download_url(), - # PEP 314 - 'provides': meta.get_provides(), - 'requires': meta.get_requires(), - 'obsoletes': meta.get_obsoletes(), - } - - data['comment'] = '' - - if self.sign: - data['gpg_signature'] = (os.path.basename(filename) + ".asc", - open(filename+".asc", "rb").read()) - - # set up the authentication - user_pass = (self.username + ":" + self.password).encode('ascii') - # The exact encoding of the authentication string is debated. - # Anyway PyPI only accepts ascii for both username or password. - auth = "Basic " + standard_b64encode(user_pass).decode('ascii') - - # Build up the MIME payload for the POST data - boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' - sep_boundary = b'\r\n--' + boundary.encode('ascii') - end_boundary = sep_boundary + b'--\r\n' - body = io.BytesIO() - for key, value in data.items(): - title = '\r\nContent-Disposition: form-data; name="%s"' % key - # handle multiple entries for the same name - if not isinstance(value, list): - value = [value] - for value in value: - if type(value) is tuple: - title += '; filename="%s"' % value[0] - value = value[1] - else: - value = str(value).encode('utf-8') - body.write(sep_boundary) - body.write(title.encode('utf-8')) - body.write(b"\r\n\r\n") - body.write(value) - body.write(end_boundary) - body = body.getvalue() - - msg = "Submitting %s to %s" % (filename, self.repository) - self.announce(msg, log.INFO) - - # build the Request - headers = { - 'Content-type': 'multipart/form-data; boundary=%s' % boundary, - 'Content-length': str(len(body)), - 'Authorization': auth, - } - - request = Request(self.repository, data=body, - headers=headers) - # send the data - try: - result = urlopen(request) - status = result.getcode() - reason = result.msg - except HTTPError as e: - status = e.code - reason = e.msg - except OSError as e: - self.announce(str(e), log.ERROR) - raise - - if status == 200: - self.announce('Server response (%s): %s' % (status, reason), - log.INFO) - if self.show_response: - text = getattr(self, '_read_pypi_response', - lambda x: None)(result) - if text is not None: - msg = '\n'.join(('-' * 75, text, '-' * 75)) - self.announce(msg, log.INFO) - else: - msg = 'Upload failed (%s): %s' % (status, reason) - self.announce(msg, log.ERROR) - raise DistutilsError(msg) - - def _load_password_from_keyring(self): - """ - Attempt to load password from keyring. Suppress Exceptions. - """ - try: - keyring = __import__('keyring') - return keyring.get_password(self.repository, self.username) - except Exception: - pass - - def _prompt_for_password(self): - """ - Prompt for a password on the tty. Suppress Exceptions. - """ - try: - return getpass.getpass() - except (Exception, KeyboardInterrupt): - pass diff --git a/venv2/lib/python2.7/site-packages/setuptools/command/upload_docs.py b/venv2/lib/python2.7/site-packages/setuptools/command/upload_docs.py deleted file mode 100644 index 07aa564..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/command/upload_docs.py +++ /dev/null @@ -1,206 +0,0 @@ -# -*- coding: utf-8 -*- -"""upload_docs - -Implements a Distutils 'upload_docs' subcommand (upload documentation to -PyPI's pythonhosted.org). -""" - -from base64 import standard_b64encode -from distutils import log -from distutils.errors import DistutilsOptionError -import os -import socket -import zipfile -import tempfile -import shutil -import itertools -import functools - -from setuptools.extern import six -from setuptools.extern.six.moves import http_client, urllib - -from pkg_resources import iter_entry_points -from .upload import upload - - -def _encode(s): - errors = 'surrogateescape' if six.PY3 else 'strict' - return s.encode('utf-8', errors) - - -class upload_docs(upload): - # override the default repository as upload_docs isn't - # supported by Warehouse (and won't be). - DEFAULT_REPOSITORY = 'https://pypi.python.org/pypi/' - - description = 'Upload documentation to PyPI' - - user_options = [ - ('repository=', 'r', - "url of repository [default: %s]" % upload.DEFAULT_REPOSITORY), - ('show-response', None, - 'display full response text from server'), - ('upload-dir=', None, 'directory to upload'), - ] - boolean_options = upload.boolean_options - - def has_sphinx(self): - if self.upload_dir is None: - for ep in iter_entry_points('distutils.commands', 'build_sphinx'): - return True - - sub_commands = [('build_sphinx', has_sphinx)] - - def initialize_options(self): - upload.initialize_options(self) - self.upload_dir = None - self.target_dir = None - - def finalize_options(self): - upload.finalize_options(self) - if self.upload_dir is None: - if self.has_sphinx(): - build_sphinx = self.get_finalized_command('build_sphinx') - self.target_dir = build_sphinx.builder_target_dir - else: - build = self.get_finalized_command('build') - self.target_dir = os.path.join(build.build_base, 'docs') - else: - self.ensure_dirname('upload_dir') - self.target_dir = self.upload_dir - if 'pypi.python.org' in self.repository: - log.warn("Upload_docs command is deprecated. Use RTD instead.") - self.announce('Using upload directory %s' % self.target_dir) - - def create_zipfile(self, filename): - zip_file = zipfile.ZipFile(filename, "w") - try: - self.mkpath(self.target_dir) # just in case - for root, dirs, files in os.walk(self.target_dir): - if root == self.target_dir and not files: - tmpl = "no files found in upload directory '%s'" - raise DistutilsOptionError(tmpl % self.target_dir) - for name in files: - full = os.path.join(root, name) - relative = root[len(self.target_dir):].lstrip(os.path.sep) - dest = os.path.join(relative, name) - zip_file.write(full, dest) - finally: - zip_file.close() - - def run(self): - # Run sub commands - for cmd_name in self.get_sub_commands(): - self.run_command(cmd_name) - - tmp_dir = tempfile.mkdtemp() - name = self.distribution.metadata.get_name() - zip_file = os.path.join(tmp_dir, "%s.zip" % name) - try: - self.create_zipfile(zip_file) - self.upload_file(zip_file) - finally: - shutil.rmtree(tmp_dir) - - @staticmethod - def _build_part(item, sep_boundary): - key, values = item - title = '\nContent-Disposition: form-data; name="%s"' % key - # handle multiple entries for the same name - if not isinstance(values, list): - values = [values] - for value in values: - if isinstance(value, tuple): - title += '; filename="%s"' % value[0] - value = value[1] - else: - value = _encode(value) - yield sep_boundary - yield _encode(title) - yield b"\n\n" - yield value - if value and value[-1:] == b'\r': - yield b'\n' # write an extra newline (lurve Macs) - - @classmethod - def _build_multipart(cls, data): - """ - Build up the MIME payload for the POST data - """ - boundary = b'--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' - sep_boundary = b'\n--' + boundary - end_boundary = sep_boundary + b'--' - end_items = end_boundary, b"\n", - builder = functools.partial( - cls._build_part, - sep_boundary=sep_boundary, - ) - part_groups = map(builder, data.items()) - parts = itertools.chain.from_iterable(part_groups) - body_items = itertools.chain(parts, end_items) - content_type = 'multipart/form-data; boundary=%s' % boundary.decode('ascii') - return b''.join(body_items), content_type - - def upload_file(self, filename): - with open(filename, 'rb') as f: - content = f.read() - meta = self.distribution.metadata - data = { - ':action': 'doc_upload', - 'name': meta.get_name(), - 'content': (os.path.basename(filename), content), - } - # set up the authentication - credentials = _encode(self.username + ':' + self.password) - credentials = standard_b64encode(credentials) - if six.PY3: - credentials = credentials.decode('ascii') - auth = "Basic " + credentials - - body, ct = self._build_multipart(data) - - msg = "Submitting documentation to %s" % (self.repository) - self.announce(msg, log.INFO) - - # build the Request - # We can't use urllib2 since we need to send the Basic - # auth right with the first request - schema, netloc, url, params, query, fragments = \ - urllib.parse.urlparse(self.repository) - assert not params and not query and not fragments - if schema == 'http': - conn = http_client.HTTPConnection(netloc) - elif schema == 'https': - conn = http_client.HTTPSConnection(netloc) - else: - raise AssertionError("unsupported schema " + schema) - - data = '' - try: - conn.connect() - conn.putrequest("POST", url) - content_type = ct - conn.putheader('Content-type', content_type) - conn.putheader('Content-length', str(len(body))) - conn.putheader('Authorization', auth) - conn.endheaders() - conn.send(body) - except socket.error as e: - self.announce(str(e), log.ERROR) - return - - r = conn.getresponse() - if r.status == 200: - msg = 'Server response (%s): %s' % (r.status, r.reason) - self.announce(msg, log.INFO) - elif r.status == 301: - location = r.getheader('Location') - if location is None: - location = 'https://pythonhosted.org/%s/' % meta.get_name() - msg = 'Upload successful. Visit %s' % location - self.announce(msg, log.INFO) - else: - msg = 'Upload failed (%s): %s' % (r.status, r.reason) - self.announce(msg, log.ERROR) - if self.show_response: - print('-' * 75, r.read(), '-' * 75) diff --git a/venv2/lib/python2.7/site-packages/setuptools/config.py b/venv2/lib/python2.7/site-packages/setuptools/config.py deleted file mode 100644 index b662604..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/config.py +++ /dev/null @@ -1,656 +0,0 @@ -from __future__ import absolute_import, unicode_literals -import io -import os -import sys - -import warnings -import functools -from collections import defaultdict -from functools import partial -from functools import wraps -from importlib import import_module - -from distutils.errors import DistutilsOptionError, DistutilsFileError -from setuptools.extern.packaging.version import LegacyVersion, parse -from setuptools.extern.six import string_types, PY3 - - -__metaclass__ = type - - -def read_configuration( - filepath, find_others=False, ignore_option_errors=False): - """Read given configuration file and returns options from it as a dict. - - :param str|unicode filepath: Path to configuration file - to get options from. - - :param bool find_others: Whether to search for other configuration files - which could be on in various places. - - :param bool ignore_option_errors: Whether to silently ignore - options, values of which could not be resolved (e.g. due to exceptions - in directives such as file:, attr:, etc.). - If False exceptions are propagated as expected. - - :rtype: dict - """ - from setuptools.dist import Distribution, _Distribution - - filepath = os.path.abspath(filepath) - - if not os.path.isfile(filepath): - raise DistutilsFileError( - 'Configuration file %s does not exist.' % filepath) - - current_directory = os.getcwd() - os.chdir(os.path.dirname(filepath)) - - try: - dist = Distribution() - - filenames = dist.find_config_files() if find_others else [] - if filepath not in filenames: - filenames.append(filepath) - - _Distribution.parse_config_files(dist, filenames=filenames) - - handlers = parse_configuration( - dist, dist.command_options, - ignore_option_errors=ignore_option_errors) - - finally: - os.chdir(current_directory) - - return configuration_to_dict(handlers) - - -def _get_option(target_obj, key): - """ - Given a target object and option key, get that option from - the target object, either through a get_{key} method or - from an attribute directly. - """ - getter_name = 'get_{key}'.format(**locals()) - by_attribute = functools.partial(getattr, target_obj, key) - getter = getattr(target_obj, getter_name, by_attribute) - return getter() - - -def configuration_to_dict(handlers): - """Returns configuration data gathered by given handlers as a dict. - - :param list[ConfigHandler] handlers: Handlers list, - usually from parse_configuration() - - :rtype: dict - """ - config_dict = defaultdict(dict) - - for handler in handlers: - for option in handler.set_options: - value = _get_option(handler.target_obj, option) - config_dict[handler.section_prefix][option] = value - - return config_dict - - -def parse_configuration( - distribution, command_options, ignore_option_errors=False): - """Performs additional parsing of configuration options - for a distribution. - - Returns a list of used option handlers. - - :param Distribution distribution: - :param dict command_options: - :param bool ignore_option_errors: Whether to silently ignore - options, values of which could not be resolved (e.g. due to exceptions - in directives such as file:, attr:, etc.). - If False exceptions are propagated as expected. - :rtype: list - """ - options = ConfigOptionsHandler( - distribution, command_options, ignore_option_errors) - options.parse() - - meta = ConfigMetadataHandler( - distribution.metadata, command_options, ignore_option_errors, - distribution.package_dir) - meta.parse() - - return meta, options - - -class ConfigHandler: - """Handles metadata supplied in configuration files.""" - - section_prefix = None - """Prefix for config sections handled by this handler. - Must be provided by class heirs. - - """ - - aliases = {} - """Options aliases. - For compatibility with various packages. E.g.: d2to1 and pbr. - Note: `-` in keys is replaced with `_` by config parser. - - """ - - def __init__(self, target_obj, options, ignore_option_errors=False): - sections = {} - - section_prefix = self.section_prefix - for section_name, section_options in options.items(): - if not section_name.startswith(section_prefix): - continue - - section_name = section_name.replace(section_prefix, '').strip('.') - sections[section_name] = section_options - - self.ignore_option_errors = ignore_option_errors - self.target_obj = target_obj - self.sections = sections - self.set_options = [] - - @property - def parsers(self): - """Metadata item name to parser function mapping.""" - raise NotImplementedError( - '%s must provide .parsers property' % self.__class__.__name__) - - def __setitem__(self, option_name, value): - unknown = tuple() - target_obj = self.target_obj - - # Translate alias into real name. - option_name = self.aliases.get(option_name, option_name) - - current_value = getattr(target_obj, option_name, unknown) - - if current_value is unknown: - raise KeyError(option_name) - - if current_value: - # Already inhabited. Skipping. - return - - skip_option = False - parser = self.parsers.get(option_name) - if parser: - try: - value = parser(value) - - except Exception: - skip_option = True - if not self.ignore_option_errors: - raise - - if skip_option: - return - - setter = getattr(target_obj, 'set_%s' % option_name, None) - if setter is None: - setattr(target_obj, option_name, value) - else: - setter(value) - - self.set_options.append(option_name) - - @classmethod - def _parse_list(cls, value, separator=','): - """Represents value as a list. - - Value is split either by separator (defaults to comma) or by lines. - - :param value: - :param separator: List items separator character. - :rtype: list - """ - if isinstance(value, list): # _get_parser_compound case - return value - - if '\n' in value: - value = value.splitlines() - else: - value = value.split(separator) - - return [chunk.strip() for chunk in value if chunk.strip()] - - @classmethod - def _parse_dict(cls, value): - """Represents value as a dict. - - :param value: - :rtype: dict - """ - separator = '=' - result = {} - for line in cls._parse_list(value): - key, sep, val = line.partition(separator) - if sep != separator: - raise DistutilsOptionError( - 'Unable to parse option value to dict: %s' % value) - result[key.strip()] = val.strip() - - return result - - @classmethod - def _parse_bool(cls, value): - """Represents value as boolean. - - :param value: - :rtype: bool - """ - value = value.lower() - return value in ('1', 'true', 'yes') - - @classmethod - def _exclude_files_parser(cls, key): - """Returns a parser function to make sure field inputs - are not files. - - Parses a value after getting the key so error messages are - more informative. - - :param key: - :rtype: callable - """ - def parser(value): - exclude_directive = 'file:' - if value.startswith(exclude_directive): - raise ValueError( - 'Only strings are accepted for the {0} field, ' - 'files are not accepted'.format(key)) - return value - return parser - - @classmethod - def _parse_file(cls, value): - """Represents value as a string, allowing including text - from nearest files using `file:` directive. - - Directive is sandboxed and won't reach anything outside - directory with setup.py. - - Examples: - file: README.rst, CHANGELOG.md, src/file.txt - - :param str value: - :rtype: str - """ - include_directive = 'file:' - - if not isinstance(value, string_types): - return value - - if not value.startswith(include_directive): - return value - - spec = value[len(include_directive):] - filepaths = (os.path.abspath(path.strip()) for path in spec.split(',')) - return '\n'.join( - cls._read_file(path) - for path in filepaths - if (cls._assert_local(path) or True) - and os.path.isfile(path) - ) - - @staticmethod - def _assert_local(filepath): - if not filepath.startswith(os.getcwd()): - raise DistutilsOptionError( - '`file:` directive can not access %s' % filepath) - - @staticmethod - def _read_file(filepath): - with io.open(filepath, encoding='utf-8') as f: - return f.read() - - @classmethod - def _parse_attr(cls, value, package_dir=None): - """Represents value as a module attribute. - - Examples: - attr: package.attr - attr: package.module.attr - - :param str value: - :rtype: str - """ - attr_directive = 'attr:' - if not value.startswith(attr_directive): - return value - - attrs_path = value.replace(attr_directive, '').strip().split('.') - attr_name = attrs_path.pop() - - module_name = '.'.join(attrs_path) - module_name = module_name or '__init__' - - parent_path = os.getcwd() - if package_dir: - if attrs_path[0] in package_dir: - # A custom path was specified for the module we want to import - custom_path = package_dir[attrs_path[0]] - parts = custom_path.rsplit('/', 1) - if len(parts) > 1: - parent_path = os.path.join(os.getcwd(), parts[0]) - module_name = parts[1] - else: - module_name = custom_path - elif '' in package_dir: - # A custom parent directory was specified for all root modules - parent_path = os.path.join(os.getcwd(), package_dir['']) - sys.path.insert(0, parent_path) - try: - module = import_module(module_name) - value = getattr(module, attr_name) - - finally: - sys.path = sys.path[1:] - - return value - - @classmethod - def _get_parser_compound(cls, *parse_methods): - """Returns parser function to represents value as a list. - - Parses a value applying given methods one after another. - - :param parse_methods: - :rtype: callable - """ - def parse(value): - parsed = value - - for method in parse_methods: - parsed = method(parsed) - - return parsed - - return parse - - @classmethod - def _parse_section_to_dict(cls, section_options, values_parser=None): - """Parses section options into a dictionary. - - Optionally applies a given parser to values. - - :param dict section_options: - :param callable values_parser: - :rtype: dict - """ - value = {} - values_parser = values_parser or (lambda val: val) - for key, (_, val) in section_options.items(): - value[key] = values_parser(val) - return value - - def parse_section(self, section_options): - """Parses configuration file section. - - :param dict section_options: - """ - for (name, (_, value)) in section_options.items(): - try: - self[name] = value - - except KeyError: - pass # Keep silent for a new option may appear anytime. - - def parse(self): - """Parses configuration file items from one - or more related sections. - - """ - for section_name, section_options in self.sections.items(): - - method_postfix = '' - if section_name: # [section.option] variant - method_postfix = '_%s' % section_name - - section_parser_method = getattr( - self, - # Dots in section names are translated into dunderscores. - ('parse_section%s' % method_postfix).replace('.', '__'), - None) - - if section_parser_method is None: - raise DistutilsOptionError( - 'Unsupported distribution option section: [%s.%s]' % ( - self.section_prefix, section_name)) - - section_parser_method(section_options) - - def _deprecated_config_handler(self, func, msg, warning_class): - """ this function will wrap around parameters that are deprecated - - :param msg: deprecation message - :param warning_class: class of warning exception to be raised - :param func: function to be wrapped around - """ - @wraps(func) - def config_handler(*args, **kwargs): - warnings.warn(msg, warning_class) - return func(*args, **kwargs) - - return config_handler - - -class ConfigMetadataHandler(ConfigHandler): - - section_prefix = 'metadata' - - aliases = { - 'home_page': 'url', - 'summary': 'description', - 'classifier': 'classifiers', - 'platform': 'platforms', - } - - strict_mode = False - """We need to keep it loose, to be partially compatible with - `pbr` and `d2to1` packages which also uses `metadata` section. - - """ - - def __init__(self, target_obj, options, ignore_option_errors=False, - package_dir=None): - super(ConfigMetadataHandler, self).__init__(target_obj, options, - ignore_option_errors) - self.package_dir = package_dir - - @property - def parsers(self): - """Metadata item name to parser function mapping.""" - parse_list = self._parse_list - parse_file = self._parse_file - parse_dict = self._parse_dict - exclude_files_parser = self._exclude_files_parser - - return { - 'platforms': parse_list, - 'keywords': parse_list, - 'provides': parse_list, - 'requires': self._deprecated_config_handler( - parse_list, - "The requires parameter is deprecated, please use " - "install_requires for runtime dependencies.", - DeprecationWarning), - 'obsoletes': parse_list, - 'classifiers': self._get_parser_compound(parse_file, parse_list), - 'license': exclude_files_parser('license'), - 'description': parse_file, - 'long_description': parse_file, - 'version': self._parse_version, - 'project_urls': parse_dict, - } - - def _parse_version(self, value): - """Parses `version` option value. - - :param value: - :rtype: str - - """ - version = self._parse_file(value) - - if version != value: - version = version.strip() - # Be strict about versions loaded from file because it's easy to - # accidentally include newlines and other unintended content - if isinstance(parse(version), LegacyVersion): - tmpl = ( - 'Version loaded from {value} does not ' - 'comply with PEP 440: {version}' - ) - raise DistutilsOptionError(tmpl.format(**locals())) - - return version - - version = self._parse_attr(value, self.package_dir) - - if callable(version): - version = version() - - if not isinstance(version, string_types): - if hasattr(version, '__iter__'): - version = '.'.join(map(str, version)) - else: - version = '%s' % version - - return version - - -class ConfigOptionsHandler(ConfigHandler): - - section_prefix = 'options' - - @property - def parsers(self): - """Metadata item name to parser function mapping.""" - parse_list = self._parse_list - parse_list_semicolon = partial(self._parse_list, separator=';') - parse_bool = self._parse_bool - parse_dict = self._parse_dict - - return { - 'zip_safe': parse_bool, - 'use_2to3': parse_bool, - 'include_package_data': parse_bool, - 'package_dir': parse_dict, - 'use_2to3_fixers': parse_list, - 'use_2to3_exclude_fixers': parse_list, - 'convert_2to3_doctests': parse_list, - 'scripts': parse_list, - 'eager_resources': parse_list, - 'dependency_links': parse_list, - 'namespace_packages': parse_list, - 'install_requires': parse_list_semicolon, - 'setup_requires': parse_list_semicolon, - 'tests_require': parse_list_semicolon, - 'packages': self._parse_packages, - 'entry_points': self._parse_file, - 'py_modules': parse_list, - } - - def _parse_packages(self, value): - """Parses `packages` option value. - - :param value: - :rtype: list - """ - find_directives = ['find:', 'find_namespace:'] - trimmed_value = value.strip() - - if trimmed_value not in find_directives: - return self._parse_list(value) - - findns = trimmed_value == find_directives[1] - if findns and not PY3: - raise DistutilsOptionError( - 'find_namespace: directive is unsupported on Python < 3.3') - - # Read function arguments from a dedicated section. - find_kwargs = self.parse_section_packages__find( - self.sections.get('packages.find', {})) - - if findns: - from setuptools import find_namespace_packages as find_packages - else: - from setuptools import find_packages - - return find_packages(**find_kwargs) - - def parse_section_packages__find(self, section_options): - """Parses `packages.find` configuration file section. - - To be used in conjunction with _parse_packages(). - - :param dict section_options: - """ - section_data = self._parse_section_to_dict( - section_options, self._parse_list) - - valid_keys = ['where', 'include', 'exclude'] - - find_kwargs = dict( - [(k, v) for k, v in section_data.items() if k in valid_keys and v]) - - where = find_kwargs.get('where') - if where is not None: - find_kwargs['where'] = where[0] # cast list to single val - - return find_kwargs - - def parse_section_entry_points(self, section_options): - """Parses `entry_points` configuration file section. - - :param dict section_options: - """ - parsed = self._parse_section_to_dict(section_options, self._parse_list) - self['entry_points'] = parsed - - def _parse_package_data(self, section_options): - parsed = self._parse_section_to_dict(section_options, self._parse_list) - - root = parsed.get('*') - if root: - parsed[''] = root - del parsed['*'] - - return parsed - - def parse_section_package_data(self, section_options): - """Parses `package_data` configuration file section. - - :param dict section_options: - """ - self['package_data'] = self._parse_package_data(section_options) - - def parse_section_exclude_package_data(self, section_options): - """Parses `exclude_package_data` configuration file section. - - :param dict section_options: - """ - self['exclude_package_data'] = self._parse_package_data( - section_options) - - def parse_section_extras_require(self, section_options): - """Parses `extras_require` configuration file section. - - :param dict section_options: - """ - parse_list = partial(self._parse_list, separator=';') - self['extras_require'] = self._parse_section_to_dict( - section_options, parse_list) - - def parse_section_data_files(self, section_options): - """Parses `data_files` configuration file section. - - :param dict section_options: - """ - parsed = self._parse_section_to_dict(section_options, self._parse_list) - self['data_files'] = [(k, v) for k, v in parsed.items()] diff --git a/venv2/lib/python2.7/site-packages/setuptools/dep_util.py b/venv2/lib/python2.7/site-packages/setuptools/dep_util.py deleted file mode 100644 index 2931c13..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/dep_util.py +++ /dev/null @@ -1,23 +0,0 @@ -from distutils.dep_util import newer_group - -# yes, this is was almost entirely copy-pasted from -# 'newer_pairwise()', this is just another convenience -# function. -def newer_pairwise_group(sources_groups, targets): - """Walk both arguments in parallel, testing if each source group is newer - than its corresponding target. Returns a pair of lists (sources_groups, - targets) where sources is newer than target, according to the semantics - of 'newer_group()'. - """ - if len(sources_groups) != len(targets): - raise ValueError("'sources_group' and 'targets' must be the same length") - - # build a pair of lists (sources_groups, targets) where source is newer - n_sources = [] - n_targets = [] - for i in range(len(sources_groups)): - if newer_group(sources_groups[i], targets[i]): - n_sources.append(sources_groups[i]) - n_targets.append(targets[i]) - - return n_sources, n_targets diff --git a/venv2/lib/python2.7/site-packages/setuptools/depends.py b/venv2/lib/python2.7/site-packages/setuptools/depends.py deleted file mode 100644 index 45e7052..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/depends.py +++ /dev/null @@ -1,186 +0,0 @@ -import sys -import imp -import marshal -from distutils.version import StrictVersion -from imp import PKG_DIRECTORY, PY_COMPILED, PY_SOURCE, PY_FROZEN - -from .py33compat import Bytecode - - -__all__ = [ - 'Require', 'find_module', 'get_module_constant', 'extract_constant' -] - - -class Require: - """A prerequisite to building or installing a distribution""" - - def __init__(self, name, requested_version, module, homepage='', - attribute=None, format=None): - - if format is None and requested_version is not None: - format = StrictVersion - - if format is not None: - requested_version = format(requested_version) - if attribute is None: - attribute = '__version__' - - self.__dict__.update(locals()) - del self.self - - def full_name(self): - """Return full package/distribution name, w/version""" - if self.requested_version is not None: - return '%s-%s' % (self.name, self.requested_version) - return self.name - - def version_ok(self, version): - """Is 'version' sufficiently up-to-date?""" - return self.attribute is None or self.format is None or \ - str(version) != "unknown" and version >= self.requested_version - - def get_version(self, paths=None, default="unknown"): - """Get version number of installed module, 'None', or 'default' - - Search 'paths' for module. If not found, return 'None'. If found, - return the extracted version attribute, or 'default' if no version - attribute was specified, or the value cannot be determined without - importing the module. The version is formatted according to the - requirement's version format (if any), unless it is 'None' or the - supplied 'default'. - """ - - if self.attribute is None: - try: - f, p, i = find_module(self.module, paths) - if f: - f.close() - return default - except ImportError: - return None - - v = get_module_constant(self.module, self.attribute, default, paths) - - if v is not None and v is not default and self.format is not None: - return self.format(v) - - return v - - def is_present(self, paths=None): - """Return true if dependency is present on 'paths'""" - return self.get_version(paths) is not None - - def is_current(self, paths=None): - """Return true if dependency is present and up-to-date on 'paths'""" - version = self.get_version(paths) - if version is None: - return False - return self.version_ok(version) - - -def find_module(module, paths=None): - """Just like 'imp.find_module()', but with package support""" - - parts = module.split('.') - - while parts: - part = parts.pop(0) - f, path, (suffix, mode, kind) = info = imp.find_module(part, paths) - - if kind == PKG_DIRECTORY: - parts = parts or ['__init__'] - paths = [path] - - elif parts: - raise ImportError("Can't find %r in %s" % (parts, module)) - - return info - - -def get_module_constant(module, symbol, default=-1, paths=None): - """Find 'module' by searching 'paths', and extract 'symbol' - - Return 'None' if 'module' does not exist on 'paths', or it does not define - 'symbol'. If the module defines 'symbol' as a constant, return the - constant. Otherwise, return 'default'.""" - - try: - f, path, (suffix, mode, kind) = find_module(module, paths) - except ImportError: - # Module doesn't exist - return None - - try: - if kind == PY_COMPILED: - f.read(8) # skip magic & date - code = marshal.load(f) - elif kind == PY_FROZEN: - code = imp.get_frozen_object(module) - elif kind == PY_SOURCE: - code = compile(f.read(), path, 'exec') - else: - # Not something we can parse; we'll have to import it. :( - if module not in sys.modules: - imp.load_module(module, f, path, (suffix, mode, kind)) - return getattr(sys.modules[module], symbol, None) - - finally: - if f: - f.close() - - return extract_constant(code, symbol, default) - - -def extract_constant(code, symbol, default=-1): - """Extract the constant value of 'symbol' from 'code' - - If the name 'symbol' is bound to a constant value by the Python code - object 'code', return that value. If 'symbol' is bound to an expression, - return 'default'. Otherwise, return 'None'. - - Return value is based on the first assignment to 'symbol'. 'symbol' must - be a global, or at least a non-"fast" local in the code block. That is, - only 'STORE_NAME' and 'STORE_GLOBAL' opcodes are checked, and 'symbol' - must be present in 'code.co_names'. - """ - if symbol not in code.co_names: - # name's not there, can't possibly be an assignment - return None - - name_idx = list(code.co_names).index(symbol) - - STORE_NAME = 90 - STORE_GLOBAL = 97 - LOAD_CONST = 100 - - const = default - - for byte_code in Bytecode(code): - op = byte_code.opcode - arg = byte_code.arg - - if op == LOAD_CONST: - const = code.co_consts[arg] - elif arg == name_idx and (op == STORE_NAME or op == STORE_GLOBAL): - return const - else: - const = default - - -def _update_globals(): - """ - Patch the globals to remove the objects not available on some platforms. - - XXX it'd be better to test assertions about bytecode instead. - """ - - if not sys.platform.startswith('java') and sys.platform != 'cli': - return - incompatible = 'extract_constant', 'get_module_constant' - for name in incompatible: - del globals()[name] - __all__.remove(name) - - -_update_globals() diff --git a/venv2/lib/python2.7/site-packages/setuptools/dist.py b/venv2/lib/python2.7/site-packages/setuptools/dist.py deleted file mode 100644 index 9a165de..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/dist.py +++ /dev/null @@ -1,1278 +0,0 @@ -# -*- coding: utf-8 -*- -__all__ = ['Distribution'] - -import io -import sys -import re -import os -import warnings -import numbers -import distutils.log -import distutils.core -import distutils.cmd -import distutils.dist -from distutils.util import strtobool -from distutils.debug import DEBUG -from distutils.fancy_getopt import translate_longopt -import itertools - -from collections import defaultdict -from email import message_from_file - -from distutils.errors import ( - DistutilsOptionError, DistutilsPlatformError, DistutilsSetupError, -) -from distutils.util import rfc822_escape -from distutils.version import StrictVersion - -from setuptools.extern import six -from setuptools.extern import packaging -from setuptools.extern.six.moves import map, filter, filterfalse - -from . import SetuptoolsDeprecationWarning - -from setuptools.depends import Require -from setuptools import windows_support -from setuptools.monkey import get_unpatched -from setuptools.config import parse_configuration -import pkg_resources - -__import__('setuptools.extern.packaging.specifiers') -__import__('setuptools.extern.packaging.version') - - -def _get_unpatched(cls): - warnings.warn("Do not call this function", DistDeprecationWarning) - return get_unpatched(cls) - - -def get_metadata_version(self): - mv = getattr(self, 'metadata_version', None) - - if mv is None: - if self.long_description_content_type or self.provides_extras: - mv = StrictVersion('2.1') - elif (self.maintainer is not None or - self.maintainer_email is not None or - getattr(self, 'python_requires', None) is not None): - mv = StrictVersion('1.2') - elif (self.provides or self.requires or self.obsoletes or - self.classifiers or self.download_url): - mv = StrictVersion('1.1') - else: - mv = StrictVersion('1.0') - - self.metadata_version = mv - - return mv - - -def read_pkg_file(self, file): - """Reads the metadata values from a file object.""" - msg = message_from_file(file) - - def _read_field(name): - value = msg[name] - if value == 'UNKNOWN': - return None - return value - - def _read_list(name): - values = msg.get_all(name, None) - if values == []: - return None - return values - - self.metadata_version = StrictVersion(msg['metadata-version']) - self.name = _read_field('name') - self.version = _read_field('version') - self.description = _read_field('summary') - # we are filling author only. - self.author = _read_field('author') - self.maintainer = None - self.author_email = _read_field('author-email') - self.maintainer_email = None - self.url = _read_field('home-page') - self.license = _read_field('license') - - if 'download-url' in msg: - self.download_url = _read_field('download-url') - else: - self.download_url = None - - self.long_description = _read_field('description') - self.description = _read_field('summary') - - if 'keywords' in msg: - self.keywords = _read_field('keywords').split(',') - - self.platforms = _read_list('platform') - self.classifiers = _read_list('classifier') - - # PEP 314 - these fields only exist in 1.1 - if self.metadata_version == StrictVersion('1.1'): - self.requires = _read_list('requires') - self.provides = _read_list('provides') - self.obsoletes = _read_list('obsoletes') - else: - self.requires = None - self.provides = None - self.obsoletes = None - - -# Based on Python 3.5 version -def write_pkg_file(self, file): - """Write the PKG-INFO format data to a file object. - """ - version = self.get_metadata_version() - - if six.PY2: - def write_field(key, value): - file.write("%s: %s\n" % (key, self._encode_field(value))) - else: - def write_field(key, value): - file.write("%s: %s\n" % (key, value)) - - write_field('Metadata-Version', str(version)) - write_field('Name', self.get_name()) - write_field('Version', self.get_version()) - write_field('Summary', self.get_description()) - write_field('Home-page', self.get_url()) - - if version < StrictVersion('1.2'): - write_field('Author', self.get_contact()) - write_field('Author-email', self.get_contact_email()) - else: - optional_fields = ( - ('Author', 'author'), - ('Author-email', 'author_email'), - ('Maintainer', 'maintainer'), - ('Maintainer-email', 'maintainer_email'), - ) - - for field, attr in optional_fields: - attr_val = getattr(self, attr) - - if attr_val is not None: - write_field(field, attr_val) - - write_field('License', self.get_license()) - if self.download_url: - write_field('Download-URL', self.download_url) - for project_url in self.project_urls.items(): - write_field('Project-URL', '%s, %s' % project_url) - - long_desc = rfc822_escape(self.get_long_description()) - write_field('Description', long_desc) - - keywords = ','.join(self.get_keywords()) - if keywords: - write_field('Keywords', keywords) - - if version >= StrictVersion('1.2'): - for platform in self.get_platforms(): - write_field('Platform', platform) - else: - self._write_list(file, 'Platform', self.get_platforms()) - - self._write_list(file, 'Classifier', self.get_classifiers()) - - # PEP 314 - self._write_list(file, 'Requires', self.get_requires()) - self._write_list(file, 'Provides', self.get_provides()) - self._write_list(file, 'Obsoletes', self.get_obsoletes()) - - # Setuptools specific for PEP 345 - if hasattr(self, 'python_requires'): - write_field('Requires-Python', self.python_requires) - - # PEP 566 - if self.long_description_content_type: - write_field( - 'Description-Content-Type', - self.long_description_content_type - ) - if self.provides_extras: - for extra in self.provides_extras: - write_field('Provides-Extra', extra) - - -sequence = tuple, list - - -def check_importable(dist, attr, value): - try: - ep = pkg_resources.EntryPoint.parse('x=' + value) - assert not ep.extras - except (TypeError, ValueError, AttributeError, AssertionError): - raise DistutilsSetupError( - "%r must be importable 'module:attrs' string (got %r)" - % (attr, value) - ) - - -def assert_string_list(dist, attr, value): - """Verify that value is a string list or None""" - try: - assert ''.join(value) != value - except (TypeError, ValueError, AttributeError, AssertionError): - raise DistutilsSetupError( - "%r must be a list of strings (got %r)" % (attr, value) - ) - - -def check_nsp(dist, attr, value): - """Verify that namespace packages are valid""" - ns_packages = value - assert_string_list(dist, attr, ns_packages) - for nsp in ns_packages: - if not dist.has_contents_for(nsp): - raise DistutilsSetupError( - "Distribution contains no modules or packages for " + - "namespace package %r" % nsp - ) - parent, sep, child = nsp.rpartition('.') - if parent and parent not in ns_packages: - distutils.log.warn( - "WARNING: %r is declared as a package namespace, but %r" - " is not: please correct this in setup.py", nsp, parent - ) - - -def check_extras(dist, attr, value): - """Verify that extras_require mapping is valid""" - try: - list(itertools.starmap(_check_extra, value.items())) - except (TypeError, ValueError, AttributeError): - raise DistutilsSetupError( - "'extras_require' must be a dictionary whose values are " - "strings or lists of strings containing valid project/version " - "requirement specifiers." - ) - - -def _check_extra(extra, reqs): - name, sep, marker = extra.partition(':') - if marker and pkg_resources.invalid_marker(marker): - raise DistutilsSetupError("Invalid environment marker: " + marker) - list(pkg_resources.parse_requirements(reqs)) - - -def assert_bool(dist, attr, value): - """Verify that value is True, False, 0, or 1""" - if bool(value) != value: - tmpl = "{attr!r} must be a boolean value (got {value!r})" - raise DistutilsSetupError(tmpl.format(attr=attr, value=value)) - - -def check_requirements(dist, attr, value): - """Verify that install_requires is a valid requirements list""" - try: - list(pkg_resources.parse_requirements(value)) - if isinstance(value, (dict, set)): - raise TypeError("Unordered types are not allowed") - except (TypeError, ValueError) as error: - tmpl = ( - "{attr!r} must be a string or list of strings " - "containing valid project/version requirement specifiers; {error}" - ) - raise DistutilsSetupError(tmpl.format(attr=attr, error=error)) - - -def check_specifier(dist, attr, value): - """Verify that value is a valid version specifier""" - try: - packaging.specifiers.SpecifierSet(value) - except packaging.specifiers.InvalidSpecifier as error: - tmpl = ( - "{attr!r} must be a string " - "containing valid version specifiers; {error}" - ) - raise DistutilsSetupError(tmpl.format(attr=attr, error=error)) - - -def check_entry_points(dist, attr, value): - """Verify that entry_points map is parseable""" - try: - pkg_resources.EntryPoint.parse_map(value) - except ValueError as e: - raise DistutilsSetupError(e) - - -def check_test_suite(dist, attr, value): - if not isinstance(value, six.string_types): - raise DistutilsSetupError("test_suite must be a string") - - -def check_package_data(dist, attr, value): - """Verify that value is a dictionary of package names to glob lists""" - if isinstance(value, dict): - for k, v in value.items(): - if not isinstance(k, str): - break - try: - iter(v) - except TypeError: - break - else: - return - raise DistutilsSetupError( - attr + " must be a dictionary mapping package names to lists of " - "wildcard patterns" - ) - - -def check_packages(dist, attr, value): - for pkgname in value: - if not re.match(r'\w+(\.\w+)*', pkgname): - distutils.log.warn( - "WARNING: %r not a valid package name; please use only " - ".-separated package names in setup.py", pkgname - ) - - -_Distribution = get_unpatched(distutils.core.Distribution) - - -class Distribution(_Distribution): - """Distribution with support for features, tests, and package data - - This is an enhanced version of 'distutils.dist.Distribution' that - effectively adds the following new optional keyword arguments to 'setup()': - - 'install_requires' -- a string or sequence of strings specifying project - versions that the distribution requires when installed, in the format - used by 'pkg_resources.require()'. They will be installed - automatically when the package is installed. If you wish to use - packages that are not available in PyPI, or want to give your users an - alternate download location, you can add a 'find_links' option to the - '[easy_install]' section of your project's 'setup.cfg' file, and then - setuptools will scan the listed web pages for links that satisfy the - requirements. - - 'extras_require' -- a dictionary mapping names of optional "extras" to the - additional requirement(s) that using those extras incurs. For example, - this:: - - extras_require = dict(reST = ["docutils>=0.3", "reSTedit"]) - - indicates that the distribution can optionally provide an extra - capability called "reST", but it can only be used if docutils and - reSTedit are installed. If the user installs your package using - EasyInstall and requests one of your extras, the corresponding - additional requirements will be installed if needed. - - 'features' **deprecated** -- a dictionary mapping option names to - 'setuptools.Feature' - objects. Features are a portion of the distribution that can be - included or excluded based on user options, inter-feature dependencies, - and availability on the current system. Excluded features are omitted - from all setup commands, including source and binary distributions, so - you can create multiple distributions from the same source tree. - Feature names should be valid Python identifiers, except that they may - contain the '-' (minus) sign. Features can be included or excluded - via the command line options '--with-X' and '--without-X', where 'X' is - the name of the feature. Whether a feature is included by default, and - whether you are allowed to control this from the command line, is - determined by the Feature object. See the 'Feature' class for more - information. - - 'test_suite' -- the name of a test suite to run for the 'test' command. - If the user runs 'python setup.py test', the package will be installed, - and the named test suite will be run. The format is the same as - would be used on a 'unittest.py' command line. That is, it is the - dotted name of an object to import and call to generate a test suite. - - 'package_data' -- a dictionary mapping package names to lists of filenames - or globs to use to find data files contained in the named packages. - If the dictionary has filenames or globs listed under '""' (the empty - string), those names will be searched for in every package, in addition - to any names for the specific package. Data files found using these - names/globs will be installed along with the package, in the same - location as the package. Note that globs are allowed to reference - the contents of non-package subdirectories, as long as you use '/' as - a path separator. (Globs are automatically converted to - platform-specific paths at runtime.) - - In addition to these new keywords, this class also has several new methods - for manipulating the distribution's contents. For example, the 'include()' - and 'exclude()' methods can be thought of as in-place add and subtract - commands that add or remove packages, modules, extensions, and so on from - the distribution. They are used by the feature subsystem to configure the - distribution for the included and excluded features. - """ - - _DISTUTILS_UNSUPPORTED_METADATA = { - 'long_description_content_type': None, - 'project_urls': dict, - 'provides_extras': set, - } - - _patched_dist = None - - def patch_missing_pkg_info(self, attrs): - # Fake up a replacement for the data that would normally come from - # PKG-INFO, but which might not yet be built if this is a fresh - # checkout. - # - if not attrs or 'name' not in attrs or 'version' not in attrs: - return - key = pkg_resources.safe_name(str(attrs['name'])).lower() - dist = pkg_resources.working_set.by_key.get(key) - if dist is not None and not dist.has_metadata('PKG-INFO'): - dist._version = pkg_resources.safe_version(str(attrs['version'])) - self._patched_dist = dist - - def __init__(self, attrs=None): - have_package_data = hasattr(self, "package_data") - if not have_package_data: - self.package_data = {} - attrs = attrs or {} - if 'features' in attrs or 'require_features' in attrs: - Feature.warn_deprecated() - self.require_features = [] - self.features = {} - self.dist_files = [] - # Filter-out setuptools' specific options. - self.src_root = attrs.pop("src_root", None) - self.patch_missing_pkg_info(attrs) - self.dependency_links = attrs.pop('dependency_links', []) - self.setup_requires = attrs.pop('setup_requires', []) - for ep in pkg_resources.iter_entry_points('distutils.setup_keywords'): - vars(self).setdefault(ep.name, None) - _Distribution.__init__(self, { - k: v for k, v in attrs.items() - if k not in self._DISTUTILS_UNSUPPORTED_METADATA - }) - - # Fill-in missing metadata fields not supported by distutils. - # Note some fields may have been set by other tools (e.g. pbr) - # above; they are taken preferrentially to setup() arguments - for option, default in self._DISTUTILS_UNSUPPORTED_METADATA.items(): - for source in self.metadata.__dict__, attrs: - if option in source: - value = source[option] - break - else: - value = default() if default else None - setattr(self.metadata, option, value) - - if isinstance(self.metadata.version, numbers.Number): - # Some people apparently take "version number" too literally :) - self.metadata.version = str(self.metadata.version) - - if self.metadata.version is not None: - try: - ver = packaging.version.Version(self.metadata.version) - normalized_version = str(ver) - if self.metadata.version != normalized_version: - warnings.warn( - "Normalizing '%s' to '%s'" % ( - self.metadata.version, - normalized_version, - ) - ) - self.metadata.version = normalized_version - except (packaging.version.InvalidVersion, TypeError): - warnings.warn( - "The version specified (%r) is an invalid version, this " - "may not work as expected with newer versions of " - "setuptools, pip, and PyPI. Please see PEP 440 for more " - "details." % self.metadata.version - ) - self._finalize_requires() - - def _finalize_requires(self): - """ - Set `metadata.python_requires` and fix environment markers - in `install_requires` and `extras_require`. - """ - if getattr(self, 'python_requires', None): - self.metadata.python_requires = self.python_requires - - if getattr(self, 'extras_require', None): - for extra in self.extras_require.keys(): - # Since this gets called multiple times at points where the - # keys have become 'converted' extras, ensure that we are only - # truly adding extras we haven't seen before here. - extra = extra.split(':')[0] - if extra: - self.metadata.provides_extras.add(extra) - - self._convert_extras_requirements() - self._move_install_requirements_markers() - - def _convert_extras_requirements(self): - """ - Convert requirements in `extras_require` of the form - `"extra": ["barbazquux; {marker}"]` to - `"extra:{marker}": ["barbazquux"]`. - """ - spec_ext_reqs = getattr(self, 'extras_require', None) or {} - self._tmp_extras_require = defaultdict(list) - for section, v in spec_ext_reqs.items(): - # Do not strip empty sections. - self._tmp_extras_require[section] - for r in pkg_resources.parse_requirements(v): - suffix = self._suffix_for(r) - self._tmp_extras_require[section + suffix].append(r) - - @staticmethod - def _suffix_for(req): - """ - For a requirement, return the 'extras_require' suffix for - that requirement. - """ - return ':' + str(req.marker) if req.marker else '' - - def _move_install_requirements_markers(self): - """ - Move requirements in `install_requires` that are using environment - markers `extras_require`. - """ - - # divide the install_requires into two sets, simple ones still - # handled by install_requires and more complex ones handled - # by extras_require. - - def is_simple_req(req): - return not req.marker - - spec_inst_reqs = getattr(self, 'install_requires', None) or () - inst_reqs = list(pkg_resources.parse_requirements(spec_inst_reqs)) - simple_reqs = filter(is_simple_req, inst_reqs) - complex_reqs = filterfalse(is_simple_req, inst_reqs) - self.install_requires = list(map(str, simple_reqs)) - - for r in complex_reqs: - self._tmp_extras_require[':' + str(r.marker)].append(r) - self.extras_require = dict( - (k, [str(r) for r in map(self._clean_req, v)]) - for k, v in self._tmp_extras_require.items() - ) - - def _clean_req(self, req): - """ - Given a Requirement, remove environment markers and return it. - """ - req.marker = None - return req - - def _parse_config_files(self, filenames=None): - """ - Adapted from distutils.dist.Distribution.parse_config_files, - this method provides the same functionality in subtly-improved - ways. - """ - from setuptools.extern.six.moves.configparser import ConfigParser - - # Ignore install directory options if we have a venv - if six.PY3 and sys.prefix != sys.base_prefix: - ignore_options = [ - 'install-base', 'install-platbase', 'install-lib', - 'install-platlib', 'install-purelib', 'install-headers', - 'install-scripts', 'install-data', 'prefix', 'exec-prefix', - 'home', 'user', 'root'] - else: - ignore_options = [] - - ignore_options = frozenset(ignore_options) - - if filenames is None: - filenames = self.find_config_files() - - if DEBUG: - self.announce("Distribution.parse_config_files():") - - parser = ConfigParser() - for filename in filenames: - with io.open(filename, encoding='utf-8') as reader: - if DEBUG: - self.announce(" reading {filename}".format(**locals())) - (parser.read_file if six.PY3 else parser.readfp)(reader) - for section in parser.sections(): - options = parser.options(section) - opt_dict = self.get_option_dict(section) - - for opt in options: - if opt != '__name__' and opt not in ignore_options: - val = self._try_str(parser.get(section, opt)) - opt = opt.replace('-', '_') - opt_dict[opt] = (filename, val) - - # Make the ConfigParser forget everything (so we retain - # the original filenames that options come from) - parser.__init__() - - # If there was a "global" section in the config file, use it - # to set Distribution options. - - if 'global' in self.command_options: - for (opt, (src, val)) in self.command_options['global'].items(): - alias = self.negative_opt.get(opt) - try: - if alias: - setattr(self, alias, not strtobool(val)) - elif opt in ('verbose', 'dry_run'): # ugh! - setattr(self, opt, strtobool(val)) - else: - setattr(self, opt, val) - except ValueError as msg: - raise DistutilsOptionError(msg) - - @staticmethod - def _try_str(val): - """ - On Python 2, much of distutils relies on string values being of - type 'str' (bytes) and not unicode text. If the value can be safely - encoded to bytes using the default encoding, prefer that. - - Why the default encoding? Because that value can be implicitly - decoded back to text if needed. - - Ref #1653 - """ - if six.PY3: - return val - try: - return val.encode() - except UnicodeEncodeError: - pass - return val - - def _set_command_options(self, command_obj, option_dict=None): - """ - Set the options for 'command_obj' from 'option_dict'. Basically - this means copying elements of a dictionary ('option_dict') to - attributes of an instance ('command'). - - 'command_obj' must be a Command instance. If 'option_dict' is not - supplied, uses the standard option dictionary for this command - (from 'self.command_options'). - - (Adopted from distutils.dist.Distribution._set_command_options) - """ - command_name = command_obj.get_command_name() - if option_dict is None: - option_dict = self.get_option_dict(command_name) - - if DEBUG: - self.announce(" setting options for '%s' command:" % command_name) - for (option, (source, value)) in option_dict.items(): - if DEBUG: - self.announce(" %s = %s (from %s)" % (option, value, - source)) - try: - bool_opts = [translate_longopt(o) - for o in command_obj.boolean_options] - except AttributeError: - bool_opts = [] - try: - neg_opt = command_obj.negative_opt - except AttributeError: - neg_opt = {} - - try: - is_string = isinstance(value, six.string_types) - if option in neg_opt and is_string: - setattr(command_obj, neg_opt[option], not strtobool(value)) - elif option in bool_opts and is_string: - setattr(command_obj, option, strtobool(value)) - elif hasattr(command_obj, option): - setattr(command_obj, option, value) - else: - raise DistutilsOptionError( - "error in %s: command '%s' has no such option '%s'" - % (source, command_name, option)) - except ValueError as msg: - raise DistutilsOptionError(msg) - - def parse_config_files(self, filenames=None, ignore_option_errors=False): - """Parses configuration files from various levels - and loads configuration. - - """ - self._parse_config_files(filenames=filenames) - - parse_configuration(self, self.command_options, - ignore_option_errors=ignore_option_errors) - self._finalize_requires() - - def parse_command_line(self): - """Process features after parsing command line options""" - result = _Distribution.parse_command_line(self) - if self.features: - self._finalize_features() - return result - - def _feature_attrname(self, name): - """Convert feature name to corresponding option attribute name""" - return 'with_' + name.replace('-', '_') - - def fetch_build_eggs(self, requires): - """Resolve pre-setup requirements""" - resolved_dists = pkg_resources.working_set.resolve( - pkg_resources.parse_requirements(requires), - installer=self.fetch_build_egg, - replace_conflicting=True, - ) - for dist in resolved_dists: - pkg_resources.working_set.add(dist, replace=True) - return resolved_dists - - def finalize_options(self): - _Distribution.finalize_options(self) - if self.features: - self._set_global_opts_from_features() - - for ep in pkg_resources.iter_entry_points('distutils.setup_keywords'): - value = getattr(self, ep.name, None) - if value is not None: - ep.require(installer=self.fetch_build_egg) - ep.load()(self, ep.name, value) - if getattr(self, 'convert_2to3_doctests', None): - # XXX may convert to set here when we can rely on set being builtin - self.convert_2to3_doctests = [ - os.path.abspath(p) - for p in self.convert_2to3_doctests - ] - else: - self.convert_2to3_doctests = [] - - def get_egg_cache_dir(self): - egg_cache_dir = os.path.join(os.curdir, '.eggs') - if not os.path.exists(egg_cache_dir): - os.mkdir(egg_cache_dir) - windows_support.hide_file(egg_cache_dir) - readme_txt_filename = os.path.join(egg_cache_dir, 'README.txt') - with open(readme_txt_filename, 'w') as f: - f.write('This directory contains eggs that were downloaded ' - 'by setuptools to build, test, and run plug-ins.\n\n') - f.write('This directory caches those eggs to prevent ' - 'repeated downloads.\n\n') - f.write('However, it is safe to delete this directory.\n\n') - - return egg_cache_dir - - def fetch_build_egg(self, req): - """Fetch an egg needed for building""" - from setuptools.command.easy_install import easy_install - dist = self.__class__({'script_args': ['easy_install']}) - opts = dist.get_option_dict('easy_install') - opts.clear() - opts.update( - (k, v) - for k, v in self.get_option_dict('easy_install').items() - if k in ( - # don't use any other settings - 'find_links', 'site_dirs', 'index_url', - 'optimize', 'site_dirs', 'allow_hosts', - )) - if self.dependency_links: - links = self.dependency_links[:] - if 'find_links' in opts: - links = opts['find_links'][1] + links - opts['find_links'] = ('setup', links) - install_dir = self.get_egg_cache_dir() - cmd = easy_install( - dist, args=["x"], install_dir=install_dir, - exclude_scripts=True, - always_copy=False, build_directory=None, editable=False, - upgrade=False, multi_version=True, no_report=True, user=False - ) - cmd.ensure_finalized() - return cmd.easy_install(req) - - def _set_global_opts_from_features(self): - """Add --with-X/--without-X options based on optional features""" - - go = [] - no = self.negative_opt.copy() - - for name, feature in self.features.items(): - self._set_feature(name, None) - feature.validate(self) - - if feature.optional: - descr = feature.description - incdef = ' (default)' - excdef = '' - if not feature.include_by_default(): - excdef, incdef = incdef, excdef - - new = ( - ('with-' + name, None, 'include ' + descr + incdef), - ('without-' + name, None, 'exclude ' + descr + excdef), - ) - go.extend(new) - no['without-' + name] = 'with-' + name - - self.global_options = self.feature_options = go + self.global_options - self.negative_opt = self.feature_negopt = no - - def _finalize_features(self): - """Add/remove features and resolve dependencies between them""" - - # First, flag all the enabled items (and thus their dependencies) - for name, feature in self.features.items(): - enabled = self.feature_is_included(name) - if enabled or (enabled is None and feature.include_by_default()): - feature.include_in(self) - self._set_feature(name, 1) - - # Then disable the rest, so that off-by-default features don't - # get flagged as errors when they're required by an enabled feature - for name, feature in self.features.items(): - if not self.feature_is_included(name): - feature.exclude_from(self) - self._set_feature(name, 0) - - def get_command_class(self, command): - """Pluggable version of get_command_class()""" - if command in self.cmdclass: - return self.cmdclass[command] - - eps = pkg_resources.iter_entry_points('distutils.commands', command) - for ep in eps: - ep.require(installer=self.fetch_build_egg) - self.cmdclass[command] = cmdclass = ep.load() - return cmdclass - else: - return _Distribution.get_command_class(self, command) - - def print_commands(self): - for ep in pkg_resources.iter_entry_points('distutils.commands'): - if ep.name not in self.cmdclass: - # don't require extras as the commands won't be invoked - cmdclass = ep.resolve() - self.cmdclass[ep.name] = cmdclass - return _Distribution.print_commands(self) - - def get_command_list(self): - for ep in pkg_resources.iter_entry_points('distutils.commands'): - if ep.name not in self.cmdclass: - # don't require extras as the commands won't be invoked - cmdclass = ep.resolve() - self.cmdclass[ep.name] = cmdclass - return _Distribution.get_command_list(self) - - def _set_feature(self, name, status): - """Set feature's inclusion status""" - setattr(self, self._feature_attrname(name), status) - - def feature_is_included(self, name): - """Return 1 if feature is included, 0 if excluded, 'None' if unknown""" - return getattr(self, self._feature_attrname(name)) - - def include_feature(self, name): - """Request inclusion of feature named 'name'""" - - if self.feature_is_included(name) == 0: - descr = self.features[name].description - raise DistutilsOptionError( - descr + " is required, but was excluded or is not available" - ) - self.features[name].include_in(self) - self._set_feature(name, 1) - - def include(self, **attrs): - """Add items to distribution that are named in keyword arguments - - For example, 'dist.include(py_modules=["x"])' would add 'x' to - the distribution's 'py_modules' attribute, if it was not already - there. - - Currently, this method only supports inclusion for attributes that are - lists or tuples. If you need to add support for adding to other - attributes in this or a subclass, you can add an '_include_X' method, - where 'X' is the name of the attribute. The method will be called with - the value passed to 'include()'. So, 'dist.include(foo={"bar":"baz"})' - will try to call 'dist._include_foo({"bar":"baz"})', which can then - handle whatever special inclusion logic is needed. - """ - for k, v in attrs.items(): - include = getattr(self, '_include_' + k, None) - if include: - include(v) - else: - self._include_misc(k, v) - - def exclude_package(self, package): - """Remove packages, modules, and extensions in named package""" - - pfx = package + '.' - if self.packages: - self.packages = [ - p for p in self.packages - if p != package and not p.startswith(pfx) - ] - - if self.py_modules: - self.py_modules = [ - p for p in self.py_modules - if p != package and not p.startswith(pfx) - ] - - if self.ext_modules: - self.ext_modules = [ - p for p in self.ext_modules - if p.name != package and not p.name.startswith(pfx) - ] - - def has_contents_for(self, package): - """Return true if 'exclude_package(package)' would do something""" - - pfx = package + '.' - - for p in self.iter_distribution_names(): - if p == package or p.startswith(pfx): - return True - - def _exclude_misc(self, name, value): - """Handle 'exclude()' for list/tuple attrs without a special handler""" - if not isinstance(value, sequence): - raise DistutilsSetupError( - "%s: setting must be a list or tuple (%r)" % (name, value) - ) - try: - old = getattr(self, name) - except AttributeError: - raise DistutilsSetupError( - "%s: No such distribution setting" % name - ) - if old is not None and not isinstance(old, sequence): - raise DistutilsSetupError( - name + ": this setting cannot be changed via include/exclude" - ) - elif old: - setattr(self, name, [item for item in old if item not in value]) - - def _include_misc(self, name, value): - """Handle 'include()' for list/tuple attrs without a special handler""" - - if not isinstance(value, sequence): - raise DistutilsSetupError( - "%s: setting must be a list (%r)" % (name, value) - ) - try: - old = getattr(self, name) - except AttributeError: - raise DistutilsSetupError( - "%s: No such distribution setting" % name - ) - if old is None: - setattr(self, name, value) - elif not isinstance(old, sequence): - raise DistutilsSetupError( - name + ": this setting cannot be changed via include/exclude" - ) - else: - new = [item for item in value if item not in old] - setattr(self, name, old + new) - - def exclude(self, **attrs): - """Remove items from distribution that are named in keyword arguments - - For example, 'dist.exclude(py_modules=["x"])' would remove 'x' from - the distribution's 'py_modules' attribute. Excluding packages uses - the 'exclude_package()' method, so all of the package's contained - packages, modules, and extensions are also excluded. - - Currently, this method only supports exclusion from attributes that are - lists or tuples. If you need to add support for excluding from other - attributes in this or a subclass, you can add an '_exclude_X' method, - where 'X' is the name of the attribute. The method will be called with - the value passed to 'exclude()'. So, 'dist.exclude(foo={"bar":"baz"})' - will try to call 'dist._exclude_foo({"bar":"baz"})', which can then - handle whatever special exclusion logic is needed. - """ - for k, v in attrs.items(): - exclude = getattr(self, '_exclude_' + k, None) - if exclude: - exclude(v) - else: - self._exclude_misc(k, v) - - def _exclude_packages(self, packages): - if not isinstance(packages, sequence): - raise DistutilsSetupError( - "packages: setting must be a list or tuple (%r)" % (packages,) - ) - list(map(self.exclude_package, packages)) - - def _parse_command_opts(self, parser, args): - # Remove --with-X/--without-X options when processing command args - self.global_options = self.__class__.global_options - self.negative_opt = self.__class__.negative_opt - - # First, expand any aliases - command = args[0] - aliases = self.get_option_dict('aliases') - while command in aliases: - src, alias = aliases[command] - del aliases[command] # ensure each alias can expand only once! - import shlex - args[:1] = shlex.split(alias, True) - command = args[0] - - nargs = _Distribution._parse_command_opts(self, parser, args) - - # Handle commands that want to consume all remaining arguments - cmd_class = self.get_command_class(command) - if getattr(cmd_class, 'command_consumes_arguments', None): - self.get_option_dict(command)['args'] = ("command line", nargs) - if nargs is not None: - return [] - - return nargs - - def get_cmdline_options(self): - """Return a '{cmd: {opt:val}}' map of all command-line options - - Option names are all long, but do not include the leading '--', and - contain dashes rather than underscores. If the option doesn't take - an argument (e.g. '--quiet'), the 'val' is 'None'. - - Note that options provided by config files are intentionally excluded. - """ - - d = {} - - for cmd, opts in self.command_options.items(): - - for opt, (src, val) in opts.items(): - - if src != "command line": - continue - - opt = opt.replace('_', '-') - - if val == 0: - cmdobj = self.get_command_obj(cmd) - neg_opt = self.negative_opt.copy() - neg_opt.update(getattr(cmdobj, 'negative_opt', {})) - for neg, pos in neg_opt.items(): - if pos == opt: - opt = neg - val = None - break - else: - raise AssertionError("Shouldn't be able to get here") - - elif val == 1: - val = None - - d.setdefault(cmd, {})[opt] = val - - return d - - def iter_distribution_names(self): - """Yield all packages, modules, and extension names in distribution""" - - for pkg in self.packages or (): - yield pkg - - for module in self.py_modules or (): - yield module - - for ext in self.ext_modules or (): - if isinstance(ext, tuple): - name, buildinfo = ext - else: - name = ext.name - if name.endswith('module'): - name = name[:-6] - yield name - - def handle_display_options(self, option_order): - """If there were any non-global "display-only" options - (--help-commands or the metadata display options) on the command - line, display the requested info and return true; else return - false. - """ - import sys - - if six.PY2 or self.help_commands: - return _Distribution.handle_display_options(self, option_order) - - # Stdout may be StringIO (e.g. in tests) - if not isinstance(sys.stdout, io.TextIOWrapper): - return _Distribution.handle_display_options(self, option_order) - - # Don't wrap stdout if utf-8 is already the encoding. Provides - # workaround for #334. - if sys.stdout.encoding.lower() in ('utf-8', 'utf8'): - return _Distribution.handle_display_options(self, option_order) - - # Print metadata in UTF-8 no matter the platform - encoding = sys.stdout.encoding - errors = sys.stdout.errors - newline = sys.platform != 'win32' and '\n' or None - line_buffering = sys.stdout.line_buffering - - sys.stdout = io.TextIOWrapper( - sys.stdout.detach(), 'utf-8', errors, newline, line_buffering) - try: - return _Distribution.handle_display_options(self, option_order) - finally: - sys.stdout = io.TextIOWrapper( - sys.stdout.detach(), encoding, errors, newline, line_buffering) - - -class Feature: - """ - **deprecated** -- The `Feature` facility was never completely implemented - or supported, `has reported issues - <https://github.com/pypa/setuptools/issues/58>`_ and will be removed in - a future version. - - A subset of the distribution that can be excluded if unneeded/wanted - - Features are created using these keyword arguments: - - 'description' -- a short, human readable description of the feature, to - be used in error messages, and option help messages. - - 'standard' -- if true, the feature is included by default if it is - available on the current system. Otherwise, the feature is only - included if requested via a command line '--with-X' option, or if - another included feature requires it. The default setting is 'False'. - - 'available' -- if true, the feature is available for installation on the - current system. The default setting is 'True'. - - 'optional' -- if true, the feature's inclusion can be controlled from the - command line, using the '--with-X' or '--without-X' options. If - false, the feature's inclusion status is determined automatically, - based on 'availabile', 'standard', and whether any other feature - requires it. The default setting is 'True'. - - 'require_features' -- a string or sequence of strings naming features - that should also be included if this feature is included. Defaults to - empty list. May also contain 'Require' objects that should be - added/removed from the distribution. - - 'remove' -- a string or list of strings naming packages to be removed - from the distribution if this feature is *not* included. If the - feature *is* included, this argument is ignored. This argument exists - to support removing features that "crosscut" a distribution, such as - defining a 'tests' feature that removes all the 'tests' subpackages - provided by other features. The default for this argument is an empty - list. (Note: the named package(s) or modules must exist in the base - distribution when the 'setup()' function is initially called.) - - other keywords -- any other keyword arguments are saved, and passed to - the distribution's 'include()' and 'exclude()' methods when the - feature is included or excluded, respectively. So, for example, you - could pass 'packages=["a","b"]' to cause packages 'a' and 'b' to be - added or removed from the distribution as appropriate. - - A feature must include at least one 'requires', 'remove', or other - keyword argument. Otherwise, it can't affect the distribution in any way. - Note also that you can subclass 'Feature' to create your own specialized - feature types that modify the distribution in other ways when included or - excluded. See the docstrings for the various methods here for more detail. - Aside from the methods, the only feature attributes that distributions look - at are 'description' and 'optional'. - """ - - @staticmethod - def warn_deprecated(): - msg = ( - "Features are deprecated and will be removed in a future " - "version. See https://github.com/pypa/setuptools/issues/65." - ) - warnings.warn(msg, DistDeprecationWarning, stacklevel=3) - - def __init__( - self, description, standard=False, available=True, - optional=True, require_features=(), remove=(), **extras): - self.warn_deprecated() - - self.description = description - self.standard = standard - self.available = available - self.optional = optional - if isinstance(require_features, (str, Require)): - require_features = require_features, - - self.require_features = [ - r for r in require_features if isinstance(r, str) - ] - er = [r for r in require_features if not isinstance(r, str)] - if er: - extras['require_features'] = er - - if isinstance(remove, str): - remove = remove, - self.remove = remove - self.extras = extras - - if not remove and not require_features and not extras: - raise DistutilsSetupError( - "Feature %s: must define 'require_features', 'remove', or " - "at least one of 'packages', 'py_modules', etc." - ) - - def include_by_default(self): - """Should this feature be included by default?""" - return self.available and self.standard - - def include_in(self, dist): - """Ensure feature and its requirements are included in distribution - - You may override this in a subclass to perform additional operations on - the distribution. Note that this method may be called more than once - per feature, and so should be idempotent. - - """ - - if not self.available: - raise DistutilsPlatformError( - self.description + " is required, " - "but is not available on this platform" - ) - - dist.include(**self.extras) - - for f in self.require_features: - dist.include_feature(f) - - def exclude_from(self, dist): - """Ensure feature is excluded from distribution - - You may override this in a subclass to perform additional operations on - the distribution. This method will be called at most once per - feature, and only after all included features have been asked to - include themselves. - """ - - dist.exclude(**self.extras) - - if self.remove: - for item in self.remove: - dist.exclude_package(item) - - def validate(self, dist): - """Verify that feature makes sense in context of distribution - - This method is called by the distribution just before it parses its - command line. It checks to ensure that the 'remove' attribute, if any, - contains only valid package/module names that are present in the base - distribution when 'setup()' is called. You may override it in a - subclass to perform any other required validation of the feature - against a target distribution. - """ - - for item in self.remove: - if not dist.has_contents_for(item): - raise DistutilsSetupError( - "%s wants to be able to remove %s, but the distribution" - " doesn't contain any packages or modules under %s" - % (self.description, item, item) - ) - - -class DistDeprecationWarning(SetuptoolsDeprecationWarning): - """Class for warning about deprecations in dist in - setuptools. Not ignored by default, unlike DeprecationWarning.""" diff --git a/venv2/lib/python2.7/site-packages/setuptools/extension.py b/venv2/lib/python2.7/site-packages/setuptools/extension.py deleted file mode 100644 index 2946889..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/extension.py +++ /dev/null @@ -1,57 +0,0 @@ -import re -import functools -import distutils.core -import distutils.errors -import distutils.extension - -from setuptools.extern.six.moves import map - -from .monkey import get_unpatched - - -def _have_cython(): - """ - Return True if Cython can be imported. - """ - cython_impl = 'Cython.Distutils.build_ext' - try: - # from (cython_impl) import build_ext - __import__(cython_impl, fromlist=['build_ext']).build_ext - return True - except Exception: - pass - return False - - -# for compatibility -have_pyrex = _have_cython - -_Extension = get_unpatched(distutils.core.Extension) - - -class Extension(_Extension): - """Extension that uses '.c' files in place of '.pyx' files""" - - def __init__(self, name, sources, *args, **kw): - # The *args is needed for compatibility as calls may use positional - # arguments. py_limited_api may be set only via keyword. - self.py_limited_api = kw.pop("py_limited_api", False) - _Extension.__init__(self, name, sources, *args, **kw) - - def _convert_pyx_sources_to_lang(self): - """ - Replace sources with .pyx extensions to sources with the target - language extension. This mechanism allows language authors to supply - pre-converted sources but to prefer the .pyx sources. - """ - if _have_cython(): - # the build has Cython, so allow it to compile the .pyx files - return - lang = self.language or '' - target_ext = '.cpp' if lang.lower() == 'c++' else '.c' - sub = functools.partial(re.sub, '.pyx$', target_ext) - self.sources = list(map(sub, self.sources)) - - -class Library(Extension): - """Just like a regular Extension, but built as a library instead""" diff --git a/venv2/lib/python2.7/site-packages/setuptools/extern/__init__.py b/venv2/lib/python2.7/site-packages/setuptools/extern/__init__.py deleted file mode 100644 index cb2fa32..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/extern/__init__.py +++ /dev/null @@ -1,73 +0,0 @@ -import sys - - -class VendorImporter: - """ - A PEP 302 meta path importer for finding optionally-vendored - or otherwise naturally-installed packages from root_name. - """ - - def __init__(self, root_name, vendored_names=(), vendor_pkg=None): - self.root_name = root_name - self.vendored_names = set(vendored_names) - self.vendor_pkg = vendor_pkg or root_name.replace('extern', '_vendor') - - @property - def search_path(self): - """ - Search first the vendor package then as a natural package. - """ - yield self.vendor_pkg + '.' - yield '' - - def find_module(self, fullname, path=None): - """ - Return self when fullname starts with root_name and the - target module is one vendored through this importer. - """ - root, base, target = fullname.partition(self.root_name + '.') - if root: - return - if not any(map(target.startswith, self.vendored_names)): - return - return self - - def load_module(self, fullname): - """ - Iterate over the search path to locate and load fullname. - """ - root, base, target = fullname.partition(self.root_name + '.') - for prefix in self.search_path: - try: - extant = prefix + target - __import__(extant) - mod = sys.modules[extant] - sys.modules[fullname] = mod - # mysterious hack: - # Remove the reference to the extant package/module - # on later Python versions to cause relative imports - # in the vendor package to resolve the same modules - # as those going through this importer. - if sys.version_info >= (3, ): - del sys.modules[extant] - return mod - except ImportError: - pass - else: - raise ImportError( - "The '{target}' package is required; " - "normally this is bundled with this package so if you get " - "this warning, consult the packager of your " - "distribution.".format(**locals()) - ) - - def install(self): - """ - Install this importer into sys.meta_path if not already present. - """ - if self not in sys.meta_path: - sys.meta_path.append(self) - - -names = 'six', 'packaging', 'pyparsing', -VendorImporter(__name__, names, 'setuptools._vendor').install() diff --git a/venv2/lib/python2.7/site-packages/setuptools/glibc.py b/venv2/lib/python2.7/site-packages/setuptools/glibc.py deleted file mode 100644 index a134591..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/glibc.py +++ /dev/null @@ -1,86 +0,0 @@ -# This file originally from pip: -# https://github.com/pypa/pip/blob/8f4f15a5a95d7d5b511ceaee9ed261176c181970/src/pip/_internal/utils/glibc.py -from __future__ import absolute_import - -import ctypes -import re -import warnings - - -def glibc_version_string(): - "Returns glibc version string, or None if not using glibc." - - # 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<major>[0-9]+)\.(?P<minor>[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) - - -# platform.libc_ver regularly returns completely nonsensical glibc -# versions. E.g. on my computer, platform says: -# -# ~$ python2.7 -c 'import platform; print(platform.libc_ver())' -# ('glibc', '2.7') -# ~$ python3.5 -c 'import platform; print(platform.libc_ver())' -# ('glibc', '2.9') -# -# But the truth is: -# -# ~$ ldd --version -# ldd (Debian GLIBC 2.22-11) 2.22 -# -# This is unfortunate, because it means that the linehaul data on libc -# versions that was generated by pip 8.1.2 and earlier is useless and -# misleading. Solution: instead of using platform, use our code that actually -# works. -def libc_ver(): - """Try to determine the glibc version - - Returns a tuple of strings (lib, version) which default to empty strings - in case the lookup fails. - """ - glibc_version = glibc_version_string() - if glibc_version is None: - return ("", "") - else: - return ("glibc", glibc_version) diff --git a/venv2/lib/python2.7/site-packages/setuptools/glob.py b/venv2/lib/python2.7/site-packages/setuptools/glob.py deleted file mode 100644 index 9d7cbc5..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/glob.py +++ /dev/null @@ -1,174 +0,0 @@ -""" -Filename globbing utility. Mostly a copy of `glob` from Python 3.5. - -Changes include: - * `yield from` and PEP3102 `*` removed. - * Hidden files are not ignored. -""" - -import os -import re -import fnmatch - -__all__ = ["glob", "iglob", "escape"] - - -def glob(pathname, recursive=False): - """Return a list of paths matching a pathname pattern. - - The pattern may contain simple shell-style wildcards a la - fnmatch. However, unlike fnmatch, filenames starting with a - dot are special cases that are not matched by '*' and '?' - patterns. - - If recursive is true, the pattern '**' will match any files and - zero or more directories and subdirectories. - """ - return list(iglob(pathname, recursive=recursive)) - - -def iglob(pathname, recursive=False): - """Return an iterator which yields the paths matching a pathname pattern. - - The pattern may contain simple shell-style wildcards a la - fnmatch. However, unlike fnmatch, filenames starting with a - dot are special cases that are not matched by '*' and '?' - patterns. - - If recursive is true, the pattern '**' will match any files and - zero or more directories and subdirectories. - """ - it = _iglob(pathname, recursive) - if recursive and _isrecursive(pathname): - s = next(it) # skip empty string - assert not s - return it - - -def _iglob(pathname, recursive): - dirname, basename = os.path.split(pathname) - if not has_magic(pathname): - if basename: - if os.path.lexists(pathname): - yield pathname - else: - # Patterns ending with a slash should match only directories - if os.path.isdir(dirname): - yield pathname - return - if not dirname: - if recursive and _isrecursive(basename): - for x in glob2(dirname, basename): - yield x - else: - for x in glob1(dirname, basename): - yield x - return - # `os.path.split()` returns the argument itself as a dirname if it is a - # drive or UNC path. Prevent an infinite recursion if a drive or UNC path - # contains magic characters (i.e. r'\\?\C:'). - if dirname != pathname and has_magic(dirname): - dirs = _iglob(dirname, recursive) - else: - dirs = [dirname] - if has_magic(basename): - if recursive and _isrecursive(basename): - glob_in_dir = glob2 - else: - glob_in_dir = glob1 - else: - glob_in_dir = glob0 - for dirname in dirs: - for name in glob_in_dir(dirname, basename): - yield os.path.join(dirname, name) - - -# These 2 helper functions non-recursively glob inside a literal directory. -# They return a list of basenames. `glob1` accepts a pattern while `glob0` -# takes a literal basename (so it only has to check for its existence). - - -def glob1(dirname, pattern): - if not dirname: - if isinstance(pattern, bytes): - dirname = os.curdir.encode('ASCII') - else: - dirname = os.curdir - try: - names = os.listdir(dirname) - except OSError: - return [] - return fnmatch.filter(names, pattern) - - -def glob0(dirname, basename): - if not basename: - # `os.path.split()` returns an empty basename for paths ending with a - # directory separator. 'q*x/' should match only directories. - if os.path.isdir(dirname): - return [basename] - else: - if os.path.lexists(os.path.join(dirname, basename)): - return [basename] - return [] - - -# This helper function recursively yields relative pathnames inside a literal -# directory. - - -def glob2(dirname, pattern): - assert _isrecursive(pattern) - yield pattern[:0] - for x in _rlistdir(dirname): - yield x - - -# Recursively yields relative pathnames inside a literal directory. -def _rlistdir(dirname): - if not dirname: - if isinstance(dirname, bytes): - dirname = os.curdir.encode('ASCII') - else: - dirname = os.curdir - try: - names = os.listdir(dirname) - except os.error: - return - for x in names: - yield x - path = os.path.join(dirname, x) if dirname else x - for y in _rlistdir(path): - yield os.path.join(x, y) - - -magic_check = re.compile('([*?[])') -magic_check_bytes = re.compile(b'([*?[])') - - -def has_magic(s): - if isinstance(s, bytes): - match = magic_check_bytes.search(s) - else: - match = magic_check.search(s) - return match is not None - - -def _isrecursive(pattern): - if isinstance(pattern, bytes): - return pattern == b'**' - else: - return pattern == '**' - - -def escape(pathname): - """Escape all special characters. - """ - # Escaping is done by wrapping any of "*?[" between square brackets. - # Metacharacters do not work in the drive part and shouldn't be escaped. - drive, pathname = os.path.splitdrive(pathname) - if isinstance(pathname, bytes): - pathname = magic_check_bytes.sub(br'[\1]', pathname) - else: - pathname = magic_check.sub(r'[\1]', pathname) - return drive + pathname diff --git a/venv2/lib/python2.7/site-packages/setuptools/gui-32.exe b/venv2/lib/python2.7/site-packages/setuptools/gui-32.exe deleted file mode 100644 index f8d3509653ba8f80ca7f3aa7f95616142ba83a94..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65536 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 diff --git a/venv2/lib/python2.7/site-packages/setuptools/gui-64.exe b/venv2/lib/python2.7/site-packages/setuptools/gui-64.exe deleted file mode 100644 index 330c51a5dde15a0bb610a48cd0ca11770c914dae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 75264 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 diff --git a/venv2/lib/python2.7/site-packages/setuptools/gui.exe b/venv2/lib/python2.7/site-packages/setuptools/gui.exe deleted file mode 100644 index f8d3509653ba8f80ca7f3aa7f95616142ba83a94..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65536 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 diff --git a/venv2/lib/python2.7/site-packages/setuptools/launch.py b/venv2/lib/python2.7/site-packages/setuptools/launch.py deleted file mode 100644 index 308283e..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/launch.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Launch the Python script on the command line after -setuptools is bootstrapped via import. -""" - -# Note that setuptools gets imported implicitly by the -# invocation of this script using python -m setuptools.launch - -import tokenize -import sys - - -def run(): - """ - Run the script in sys.argv[1] as if it had - been invoked naturally. - """ - __builtins__ - script_name = sys.argv[1] - namespace = dict( - __file__=script_name, - __name__='__main__', - __doc__=None, - ) - sys.argv[:] = sys.argv[1:] - - open_ = getattr(tokenize, 'open', open) - script = open_(script_name).read() - norm_script = script.replace('\\r\\n', '\\n') - code = compile(norm_script, script_name, 'exec') - exec(code, namespace) - - -if __name__ == '__main__': - run() diff --git a/venv2/lib/python2.7/site-packages/setuptools/lib2to3_ex.py b/venv2/lib/python2.7/site-packages/setuptools/lib2to3_ex.py deleted file mode 100644 index 4b1a73f..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/lib2to3_ex.py +++ /dev/null @@ -1,62 +0,0 @@ -""" -Customized Mixin2to3 support: - - - adds support for converting doctests - - -This module raises an ImportError on Python 2. -""" - -from distutils.util import Mixin2to3 as _Mixin2to3 -from distutils import log -from lib2to3.refactor import RefactoringTool, get_fixers_from_package - -import setuptools - - -class DistutilsRefactoringTool(RefactoringTool): - def log_error(self, msg, *args, **kw): - log.error(msg, *args) - - def log_message(self, msg, *args): - log.info(msg, *args) - - def log_debug(self, msg, *args): - log.debug(msg, *args) - - -class Mixin2to3(_Mixin2to3): - def run_2to3(self, files, doctests=False): - # See of the distribution option has been set, otherwise check the - # setuptools default. - if self.distribution.use_2to3 is not True: - return - if not files: - return - log.info("Fixing " + " ".join(files)) - self.__build_fixer_names() - self.__exclude_fixers() - if doctests: - if setuptools.run_2to3_on_doctests: - r = DistutilsRefactoringTool(self.fixer_names) - r.refactor(files, write=True, doctests_only=True) - else: - _Mixin2to3.run_2to3(self, files) - - def __build_fixer_names(self): - if self.fixer_names: - return - self.fixer_names = [] - for p in setuptools.lib2to3_fixer_packages: - self.fixer_names.extend(get_fixers_from_package(p)) - if self.distribution.use_2to3_fixers is not None: - for p in self.distribution.use_2to3_fixers: - self.fixer_names.extend(get_fixers_from_package(p)) - - def __exclude_fixers(self): - excluded_fixers = getattr(self, 'exclude_fixers', []) - if self.distribution.use_2to3_exclude_fixers is not None: - excluded_fixers.extend(self.distribution.use_2to3_exclude_fixers) - for fixer_name in excluded_fixers: - if fixer_name in self.fixer_names: - self.fixer_names.remove(fixer_name) diff --git a/venv2/lib/python2.7/site-packages/setuptools/monkey.py b/venv2/lib/python2.7/site-packages/setuptools/monkey.py deleted file mode 100644 index 3c77f8c..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/monkey.py +++ /dev/null @@ -1,179 +0,0 @@ -""" -Monkey patching of distutils. -""" - -import sys -import distutils.filelist -import platform -import types -import functools -from importlib import import_module -import inspect - -from setuptools.extern import six - -import setuptools - -__all__ = [] -""" -Everything is private. Contact the project team -if you think you need this functionality. -""" - - -def _get_mro(cls): - """ - Returns the bases classes for cls sorted by the MRO. - - Works around an issue on Jython where inspect.getmro will not return all - base classes if multiple classes share the same name. Instead, this - function will return a tuple containing the class itself, and the contents - of cls.__bases__. See https://github.com/pypa/setuptools/issues/1024. - """ - if platform.python_implementation() == "Jython": - return (cls,) + cls.__bases__ - return inspect.getmro(cls) - - -def get_unpatched(item): - lookup = ( - get_unpatched_class if isinstance(item, six.class_types) else - get_unpatched_function if isinstance(item, types.FunctionType) else - lambda item: None - ) - return lookup(item) - - -def get_unpatched_class(cls): - """Protect against re-patching the distutils if reloaded - - Also ensures that no other distutils extension monkeypatched the distutils - first. - """ - external_bases = ( - cls - for cls in _get_mro(cls) - if not cls.__module__.startswith('setuptools') - ) - base = next(external_bases) - if not base.__module__.startswith('distutils'): - msg = "distutils has already been patched by %r" % cls - raise AssertionError(msg) - return base - - -def patch_all(): - # we can't patch distutils.cmd, alas - distutils.core.Command = setuptools.Command - - has_issue_12885 = sys.version_info <= (3, 5, 3) - - if has_issue_12885: - # fix findall bug in distutils (http://bugs.python.org/issue12885) - distutils.filelist.findall = setuptools.findall - - needs_warehouse = ( - sys.version_info < (2, 7, 13) - or - (3, 4) < sys.version_info < (3, 4, 6) - or - (3, 5) < sys.version_info <= (3, 5, 3) - ) - - if needs_warehouse: - warehouse = 'https://upload.pypi.org/legacy/' - distutils.config.PyPIRCCommand.DEFAULT_REPOSITORY = warehouse - - _patch_distribution_metadata() - - # Install Distribution throughout the distutils - for module in distutils.dist, distutils.core, distutils.cmd: - module.Distribution = setuptools.dist.Distribution - - # Install the patched Extension - distutils.core.Extension = setuptools.extension.Extension - distutils.extension.Extension = setuptools.extension.Extension - if 'distutils.command.build_ext' in sys.modules: - sys.modules['distutils.command.build_ext'].Extension = ( - setuptools.extension.Extension - ) - - patch_for_msvc_specialized_compiler() - - -def _patch_distribution_metadata(): - """Patch write_pkg_file and read_pkg_file for higher metadata standards""" - for attr in ('write_pkg_file', 'read_pkg_file', 'get_metadata_version'): - new_val = getattr(setuptools.dist, attr) - setattr(distutils.dist.DistributionMetadata, attr, new_val) - - -def patch_func(replacement, target_mod, func_name): - """ - Patch func_name in target_mod with replacement - - Important - original must be resolved by name to avoid - patching an already patched function. - """ - original = getattr(target_mod, func_name) - - # set the 'unpatched' attribute on the replacement to - # point to the original. - vars(replacement).setdefault('unpatched', original) - - # replace the function in the original module - setattr(target_mod, func_name, replacement) - - -def get_unpatched_function(candidate): - return getattr(candidate, 'unpatched') - - -def patch_for_msvc_specialized_compiler(): - """ - Patch functions in distutils to use standalone Microsoft Visual C++ - compilers. - """ - # import late to avoid circular imports on Python < 3.5 - msvc = import_module('setuptools.msvc') - - if platform.system() != 'Windows': - # Compilers only availables on Microsoft Windows - return - - def patch_params(mod_name, func_name): - """ - Prepare the parameters for patch_func to patch indicated function. - """ - repl_prefix = 'msvc9_' if 'msvc9' in mod_name else 'msvc14_' - repl_name = repl_prefix + func_name.lstrip('_') - repl = getattr(msvc, repl_name) - mod = import_module(mod_name) - if not hasattr(mod, func_name): - raise ImportError(func_name) - return repl, mod, func_name - - # Python 2.7 to 3.4 - msvc9 = functools.partial(patch_params, 'distutils.msvc9compiler') - - # Python 3.5+ - msvc14 = functools.partial(patch_params, 'distutils._msvccompiler') - - try: - # Patch distutils.msvc9compiler - patch_func(*msvc9('find_vcvarsall')) - patch_func(*msvc9('query_vcvarsall')) - except ImportError: - pass - - try: - # Patch distutils._msvccompiler._get_vc_env - patch_func(*msvc14('_get_vc_env')) - except ImportError: - pass - - try: - # Patch distutils._msvccompiler.gen_lib_options for Numpy - patch_func(*msvc14('gen_lib_options')) - except ImportError: - pass diff --git a/venv2/lib/python2.7/site-packages/setuptools/msvc.py b/venv2/lib/python2.7/site-packages/setuptools/msvc.py deleted file mode 100644 index b9c472f..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/msvc.py +++ /dev/null @@ -1,1301 +0,0 @@ -""" -Improved support for Microsoft Visual C++ compilers. - -Known supported compilers: --------------------------- -Microsoft Visual C++ 9.0: - Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64) - Microsoft Windows SDK 6.1 (x86, x64, ia64) - Microsoft Windows SDK 7.0 (x86, x64, ia64) - -Microsoft Visual C++ 10.0: - Microsoft Windows SDK 7.1 (x86, x64, ia64) - -Microsoft Visual C++ 14.0: - Microsoft Visual C++ Build Tools 2015 (x86, x64, arm) - Microsoft Visual Studio 2017 (x86, x64, arm, arm64) - Microsoft Visual Studio Build Tools 2017 (x86, x64, arm, arm64) -""" - -import os -import sys -import platform -import itertools -import distutils.errors -from setuptools.extern.packaging.version import LegacyVersion - -from setuptools.extern.six.moves import filterfalse - -from .monkey import get_unpatched - -if platform.system() == 'Windows': - from setuptools.extern.six.moves import winreg - safe_env = os.environ -else: - """ - Mock winreg and environ so the module can be imported - on this platform. - """ - - class winreg: - HKEY_USERS = None - HKEY_CURRENT_USER = None - HKEY_LOCAL_MACHINE = None - HKEY_CLASSES_ROOT = None - - safe_env = dict() - -_msvc9_suppress_errors = ( - # msvc9compiler isn't available on some platforms - ImportError, - - # msvc9compiler raises DistutilsPlatformError in some - # environments. See #1118. - distutils.errors.DistutilsPlatformError, -) - -try: - from distutils.msvc9compiler import Reg -except _msvc9_suppress_errors: - pass - - -def msvc9_find_vcvarsall(version): - """ - Patched "distutils.msvc9compiler.find_vcvarsall" to use the standalone - compiler build for Python (VCForPython). Fall back to original behavior - when the standalone compiler is not available. - - Redirect the path of "vcvarsall.bat". - - Known supported compilers - ------------------------- - Microsoft Visual C++ 9.0: - Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64) - - Parameters - ---------- - version: float - Required Microsoft Visual C++ version. - - Return - ------ - vcvarsall.bat path: str - """ - VC_BASE = r'Software\%sMicrosoft\DevDiv\VCForPython\%0.1f' - key = VC_BASE % ('', version) - try: - # Per-user installs register the compiler path here - productdir = Reg.get_value(key, "installdir") - except KeyError: - try: - # All-user installs on a 64-bit system register here - key = VC_BASE % ('Wow6432Node\\', version) - productdir = Reg.get_value(key, "installdir") - except KeyError: - productdir = None - - if productdir: - vcvarsall = os.path.os.path.join(productdir, "vcvarsall.bat") - if os.path.isfile(vcvarsall): - return vcvarsall - - return get_unpatched(msvc9_find_vcvarsall)(version) - - -def msvc9_query_vcvarsall(ver, arch='x86', *args, **kwargs): - """ - Patched "distutils.msvc9compiler.query_vcvarsall" for support extra - compilers. - - Set environment without use of "vcvarsall.bat". - - Known supported compilers - ------------------------- - Microsoft Visual C++ 9.0: - Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64) - Microsoft Windows SDK 6.1 (x86, x64, ia64) - Microsoft Windows SDK 7.0 (x86, x64, ia64) - - Microsoft Visual C++ 10.0: - Microsoft Windows SDK 7.1 (x86, x64, ia64) - - Parameters - ---------- - ver: float - Required Microsoft Visual C++ version. - arch: str - Target architecture. - - Return - ------ - environment: dict - """ - # Try to get environement from vcvarsall.bat (Classical way) - try: - orig = get_unpatched(msvc9_query_vcvarsall) - return orig(ver, arch, *args, **kwargs) - except distutils.errors.DistutilsPlatformError: - # Pass error if Vcvarsall.bat is missing - pass - except ValueError: - # Pass error if environment not set after executing vcvarsall.bat - pass - - # If error, try to set environment directly - try: - return EnvironmentInfo(arch, ver).return_env() - except distutils.errors.DistutilsPlatformError as exc: - _augment_exception(exc, ver, arch) - raise - - -def msvc14_get_vc_env(plat_spec): - """ - Patched "distutils._msvccompiler._get_vc_env" for support extra - compilers. - - Set environment without use of "vcvarsall.bat". - - Known supported compilers - ------------------------- - Microsoft Visual C++ 14.0: - Microsoft Visual C++ Build Tools 2015 (x86, x64, arm) - Microsoft Visual Studio 2017 (x86, x64, arm, arm64) - Microsoft Visual Studio Build Tools 2017 (x86, x64, arm, arm64) - - Parameters - ---------- - plat_spec: str - Target architecture. - - Return - ------ - environment: dict - """ - # Try to get environment from vcvarsall.bat (Classical way) - try: - return get_unpatched(msvc14_get_vc_env)(plat_spec) - except distutils.errors.DistutilsPlatformError: - # Pass error Vcvarsall.bat is missing - pass - - # If error, try to set environment directly - try: - return EnvironmentInfo(plat_spec, vc_min_ver=14.0).return_env() - except distutils.errors.DistutilsPlatformError as exc: - _augment_exception(exc, 14.0) - raise - - -def msvc14_gen_lib_options(*args, **kwargs): - """ - Patched "distutils._msvccompiler.gen_lib_options" for fix - compatibility between "numpy.distutils" and "distutils._msvccompiler" - (for Numpy < 1.11.2) - """ - if "numpy.distutils" in sys.modules: - import numpy as np - if LegacyVersion(np.__version__) < LegacyVersion('1.11.2'): - return np.distutils.ccompiler.gen_lib_options(*args, **kwargs) - return get_unpatched(msvc14_gen_lib_options)(*args, **kwargs) - - -def _augment_exception(exc, version, arch=''): - """ - Add details to the exception message to help guide the user - as to what action will resolve it. - """ - # Error if MSVC++ directory not found or environment not set - message = exc.args[0] - - if "vcvarsall" in message.lower() or "visual c" in message.lower(): - # Special error message if MSVC++ not installed - tmpl = 'Microsoft Visual C++ {version:0.1f} is required.' - message = tmpl.format(**locals()) - msdownload = 'www.microsoft.com/download/details.aspx?id=%d' - if version == 9.0: - if arch.lower().find('ia64') > -1: - # For VC++ 9.0, if IA64 support is needed, redirect user - # to Windows SDK 7.0 - message += ' Get it with "Microsoft Windows SDK 7.0": ' - message += msdownload % 3138 - else: - # For VC++ 9.0 redirect user to Vc++ for Python 2.7 : - # This redirection link is maintained by Microsoft. - # Contact vspython@microsoft.com if it needs updating. - message += ' Get it from http://aka.ms/vcpython27' - elif version == 10.0: - # For VC++ 10.0 Redirect user to Windows SDK 7.1 - message += ' Get it with "Microsoft Windows SDK 7.1": ' - message += msdownload % 8279 - elif version >= 14.0: - # For VC++ 14.0 Redirect user to Visual C++ Build Tools - message += (' Get it with "Microsoft Visual C++ Build Tools": ' - r'https://visualstudio.microsoft.com/downloads/') - - exc.args = (message, ) - - -class PlatformInfo: - """ - Current and Target Architectures informations. - - Parameters - ---------- - arch: str - Target architecture. - """ - current_cpu = safe_env.get('processor_architecture', '').lower() - - def __init__(self, arch): - self.arch = arch.lower().replace('x64', 'amd64') - - @property - def target_cpu(self): - return self.arch[self.arch.find('_') + 1:] - - def target_is_x86(self): - return self.target_cpu == 'x86' - - def current_is_x86(self): - return self.current_cpu == 'x86' - - def current_dir(self, hidex86=False, x64=False): - """ - Current platform specific subfolder. - - Parameters - ---------- - hidex86: bool - return '' and not '\x86' if architecture is x86. - x64: bool - return '\x64' and not '\amd64' if architecture is amd64. - - Return - ------ - subfolder: str - '\target', or '' (see hidex86 parameter) - """ - return ( - '' if (self.current_cpu == 'x86' and hidex86) else - r'\x64' if (self.current_cpu == 'amd64' and x64) else - r'\%s' % self.current_cpu - ) - - def target_dir(self, hidex86=False, x64=False): - r""" - Target platform specific subfolder. - - Parameters - ---------- - hidex86: bool - return '' and not '\x86' if architecture is x86. - x64: bool - return '\x64' and not '\amd64' if architecture is amd64. - - Return - ------ - subfolder: str - '\current', or '' (see hidex86 parameter) - """ - return ( - '' if (self.target_cpu == 'x86' and hidex86) else - r'\x64' if (self.target_cpu == 'amd64' and x64) else - r'\%s' % self.target_cpu - ) - - def cross_dir(self, forcex86=False): - r""" - Cross platform specific subfolder. - - Parameters - ---------- - forcex86: bool - Use 'x86' as current architecture even if current acritecture is - not x86. - - Return - ------ - subfolder: str - '' if target architecture is current architecture, - '\current_target' if not. - """ - current = 'x86' if forcex86 else self.current_cpu - return ( - '' if self.target_cpu == current else - self.target_dir().replace('\\', '\\%s_' % current) - ) - - -class RegistryInfo: - """ - Microsoft Visual Studio related registry informations. - - Parameters - ---------- - platform_info: PlatformInfo - "PlatformInfo" instance. - """ - HKEYS = (winreg.HKEY_USERS, - winreg.HKEY_CURRENT_USER, - winreg.HKEY_LOCAL_MACHINE, - winreg.HKEY_CLASSES_ROOT) - - def __init__(self, platform_info): - self.pi = platform_info - - @property - def visualstudio(self): - """ - Microsoft Visual Studio root registry key. - """ - return 'VisualStudio' - - @property - def sxs(self): - """ - Microsoft Visual Studio SxS registry key. - """ - return os.path.join(self.visualstudio, 'SxS') - - @property - def vc(self): - """ - Microsoft Visual C++ VC7 registry key. - """ - return os.path.join(self.sxs, 'VC7') - - @property - def vs(self): - """ - Microsoft Visual Studio VS7 registry key. - """ - return os.path.join(self.sxs, 'VS7') - - @property - def vc_for_python(self): - """ - Microsoft Visual C++ for Python registry key. - """ - return r'DevDiv\VCForPython' - - @property - def microsoft_sdk(self): - """ - Microsoft SDK registry key. - """ - return 'Microsoft SDKs' - - @property - def windows_sdk(self): - """ - Microsoft Windows/Platform SDK registry key. - """ - return os.path.join(self.microsoft_sdk, 'Windows') - - @property - def netfx_sdk(self): - """ - Microsoft .NET Framework SDK registry key. - """ - return os.path.join(self.microsoft_sdk, 'NETFXSDK') - - @property - def windows_kits_roots(self): - """ - Microsoft Windows Kits Roots registry key. - """ - return r'Windows Kits\Installed Roots' - - def microsoft(self, key, x86=False): - """ - Return key in Microsoft software registry. - - Parameters - ---------- - key: str - Registry key path where look. - x86: str - Force x86 software registry. - - Return - ------ - str: value - """ - node64 = '' if self.pi.current_is_x86() or x86 else 'Wow6432Node' - return os.path.join('Software', node64, 'Microsoft', key) - - def lookup(self, key, name): - """ - Look for values in registry in Microsoft software registry. - - Parameters - ---------- - key: str - Registry key path where look. - name: str - Value name to find. - - Return - ------ - str: value - """ - KEY_READ = winreg.KEY_READ - openkey = winreg.OpenKey - ms = self.microsoft - for hkey in self.HKEYS: - try: - bkey = openkey(hkey, ms(key), 0, KEY_READ) - except (OSError, IOError): - if not self.pi.current_is_x86(): - try: - bkey = openkey(hkey, ms(key, True), 0, KEY_READ) - except (OSError, IOError): - continue - else: - continue - try: - return winreg.QueryValueEx(bkey, name)[0] - except (OSError, IOError): - pass - - -class SystemInfo: - """ - Microsoft Windows and Visual Studio related system inormations. - - Parameters - ---------- - registry_info: RegistryInfo - "RegistryInfo" instance. - vc_ver: float - Required Microsoft Visual C++ version. - """ - - # Variables and properties in this class use originals CamelCase variables - # names from Microsoft source files for more easy comparaison. - WinDir = safe_env.get('WinDir', '') - ProgramFiles = safe_env.get('ProgramFiles', '') - ProgramFilesx86 = safe_env.get('ProgramFiles(x86)', ProgramFiles) - - def __init__(self, registry_info, vc_ver=None): - self.ri = registry_info - self.pi = self.ri.pi - self.vc_ver = vc_ver or self._find_latest_available_vc_ver() - - def _find_latest_available_vc_ver(self): - try: - return self.find_available_vc_vers()[-1] - except IndexError: - err = 'No Microsoft Visual C++ version found' - raise distutils.errors.DistutilsPlatformError(err) - - def find_available_vc_vers(self): - """ - Find all available Microsoft Visual C++ versions. - """ - ms = self.ri.microsoft - vckeys = (self.ri.vc, self.ri.vc_for_python, self.ri.vs) - vc_vers = [] - for hkey in self.ri.HKEYS: - for key in vckeys: - try: - bkey = winreg.OpenKey(hkey, ms(key), 0, winreg.KEY_READ) - except (OSError, IOError): - continue - subkeys, values, _ = winreg.QueryInfoKey(bkey) - for i in range(values): - try: - ver = float(winreg.EnumValue(bkey, i)[0]) - if ver not in vc_vers: - vc_vers.append(ver) - except ValueError: - pass - for i in range(subkeys): - try: - ver = float(winreg.EnumKey(bkey, i)) - if ver not in vc_vers: - vc_vers.append(ver) - except ValueError: - pass - return sorted(vc_vers) - - @property - def VSInstallDir(self): - """ - Microsoft Visual Studio directory. - """ - # Default path - name = 'Microsoft Visual Studio %0.1f' % self.vc_ver - default = os.path.join(self.ProgramFilesx86, name) - - # Try to get path from registry, if fail use default path - return self.ri.lookup(self.ri.vs, '%0.1f' % self.vc_ver) or default - - @property - def VCInstallDir(self): - """ - Microsoft Visual C++ directory. - """ - self.VSInstallDir - - guess_vc = self._guess_vc() or self._guess_vc_legacy() - - # Try to get "VC++ for Python" path from registry as default path - reg_path = os.path.join(self.ri.vc_for_python, '%0.1f' % self.vc_ver) - python_vc = self.ri.lookup(reg_path, 'installdir') - default_vc = os.path.join(python_vc, 'VC') if python_vc else guess_vc - - # Try to get path from registry, if fail use default path - path = self.ri.lookup(self.ri.vc, '%0.1f' % self.vc_ver) or default_vc - - if not os.path.isdir(path): - msg = 'Microsoft Visual C++ directory not found' - raise distutils.errors.DistutilsPlatformError(msg) - - return path - - def _guess_vc(self): - """ - Locate Visual C for 2017 - """ - if self.vc_ver <= 14.0: - return - - default = r'VC\Tools\MSVC' - guess_vc = os.path.join(self.VSInstallDir, default) - # Subdir with VC exact version as name - try: - vc_exact_ver = os.listdir(guess_vc)[-1] - return os.path.join(guess_vc, vc_exact_ver) - except (OSError, IOError, IndexError): - pass - - def _guess_vc_legacy(self): - """ - Locate Visual C for versions prior to 2017 - """ - default = r'Microsoft Visual Studio %0.1f\VC' % self.vc_ver - return os.path.join(self.ProgramFilesx86, default) - - @property - def WindowsSdkVersion(self): - """ - Microsoft Windows SDK versions for specified MSVC++ version. - """ - if self.vc_ver <= 9.0: - return ('7.0', '6.1', '6.0a') - elif self.vc_ver == 10.0: - return ('7.1', '7.0a') - elif self.vc_ver == 11.0: - return ('8.0', '8.0a') - elif self.vc_ver == 12.0: - return ('8.1', '8.1a') - elif self.vc_ver >= 14.0: - return ('10.0', '8.1') - - @property - def WindowsSdkLastVersion(self): - """ - Microsoft Windows SDK last version - """ - return self._use_last_dir_name(os.path.join( - self.WindowsSdkDir, 'lib')) - - @property - def WindowsSdkDir(self): - """ - Microsoft Windows SDK directory. - """ - sdkdir = '' - for ver in self.WindowsSdkVersion: - # Try to get it from registry - loc = os.path.join(self.ri.windows_sdk, 'v%s' % ver) - sdkdir = self.ri.lookup(loc, 'installationfolder') - if sdkdir: - break - if not sdkdir or not os.path.isdir(sdkdir): - # Try to get "VC++ for Python" version from registry - path = os.path.join(self.ri.vc_for_python, '%0.1f' % self.vc_ver) - install_base = self.ri.lookup(path, 'installdir') - if install_base: - sdkdir = os.path.join(install_base, 'WinSDK') - if not sdkdir or not os.path.isdir(sdkdir): - # If fail, use default new path - for ver in self.WindowsSdkVersion: - intver = ver[:ver.rfind('.')] - path = r'Microsoft SDKs\Windows Kits\%s' % (intver) - d = os.path.join(self.ProgramFiles, path) - if os.path.isdir(d): - sdkdir = d - if not sdkdir or not os.path.isdir(sdkdir): - # If fail, use default old path - for ver in self.WindowsSdkVersion: - path = r'Microsoft SDKs\Windows\v%s' % ver - d = os.path.join(self.ProgramFiles, path) - if os.path.isdir(d): - sdkdir = d - if not sdkdir: - # If fail, use Platform SDK - sdkdir = os.path.join(self.VCInstallDir, 'PlatformSDK') - return sdkdir - - @property - def WindowsSDKExecutablePath(self): - """ - Microsoft Windows SDK executable directory. - """ - # Find WinSDK NetFx Tools registry dir name - if self.vc_ver <= 11.0: - netfxver = 35 - arch = '' - else: - netfxver = 40 - hidex86 = True if self.vc_ver <= 12.0 else False - arch = self.pi.current_dir(x64=True, hidex86=hidex86) - fx = 'WinSDK-NetFx%dTools%s' % (netfxver, arch.replace('\\', '-')) - - # liste all possibles registry paths - regpaths = [] - if self.vc_ver >= 14.0: - for ver in self.NetFxSdkVersion: - regpaths += [os.path.join(self.ri.netfx_sdk, ver, fx)] - - for ver in self.WindowsSdkVersion: - regpaths += [os.path.join(self.ri.windows_sdk, 'v%sA' % ver, fx)] - - # Return installation folder from the more recent path - for path in regpaths: - execpath = self.ri.lookup(path, 'installationfolder') - if execpath: - break - return execpath - - @property - def FSharpInstallDir(self): - """ - Microsoft Visual F# directory. - """ - path = r'%0.1f\Setup\F#' % self.vc_ver - path = os.path.join(self.ri.visualstudio, path) - return self.ri.lookup(path, 'productdir') or '' - - @property - def UniversalCRTSdkDir(self): - """ - Microsoft Universal CRT SDK directory. - """ - # Set Kit Roots versions for specified MSVC++ version - if self.vc_ver >= 14.0: - vers = ('10', '81') - else: - vers = () - - # Find path of the more recent Kit - for ver in vers: - sdkdir = self.ri.lookup(self.ri.windows_kits_roots, - 'kitsroot%s' % ver) - if sdkdir: - break - return sdkdir or '' - - @property - def UniversalCRTSdkLastVersion(self): - """ - Microsoft Universal C Runtime SDK last version - """ - return self._use_last_dir_name(os.path.join( - self.UniversalCRTSdkDir, 'lib')) - - @property - def NetFxSdkVersion(self): - """ - Microsoft .NET Framework SDK versions. - """ - # Set FxSdk versions for specified MSVC++ version - if self.vc_ver >= 14.0: - return ('4.6.1', '4.6') - else: - return () - - @property - def NetFxSdkDir(self): - """ - Microsoft .NET Framework SDK directory. - """ - for ver in self.NetFxSdkVersion: - loc = os.path.join(self.ri.netfx_sdk, ver) - sdkdir = self.ri.lookup(loc, 'kitsinstallationfolder') - if sdkdir: - break - return sdkdir or '' - - @property - def FrameworkDir32(self): - """ - Microsoft .NET Framework 32bit directory. - """ - # Default path - guess_fw = os.path.join(self.WinDir, r'Microsoft.NET\Framework') - - # Try to get path from registry, if fail use default path - return self.ri.lookup(self.ri.vc, 'frameworkdir32') or guess_fw - - @property - def FrameworkDir64(self): - """ - Microsoft .NET Framework 64bit directory. - """ - # Default path - guess_fw = os.path.join(self.WinDir, r'Microsoft.NET\Framework64') - - # Try to get path from registry, if fail use default path - return self.ri.lookup(self.ri.vc, 'frameworkdir64') or guess_fw - - @property - def FrameworkVersion32(self): - """ - Microsoft .NET Framework 32bit versions. - """ - return self._find_dot_net_versions(32) - - @property - def FrameworkVersion64(self): - """ - Microsoft .NET Framework 64bit versions. - """ - return self._find_dot_net_versions(64) - - def _find_dot_net_versions(self, bits): - """ - Find Microsoft .NET Framework versions. - - Parameters - ---------- - bits: int - Platform number of bits: 32 or 64. - """ - # Find actual .NET version in registry - reg_ver = self.ri.lookup(self.ri.vc, 'frameworkver%d' % bits) - dot_net_dir = getattr(self, 'FrameworkDir%d' % bits) - ver = reg_ver or self._use_last_dir_name(dot_net_dir, 'v') or '' - - # Set .NET versions for specified MSVC++ version - if self.vc_ver >= 12.0: - frameworkver = (ver, 'v4.0') - elif self.vc_ver >= 10.0: - frameworkver = ('v4.0.30319' if ver.lower()[:2] != 'v4' else ver, - 'v3.5') - elif self.vc_ver == 9.0: - frameworkver = ('v3.5', 'v2.0.50727') - if self.vc_ver == 8.0: - frameworkver = ('v3.0', 'v2.0.50727') - return frameworkver - - def _use_last_dir_name(self, path, prefix=''): - """ - Return name of the last dir in path or '' if no dir found. - - Parameters - ---------- - path: str - Use dirs in this path - prefix: str - Use only dirs startings by this prefix - """ - matching_dirs = ( - dir_name - for dir_name in reversed(os.listdir(path)) - if os.path.isdir(os.path.join(path, dir_name)) and - dir_name.startswith(prefix) - ) - return next(matching_dirs, None) or '' - - -class EnvironmentInfo: - """ - Return environment variables for specified Microsoft Visual C++ version - and platform : Lib, Include, Path and libpath. - - This function is compatible with Microsoft Visual C++ 9.0 to 14.0. - - Script created by analysing Microsoft environment configuration files like - "vcvars[...].bat", "SetEnv.Cmd", "vcbuildtools.bat", ... - - Parameters - ---------- - arch: str - Target architecture. - vc_ver: float - Required Microsoft Visual C++ version. If not set, autodetect the last - version. - vc_min_ver: float - Minimum Microsoft Visual C++ version. - """ - - # Variables and properties in this class use originals CamelCase variables - # names from Microsoft source files for more easy comparaison. - - def __init__(self, arch, vc_ver=None, vc_min_ver=0): - self.pi = PlatformInfo(arch) - self.ri = RegistryInfo(self.pi) - self.si = SystemInfo(self.ri, vc_ver) - - if self.vc_ver < vc_min_ver: - err = 'No suitable Microsoft Visual C++ version found' - raise distutils.errors.DistutilsPlatformError(err) - - @property - def vc_ver(self): - """ - Microsoft Visual C++ version. - """ - return self.si.vc_ver - - @property - def VSTools(self): - """ - Microsoft Visual Studio Tools - """ - paths = [r'Common7\IDE', r'Common7\Tools'] - - if self.vc_ver >= 14.0: - arch_subdir = self.pi.current_dir(hidex86=True, x64=True) - paths += [r'Common7\IDE\CommonExtensions\Microsoft\TestWindow'] - paths += [r'Team Tools\Performance Tools'] - paths += [r'Team Tools\Performance Tools%s' % arch_subdir] - - return [os.path.join(self.si.VSInstallDir, path) for path in paths] - - @property - def VCIncludes(self): - """ - Microsoft Visual C++ & Microsoft Foundation Class Includes - """ - return [os.path.join(self.si.VCInstallDir, 'Include'), - os.path.join(self.si.VCInstallDir, r'ATLMFC\Include')] - - @property - def VCLibraries(self): - """ - Microsoft Visual C++ & Microsoft Foundation Class Libraries - """ - if self.vc_ver >= 15.0: - arch_subdir = self.pi.target_dir(x64=True) - else: - arch_subdir = self.pi.target_dir(hidex86=True) - paths = ['Lib%s' % arch_subdir, r'ATLMFC\Lib%s' % arch_subdir] - - if self.vc_ver >= 14.0: - paths += [r'Lib\store%s' % arch_subdir] - - return [os.path.join(self.si.VCInstallDir, path) for path in paths] - - @property - def VCStoreRefs(self): - """ - Microsoft Visual C++ store references Libraries - """ - if self.vc_ver < 14.0: - return [] - return [os.path.join(self.si.VCInstallDir, r'Lib\store\references')] - - @property - def VCTools(self): - """ - Microsoft Visual C++ Tools - """ - si = self.si - tools = [os.path.join(si.VCInstallDir, 'VCPackages')] - - forcex86 = True if self.vc_ver <= 10.0 else False - arch_subdir = self.pi.cross_dir(forcex86) - if arch_subdir: - tools += [os.path.join(si.VCInstallDir, 'Bin%s' % arch_subdir)] - - if self.vc_ver == 14.0: - path = 'Bin%s' % self.pi.current_dir(hidex86=True) - tools += [os.path.join(si.VCInstallDir, path)] - - elif self.vc_ver >= 15.0: - host_dir = (r'bin\HostX86%s' if self.pi.current_is_x86() else - r'bin\HostX64%s') - tools += [os.path.join( - si.VCInstallDir, host_dir % self.pi.target_dir(x64=True))] - - if self.pi.current_cpu != self.pi.target_cpu: - tools += [os.path.join( - si.VCInstallDir, host_dir % self.pi.current_dir(x64=True))] - - else: - tools += [os.path.join(si.VCInstallDir, 'Bin')] - - return tools - - @property - def OSLibraries(self): - """ - Microsoft Windows SDK Libraries - """ - if self.vc_ver <= 10.0: - arch_subdir = self.pi.target_dir(hidex86=True, x64=True) - return [os.path.join(self.si.WindowsSdkDir, 'Lib%s' % arch_subdir)] - - else: - arch_subdir = self.pi.target_dir(x64=True) - lib = os.path.join(self.si.WindowsSdkDir, 'lib') - libver = self._sdk_subdir - return [os.path.join(lib, '%sum%s' % (libver , arch_subdir))] - - @property - def OSIncludes(self): - """ - Microsoft Windows SDK Include - """ - include = os.path.join(self.si.WindowsSdkDir, 'include') - - if self.vc_ver <= 10.0: - return [include, os.path.join(include, 'gl')] - - else: - if self.vc_ver >= 14.0: - sdkver = self._sdk_subdir - else: - sdkver = '' - return [os.path.join(include, '%sshared' % sdkver), - os.path.join(include, '%sum' % sdkver), - os.path.join(include, '%swinrt' % sdkver)] - - @property - def OSLibpath(self): - """ - Microsoft Windows SDK Libraries Paths - """ - ref = os.path.join(self.si.WindowsSdkDir, 'References') - libpath = [] - - if self.vc_ver <= 9.0: - libpath += self.OSLibraries - - if self.vc_ver >= 11.0: - libpath += [os.path.join(ref, r'CommonConfiguration\Neutral')] - - if self.vc_ver >= 14.0: - libpath += [ - ref, - os.path.join(self.si.WindowsSdkDir, 'UnionMetadata'), - os.path.join( - ref, - 'Windows.Foundation.UniversalApiContract', - '1.0.0.0', - ), - os.path.join( - ref, - 'Windows.Foundation.FoundationContract', - '1.0.0.0', - ), - os.path.join( - ref, - 'Windows.Networking.Connectivity.WwanContract', - '1.0.0.0', - ), - os.path.join( - self.si.WindowsSdkDir, - 'ExtensionSDKs', - 'Microsoft.VCLibs', - '%0.1f' % self.vc_ver, - 'References', - 'CommonConfiguration', - 'neutral', - ), - ] - return libpath - - @property - def SdkTools(self): - """ - Microsoft Windows SDK Tools - """ - return list(self._sdk_tools()) - - def _sdk_tools(self): - """ - Microsoft Windows SDK Tools paths generator - """ - if self.vc_ver < 15.0: - bin_dir = 'Bin' if self.vc_ver <= 11.0 else r'Bin\x86' - yield os.path.join(self.si.WindowsSdkDir, bin_dir) - - if not self.pi.current_is_x86(): - arch_subdir = self.pi.current_dir(x64=True) - path = 'Bin%s' % arch_subdir - yield os.path.join(self.si.WindowsSdkDir, path) - - if self.vc_ver == 10.0 or self.vc_ver == 11.0: - if self.pi.target_is_x86(): - arch_subdir = '' - else: - arch_subdir = self.pi.current_dir(hidex86=True, x64=True) - path = r'Bin\NETFX 4.0 Tools%s' % arch_subdir - yield os.path.join(self.si.WindowsSdkDir, path) - - elif self.vc_ver >= 15.0: - path = os.path.join(self.si.WindowsSdkDir, 'Bin') - arch_subdir = self.pi.current_dir(x64=True) - sdkver = self.si.WindowsSdkLastVersion - yield os.path.join(path, '%s%s' % (sdkver, arch_subdir)) - - if self.si.WindowsSDKExecutablePath: - yield self.si.WindowsSDKExecutablePath - - @property - def _sdk_subdir(self): - """ - Microsoft Windows SDK version subdir - """ - ucrtver = self.si.WindowsSdkLastVersion - return ('%s\\' % ucrtver) if ucrtver else '' - - @property - def SdkSetup(self): - """ - Microsoft Windows SDK Setup - """ - if self.vc_ver > 9.0: - return [] - - return [os.path.join(self.si.WindowsSdkDir, 'Setup')] - - @property - def FxTools(self): - """ - Microsoft .NET Framework Tools - """ - pi = self.pi - si = self.si - - if self.vc_ver <= 10.0: - include32 = True - include64 = not pi.target_is_x86() and not pi.current_is_x86() - else: - include32 = pi.target_is_x86() or pi.current_is_x86() - include64 = pi.current_cpu == 'amd64' or pi.target_cpu == 'amd64' - - tools = [] - if include32: - tools += [os.path.join(si.FrameworkDir32, ver) - for ver in si.FrameworkVersion32] - if include64: - tools += [os.path.join(si.FrameworkDir64, ver) - for ver in si.FrameworkVersion64] - return tools - - @property - def NetFxSDKLibraries(self): - """ - Microsoft .Net Framework SDK Libraries - """ - if self.vc_ver < 14.0 or not self.si.NetFxSdkDir: - return [] - - arch_subdir = self.pi.target_dir(x64=True) - return [os.path.join(self.si.NetFxSdkDir, r'lib\um%s' % arch_subdir)] - - @property - def NetFxSDKIncludes(self): - """ - Microsoft .Net Framework SDK Includes - """ - if self.vc_ver < 14.0 or not self.si.NetFxSdkDir: - return [] - - return [os.path.join(self.si.NetFxSdkDir, r'include\um')] - - @property - def VsTDb(self): - """ - Microsoft Visual Studio Team System Database - """ - return [os.path.join(self.si.VSInstallDir, r'VSTSDB\Deploy')] - - @property - def MSBuild(self): - """ - Microsoft Build Engine - """ - if self.vc_ver < 12.0: - return [] - elif self.vc_ver < 15.0: - base_path = self.si.ProgramFilesx86 - arch_subdir = self.pi.current_dir(hidex86=True) - else: - base_path = self.si.VSInstallDir - arch_subdir = '' - - path = r'MSBuild\%0.1f\bin%s' % (self.vc_ver, arch_subdir) - build = [os.path.join(base_path, path)] - - if self.vc_ver >= 15.0: - # Add Roslyn C# & Visual Basic Compiler - build += [os.path.join(base_path, path, 'Roslyn')] - - return build - - @property - def HTMLHelpWorkshop(self): - """ - Microsoft HTML Help Workshop - """ - if self.vc_ver < 11.0: - return [] - - return [os.path.join(self.si.ProgramFilesx86, 'HTML Help Workshop')] - - @property - def UCRTLibraries(self): - """ - Microsoft Universal C Runtime SDK Libraries - """ - if self.vc_ver < 14.0: - return [] - - arch_subdir = self.pi.target_dir(x64=True) - lib = os.path.join(self.si.UniversalCRTSdkDir, 'lib') - ucrtver = self._ucrt_subdir - return [os.path.join(lib, '%sucrt%s' % (ucrtver, arch_subdir))] - - @property - def UCRTIncludes(self): - """ - Microsoft Universal C Runtime SDK Include - """ - if self.vc_ver < 14.0: - return [] - - include = os.path.join(self.si.UniversalCRTSdkDir, 'include') - return [os.path.join(include, '%sucrt' % self._ucrt_subdir)] - - @property - def _ucrt_subdir(self): - """ - Microsoft Universal C Runtime SDK version subdir - """ - ucrtver = self.si.UniversalCRTSdkLastVersion - return ('%s\\' % ucrtver) if ucrtver else '' - - @property - def FSharp(self): - """ - Microsoft Visual F# - """ - if self.vc_ver < 11.0 and self.vc_ver > 12.0: - return [] - - return self.si.FSharpInstallDir - - @property - def VCRuntimeRedist(self): - """ - Microsoft Visual C++ runtime redistribuable dll - """ - arch_subdir = self.pi.target_dir(x64=True) - if self.vc_ver < 15: - redist_path = self.si.VCInstallDir - vcruntime = 'redist%s\\Microsoft.VC%d0.CRT\\vcruntime%d0.dll' - else: - redist_path = self.si.VCInstallDir.replace('\\Tools', '\\Redist') - vcruntime = 'onecore%s\\Microsoft.VC%d0.CRT\\vcruntime%d0.dll' - - # Visual Studio 2017 is still Visual C++ 14.0 - dll_ver = 14.0 if self.vc_ver == 15 else self.vc_ver - - vcruntime = vcruntime % (arch_subdir, self.vc_ver, dll_ver) - return os.path.join(redist_path, vcruntime) - - def return_env(self, exists=True): - """ - Return environment dict. - - Parameters - ---------- - exists: bool - It True, only return existing paths. - """ - env = dict( - include=self._build_paths('include', - [self.VCIncludes, - self.OSIncludes, - self.UCRTIncludes, - self.NetFxSDKIncludes], - exists), - lib=self._build_paths('lib', - [self.VCLibraries, - self.OSLibraries, - self.FxTools, - self.UCRTLibraries, - self.NetFxSDKLibraries], - exists), - libpath=self._build_paths('libpath', - [self.VCLibraries, - self.FxTools, - self.VCStoreRefs, - self.OSLibpath], - exists), - path=self._build_paths('path', - [self.VCTools, - self.VSTools, - self.VsTDb, - self.SdkTools, - self.SdkSetup, - self.FxTools, - self.MSBuild, - self.HTMLHelpWorkshop, - self.FSharp], - exists), - ) - if self.vc_ver >= 14 and os.path.isfile(self.VCRuntimeRedist): - env['py_vcruntime_redist'] = self.VCRuntimeRedist - return env - - def _build_paths(self, name, spec_path_lists, exists): - """ - Given an environment variable name and specified paths, - return a pathsep-separated string of paths containing - unique, extant, directories from those paths and from - the environment variable. Raise an error if no paths - are resolved. - """ - # flatten spec_path_lists - spec_paths = itertools.chain.from_iterable(spec_path_lists) - env_paths = safe_env.get(name, '').split(os.pathsep) - paths = itertools.chain(spec_paths, env_paths) - extant_paths = list(filter(os.path.isdir, paths)) if exists else paths - if not extant_paths: - msg = "%s environment variable is empty" % name.upper() - raise distutils.errors.DistutilsPlatformError(msg) - unique_paths = self._unique_everseen(extant_paths) - return os.pathsep.join(unique_paths) - - # from Python docs - def _unique_everseen(self, iterable, key=None): - """ - List unique elements, preserving order. - Remember all elements ever seen. - - _unique_everseen('AAAABBBCCDAABBB') --> A B C D - - _unique_everseen('ABBCcAD', str.lower) --> A B C D - """ - seen = set() - seen_add = seen.add - if key is None: - for element in filterfalse(seen.__contains__, iterable): - seen_add(element) - yield element - else: - for element in iterable: - k = key(element) - if k not in seen: - seen_add(k) - yield element diff --git a/venv2/lib/python2.7/site-packages/setuptools/namespaces.py b/venv2/lib/python2.7/site-packages/setuptools/namespaces.py deleted file mode 100644 index dc16106..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/namespaces.py +++ /dev/null @@ -1,107 +0,0 @@ -import os -from distutils import log -import itertools - -from setuptools.extern.six.moves import map - - -flatten = itertools.chain.from_iterable - - -class Installer: - - nspkg_ext = '-nspkg.pth' - - def install_namespaces(self): - nsp = self._get_all_ns_packages() - if not nsp: - return - filename, ext = os.path.splitext(self._get_target()) - filename += self.nspkg_ext - self.outputs.append(filename) - log.info("Installing %s", filename) - lines = map(self._gen_nspkg_line, nsp) - - if self.dry_run: - # always generate the lines, even in dry run - list(lines) - return - - with open(filename, 'wt') as f: - f.writelines(lines) - - def uninstall_namespaces(self): - filename, ext = os.path.splitext(self._get_target()) - filename += self.nspkg_ext - if not os.path.exists(filename): - return - log.info("Removing %s", filename) - os.remove(filename) - - def _get_target(self): - return self.target - - _nspkg_tmpl = ( - "import sys, types, os", - "has_mfs = sys.version_info > (3, 5)", - "p = os.path.join(%(root)s, *%(pth)r)", - "importlib = has_mfs and __import__('importlib.util')", - "has_mfs and __import__('importlib.machinery')", - "m = has_mfs and " - "sys.modules.setdefault(%(pkg)r, " - "importlib.util.module_from_spec(" - "importlib.machinery.PathFinder.find_spec(%(pkg)r, " - "[os.path.dirname(p)])))", - "m = m or " - "sys.modules.setdefault(%(pkg)r, types.ModuleType(%(pkg)r))", - "mp = (m or []) and m.__dict__.setdefault('__path__',[])", - "(p not in mp) and mp.append(p)", - ) - "lines for the namespace installer" - - _nspkg_tmpl_multi = ( - 'm and setattr(sys.modules[%(parent)r], %(child)r, m)', - ) - "additional line(s) when a parent package is indicated" - - def _get_root(self): - return "sys._getframe(1).f_locals['sitedir']" - - def _gen_nspkg_line(self, pkg): - # ensure pkg is not a unicode string under Python 2.7 - pkg = str(pkg) - pth = tuple(pkg.split('.')) - root = self._get_root() - tmpl_lines = self._nspkg_tmpl - parent, sep, child = pkg.rpartition('.') - if parent: - tmpl_lines += self._nspkg_tmpl_multi - return ';'.join(tmpl_lines) % locals() + '\n' - - def _get_all_ns_packages(self): - """Return sorted list of all package namespaces""" - pkgs = self.distribution.namespace_packages or [] - return sorted(flatten(map(self._pkg_names, pkgs))) - - @staticmethod - def _pkg_names(pkg): - """ - Given a namespace package, yield the components of that - package. - - >>> names = Installer._pkg_names('a.b.c') - >>> set(names) == set(['a', 'a.b', 'a.b.c']) - True - """ - parts = pkg.split('.') - while parts: - yield '.'.join(parts) - parts.pop() - - -class DevelopInstaller(Installer): - def _get_root(self): - return repr(str(self.egg_path)) - - def _get_target(self): - return self.egg_link diff --git a/venv2/lib/python2.7/site-packages/setuptools/package_index.py b/venv2/lib/python2.7/site-packages/setuptools/package_index.py deleted file mode 100644 index 6b06f2c..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/package_index.py +++ /dev/null @@ -1,1136 +0,0 @@ -"""PyPI and direct package downloading""" -import sys -import os -import re -import shutil -import socket -import base64 -import hashlib -import itertools -import warnings -from functools import wraps - -from setuptools.extern import six -from setuptools.extern.six.moves import urllib, http_client, configparser, map - -import setuptools -from pkg_resources import ( - CHECKOUT_DIST, Distribution, BINARY_DIST, normalize_path, SOURCE_DIST, - Environment, find_distributions, safe_name, safe_version, - to_filename, Requirement, DEVELOP_DIST, EGG_DIST, -) -from setuptools import ssl_support -from distutils import log -from distutils.errors import DistutilsError -from fnmatch import translate -from setuptools.py27compat import get_all_headers -from setuptools.py33compat import unescape -from setuptools.wheel import Wheel - -__metaclass__ = type - -EGG_FRAGMENT = re.compile(r'^egg=([-A-Za-z0-9_.+!]+)$') -HREF = re.compile(r"""href\s*=\s*['"]?([^'"> ]+)""", re.I) -PYPI_MD5 = re.compile( - r'<a href="([^"#]+)">([^<]+)</a>\n\s+\(<a (?:title="MD5 hash"\n\s+)' - r'href="[^?]+\?:action=show_md5&digest=([0-9a-f]{32})">md5</a>\)' -) -URL_SCHEME = re.compile('([-+.a-z0-9]{2,}):', re.I).match -EXTENSIONS = ".tar.gz .tar.bz2 .tar .zip .tgz".split() - -__all__ = [ - 'PackageIndex', 'distros_for_url', 'parse_bdist_wininst', - 'interpret_distro_name', -] - -_SOCKET_TIMEOUT = 15 - -_tmpl = "setuptools/{setuptools.__version__} Python-urllib/{py_major}" -user_agent = _tmpl.format(py_major=sys.version[:3], setuptools=setuptools) - - -def parse_requirement_arg(spec): - try: - return Requirement.parse(spec) - except ValueError: - raise DistutilsError( - "Not a URL, existing file, or requirement spec: %r" % (spec,) - ) - - -def parse_bdist_wininst(name): - """Return (base,pyversion) or (None,None) for possible .exe name""" - - lower = name.lower() - base, py_ver, plat = None, None, None - - if lower.endswith('.exe'): - if lower.endswith('.win32.exe'): - base = name[:-10] - plat = 'win32' - elif lower.startswith('.win32-py', -16): - py_ver = name[-7:-4] - base = name[:-16] - plat = 'win32' - elif lower.endswith('.win-amd64.exe'): - base = name[:-14] - plat = 'win-amd64' - elif lower.startswith('.win-amd64-py', -20): - py_ver = name[-7:-4] - base = name[:-20] - plat = 'win-amd64' - return base, py_ver, plat - - -def egg_info_for_url(url): - parts = urllib.parse.urlparse(url) - scheme, server, path, parameters, query, fragment = parts - base = urllib.parse.unquote(path.split('/')[-1]) - if server == 'sourceforge.net' and base == 'download': # XXX Yuck - base = urllib.parse.unquote(path.split('/')[-2]) - if '#' in base: - base, fragment = base.split('#', 1) - return base, fragment - - -def distros_for_url(url, metadata=None): - """Yield egg or source distribution objects that might be found at a URL""" - base, fragment = egg_info_for_url(url) - for dist in distros_for_location(url, base, metadata): - yield dist - if fragment: - match = EGG_FRAGMENT.match(fragment) - if match: - for dist in interpret_distro_name( - url, match.group(1), metadata, precedence=CHECKOUT_DIST - ): - yield dist - - -def distros_for_location(location, basename, metadata=None): - """Yield egg or source distribution objects based on basename""" - if basename.endswith('.egg.zip'): - basename = basename[:-4] # strip the .zip - if basename.endswith('.egg') and '-' in basename: - # only one, unambiguous interpretation - return [Distribution.from_location(location, basename, metadata)] - if basename.endswith('.whl') and '-' in basename: - wheel = Wheel(basename) - if not wheel.is_compatible(): - return [] - return [Distribution( - location=location, - project_name=wheel.project_name, - version=wheel.version, - # Increase priority over eggs. - precedence=EGG_DIST + 1, - )] - if basename.endswith('.exe'): - win_base, py_ver, platform = parse_bdist_wininst(basename) - if win_base is not None: - return interpret_distro_name( - location, win_base, metadata, py_ver, BINARY_DIST, platform - ) - # Try source distro extensions (.zip, .tgz, etc.) - # - for ext in EXTENSIONS: - if basename.endswith(ext): - basename = basename[:-len(ext)] - return interpret_distro_name(location, basename, metadata) - return [] # no extension matched - - -def distros_for_filename(filename, metadata=None): - """Yield possible egg or source distribution objects based on a filename""" - return distros_for_location( - normalize_path(filename), os.path.basename(filename), metadata - ) - - -def interpret_distro_name( - location, basename, metadata, py_version=None, precedence=SOURCE_DIST, - platform=None -): - """Generate alternative interpretations of a source distro name - - Note: if `location` is a filesystem filename, you should call - ``pkg_resources.normalize_path()`` on it before passing it to this - routine! - """ - # Generate alternative interpretations of a source distro name - # Because some packages are ambiguous as to name/versions split - # e.g. "adns-python-1.1.0", "egenix-mx-commercial", etc. - # So, we generate each possible interepretation (e.g. "adns, python-1.1.0" - # "adns-python, 1.1.0", and "adns-python-1.1.0, no version"). In practice, - # the spurious interpretations should be ignored, because in the event - # there's also an "adns" package, the spurious "python-1.1.0" version will - # compare lower than any numeric version number, and is therefore unlikely - # to match a request for it. It's still a potential problem, though, and - # in the long run PyPI and the distutils should go for "safe" names and - # versions in distribution archive names (sdist and bdist). - - parts = basename.split('-') - if not py_version and any(re.match(r'py\d\.\d$', p) for p in parts[2:]): - # it is a bdist_dumb, not an sdist -- bail out - return - - for p in range(1, len(parts) + 1): - yield Distribution( - location, metadata, '-'.join(parts[:p]), '-'.join(parts[p:]), - py_version=py_version, precedence=precedence, - platform=platform - ) - - -# From Python 2.7 docs -def unique_everseen(iterable, key=None): - "List unique elements, preserving order. Remember all elements ever seen." - # unique_everseen('AAAABBBCCDAABBB') --> A B C D - # unique_everseen('ABBCcAD', str.lower) --> A B C D - seen = set() - seen_add = seen.add - if key is None: - for element in six.moves.filterfalse(seen.__contains__, iterable): - seen_add(element) - yield element - else: - for element in iterable: - k = key(element) - if k not in seen: - seen_add(k) - yield element - - -def unique_values(func): - """ - Wrap a function returning an iterable such that the resulting iterable - only ever yields unique items. - """ - - @wraps(func) - def wrapper(*args, **kwargs): - return unique_everseen(func(*args, **kwargs)) - - return wrapper - - -REL = re.compile(r"""<([^>]*\srel\s*=\s*['"]?([^'">]+)[^>]*)>""", re.I) -# this line is here to fix emacs' cruddy broken syntax highlighting - - -@unique_values -def find_external_links(url, page): - """Find rel="homepage" and rel="download" links in `page`, yielding URLs""" - - for match in REL.finditer(page): - tag, rel = match.groups() - rels = set(map(str.strip, rel.lower().split(','))) - if 'homepage' in rels or 'download' in rels: - for match in HREF.finditer(tag): - yield urllib.parse.urljoin(url, htmldecode(match.group(1))) - - for tag in ("<th>Home Page", "<th>Download URL"): - pos = page.find(tag) - if pos != -1: - match = HREF.search(page, pos) - if match: - yield urllib.parse.urljoin(url, htmldecode(match.group(1))) - - -class ContentChecker: - """ - A null content checker that defines the interface for checking content - """ - - def feed(self, block): - """ - Feed a block of data to the hash. - """ - return - - def is_valid(self): - """ - Check the hash. Return False if validation fails. - """ - return True - - def report(self, reporter, template): - """ - Call reporter with information about the checker (hash name) - substituted into the template. - """ - return - - -class HashChecker(ContentChecker): - pattern = re.compile( - r'(?P<hash_name>sha1|sha224|sha384|sha256|sha512|md5)=' - r'(?P<expected>[a-f0-9]+)' - ) - - def __init__(self, hash_name, expected): - self.hash_name = hash_name - self.hash = hashlib.new(hash_name) - self.expected = expected - - @classmethod - def from_url(cls, url): - "Construct a (possibly null) ContentChecker from a URL" - fragment = urllib.parse.urlparse(url)[-1] - if not fragment: - return ContentChecker() - match = cls.pattern.search(fragment) - if not match: - return ContentChecker() - return cls(**match.groupdict()) - - def feed(self, block): - self.hash.update(block) - - def is_valid(self): - return self.hash.hexdigest() == self.expected - - def report(self, reporter, template): - msg = template % self.hash_name - return reporter(msg) - - -class PackageIndex(Environment): - """A distribution index that scans web pages for download URLs""" - - def __init__( - self, index_url="https://pypi.org/simple/", hosts=('*',), - ca_bundle=None, verify_ssl=True, *args, **kw - ): - Environment.__init__(self, *args, **kw) - self.index_url = index_url + "/" [:not index_url.endswith('/')] - self.scanned_urls = {} - self.fetched_urls = {} - self.package_pages = {} - self.allows = re.compile('|'.join(map(translate, hosts))).match - self.to_scan = [] - use_ssl = ( - verify_ssl - and ssl_support.is_available - and (ca_bundle or ssl_support.find_ca_bundle()) - ) - if use_ssl: - self.opener = ssl_support.opener_for(ca_bundle) - else: - self.opener = urllib.request.urlopen - - def process_url(self, url, retrieve=False): - """Evaluate a URL as a possible download, and maybe retrieve it""" - if url in self.scanned_urls and not retrieve: - return - self.scanned_urls[url] = True - if not URL_SCHEME(url): - self.process_filename(url) - return - else: - dists = list(distros_for_url(url)) - if dists: - if not self.url_ok(url): - return - self.debug("Found link: %s", url) - - if dists or not retrieve or url in self.fetched_urls: - list(map(self.add, dists)) - return # don't need the actual page - - if not self.url_ok(url): - self.fetched_urls[url] = True - return - - self.info("Reading %s", url) - self.fetched_urls[url] = True # prevent multiple fetch attempts - tmpl = "Download error on %s: %%s -- Some packages may not be found!" - f = self.open_url(url, tmpl % url) - if f is None: - return - self.fetched_urls[f.url] = True - if 'html' not in f.headers.get('content-type', '').lower(): - f.close() # not html, we can't process it - return - - base = f.url # handle redirects - page = f.read() - if not isinstance(page, str): - # In Python 3 and got bytes but want str. - if isinstance(f, urllib.error.HTTPError): - # Errors have no charset, assume latin1: - charset = 'latin-1' - else: - charset = f.headers.get_param('charset') or 'latin-1' - page = page.decode(charset, "ignore") - f.close() - for match in HREF.finditer(page): - link = urllib.parse.urljoin(base, htmldecode(match.group(1))) - self.process_url(link) - if url.startswith(self.index_url) and getattr(f, 'code', None) != 404: - page = self.process_index(url, page) - - def process_filename(self, fn, nested=False): - # process filenames or directories - if not os.path.exists(fn): - self.warn("Not found: %s", fn) - return - - if os.path.isdir(fn) and not nested: - path = os.path.realpath(fn) - for item in os.listdir(path): - self.process_filename(os.path.join(path, item), True) - - dists = distros_for_filename(fn) - if dists: - self.debug("Found: %s", fn) - list(map(self.add, dists)) - - def url_ok(self, url, fatal=False): - s = URL_SCHEME(url) - is_file = s and s.group(1).lower() == 'file' - if is_file or self.allows(urllib.parse.urlparse(url)[1]): - return True - msg = ( - "\nNote: Bypassing %s (disallowed host; see " - "http://bit.ly/2hrImnY for details).\n") - if fatal: - raise DistutilsError(msg % url) - else: - self.warn(msg, url) - - def scan_egg_links(self, search_path): - dirs = filter(os.path.isdir, search_path) - egg_links = ( - (path, entry) - for path in dirs - for entry in os.listdir(path) - if entry.endswith('.egg-link') - ) - list(itertools.starmap(self.scan_egg_link, egg_links)) - - def scan_egg_link(self, path, entry): - with open(os.path.join(path, entry)) as raw_lines: - # filter non-empty lines - lines = list(filter(None, map(str.strip, raw_lines))) - - if len(lines) != 2: - # format is not recognized; punt - return - - egg_path, setup_path = lines - - for dist in find_distributions(os.path.join(path, egg_path)): - dist.location = os.path.join(path, *lines) - dist.precedence = SOURCE_DIST - self.add(dist) - - def process_index(self, url, page): - """Process the contents of a PyPI page""" - - def scan(link): - # Process a URL to see if it's for a package page - if link.startswith(self.index_url): - parts = list(map( - urllib.parse.unquote, link[len(self.index_url):].split('/') - )) - if len(parts) == 2 and '#' not in parts[1]: - # it's a package page, sanitize and index it - pkg = safe_name(parts[0]) - ver = safe_version(parts[1]) - self.package_pages.setdefault(pkg.lower(), {})[link] = True - return to_filename(pkg), to_filename(ver) - return None, None - - # process an index page into the package-page index - for match in HREF.finditer(page): - try: - scan(urllib.parse.urljoin(url, htmldecode(match.group(1)))) - except ValueError: - pass - - pkg, ver = scan(url) # ensure this page is in the page index - if pkg: - # process individual package page - for new_url in find_external_links(url, page): - # Process the found URL - base, frag = egg_info_for_url(new_url) - if base.endswith('.py') and not frag: - if ver: - new_url += '#egg=%s-%s' % (pkg, ver) - else: - self.need_version_info(url) - self.scan_url(new_url) - - return PYPI_MD5.sub( - lambda m: '<a href="%s#md5=%s">%s</a>' % m.group(1, 3, 2), page - ) - else: - return "" # no sense double-scanning non-package pages - - def need_version_info(self, url): - self.scan_all( - "Page at %s links to .py file(s) without version info; an index " - "scan is required.", url - ) - - def scan_all(self, msg=None, *args): - if self.index_url not in self.fetched_urls: - if msg: - self.warn(msg, *args) - self.info( - "Scanning index of all packages (this may take a while)" - ) - self.scan_url(self.index_url) - - def find_packages(self, requirement): - self.scan_url(self.index_url + requirement.unsafe_name + '/') - - if not self.package_pages.get(requirement.key): - # Fall back to safe version of the name - self.scan_url(self.index_url + requirement.project_name + '/') - - if not self.package_pages.get(requirement.key): - # We couldn't find the target package, so search the index page too - self.not_found_in_index(requirement) - - for url in list(self.package_pages.get(requirement.key, ())): - # scan each page that might be related to the desired package - self.scan_url(url) - - def obtain(self, requirement, installer=None): - self.prescan() - self.find_packages(requirement) - for dist in self[requirement.key]: - if dist in requirement: - return dist - self.debug("%s does not match %s", requirement, dist) - return super(PackageIndex, self).obtain(requirement, installer) - - def check_hash(self, checker, filename, tfp): - """ - checker is a ContentChecker - """ - checker.report( - self.debug, - "Validating %%s checksum for %s" % filename) - if not checker.is_valid(): - tfp.close() - os.unlink(filename) - raise DistutilsError( - "%s validation failed for %s; " - "possible download problem?" - % (checker.hash.name, os.path.basename(filename)) - ) - - def add_find_links(self, urls): - """Add `urls` to the list that will be prescanned for searches""" - for url in urls: - if ( - self.to_scan is None # if we have already "gone online" - or not URL_SCHEME(url) # or it's a local file/directory - or url.startswith('file:') - or list(distros_for_url(url)) # or a direct package link - ): - # then go ahead and process it now - self.scan_url(url) - else: - # otherwise, defer retrieval till later - self.to_scan.append(url) - - def prescan(self): - """Scan urls scheduled for prescanning (e.g. --find-links)""" - if self.to_scan: - list(map(self.scan_url, self.to_scan)) - self.to_scan = None # from now on, go ahead and process immediately - - def not_found_in_index(self, requirement): - if self[requirement.key]: # we've seen at least one distro - meth, msg = self.info, "Couldn't retrieve index page for %r" - else: # no distros seen for this name, might be misspelled - meth, msg = ( - self.warn, - "Couldn't find index page for %r (maybe misspelled?)") - meth(msg, requirement.unsafe_name) - self.scan_all() - - def download(self, spec, tmpdir): - """Locate and/or download `spec` to `tmpdir`, returning a local path - - `spec` may be a ``Requirement`` object, or a string containing a URL, - an existing local filename, or a project/version requirement spec - (i.e. the string form of a ``Requirement`` object). If it is the URL - of a .py file with an unambiguous ``#egg=name-version`` tag (i.e., one - that escapes ``-`` as ``_`` throughout), a trivial ``setup.py`` is - automatically created alongside the downloaded file. - - If `spec` is a ``Requirement`` object or a string containing a - project/version requirement spec, this method returns the location of - a matching distribution (possibly after downloading it to `tmpdir`). - If `spec` is a locally existing file or directory name, it is simply - returned unchanged. If `spec` is a URL, it is downloaded to a subpath - of `tmpdir`, and the local filename is returned. Various errors may be - raised if a problem occurs during downloading. - """ - if not isinstance(spec, Requirement): - scheme = URL_SCHEME(spec) - if scheme: - # It's a url, download it to tmpdir - found = self._download_url(scheme.group(1), spec, tmpdir) - base, fragment = egg_info_for_url(spec) - if base.endswith('.py'): - found = self.gen_setup(found, fragment, tmpdir) - return found - elif os.path.exists(spec): - # Existing file or directory, just return it - return spec - else: - spec = parse_requirement_arg(spec) - return getattr(self.fetch_distribution(spec, tmpdir), 'location', None) - - def fetch_distribution( - self, requirement, tmpdir, force_scan=False, source=False, - develop_ok=False, local_index=None): - """Obtain a distribution suitable for fulfilling `requirement` - - `requirement` must be a ``pkg_resources.Requirement`` instance. - If necessary, or if the `force_scan` flag is set, the requirement is - searched for in the (online) package index as well as the locally - installed packages. If a distribution matching `requirement` is found, - the returned distribution's ``location`` is the value you would have - gotten from calling the ``download()`` method with the matching - distribution's URL or filename. If no matching distribution is found, - ``None`` is returned. - - If the `source` flag is set, only source distributions and source - checkout links will be considered. Unless the `develop_ok` flag is - set, development and system eggs (i.e., those using the ``.egg-info`` - format) will be ignored. - """ - # process a Requirement - self.info("Searching for %s", requirement) - skipped = {} - dist = None - - def find(req, env=None): - if env is None: - env = self - # Find a matching distribution; may be called more than once - - for dist in env[req.key]: - - if dist.precedence == DEVELOP_DIST and not develop_ok: - if dist not in skipped: - self.warn( - "Skipping development or system egg: %s", dist, - ) - skipped[dist] = 1 - continue - - test = ( - dist in req - and (dist.precedence <= SOURCE_DIST or not source) - ) - if test: - loc = self.download(dist.location, tmpdir) - dist.download_location = loc - if os.path.exists(dist.download_location): - return dist - - if force_scan: - self.prescan() - self.find_packages(requirement) - dist = find(requirement) - - if not dist and local_index is not None: - dist = find(requirement, local_index) - - if dist is None: - if self.to_scan is not None: - self.prescan() - dist = find(requirement) - - if dist is None and not force_scan: - self.find_packages(requirement) - dist = find(requirement) - - if dist is None: - self.warn( - "No local packages or working download links found for %s%s", - (source and "a source distribution of " or ""), - requirement, - ) - else: - self.info("Best match: %s", dist) - return dist.clone(location=dist.download_location) - - def fetch(self, requirement, tmpdir, force_scan=False, source=False): - """Obtain a file suitable for fulfilling `requirement` - - DEPRECATED; use the ``fetch_distribution()`` method now instead. For - backward compatibility, this routine is identical but returns the - ``location`` of the downloaded distribution instead of a distribution - object. - """ - dist = self.fetch_distribution(requirement, tmpdir, force_scan, source) - if dist is not None: - return dist.location - return None - - def gen_setup(self, filename, fragment, tmpdir): - match = EGG_FRAGMENT.match(fragment) - dists = match and [ - d for d in - interpret_distro_name(filename, match.group(1), None) if d.version - ] or [] - - if len(dists) == 1: # unambiguous ``#egg`` fragment - basename = os.path.basename(filename) - - # Make sure the file has been downloaded to the temp dir. - if os.path.dirname(filename) != tmpdir: - dst = os.path.join(tmpdir, basename) - from setuptools.command.easy_install import samefile - if not samefile(filename, dst): - shutil.copy2(filename, dst) - filename = dst - - with open(os.path.join(tmpdir, 'setup.py'), 'w') as file: - file.write( - "from setuptools import setup\n" - "setup(name=%r, version=%r, py_modules=[%r])\n" - % ( - dists[0].project_name, dists[0].version, - os.path.splitext(basename)[0] - ) - ) - return filename - - elif match: - raise DistutilsError( - "Can't unambiguously interpret project/version identifier %r; " - "any dashes in the name or version should be escaped using " - "underscores. %r" % (fragment, dists) - ) - else: - raise DistutilsError( - "Can't process plain .py files without an '#egg=name-version'" - " suffix to enable automatic setup script generation." - ) - - dl_blocksize = 8192 - - def _download_to(self, url, filename): - self.info("Downloading %s", url) - # Download the file - fp = None - try: - checker = HashChecker.from_url(url) - fp = self.open_url(url) - if isinstance(fp, urllib.error.HTTPError): - raise DistutilsError( - "Can't download %s: %s %s" % (url, fp.code, fp.msg) - ) - headers = fp.info() - blocknum = 0 - bs = self.dl_blocksize - size = -1 - if "content-length" in headers: - # Some servers return multiple Content-Length headers :( - sizes = get_all_headers(headers, 'Content-Length') - size = max(map(int, sizes)) - self.reporthook(url, filename, blocknum, bs, size) - with open(filename, 'wb') as tfp: - while True: - block = fp.read(bs) - if block: - checker.feed(block) - tfp.write(block) - blocknum += 1 - self.reporthook(url, filename, blocknum, bs, size) - else: - break - self.check_hash(checker, filename, tfp) - return headers - finally: - if fp: - fp.close() - - def reporthook(self, url, filename, blocknum, blksize, size): - pass # no-op - - def open_url(self, url, warning=None): - if url.startswith('file:'): - return local_open(url) - try: - return open_with_auth(url, self.opener) - except (ValueError, http_client.InvalidURL) as v: - msg = ' '.join([str(arg) for arg in v.args]) - if warning: - self.warn(warning, msg) - else: - raise DistutilsError('%s %s' % (url, msg)) - except urllib.error.HTTPError as v: - return v - except urllib.error.URLError as v: - if warning: - self.warn(warning, v.reason) - else: - raise DistutilsError("Download error for %s: %s" - % (url, v.reason)) - except http_client.BadStatusLine as v: - if warning: - self.warn(warning, v.line) - else: - raise DistutilsError( - '%s returned a bad status line. The server might be ' - 'down, %s' % - (url, v.line) - ) - except (http_client.HTTPException, socket.error) as v: - if warning: - self.warn(warning, v) - else: - raise DistutilsError("Download error for %s: %s" - % (url, v)) - - def _download_url(self, scheme, url, tmpdir): - # Determine download filename - # - name, fragment = egg_info_for_url(url) - if name: - while '..' in name: - name = name.replace('..', '.').replace('\\', '_') - else: - name = "__downloaded__" # default if URL has no path contents - - if name.endswith('.egg.zip'): - name = name[:-4] # strip the extra .zip before download - - filename = os.path.join(tmpdir, name) - - # Download the file - # - if scheme == 'svn' or scheme.startswith('svn+'): - return self._download_svn(url, filename) - elif scheme == 'git' or scheme.startswith('git+'): - return self._download_git(url, filename) - elif scheme.startswith('hg+'): - return self._download_hg(url, filename) - elif scheme == 'file': - return urllib.request.url2pathname(urllib.parse.urlparse(url)[2]) - else: - self.url_ok(url, True) # raises error if not allowed - return self._attempt_download(url, filename) - - def scan_url(self, url): - self.process_url(url, True) - - def _attempt_download(self, url, filename): - headers = self._download_to(url, filename) - if 'html' in headers.get('content-type', '').lower(): - return self._download_html(url, headers, filename) - else: - return filename - - def _download_html(self, url, headers, filename): - file = open(filename) - for line in file: - if line.strip(): - # Check for a subversion index page - if re.search(r'<title>([^- ]+ - )?Revision \d+:', line): - # it's a subversion index page: - file.close() - os.unlink(filename) - return self._download_svn(url, filename) - break # not an index page - file.close() - os.unlink(filename) - raise DistutilsError("Unexpected HTML page found at " + url) - - def _download_svn(self, url, filename): - warnings.warn("SVN download support is deprecated", UserWarning) - url = url.split('#', 1)[0] # remove any fragment for svn's sake - creds = '' - if url.lower().startswith('svn:') and '@' in url: - scheme, netloc, path, p, q, f = urllib.parse.urlparse(url) - if not netloc and path.startswith('//') and '/' in path[2:]: - netloc, path = path[2:].split('/', 1) - auth, host = _splituser(netloc) - if auth: - if ':' in auth: - user, pw = auth.split(':', 1) - creds = " --username=%s --password=%s" % (user, pw) - else: - creds = " --username=" + auth - netloc = host - parts = scheme, netloc, url, p, q, f - url = urllib.parse.urlunparse(parts) - self.info("Doing subversion checkout from %s to %s", url, filename) - os.system("svn checkout%s -q %s %s" % (creds, url, filename)) - return filename - - @staticmethod - def _vcs_split_rev_from_url(url, pop_prefix=False): - scheme, netloc, path, query, frag = urllib.parse.urlsplit(url) - - scheme = scheme.split('+', 1)[-1] - - # Some fragment identification fails - path = path.split('#', 1)[0] - - rev = None - if '@' in path: - path, rev = path.rsplit('@', 1) - - # Also, discard fragment - url = urllib.parse.urlunsplit((scheme, netloc, path, query, '')) - - return url, rev - - def _download_git(self, url, filename): - filename = filename.split('#', 1)[0] - url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True) - - self.info("Doing git clone from %s to %s", url, filename) - os.system("git clone --quiet %s %s" % (url, filename)) - - if rev is not None: - self.info("Checking out %s", rev) - os.system("git -C %s checkout --quiet %s" % ( - filename, - rev, - )) - - return filename - - def _download_hg(self, url, filename): - filename = filename.split('#', 1)[0] - url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True) - - self.info("Doing hg clone from %s to %s", url, filename) - os.system("hg clone --quiet %s %s" % (url, filename)) - - if rev is not None: - self.info("Updating to %s", rev) - os.system("hg --cwd %s up -C -r %s -q" % ( - filename, - rev, - )) - - return filename - - def debug(self, msg, *args): - log.debug(msg, *args) - - def info(self, msg, *args): - log.info(msg, *args) - - def warn(self, msg, *args): - log.warn(msg, *args) - - -# This pattern matches a character entity reference (a decimal numeric -# references, a hexadecimal numeric reference, or a named reference). -entity_sub = re.compile(r'&(#(\d+|x[\da-fA-F]+)|[\w.:-]+);?').sub - - -def decode_entity(match): - what = match.group(0) - return unescape(what) - - -def htmldecode(text): - """ - Decode HTML entities in the given text. - - >>> htmldecode( - ... 'https://../package_name-0.1.2.tar.gz' - ... '?tokena=A&tokenb=B">package_name-0.1.2.tar.gz') - 'https://../package_name-0.1.2.tar.gz?tokena=A&tokenb=B">package_name-0.1.2.tar.gz' - """ - return entity_sub(decode_entity, text) - - -def socket_timeout(timeout=15): - def _socket_timeout(func): - def _socket_timeout(*args, **kwargs): - old_timeout = socket.getdefaulttimeout() - socket.setdefaulttimeout(timeout) - try: - return func(*args, **kwargs) - finally: - socket.setdefaulttimeout(old_timeout) - - return _socket_timeout - - return _socket_timeout - - -def _encode_auth(auth): - """ - A function compatible with Python 2.3-3.3 that will encode - auth from a URL suitable for an HTTP header. - >>> str(_encode_auth('username%3Apassword')) - 'dXNlcm5hbWU6cGFzc3dvcmQ=' - - Long auth strings should not cause a newline to be inserted. - >>> long_auth = 'username:' + 'password'*10 - >>> chr(10) in str(_encode_auth(long_auth)) - False - """ - auth_s = urllib.parse.unquote(auth) - # convert to bytes - auth_bytes = auth_s.encode() - encoded_bytes = base64.b64encode(auth_bytes) - # convert back to a string - encoded = encoded_bytes.decode() - # strip the trailing carriage return - return encoded.replace('\n', '') - - -class Credential: - """ - A username/password pair. Use like a namedtuple. - """ - - def __init__(self, username, password): - self.username = username - self.password = password - - def __iter__(self): - yield self.username - yield self.password - - def __str__(self): - return '%(username)s:%(password)s' % vars(self) - - -class PyPIConfig(configparser.RawConfigParser): - def __init__(self): - """ - Load from ~/.pypirc - """ - defaults = dict.fromkeys(['username', 'password', 'repository'], '') - configparser.RawConfigParser.__init__(self, defaults) - - rc = os.path.join(os.path.expanduser('~'), '.pypirc') - if os.path.exists(rc): - self.read(rc) - - @property - def creds_by_repository(self): - sections_with_repositories = [ - section for section in self.sections() - if self.get(section, 'repository').strip() - ] - - return dict(map(self._get_repo_cred, sections_with_repositories)) - - def _get_repo_cred(self, section): - repo = self.get(section, 'repository').strip() - return repo, Credential( - self.get(section, 'username').strip(), - self.get(section, 'password').strip(), - ) - - def find_credential(self, url): - """ - If the URL indicated appears to be a repository defined in this - config, return the credential for that repository. - """ - for repository, cred in self.creds_by_repository.items(): - if url.startswith(repository): - return cred - - -def open_with_auth(url, opener=urllib.request.urlopen): - """Open a urllib2 request, handling HTTP authentication""" - - parsed = urllib.parse.urlparse(url) - scheme, netloc, path, params, query, frag = parsed - - # Double scheme does not raise on Mac OS X as revealed by a - # failing test. We would expect "nonnumeric port". Refs #20. - if netloc.endswith(':'): - raise http_client.InvalidURL("nonnumeric port: ''") - - if scheme in ('http', 'https'): - auth, address = _splituser(netloc) - else: - auth = None - - if not auth: - cred = PyPIConfig().find_credential(url) - if cred: - auth = str(cred) - info = cred.username, url - log.info('Authenticating as %s for %s (from .pypirc)', *info) - - if auth: - auth = "Basic " + _encode_auth(auth) - parts = scheme, address, path, params, query, frag - new_url = urllib.parse.urlunparse(parts) - request = urllib.request.Request(new_url) - request.add_header("Authorization", auth) - else: - request = urllib.request.Request(url) - - request.add_header('User-Agent', user_agent) - fp = opener(request) - - if auth: - # Put authentication info back into request URL if same host, - # so that links found on the page will work - s2, h2, path2, param2, query2, frag2 = urllib.parse.urlparse(fp.url) - if s2 == scheme and h2 == address: - parts = s2, netloc, path2, param2, query2, frag2 - fp.url = urllib.parse.urlunparse(parts) - - return fp - - -# copy of urllib.parse._splituser from Python 3.8 -def _splituser(host): - """splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'.""" - user, delim, host = host.rpartition('@') - return (user if delim else None), host - - -# adding a timeout to avoid freezing package_index -open_with_auth = socket_timeout(_SOCKET_TIMEOUT)(open_with_auth) - - -def fix_sf_url(url): - return url # backward compatibility - - -def local_open(url): - """Read a local path, with special support for directories""" - scheme, server, path, param, query, frag = urllib.parse.urlparse(url) - filename = urllib.request.url2pathname(path) - if os.path.isfile(filename): - return urllib.request.urlopen(url) - elif path.endswith('/') and os.path.isdir(filename): - files = [] - for f in os.listdir(filename): - filepath = os.path.join(filename, f) - if f == 'index.html': - with open(filepath, 'r') as fp: - body = fp.read() - break - elif os.path.isdir(filepath): - f += '/' - files.append('<a href="{name}">{name}</a>'.format(name=f)) - else: - tmpl = ( - "<html><head><title>{url}" - "{files}") - body = tmpl.format(url=url, files='\n'.join(files)) - status, message = 200, "OK" - else: - status, message, body = 404, "Path not found", "Not found" - - headers = {'content-type': 'text/html'} - body_stream = six.StringIO(body) - return urllib.error.HTTPError(url, status, message, headers, body_stream) diff --git a/venv2/lib/python2.7/site-packages/setuptools/pep425tags.py b/venv2/lib/python2.7/site-packages/setuptools/pep425tags.py deleted file mode 100644 index 48745a2..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/pep425tags.py +++ /dev/null @@ -1,319 +0,0 @@ -# This file originally from pip: -# https://github.com/pypa/pip/blob/8f4f15a5a95d7d5b511ceaee9ed261176c181970/src/pip/_internal/pep425tags.py -"""Generate and work with PEP 425 Compatibility Tags.""" -from __future__ import absolute_import - -import distutils.util -from distutils import log -import platform -import re -import sys -import sysconfig -import warnings -from collections import OrderedDict - -from .extern import six - -from . import glibc - -_osx_arch_pat = re.compile(r'(.+)_(\d+)_(\d+)_(.+)') - - -def get_config_var(var): - try: - return sysconfig.get_config_var(var) - except IOError as e: # Issue #1074 - warnings.warn("{}".format(e), RuntimeWarning) - return None - - -def get_abbr_impl(): - """Return abbreviated implementation name.""" - if hasattr(sys, 'pypy_version_info'): - pyimpl = 'pp' - elif sys.platform.startswith('java'): - pyimpl = 'jy' - elif sys.platform == 'cli': - pyimpl = 'ip' - else: - pyimpl = 'cp' - return pyimpl - - -def get_impl_ver(): - """Return implementation version.""" - impl_ver = get_config_var("py_version_nodot") - if not impl_ver or get_abbr_impl() == 'pp': - impl_ver = ''.join(map(str, get_impl_version_info())) - return impl_ver - - -def get_impl_version_info(): - """Return sys.version_info-like tuple for use in decrementing the minor - version.""" - if get_abbr_impl() == 'pp': - # as per https://github.com/pypa/pip/issues/2882 - return (sys.version_info[0], sys.pypy_version_info.major, - sys.pypy_version_info.minor) - else: - return sys.version_info[0], sys.version_info[1] - - -def get_impl_tag(): - """ - Returns the Tag for this specific implementation. - """ - return "{}{}".format(get_abbr_impl(), get_impl_ver()) - - -def get_flag(var, fallback, expected=True, warn=True): - """Use a fallback method for determining SOABI flags if the needed config - var is unset or unavailable.""" - val = get_config_var(var) - if val is None: - if warn: - log.debug("Config variable '%s' is unset, Python ABI tag may " - "be incorrect", var) - return fallback() - return val == expected - - -def get_abi_tag(): - """Return the ABI tag based on SOABI (if available) or emulate SOABI - (CPython 2, PyPy).""" - soabi = get_config_var('SOABI') - impl = get_abbr_impl() - if not soabi and impl in {'cp', 'pp'} and hasattr(sys, 'maxunicode'): - d = '' - m = '' - u = '' - if get_flag('Py_DEBUG', - lambda: hasattr(sys, 'gettotalrefcount'), - warn=(impl == 'cp')): - d = 'd' - if get_flag('WITH_PYMALLOC', - lambda: impl == 'cp', - warn=(impl == 'cp')): - m = 'm' - if get_flag('Py_UNICODE_SIZE', - lambda: sys.maxunicode == 0x10ffff, - expected=4, - warn=(impl == 'cp' and - six.PY2)) \ - and six.PY2: - u = 'u' - abi = '%s%s%s%s%s' % (impl, get_impl_ver(), d, m, u) - elif soabi and soabi.startswith('cpython-'): - abi = 'cp' + soabi.split('-')[1] - elif soabi: - abi = soabi.replace('.', '_').replace('-', '_') - else: - abi = None - return abi - - -def _is_running_32bit(): - return sys.maxsize == 2147483647 - - -def get_platform(): - """Return our platform name 'win32', 'linux_x86_64'""" - if sys.platform == 'darwin': - # distutils.util.get_platform() returns the release based on the value - # of MACOSX_DEPLOYMENT_TARGET on which Python was built, which may - # be significantly older than the user's current machine. - release, _, machine = platform.mac_ver() - split_ver = release.split('.') - - if machine == "x86_64" and _is_running_32bit(): - machine = "i386" - elif machine == "ppc64" and _is_running_32bit(): - machine = "ppc" - - return 'macosx_{}_{}_{}'.format(split_ver[0], split_ver[1], machine) - - # XXX remove distutils dependency - result = distutils.util.get_platform().replace('.', '_').replace('-', '_') - if result == "linux_x86_64" and _is_running_32bit(): - # 32 bit Python program (running on a 64 bit Linux): pip should only - # install and run 32 bit compiled extensions in that case. - result = "linux_i686" - - return result - - -def is_manylinux1_compatible(): - # Only Linux, and only x86-64 / i686 - if get_platform() not in {"linux_x86_64", "linux_i686"}: - return False - - # Check for presence of _manylinux module - try: - import _manylinux - return bool(_manylinux.manylinux1_compatible) - except (ImportError, AttributeError): - # Fall through to heuristic check below - pass - - # Check glibc version. CentOS 5 uses glibc 2.5. - return glibc.have_compatible_glibc(2, 5) - - -def get_darwin_arches(major, minor, machine): - """Return a list of supported arches (including group arches) for - the given major, minor and machine architecture of a macOS machine. - """ - arches = [] - - def _supports_arch(major, minor, arch): - # Looking at the application support for macOS versions in the chart - # provided by https://en.wikipedia.org/wiki/OS_X#Versions it appears - # our timeline looks roughly like: - # - # 10.0 - Introduces ppc support. - # 10.4 - Introduces ppc64, i386, and x86_64 support, however the ppc64 - # and x86_64 support is CLI only, and cannot be used for GUI - # applications. - # 10.5 - Extends ppc64 and x86_64 support to cover GUI applications. - # 10.6 - Drops support for ppc64 - # 10.7 - Drops support for ppc - # - # Given that we do not know if we're installing a CLI or a GUI - # application, we must be conservative and assume it might be a GUI - # application and behave as if ppc64 and x86_64 support did not occur - # until 10.5. - # - # Note: The above information is taken from the "Application support" - # column in the chart not the "Processor support" since I believe - # that we care about what instruction sets an application can use - # not which processors the OS supports. - if arch == 'ppc': - return (major, minor) <= (10, 5) - if arch == 'ppc64': - return (major, minor) == (10, 5) - if arch == 'i386': - return (major, minor) >= (10, 4) - if arch == 'x86_64': - return (major, minor) >= (10, 5) - if arch in groups: - for garch in groups[arch]: - if _supports_arch(major, minor, garch): - return True - return False - - groups = OrderedDict([ - ("fat", ("i386", "ppc")), - ("intel", ("x86_64", "i386")), - ("fat64", ("x86_64", "ppc64")), - ("fat32", ("x86_64", "i386", "ppc")), - ]) - - if _supports_arch(major, minor, machine): - arches.append(machine) - - for garch in groups: - if machine in groups[garch] and _supports_arch(major, minor, garch): - arches.append(garch) - - arches.append('universal') - - return arches - - -def get_supported(versions=None, noarch=False, platform=None, - impl=None, abi=None): - """Return a list of supported tags for each version specified in - `versions`. - - :param versions: a list of string versions, of the form ["33", "32"], - or None. The first version will be assumed to support our ABI. - :param platform: specify the exact platform you want valid - tags for, or None. If None, use the local system platform. - :param impl: specify the exact implementation you want valid - tags for, or None. If None, use the local interpreter impl. - :param abi: specify the exact abi you want valid - tags for, or None. If None, use the local interpreter abi. - """ - supported = [] - - # Versions must be given with respect to the preference - if versions is None: - versions = [] - version_info = get_impl_version_info() - major = version_info[:-1] - # Support all previous minor Python versions. - for minor in range(version_info[-1], -1, -1): - versions.append(''.join(map(str, major + (minor,)))) - - impl = impl or get_abbr_impl() - - abis = [] - - abi = abi or get_abi_tag() - if abi: - abis[0:0] = [abi] - - abi3s = set() - import imp - for suffix in imp.get_suffixes(): - if suffix[0].startswith('.abi'): - abi3s.add(suffix[0].split('.', 2)[1]) - - abis.extend(sorted(list(abi3s))) - - abis.append('none') - - if not noarch: - arch = platform or get_platform() - if arch.startswith('macosx'): - # support macosx-10.6-intel on macosx-10.9-x86_64 - match = _osx_arch_pat.match(arch) - if match: - name, major, minor, actual_arch = match.groups() - tpl = '{}_{}_%i_%s'.format(name, major) - arches = [] - for m in reversed(range(int(minor) + 1)): - for a in get_darwin_arches(int(major), m, actual_arch): - arches.append(tpl % (m, a)) - else: - # arch pattern didn't match (?!) - arches = [arch] - elif platform is None and is_manylinux1_compatible(): - arches = [arch.replace('linux', 'manylinux1'), arch] - else: - arches = [arch] - - # Current version, current API (built specifically for our Python): - for abi in abis: - for arch in arches: - supported.append(('%s%s' % (impl, versions[0]), abi, arch)) - - # abi3 modules compatible with older version of Python - for version in versions[1:]: - # abi3 was introduced in Python 3.2 - if version in {'31', '30'}: - break - for abi in abi3s: # empty set if not Python 3 - for arch in arches: - supported.append(("%s%s" % (impl, version), abi, arch)) - - # Has binaries, does not use the Python API: - for arch in arches: - supported.append(('py%s' % (versions[0][0]), 'none', arch)) - - # No abi / arch, but requires our implementation: - supported.append(('%s%s' % (impl, versions[0]), 'none', 'any')) - # Tagged specifically as being cross-version compatible - # (with just the major version specified) - supported.append(('%s%s' % (impl, versions[0][0]), 'none', 'any')) - - # No abi / arch, generic Python - for i, version in enumerate(versions): - supported.append(('py%s' % (version,), 'none', 'any')) - if i == 0: - supported.append(('py%s' % (version[0]), 'none', 'any')) - - return supported - - -implementation_tag = get_impl_tag() diff --git a/venv2/lib/python2.7/site-packages/setuptools/py27compat.py b/venv2/lib/python2.7/site-packages/setuptools/py27compat.py deleted file mode 100644 index 2985011..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/py27compat.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -Compatibility Support for Python 2.7 and earlier -""" - -import platform - -from setuptools.extern import six - - -def get_all_headers(message, key): - """ - Given an HTTPMessage, return all headers matching a given key. - """ - return message.get_all(key) - - -if six.PY2: - def get_all_headers(message, key): - return message.getheaders(key) - - -linux_py2_ascii = ( - platform.system() == 'Linux' and - six.PY2 -) - -rmtree_safe = str if linux_py2_ascii else lambda x: x -"""Workaround for http://bugs.python.org/issue24672""" diff --git a/venv2/lib/python2.7/site-packages/setuptools/py31compat.py b/venv2/lib/python2.7/site-packages/setuptools/py31compat.py deleted file mode 100644 index e1da7ee..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/py31compat.py +++ /dev/null @@ -1,32 +0,0 @@ -__all__ = [] - -__metaclass__ = type - - -try: - # Python >=3.2 - from tempfile import TemporaryDirectory -except ImportError: - import shutil - import tempfile - - class TemporaryDirectory: - """ - Very simple temporary directory context manager. - Will try to delete afterward, but will also ignore OS and similar - errors on deletion. - """ - - def __init__(self, **kwargs): - self.name = None # Handle mkdtemp raising an exception - self.name = tempfile.mkdtemp(**kwargs) - - def __enter__(self): - return self.name - - def __exit__(self, exctype, excvalue, exctrace): - try: - shutil.rmtree(self.name, True) - except OSError: # removal errors are not the only possible - pass - self.name = None diff --git a/venv2/lib/python2.7/site-packages/setuptools/py33compat.py b/venv2/lib/python2.7/site-packages/setuptools/py33compat.py deleted file mode 100644 index 87cf539..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/py33compat.py +++ /dev/null @@ -1,55 +0,0 @@ -import dis -import array -import collections - -try: - import html -except ImportError: - html = None - -from setuptools.extern import six -from setuptools.extern.six.moves import html_parser - -__metaclass__ = type - -OpArg = collections.namedtuple('OpArg', 'opcode arg') - - -class Bytecode_compat: - def __init__(self, code): - self.code = code - - def __iter__(self): - """Yield '(op,arg)' pair for each operation in code object 'code'""" - - bytes = array.array('b', self.code.co_code) - eof = len(self.code.co_code) - - ptr = 0 - extended_arg = 0 - - while ptr < eof: - - op = bytes[ptr] - - if op >= dis.HAVE_ARGUMENT: - - arg = bytes[ptr + 1] + bytes[ptr + 2] * 256 + extended_arg - ptr += 3 - - if op == dis.EXTENDED_ARG: - long_type = six.integer_types[-1] - extended_arg = arg * long_type(65536) - continue - - else: - arg = None - ptr += 1 - - yield OpArg(op, arg) - - -Bytecode = getattr(dis, 'Bytecode', Bytecode_compat) - - -unescape = getattr(html, 'unescape', html_parser.HTMLParser().unescape) diff --git a/venv2/lib/python2.7/site-packages/setuptools/sandbox.py b/venv2/lib/python2.7/site-packages/setuptools/sandbox.py deleted file mode 100644 index 685f3f7..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/sandbox.py +++ /dev/null @@ -1,491 +0,0 @@ -import os -import sys -import tempfile -import operator -import functools -import itertools -import re -import contextlib -import pickle -import textwrap - -from setuptools.extern import six -from setuptools.extern.six.moves import builtins, map - -import pkg_resources.py31compat - -if sys.platform.startswith('java'): - import org.python.modules.posix.PosixModule as _os -else: - _os = sys.modules[os.name] -try: - _file = file -except NameError: - _file = None -_open = open -from distutils.errors import DistutilsError -from pkg_resources import working_set - - -__all__ = [ - "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", -] - - -def _execfile(filename, globals, locals=None): - """ - Python 3 implementation of execfile. - """ - mode = 'rb' - with open(filename, mode) as stream: - script = stream.read() - if locals is None: - locals = globals - code = compile(script, filename, 'exec') - exec(code, globals, locals) - - -@contextlib.contextmanager -def save_argv(repl=None): - saved = sys.argv[:] - if repl is not None: - sys.argv[:] = repl - try: - yield saved - finally: - sys.argv[:] = saved - - -@contextlib.contextmanager -def save_path(): - saved = sys.path[:] - try: - yield saved - finally: - sys.path[:] = saved - - -@contextlib.contextmanager -def override_temp(replacement): - """ - Monkey-patch tempfile.tempdir with replacement, ensuring it exists - """ - pkg_resources.py31compat.makedirs(replacement, exist_ok=True) - - saved = tempfile.tempdir - - tempfile.tempdir = replacement - - try: - yield - finally: - tempfile.tempdir = saved - - -@contextlib.contextmanager -def pushd(target): - saved = os.getcwd() - os.chdir(target) - try: - yield saved - finally: - os.chdir(saved) - - -class UnpickleableException(Exception): - """ - An exception representing another Exception that could not be pickled. - """ - - @staticmethod - def dump(type, exc): - """ - Always return a dumped (pickled) type and exc. If exc can't be pickled, - wrap it in UnpickleableException first. - """ - try: - return pickle.dumps(type), pickle.dumps(exc) - except Exception: - # get UnpickleableException inside the sandbox - from setuptools.sandbox import UnpickleableException as cls - return cls.dump(cls, cls(repr(exc))) - - -class ExceptionSaver: - """ - A Context Manager that will save an exception, serialized, and restore it - later. - """ - - def __enter__(self): - return self - - def __exit__(self, type, exc, tb): - if not exc: - return - - # dump the exception - self._saved = UnpickleableException.dump(type, exc) - self._tb = tb - - # suppress the exception - return True - - def resume(self): - "restore and re-raise any exception" - - if '_saved' not in vars(self): - return - - type, exc = map(pickle.loads, self._saved) - six.reraise(type, exc, self._tb) - - -@contextlib.contextmanager -def save_modules(): - """ - Context in which imported modules are saved. - - Translates exceptions internal to the context into the equivalent exception - outside the context. - """ - saved = sys.modules.copy() - with ExceptionSaver() as saved_exc: - yield saved - - sys.modules.update(saved) - # remove any modules imported since - del_modules = ( - mod_name for mod_name in sys.modules - if mod_name not in saved - # exclude any encodings modules. See #285 - and not mod_name.startswith('encodings.') - ) - _clear_modules(del_modules) - - saved_exc.resume() - - -def _clear_modules(module_names): - for mod_name in list(module_names): - del sys.modules[mod_name] - - -@contextlib.contextmanager -def save_pkg_resources_state(): - saved = pkg_resources.__getstate__() - try: - yield saved - finally: - pkg_resources.__setstate__(saved) - - -@contextlib.contextmanager -def setup_context(setup_dir): - temp_dir = os.path.join(setup_dir, 'temp') - with save_pkg_resources_state(): - with save_modules(): - hide_setuptools() - with save_path(): - with save_argv(): - with override_temp(temp_dir): - with pushd(setup_dir): - # ensure setuptools commands are available - __import__('setuptools') - yield - - -def _needs_hiding(mod_name): - """ - >>> _needs_hiding('setuptools') - True - >>> _needs_hiding('pkg_resources') - True - >>> _needs_hiding('setuptools_plugin') - False - >>> _needs_hiding('setuptools.__init__') - True - >>> _needs_hiding('distutils') - True - >>> _needs_hiding('os') - False - >>> _needs_hiding('Cython') - True - """ - pattern = re.compile(r'(setuptools|pkg_resources|distutils|Cython)(\.|$)') - return bool(pattern.match(mod_name)) - - -def hide_setuptools(): - """ - Remove references to setuptools' modules from sys.modules to allow the - invocation to import the most appropriate setuptools. This technique is - necessary to avoid issues such as #315 where setuptools upgrading itself - would fail to find a function declared in the metadata. - """ - modules = filter(_needs_hiding, sys.modules) - _clear_modules(modules) - - -def run_setup(setup_script, args): - """Run a distutils setup script, sandboxed in its directory""" - setup_dir = os.path.abspath(os.path.dirname(setup_script)) - with setup_context(setup_dir): - try: - sys.argv[:] = [setup_script] + list(args) - sys.path.insert(0, setup_dir) - # reset to include setup dir, w/clean callback list - working_set.__init__() - working_set.callbacks.append(lambda dist: dist.activate()) - - # __file__ should be a byte string on Python 2 (#712) - dunder_file = ( - setup_script - if isinstance(setup_script, str) else - setup_script.encode(sys.getfilesystemencoding()) - ) - - with DirectorySandbox(setup_dir): - ns = dict(__file__=dunder_file, __name__='__main__') - _execfile(setup_script, ns) - except SystemExit as v: - if v.args and v.args[0]: - raise - # Normal exit, just return - - -class AbstractSandbox: - """Wrap 'os' module and 'open()' builtin for virtualizing setup scripts""" - - _active = False - - def __init__(self): - self._attrs = [ - name for name in dir(_os) - if not name.startswith('_') and hasattr(self, name) - ] - - def _copy(self, source): - for name in self._attrs: - setattr(os, name, getattr(source, name)) - - def __enter__(self): - self._copy(self) - if _file: - builtins.file = self._file - builtins.open = self._open - self._active = True - - def __exit__(self, exc_type, exc_value, traceback): - self._active = False - if _file: - builtins.file = _file - builtins.open = _open - self._copy(_os) - - def run(self, func): - """Run 'func' under os sandboxing""" - with self: - return func() - - def _mk_dual_path_wrapper(name): - original = getattr(_os, name) - - def wrap(self, src, dst, *args, **kw): - if self._active: - src, dst = self._remap_pair(name, src, dst, *args, **kw) - return original(src, dst, *args, **kw) - - return wrap - - for name in ["rename", "link", "symlink"]: - if hasattr(_os, name): - locals()[name] = _mk_dual_path_wrapper(name) - - def _mk_single_path_wrapper(name, original=None): - original = original or getattr(_os, name) - - def wrap(self, path, *args, **kw): - if self._active: - path = self._remap_input(name, path, *args, **kw) - return original(path, *args, **kw) - - return wrap - - if _file: - _file = _mk_single_path_wrapper('file', _file) - _open = _mk_single_path_wrapper('open', _open) - for name in [ - "stat", "listdir", "chdir", "open", "chmod", "chown", "mkdir", - "remove", "unlink", "rmdir", "utime", "lchown", "chroot", "lstat", - "startfile", "mkfifo", "mknod", "pathconf", "access" - ]: - if hasattr(_os, name): - locals()[name] = _mk_single_path_wrapper(name) - - def _mk_single_with_return(name): - original = getattr(_os, name) - - def wrap(self, path, *args, **kw): - if self._active: - path = self._remap_input(name, path, *args, **kw) - return self._remap_output(name, original(path, *args, **kw)) - return original(path, *args, **kw) - - return wrap - - for name in ['readlink', 'tempnam']: - if hasattr(_os, name): - locals()[name] = _mk_single_with_return(name) - - def _mk_query(name): - original = getattr(_os, name) - - def wrap(self, *args, **kw): - retval = original(*args, **kw) - if self._active: - return self._remap_output(name, retval) - return retval - - return wrap - - for name in ['getcwd', 'tmpnam']: - if hasattr(_os, name): - locals()[name] = _mk_query(name) - - def _validate_path(self, path): - """Called to remap or validate any path, whether input or output""" - return path - - def _remap_input(self, operation, path, *args, **kw): - """Called for path inputs""" - return self._validate_path(path) - - def _remap_output(self, operation, path): - """Called for path outputs""" - return self._validate_path(path) - - def _remap_pair(self, operation, src, dst, *args, **kw): - """Called for path pairs like rename, link, and symlink operations""" - return ( - self._remap_input(operation + '-from', src, *args, **kw), - self._remap_input(operation + '-to', dst, *args, **kw) - ) - - -if hasattr(os, 'devnull'): - _EXCEPTIONS = [os.devnull,] -else: - _EXCEPTIONS = [] - - -class DirectorySandbox(AbstractSandbox): - """Restrict operations to a single subdirectory - pseudo-chroot""" - - write_ops = dict.fromkeys([ - "open", "chmod", "chown", "mkdir", "remove", "unlink", "rmdir", - "utime", "lchown", "chroot", "mkfifo", "mknod", "tempnam", - ]) - - _exception_patterns = [ - # Allow lib2to3 to attempt to save a pickled grammar object (#121) - r'.*lib2to3.*\.pickle$', - ] - "exempt writing to paths that match the pattern" - - def __init__(self, sandbox, exceptions=_EXCEPTIONS): - self._sandbox = os.path.normcase(os.path.realpath(sandbox)) - self._prefix = os.path.join(self._sandbox, '') - self._exceptions = [ - os.path.normcase(os.path.realpath(path)) - for path in exceptions - ] - AbstractSandbox.__init__(self) - - def _violation(self, operation, *args, **kw): - from setuptools.sandbox import SandboxViolation - raise SandboxViolation(operation, args, kw) - - if _file: - - def _file(self, path, mode='r', *args, **kw): - if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path): - self._violation("file", path, mode, *args, **kw) - return _file(path, mode, *args, **kw) - - def _open(self, path, mode='r', *args, **kw): - if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path): - self._violation("open", path, mode, *args, **kw) - return _open(path, mode, *args, **kw) - - def tmpnam(self): - self._violation("tmpnam") - - def _ok(self, path): - active = self._active - try: - self._active = False - realpath = os.path.normcase(os.path.realpath(path)) - return ( - self._exempted(realpath) - or realpath == self._sandbox - or realpath.startswith(self._prefix) - ) - finally: - self._active = active - - def _exempted(self, filepath): - start_matches = ( - filepath.startswith(exception) - for exception in self._exceptions - ) - pattern_matches = ( - re.match(pattern, filepath) - for pattern in self._exception_patterns - ) - candidates = itertools.chain(start_matches, pattern_matches) - return any(candidates) - - def _remap_input(self, operation, path, *args, **kw): - """Called for path inputs""" - if operation in self.write_ops and not self._ok(path): - self._violation(operation, os.path.realpath(path), *args, **kw) - return path - - def _remap_pair(self, operation, src, dst, *args, **kw): - """Called for path pairs like rename, link, and symlink operations""" - if not self._ok(src) or not self._ok(dst): - self._violation(operation, src, dst, *args, **kw) - return (src, dst) - - def open(self, file, flags, mode=0o777, *args, **kw): - """Called for low-level os.open()""" - if flags & WRITE_FLAGS and not self._ok(file): - self._violation("os.open", file, flags, mode, *args, **kw) - return _os.open(file, flags, mode, *args, **kw) - - -WRITE_FLAGS = functools.reduce( - operator.or_, [getattr(_os, a, 0) for a in - "O_WRONLY O_RDWR O_APPEND O_CREAT O_TRUNC O_TEMPORARY".split()] -) - - -class SandboxViolation(DistutilsError): - """A setup script attempted to modify the filesystem outside the sandbox""" - - tmpl = textwrap.dedent(""" - SandboxViolation: {cmd}{args!r} {kwargs} - - The package setup script has attempted to modify files on your system - that are not within the EasyInstall build area, and has been aborted. - - This package cannot be safely installed by EasyInstall, and may not - support alternate installation locations even if you run its setup - script by hand. Please inform the package's author and the EasyInstall - maintainers to find out if a fix or workaround is available. - """).lstrip() - - def __str__(self): - cmd, args, kwargs = self.args - return self.tmpl.format(**locals()) diff --git a/venv2/lib/python2.7/site-packages/setuptools/script (dev).tmpl b/venv2/lib/python2.7/site-packages/setuptools/script (dev).tmpl deleted file mode 100644 index 39a24b0..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/script (dev).tmpl +++ /dev/null @@ -1,6 +0,0 @@ -# EASY-INSTALL-DEV-SCRIPT: %(spec)r,%(script_name)r -__requires__ = %(spec)r -__import__('pkg_resources').require(%(spec)r) -__file__ = %(dev_path)r -with open(__file__) as f: - exec(compile(f.read(), __file__, 'exec')) diff --git a/venv2/lib/python2.7/site-packages/setuptools/script.tmpl b/venv2/lib/python2.7/site-packages/setuptools/script.tmpl deleted file mode 100644 index ff5efbc..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/script.tmpl +++ /dev/null @@ -1,3 +0,0 @@ -# EASY-INSTALL-SCRIPT: %(spec)r,%(script_name)r -__requires__ = %(spec)r -__import__('pkg_resources').run_script(%(spec)r, %(script_name)r) diff --git a/venv2/lib/python2.7/site-packages/setuptools/site-patch.py b/venv2/lib/python2.7/site-packages/setuptools/site-patch.py deleted file mode 100644 index 40b00de..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/site-patch.py +++ /dev/null @@ -1,74 +0,0 @@ -def __boot(): - import sys - import os - PYTHONPATH = os.environ.get('PYTHONPATH') - if PYTHONPATH is None or (sys.platform == 'win32' and not PYTHONPATH): - PYTHONPATH = [] - else: - PYTHONPATH = PYTHONPATH.split(os.pathsep) - - pic = getattr(sys, 'path_importer_cache', {}) - stdpath = sys.path[len(PYTHONPATH):] - mydir = os.path.dirname(__file__) - - for item in stdpath: - if item == mydir or not item: - continue # skip if current dir. on Windows, or my own directory - importer = pic.get(item) - if importer is not None: - loader = importer.find_module('site') - if loader is not None: - # This should actually reload the current module - loader.load_module('site') - break - else: - try: - import imp # Avoid import loop in Python 3 - stream, path, descr = imp.find_module('site', [item]) - except ImportError: - continue - if stream is None: - continue - try: - # This should actually reload the current module - imp.load_module('site', stream, path, descr) - finally: - stream.close() - break - else: - raise ImportError("Couldn't find the real 'site' module") - - known_paths = dict([(makepath(item)[1], 1) for item in sys.path]) # 2.2 comp - - oldpos = getattr(sys, '__egginsert', 0) # save old insertion position - sys.__egginsert = 0 # and reset the current one - - for item in PYTHONPATH: - addsitedir(item) - - sys.__egginsert += oldpos # restore effective old position - - d, nd = makepath(stdpath[0]) - insert_at = None - new_path = [] - - for item in sys.path: - p, np = makepath(item) - - if np == nd and insert_at is None: - # We've hit the first 'system' path entry, so added entries go here - insert_at = len(new_path) - - if np in known_paths or insert_at is None: - new_path.append(item) - else: - # new path after the insert point, back-insert it - new_path.insert(insert_at, item) - insert_at += 1 - - sys.path[:] = new_path - - -if __name__ == 'site': - __boot() - del __boot diff --git a/venv2/lib/python2.7/site-packages/setuptools/ssl_support.py b/venv2/lib/python2.7/site-packages/setuptools/ssl_support.py deleted file mode 100644 index 226db69..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/ssl_support.py +++ /dev/null @@ -1,260 +0,0 @@ -import os -import socket -import atexit -import re -import functools - -from setuptools.extern.six.moves import urllib, http_client, map, filter - -from pkg_resources import ResolutionError, ExtractionError - -try: - import ssl -except ImportError: - ssl = None - -__all__ = [ - 'VerifyingHTTPSHandler', 'find_ca_bundle', 'is_available', 'cert_paths', - 'opener_for' -] - -cert_paths = """ -/etc/pki/tls/certs/ca-bundle.crt -/etc/ssl/certs/ca-certificates.crt -/usr/share/ssl/certs/ca-bundle.crt -/usr/local/share/certs/ca-root.crt -/etc/ssl/cert.pem -/System/Library/OpenSSL/certs/cert.pem -/usr/local/share/certs/ca-root-nss.crt -/etc/ssl/ca-bundle.pem -""".strip().split() - -try: - HTTPSHandler = urllib.request.HTTPSHandler - HTTPSConnection = http_client.HTTPSConnection -except AttributeError: - HTTPSHandler = HTTPSConnection = object - -is_available = ssl is not None and object not in (HTTPSHandler, HTTPSConnection) - - -try: - from ssl import CertificateError, match_hostname -except ImportError: - try: - from backports.ssl_match_hostname import CertificateError - from backports.ssl_match_hostname import match_hostname - except ImportError: - CertificateError = None - match_hostname = None - -if not CertificateError: - - class CertificateError(ValueError): - pass - - -if not match_hostname: - - def _dnsname_match(dn, hostname, max_wildcards=1): - """Matching according to RFC 6125, section 6.4.3 - - https://tools.ietf.org/html/rfc6125#section-6.4.3 - """ - pats = [] - if not dn: - return False - - # Ported from python3-syntax: - # leftmost, *remainder = dn.split(r'.') - parts = dn.split(r'.') - leftmost = parts[0] - remainder = 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") - 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") - - -class VerifyingHTTPSHandler(HTTPSHandler): - """Simple verifying handler: no auth, subclasses, timeouts, etc.""" - - def __init__(self, ca_bundle): - self.ca_bundle = ca_bundle - HTTPSHandler.__init__(self) - - def https_open(self, req): - return self.do_open( - lambda host, **kw: VerifyingHTTPSConn(host, self.ca_bundle, **kw), req - ) - - -class VerifyingHTTPSConn(HTTPSConnection): - """Simple verifying connection: no auth, subclasses, timeouts, etc.""" - - def __init__(self, host, ca_bundle, **kw): - HTTPSConnection.__init__(self, host, **kw) - self.ca_bundle = ca_bundle - - def connect(self): - sock = socket.create_connection( - (self.host, self.port), getattr(self, 'source_address', None) - ) - - # Handle the socket if a (proxy) tunnel is present - if hasattr(self, '_tunnel') and getattr(self, '_tunnel_host', None): - self.sock = sock - self._tunnel() - # http://bugs.python.org/issue7776: Python>=3.4.1 and >=2.7.7 - # change self.host to mean the proxy server host when tunneling is - # being used. Adapt, since we are interested in the destination - # host for the match_hostname() comparison. - actual_host = self._tunnel_host - else: - actual_host = self.host - - if hasattr(ssl, 'create_default_context'): - ctx = ssl.create_default_context(cafile=self.ca_bundle) - self.sock = ctx.wrap_socket(sock, server_hostname=actual_host) - else: - # This is for python < 2.7.9 and < 3.4? - self.sock = ssl.wrap_socket( - sock, cert_reqs=ssl.CERT_REQUIRED, ca_certs=self.ca_bundle - ) - try: - match_hostname(self.sock.getpeercert(), actual_host) - except CertificateError: - self.sock.shutdown(socket.SHUT_RDWR) - self.sock.close() - raise - - -def opener_for(ca_bundle=None): - """Get a urlopen() replacement that uses ca_bundle for verification""" - return urllib.request.build_opener( - VerifyingHTTPSHandler(ca_bundle or find_ca_bundle()) - ).open - - -# from jaraco.functools -def once(func): - @functools.wraps(func) - def wrapper(*args, **kwargs): - if not hasattr(func, 'always_returns'): - func.always_returns = func(*args, **kwargs) - return func.always_returns - return wrapper - - -@once -def get_win_certfile(): - try: - import wincertstore - except ImportError: - return None - - class CertFile(wincertstore.CertFile): - def __init__(self): - super(CertFile, self).__init__() - atexit.register(self.close) - - def close(self): - try: - super(CertFile, self).close() - except OSError: - pass - - _wincerts = CertFile() - _wincerts.addstore('CA') - _wincerts.addstore('ROOT') - return _wincerts.name - - -def find_ca_bundle(): - """Return an existing CA bundle path, or None""" - extant_cert_paths = filter(os.path.isfile, cert_paths) - return ( - get_win_certfile() - or next(extant_cert_paths, None) - or _certifi_where() - ) - - -def _certifi_where(): - try: - return __import__('certifi').where() - except (ImportError, ResolutionError, ExtractionError): - pass diff --git a/venv2/lib/python2.7/site-packages/setuptools/unicode_utils.py b/venv2/lib/python2.7/site-packages/setuptools/unicode_utils.py deleted file mode 100644 index 7c63efd..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/unicode_utils.py +++ /dev/null @@ -1,44 +0,0 @@ -import unicodedata -import sys - -from setuptools.extern import six - - -# HFS Plus uses decomposed UTF-8 -def decompose(path): - if isinstance(path, six.text_type): - return unicodedata.normalize('NFD', path) - try: - path = path.decode('utf-8') - path = unicodedata.normalize('NFD', path) - path = path.encode('utf-8') - except UnicodeError: - pass # Not UTF-8 - return path - - -def filesys_decode(path): - """ - Ensure that the given path is decoded, - NONE when no expected encoding works - """ - - if isinstance(path, six.text_type): - return path - - fs_enc = sys.getfilesystemencoding() or 'utf-8' - candidates = fs_enc, 'utf-8' - - for enc in candidates: - try: - return path.decode(enc) - except UnicodeDecodeError: - continue - - -def try_encode(string, enc): - "turn unicode encoding into a functional routine" - try: - return string.encode(enc) - except UnicodeEncodeError: - return None diff --git a/venv2/lib/python2.7/site-packages/setuptools/version.py b/venv2/lib/python2.7/site-packages/setuptools/version.py deleted file mode 100644 index 95e1869..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/version.py +++ /dev/null @@ -1,6 +0,0 @@ -import pkg_resources - -try: - __version__ = pkg_resources.get_distribution('setuptools').version -except Exception: - __version__ = 'unknown' diff --git a/venv2/lib/python2.7/site-packages/setuptools/wheel.py b/venv2/lib/python2.7/site-packages/setuptools/wheel.py deleted file mode 100644 index e11f0a1..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/wheel.py +++ /dev/null @@ -1,211 +0,0 @@ -"""Wheels support.""" - -from distutils.util import get_platform -import email -import itertools -import os -import posixpath -import re -import zipfile - -import pkg_resources -import setuptools -from pkg_resources import parse_version -from setuptools.extern.packaging.utils import canonicalize_name -from setuptools.extern.six import PY3 -from setuptools import pep425tags -from setuptools.command.egg_info import write_requirements - - -__metaclass__ = type - - -WHEEL_NAME = re.compile( - r"""^(?P.+?)-(?P\d.*?) - ((-(?P\d.*?))?-(?P.+?)-(?P.+?)-(?P.+?) - )\.whl$""", - re.VERBOSE).match - -NAMESPACE_PACKAGE_INIT = '''\ -try: - __import__('pkg_resources').declare_namespace(__name__) -except ImportError: - __path__ = __import__('pkgutil').extend_path(__path__, __name__) -''' - - -def unpack(src_dir, dst_dir): - '''Move everything under `src_dir` to `dst_dir`, and delete the former.''' - for dirpath, dirnames, filenames in os.walk(src_dir): - subdir = os.path.relpath(dirpath, src_dir) - for f in filenames: - src = os.path.join(dirpath, f) - dst = os.path.join(dst_dir, subdir, f) - os.renames(src, dst) - for n, d in reversed(list(enumerate(dirnames))): - src = os.path.join(dirpath, d) - dst = os.path.join(dst_dir, subdir, d) - if not os.path.exists(dst): - # Directory does not exist in destination, - # rename it and prune it from os.walk list. - os.renames(src, dst) - del dirnames[n] - # Cleanup. - for dirpath, dirnames, filenames in os.walk(src_dir, topdown=True): - assert not filenames - os.rmdir(dirpath) - - -class Wheel: - - def __init__(self, filename): - match = WHEEL_NAME(os.path.basename(filename)) - if match is None: - raise ValueError('invalid wheel name: %r' % filename) - self.filename = filename - for k, v in match.groupdict().items(): - setattr(self, k, v) - - def tags(self): - '''List tags (py_version, abi, platform) supported by this wheel.''' - return itertools.product( - self.py_version.split('.'), - self.abi.split('.'), - self.platform.split('.'), - ) - - def is_compatible(self): - '''Is the wheel is compatible with the current platform?''' - supported_tags = pep425tags.get_supported() - return next((True for t in self.tags() if t in supported_tags), False) - - def egg_name(self): - return pkg_resources.Distribution( - project_name=self.project_name, version=self.version, - platform=(None if self.platform == 'any' else get_platform()), - ).egg_name() + '.egg' - - def get_dist_info(self, zf): - # find the correct name of the .dist-info dir in the wheel file - for member in zf.namelist(): - dirname = posixpath.dirname(member) - if (dirname.endswith('.dist-info') and - canonicalize_name(dirname).startswith( - canonicalize_name(self.project_name))): - return dirname - raise ValueError("unsupported wheel format. .dist-info not found") - - def install_as_egg(self, destination_eggdir): - '''Install wheel as an egg directory.''' - with zipfile.ZipFile(self.filename) as zf: - self._install_as_egg(destination_eggdir, zf) - - def _install_as_egg(self, destination_eggdir, zf): - dist_basename = '%s-%s' % (self.project_name, self.version) - dist_info = self.get_dist_info(zf) - dist_data = '%s.data' % dist_basename - egg_info = os.path.join(destination_eggdir, 'EGG-INFO') - - self._convert_metadata(zf, destination_eggdir, dist_info, egg_info) - self._move_data_entries(destination_eggdir, dist_data) - self._fix_namespace_packages(egg_info, destination_eggdir) - - @staticmethod - def _convert_metadata(zf, destination_eggdir, dist_info, egg_info): - def get_metadata(name): - with zf.open(posixpath.join(dist_info, name)) as fp: - value = fp.read().decode('utf-8') if PY3 else fp.read() - return email.parser.Parser().parsestr(value) - - wheel_metadata = get_metadata('WHEEL') - # Check wheel format version is supported. - wheel_version = parse_version(wheel_metadata.get('Wheel-Version')) - wheel_v1 = ( - parse_version('1.0') <= wheel_version < parse_version('2.0dev0') - ) - if not wheel_v1: - raise ValueError( - 'unsupported wheel format version: %s' % wheel_version) - # Extract to target directory. - os.mkdir(destination_eggdir) - zf.extractall(destination_eggdir) - # Convert metadata. - dist_info = os.path.join(destination_eggdir, dist_info) - dist = pkg_resources.Distribution.from_location( - destination_eggdir, dist_info, - metadata=pkg_resources.PathMetadata(destination_eggdir, dist_info), - ) - - # Note: Evaluate and strip markers now, - # as it's difficult to convert back from the syntax: - # foobar; "linux" in sys_platform and extra == 'test' - def raw_req(req): - req.marker = None - return str(req) - install_requires = list(sorted(map(raw_req, dist.requires()))) - extras_require = { - extra: sorted( - req - for req in map(raw_req, dist.requires((extra,))) - if req not in install_requires - ) - for extra in dist.extras - } - os.rename(dist_info, egg_info) - os.rename( - os.path.join(egg_info, 'METADATA'), - os.path.join(egg_info, 'PKG-INFO'), - ) - setup_dist = setuptools.Distribution( - attrs=dict( - install_requires=install_requires, - extras_require=extras_require, - ), - ) - write_requirements( - setup_dist.get_command_obj('egg_info'), - None, - os.path.join(egg_info, 'requires.txt'), - ) - - @staticmethod - def _move_data_entries(destination_eggdir, dist_data): - """Move data entries to their correct location.""" - dist_data = os.path.join(destination_eggdir, dist_data) - dist_data_scripts = os.path.join(dist_data, 'scripts') - if os.path.exists(dist_data_scripts): - egg_info_scripts = os.path.join( - destination_eggdir, 'EGG-INFO', 'scripts') - os.mkdir(egg_info_scripts) - for entry in os.listdir(dist_data_scripts): - # Remove bytecode, as it's not properly handled - # during easy_install scripts install phase. - if entry.endswith('.pyc'): - os.unlink(os.path.join(dist_data_scripts, entry)) - else: - os.rename( - os.path.join(dist_data_scripts, entry), - os.path.join(egg_info_scripts, entry), - ) - os.rmdir(dist_data_scripts) - for subdir in filter(os.path.exists, ( - os.path.join(dist_data, d) - for d in ('data', 'headers', 'purelib', 'platlib') - )): - unpack(subdir, destination_eggdir) - if os.path.exists(dist_data): - os.rmdir(dist_data) - - @staticmethod - def _fix_namespace_packages(egg_info, destination_eggdir): - namespace_packages = os.path.join( - egg_info, 'namespace_packages.txt') - if os.path.exists(namespace_packages): - with open(namespace_packages) as fp: - namespace_packages = fp.read().split() - for mod in namespace_packages: - mod_dir = os.path.join(destination_eggdir, *mod.split('.')) - mod_init = os.path.join(mod_dir, '__init__.py') - if os.path.exists(mod_dir) and not os.path.exists(mod_init): - with open(mod_init, 'w') as fp: - fp.write(NAMESPACE_PACKAGE_INIT) diff --git a/venv2/lib/python2.7/site-packages/setuptools/windows_support.py b/venv2/lib/python2.7/site-packages/setuptools/windows_support.py deleted file mode 100644 index cb977cf..0000000 --- a/venv2/lib/python2.7/site-packages/setuptools/windows_support.py +++ /dev/null @@ -1,29 +0,0 @@ -import platform -import ctypes - - -def windows_only(func): - if platform.system() != 'Windows': - return lambda *args, **kwargs: None - return func - - -@windows_only -def hide_file(path): - """ - Set the hidden attribute on a file or directory. - - From http://stackoverflow.com/questions/19622133/ - - `path` must be text. - """ - __import__('ctypes.wintypes') - SetFileAttributes = ctypes.windll.kernel32.SetFileAttributesW - SetFileAttributes.argtypes = ctypes.wintypes.LPWSTR, ctypes.wintypes.DWORD - SetFileAttributes.restype = ctypes.wintypes.BOOL - - FILE_ATTRIBUTE_HIDDEN = 0x02 - - ret = SetFileAttributes(path, FILE_ATTRIBUTE_HIDDEN) - if not ret: - raise ctypes.WinError() diff --git a/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/INSTALLER b/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/LICENSE.txt b/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/LICENSE.txt deleted file mode 100644 index c3441e6..0000000 --- a/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/LICENSE.txt +++ /dev/null @@ -1,22 +0,0 @@ -"wheel" copyright (c) 2012-2014 Daniel Holth and -contributors. - -The MIT License - -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. diff --git a/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/METADATA b/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/METADATA deleted file mode 100644 index 3685e11..0000000 --- a/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/METADATA +++ /dev/null @@ -1,60 +0,0 @@ -Metadata-Version: 2.1 -Name: wheel -Version: 0.33.4 -Summary: A built-package format for Python. -Home-page: https://github.com/pypa/wheel -Author: Daniel Holth -Author-email: dholth@fastmail.fm -Maintainer: Alex Grönholm -Maintainer-email: alex.gronholm@nextday.fi -License: MIT -Project-URL: Documentation, https://wheel.readthedocs.io/ -Project-URL: Changelog, https://wheel.readthedocs.io/en/stable/news.html -Project-URL: Issue Tracker, https://github.com/pypa/wheel/issues -Keywords: wheel,packaging -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: Topic :: System :: Archiving :: Packaging -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python -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 -Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* -Provides-Extra: test -Requires-Dist: pytest (>=3.0.0) ; extra == 'test' -Requires-Dist: pytest-cov ; extra == 'test' - -wheel -===== - -This library is the reference implementation of the Python wheel packaging -standard, as defined in `PEP 427`_. - -It has two different roles: - -#. A setuptools_ extension for building wheels that provides the - ``bdist_wheel`` setuptools command -#. A command line tool for working with wheel files - -It should be noted that wheel is **not** intended to be used as a library, and -as such there is no stable, public API. - -.. _PEP 427: https://www.python.org/dev/peps/pep-0427/ -.. _setuptools: https://pypi.org/project/setuptools/ - - -Code of Conduct ---------------- - -Everyone interacting in the wheel project's codebases, issue trackers, chat -rooms, and mailing lists is expected to follow the `PyPA Code of Conduct`_. - -.. _PyPA Code of Conduct: https://www.pypa.io/en/latest/code-of-conduct/ - - diff --git a/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/RECORD b/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/RECORD deleted file mode 100644 index deca304..0000000 --- a/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/RECORD +++ /dev/null @@ -1,32 +0,0 @@ -../../../bin/wheel,sha256=tIBOR3sKUe3heoxaSjCebQvE9LLezH5OpmNr4YOr8AI,244 -wheel-0.33.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -wheel-0.33.4.dist-info/LICENSE.txt,sha256=zKniDGrx_Pv2lAjzd3aShsvuvN7TNhAMm0o_NfvmNeQ,1125 -wheel-0.33.4.dist-info/METADATA,sha256=wyJg2oitG9m-Uh5ia99JynhzPDzo2cJmrCSsqYpRMtc,2082 -wheel-0.33.4.dist-info/RECORD,, -wheel-0.33.4.dist-info/WHEEL,sha256=h_aVn5OB2IERUjMbi2pucmR_zzWJtk303YXvhh60NJ8,110 -wheel-0.33.4.dist-info/entry_points.txt,sha256=N8HbYFST3yrNQYeB2wXWBEPUhFsEtKNRPaCFGJPyqyc,108 -wheel-0.33.4.dist-info/top_level.txt,sha256=HxSBIbgEstMPe4eFawhA66Mq-QYHMopXVoAncfjb_1c,6 -wheel/__init__.py,sha256=gdfDa6ufU3P8afREFDBD26jo-ncuKtumgvlnZIGSmKc,96 -wheel/__init__.pyc,, -wheel/__main__.py,sha256=lF-YLO4hdQmoWuh4eWZd8YL1U95RSdm76sNLBXa0vjE,417 -wheel/__main__.pyc,, -wheel/bdist_wheel.py,sha256=U3ljAOGgc8UGMKqxOf5YEKE1W-nt99X6RemMi-poBB8,14757 -wheel/bdist_wheel.pyc,, -wheel/cli/__init__.py,sha256=GWSoGUpRabTf8bk3FsNTPrc5Fsr8YOv2dX55iY2W7eY,2572 -wheel/cli/__init__.pyc,, -wheel/cli/convert.py,sha256=me0l6G4gSw-EBVhzjSr7yWYWBp9spMz7mnXlyJTiXso,9497 -wheel/cli/convert.pyc,, -wheel/cli/pack.py,sha256=vkvZc4-rRZyWiwc6sHjpqIjzwDRMEF5u3JUNU9NY_jA,2263 -wheel/cli/pack.pyc,, -wheel/cli/unpack.py,sha256=0VWzT7U_xyenTPwEVavxqvdee93GPvAFHnR3Uu91aRc,673 -wheel/cli/unpack.pyc,, -wheel/metadata.py,sha256=uBv2aOz4U2sERF834C8DeNo235drcsp3ypTzT7MTWEA,4699 -wheel/metadata.pyc,, -wheel/pep425tags.py,sha256=Jdjbnq17kqwPRKJCMb2E1VccNgnC3H6iQL7VGaxkPao,5908 -wheel/pep425tags.pyc,, -wheel/pkginfo.py,sha256=GR76kupQzn1x9sKDaXuE6B6FsZ4OkfRtG7pndlXPvQ4,1257 -wheel/pkginfo.pyc,, -wheel/util.py,sha256=zwVIk-9qWVQLRMgkgQTMp4TRE4HY03-tCUxLrtCpsfU,924 -wheel/util.pyc,, -wheel/wheelfile.py,sha256=Mtt6mUaea-wABqtN5SW3Rn6bVvw-bdcSKaR2SjWZLG4,7222 -wheel/wheelfile.pyc,, diff --git a/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/WHEEL b/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/WHEEL deleted file mode 100644 index 78e6f69..0000000 --- a/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.33.4) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/entry_points.txt b/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/entry_points.txt deleted file mode 100644 index b27acad..0000000 --- a/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/entry_points.txt +++ /dev/null @@ -1,6 +0,0 @@ -[console_scripts] -wheel = wheel.cli:main - -[distutils.commands] -bdist_wheel = wheel.bdist_wheel:bdist_wheel - diff --git a/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/top_level.txt b/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/top_level.txt deleted file mode 100644 index 2309722..0000000 --- a/venv2/lib/python2.7/site-packages/wheel-0.33.4.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -wheel diff --git a/venv2/lib/python2.7/site-packages/wheel/__init__.py b/venv2/lib/python2.7/site-packages/wheel/__init__.py deleted file mode 100644 index 0f8ca70..0000000 --- a/venv2/lib/python2.7/site-packages/wheel/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# __variables__ with double-quoted values will be available in setup.py: -__version__ = "0.33.4" diff --git a/venv2/lib/python2.7/site-packages/wheel/__main__.py b/venv2/lib/python2.7/site-packages/wheel/__main__.py deleted file mode 100644 index b3773a2..0000000 --- a/venv2/lib/python2.7/site-packages/wheel/__main__.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -Wheel command line tool (enable python -m wheel syntax) -""" - -import sys - - -def main(): # needed for console script - if __package__ == '': - # To be able to run 'python wheel-0.9.whl/wheel': - import os.path - path = os.path.dirname(os.path.dirname(__file__)) - sys.path[0:0] = [path] - import wheel.cli - sys.exit(wheel.cli.main()) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/venv2/lib/python2.7/site-packages/wheel/bdist_wheel.py b/venv2/lib/python2.7/site-packages/wheel/bdist_wheel.py deleted file mode 100644 index c79307b..0000000 --- a/venv2/lib/python2.7/site-packages/wheel/bdist_wheel.py +++ /dev/null @@ -1,372 +0,0 @@ -""" -Create a wheel (.whl) distribution. - -A wheel is a built archive format. -""" - -import os -import shutil -import sys -import re -from email.generator import Generator -from distutils.core import Command -from distutils.sysconfig import get_python_version -from distutils import log as logger -from glob import iglob -from shutil import rmtree -from warnings import warn - -import pkg_resources - -from .pep425tags import get_abbr_impl, get_impl_ver, get_abi_tag, get_platform -from .pkginfo import write_pkg_info -from .metadata import pkginfo_to_metadata -from .wheelfile import WheelFile -from . import pep425tags -from . import __version__ as wheel_version - - -safe_name = pkg_resources.safe_name -safe_version = pkg_resources.safe_version - -PY_LIMITED_API_PATTERN = r'cp3\d' - - -def safer_name(name): - return safe_name(name).replace('-', '_') - - -def safer_version(version): - return safe_version(version).replace('-', '_') - - -class bdist_wheel(Command): - - description = 'create a wheel distribution' - - user_options = [('bdist-dir=', 'b', - "temporary directory for creating the distribution"), - ('plat-name=', 'p', - "platform name to embed in generated filenames " - "(default: %s)" % get_platform()), - ('keep-temp', 'k', - "keep the pseudo-installation tree around after " + - "creating the distribution archive"), - ('dist-dir=', 'd', - "directory to put final built distributions in"), - ('skip-build', None, - "skip rebuilding everything (for testing/debugging)"), - ('relative', None, - "build the archive using relative paths " - "(default: false)"), - ('owner=', 'u', - "Owner name used when creating a tar file" - " [default: current user]"), - ('group=', 'g', - "Group name used when creating a tar file" - " [default: current group]"), - ('universal', None, - "make a universal wheel" - " (default: false)"), - ('python-tag=', None, - "Python implementation compatibility tag" - " (default: py%s)" % get_impl_ver()[0]), - ('build-number=', None, - "Build number for this particular version. " - "As specified in PEP-0427, this must start with a digit. " - "[default: None]"), - ('py-limited-api=', None, - "Python tag (cp32|cp33|cpNN) for abi3 wheel tag" - " (default: false)"), - ] - - boolean_options = ['keep-temp', 'skip-build', 'relative', 'universal'] - - def initialize_options(self): - self.bdist_dir = None - self.data_dir = None - self.plat_name = None - self.plat_tag = None - self.format = 'zip' - self.keep_temp = False - self.dist_dir = None - self.egginfo_dir = None - self.root_is_pure = None - self.skip_build = None - self.relative = False - self.owner = None - self.group = None - self.universal = False - self.python_tag = 'py' + get_impl_ver()[0] - self.build_number = None - self.py_limited_api = False - self.plat_name_supplied = False - - def finalize_options(self): - if self.bdist_dir is None: - bdist_base = self.get_finalized_command('bdist').bdist_base - self.bdist_dir = os.path.join(bdist_base, 'wheel') - - self.data_dir = self.wheel_dist_name + '.data' - self.plat_name_supplied = self.plat_name is not None - - need_options = ('dist_dir', 'plat_name', 'skip_build') - - self.set_undefined_options('bdist', - *zip(need_options, need_options)) - - self.root_is_pure = not (self.distribution.has_ext_modules() - or self.distribution.has_c_libraries()) - - if self.py_limited_api and not re.match(PY_LIMITED_API_PATTERN, self.py_limited_api): - raise ValueError("py-limited-api must match '%s'" % PY_LIMITED_API_PATTERN) - - # Support legacy [wheel] section for setting universal - wheel = self.distribution.get_option_dict('wheel') - if 'universal' in wheel: - # please don't define this in your global configs - logger.warn('The [wheel] section is deprecated. Use [bdist_wheel] instead.') - val = wheel['universal'][1].strip() - if val.lower() in ('1', 'true', 'yes'): - self.universal = True - - if self.build_number is not None and not self.build_number[:1].isdigit(): - raise ValueError("Build tag (build-number) must start with a digit.") - - @property - def wheel_dist_name(self): - """Return distribution full name with - replaced with _""" - components = (safer_name(self.distribution.get_name()), - safer_version(self.distribution.get_version())) - if self.build_number: - components += (self.build_number,) - return '-'.join(components) - - def get_tag(self): - # bdist sets self.plat_name if unset, we should only use it for purepy - # wheels if the user supplied it. - if self.plat_name_supplied: - plat_name = self.plat_name - elif self.root_is_pure: - plat_name = 'any' - else: - plat_name = self.plat_name or get_platform() - if plat_name in ('linux-x86_64', 'linux_x86_64') and sys.maxsize == 2147483647: - plat_name = 'linux_i686' - plat_name = plat_name.replace('-', '_').replace('.', '_') - - if self.root_is_pure: - if self.universal: - impl = 'py2.py3' - else: - impl = self.python_tag - tag = (impl, 'none', plat_name) - else: - impl_name = get_abbr_impl() - impl_ver = get_impl_ver() - impl = impl_name + impl_ver - # We don't work on CPython 3.1, 3.0. - if self.py_limited_api and (impl_name + impl_ver).startswith('cp3'): - impl = self.py_limited_api - abi_tag = 'abi3' - else: - abi_tag = str(get_abi_tag()).lower() - tag = (impl, abi_tag, plat_name) - supported_tags = pep425tags.get_supported( - supplied_platform=plat_name if self.plat_name_supplied else None) - # XXX switch to this alternate implementation for non-pure: - if not self.py_limited_api: - assert tag == supported_tags[0], "%s != %s" % (tag, supported_tags[0]) - assert tag in supported_tags, "would build wheel with unsupported tag {}".format(tag) - return tag - - def run(self): - build_scripts = self.reinitialize_command('build_scripts') - build_scripts.executable = 'python' - build_scripts.force = True - - build_ext = self.reinitialize_command('build_ext') - build_ext.inplace = False - - if not self.skip_build: - self.run_command('build') - - install = self.reinitialize_command('install', - reinit_subcommands=True) - install.root = self.bdist_dir - install.compile = False - install.skip_build = self.skip_build - install.warn_dir = False - - # A wheel without setuptools scripts is more cross-platform. - # Use the (undocumented) `no_ep` option to setuptools' - # install_scripts command to avoid creating entry point scripts. - install_scripts = self.reinitialize_command('install_scripts') - install_scripts.no_ep = True - - # Use a custom scheme for the archive, because we have to decide - # at installation time which scheme to use. - for key in ('headers', 'scripts', 'data', 'purelib', 'platlib'): - setattr(install, - 'install_' + key, - os.path.join(self.data_dir, key)) - - basedir_observed = '' - - if os.name == 'nt': - # win32 barfs if any of these are ''; could be '.'? - # (distutils.command.install:change_roots bug) - basedir_observed = os.path.normpath(os.path.join(self.data_dir, '..')) - self.install_libbase = self.install_lib = basedir_observed - - setattr(install, - 'install_purelib' if self.root_is_pure else 'install_platlib', - basedir_observed) - - logger.info("installing to %s", self.bdist_dir) - - self.run_command('install') - - impl_tag, abi_tag, plat_tag = self.get_tag() - archive_basename = "{}-{}-{}-{}".format(self.wheel_dist_name, impl_tag, abi_tag, plat_tag) - if not self.relative: - archive_root = self.bdist_dir - else: - archive_root = os.path.join( - self.bdist_dir, - self._ensure_relative(install.install_base)) - - self.set_undefined_options('install_egg_info', ('target', 'egginfo_dir')) - distinfo_dirname = '{}-{}.dist-info'.format( - safer_name(self.distribution.get_name()), - safer_version(self.distribution.get_version())) - distinfo_dir = os.path.join(self.bdist_dir, distinfo_dirname) - self.egg2dist(self.egginfo_dir, distinfo_dir) - - self.write_wheelfile(distinfo_dir) - - # Make the archive - if not os.path.exists(self.dist_dir): - os.makedirs(self.dist_dir) - - wheel_path = os.path.join(self.dist_dir, archive_basename + '.whl') - with WheelFile(wheel_path, 'w') as wf: - wf.write_files(archive_root) - - # Add to 'Distribution.dist_files' so that the "upload" command works - getattr(self.distribution, 'dist_files', []).append( - ('bdist_wheel', get_python_version(), wheel_path)) - - if not self.keep_temp: - logger.info('removing %s', self.bdist_dir) - if not self.dry_run: - rmtree(self.bdist_dir) - - def write_wheelfile(self, wheelfile_base, generator='bdist_wheel (' + wheel_version + ')'): - from email.message import Message - msg = Message() - msg['Wheel-Version'] = '1.0' # of the spec - msg['Generator'] = generator - msg['Root-Is-Purelib'] = str(self.root_is_pure).lower() - if self.build_number is not None: - msg['Build'] = self.build_number - - # Doesn't work for bdist_wininst - impl_tag, abi_tag, plat_tag = self.get_tag() - for impl in impl_tag.split('.'): - for abi in abi_tag.split('.'): - for plat in plat_tag.split('.'): - msg['Tag'] = '-'.join((impl, abi, plat)) - - wheelfile_path = os.path.join(wheelfile_base, 'WHEEL') - logger.info('creating %s', wheelfile_path) - with open(wheelfile_path, 'w') as f: - Generator(f, maxheaderlen=0).flatten(msg) - - def _ensure_relative(self, path): - # copied from dir_util, deleted - drive, path = os.path.splitdrive(path) - if path[0:1] == os.sep: - path = drive + path[1:] - return path - - @property - def license_paths(self): - metadata = self.distribution.get_option_dict('metadata') - files = set() - patterns = sorted({ - option for option in metadata.get('license_files', ('', ''))[1].split() - }) - - if 'license_file' in metadata: - warn('The "license_file" option is deprecated. Use "license_files" instead.', - DeprecationWarning) - files.add(metadata['license_file'][1]) - - if 'license_file' not in metadata and 'license_files' not in metadata: - patterns = ('LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*') - - for pattern in patterns: - for path in iglob(pattern): - if path not in files and os.path.isfile(path): - logger.info('adding license file "%s" (matched pattern "%s")', path, pattern) - files.add(path) - - return files - - def egg2dist(self, egginfo_path, distinfo_path): - """Convert an .egg-info directory into a .dist-info directory""" - def adios(p): - """Appropriately delete directory, file or link.""" - if os.path.exists(p) and not os.path.islink(p) and os.path.isdir(p): - shutil.rmtree(p) - elif os.path.exists(p): - os.unlink(p) - - adios(distinfo_path) - - if not os.path.exists(egginfo_path): - # There is no egg-info. This is probably because the egg-info - # file/directory is not named matching the distribution name used - # to name the archive file. Check for this case and report - # accordingly. - import glob - pat = os.path.join(os.path.dirname(egginfo_path), '*.egg-info') - possible = glob.glob(pat) - err = "Egg metadata expected at %s but not found" % (egginfo_path,) - if possible: - alt = os.path.basename(possible[0]) - err += " (%s found - possible misnamed archive file?)" % (alt,) - - raise ValueError(err) - - if os.path.isfile(egginfo_path): - # .egg-info is a single file - pkginfo_path = egginfo_path - pkg_info = pkginfo_to_metadata(egginfo_path, egginfo_path) - os.mkdir(distinfo_path) - else: - # .egg-info is a directory - pkginfo_path = os.path.join(egginfo_path, 'PKG-INFO') - pkg_info = pkginfo_to_metadata(egginfo_path, pkginfo_path) - - # ignore common egg metadata that is useless to wheel - shutil.copytree(egginfo_path, distinfo_path, - ignore=lambda x, y: {'PKG-INFO', 'requires.txt', 'SOURCES.txt', - 'not-zip-safe'} - ) - - # delete dependency_links if it is only whitespace - dependency_links_path = os.path.join(distinfo_path, 'dependency_links.txt') - with open(dependency_links_path, 'r') as dependency_links_file: - dependency_links = dependency_links_file.read().strip() - if not dependency_links: - adios(dependency_links_path) - - write_pkg_info(os.path.join(distinfo_path, 'METADATA'), pkg_info) - - for license_path in self.license_paths: - filename = os.path.basename(license_path) - shutil.copy(license_path, os.path.join(distinfo_path, filename)) - - adios(egginfo_path) diff --git a/venv2/lib/python2.7/site-packages/wheel/cli/__init__.py b/venv2/lib/python2.7/site-packages/wheel/cli/__init__.py deleted file mode 100644 index 95740bf..0000000 --- a/venv2/lib/python2.7/site-packages/wheel/cli/__init__.py +++ /dev/null @@ -1,88 +0,0 @@ -""" -Wheel command-line utility. -""" - -from __future__ import print_function - -import argparse -import os -import sys - - -def require_pkgresources(name): - try: - import pkg_resources # noqa: F401 - except ImportError: - raise RuntimeError("'{0}' needs pkg_resources (part of setuptools).".format(name)) - - -class WheelError(Exception): - pass - - -def unpack_f(args): - from .unpack import unpack - unpack(args.wheelfile, args.dest) - - -def pack_f(args): - from .pack import pack - pack(args.directory, args.dest_dir, args.build_number) - - -def convert_f(args): - from .convert import convert - convert(args.files, args.dest_dir, args.verbose) - - -def version_f(args): - from .. import __version__ - print("wheel %s" % __version__) - - -def parser(): - p = argparse.ArgumentParser() - s = p.add_subparsers(help="commands") - - unpack_parser = s.add_parser('unpack', help='Unpack wheel') - unpack_parser.add_argument('--dest', '-d', help='Destination directory', - default='.') - unpack_parser.add_argument('wheelfile', help='Wheel file') - unpack_parser.set_defaults(func=unpack_f) - - repack_parser = s.add_parser('pack', help='Repack wheel') - repack_parser.add_argument('directory', help='Root directory of the unpacked wheel') - repack_parser.add_argument('--dest-dir', '-d', default=os.path.curdir, - help="Directory to store the wheel (default %(default)s)") - repack_parser.add_argument('--build-number', help="Build tag to use in the wheel name") - repack_parser.set_defaults(func=pack_f) - - convert_parser = s.add_parser('convert', help='Convert egg or wininst to wheel') - convert_parser.add_argument('files', nargs='*', help='Files to convert') - convert_parser.add_argument('--dest-dir', '-d', default=os.path.curdir, - help="Directory to store wheels (default %(default)s)") - convert_parser.add_argument('--verbose', '-v', action='store_true') - convert_parser.set_defaults(func=convert_f) - - version_parser = s.add_parser('version', help='Print version and exit') - version_parser.set_defaults(func=version_f) - - help_parser = s.add_parser('help', help='Show this help') - help_parser.set_defaults(func=lambda args: p.print_help()) - - return p - - -def main(): - p = parser() - args = p.parse_args() - if not hasattr(args, 'func'): - p.print_help() - else: - try: - args.func(args) - return 0 - except WheelError as e: - print(e, file=sys.stderr) - - return 1 diff --git a/venv2/lib/python2.7/site-packages/wheel/cli/convert.py b/venv2/lib/python2.7/site-packages/wheel/cli/convert.py deleted file mode 100644 index f1a793a..0000000 --- a/venv2/lib/python2.7/site-packages/wheel/cli/convert.py +++ /dev/null @@ -1,269 +0,0 @@ -import os.path -import re -import shutil -import sys -import tempfile -import zipfile -from distutils import dist -from glob import iglob - -from ..bdist_wheel import bdist_wheel -from ..wheelfile import WheelFile -from . import WheelError, require_pkgresources - -egg_info_re = re.compile(r''' - (?P.+?)-(?P.+?) - (-(?Ppy\d\.\d) - (-(?P.+?))? - )?.egg$''', re.VERBOSE) - - -class _bdist_wheel_tag(bdist_wheel): - # allow the client to override the default generated wheel tag - # The default bdist_wheel implementation uses python and abi tags - # of the running python process. This is not suitable for - # generating/repackaging prebuild binaries. - - full_tag_supplied = False - full_tag = None # None or a (pytag, soabitag, plattag) triple - - def get_tag(self): - if self.full_tag_supplied and self.full_tag is not None: - return self.full_tag - else: - return bdist_wheel.get_tag(self) - - -def egg2wheel(egg_path, dest_dir): - filename = os.path.basename(egg_path) - match = egg_info_re.match(filename) - if not match: - raise WheelError('Invalid egg file name: {}'.format(filename)) - - egg_info = match.groupdict() - dir = tempfile.mkdtemp(suffix="_e2w") - if os.path.isfile(egg_path): - # assume we have a bdist_egg otherwise - with zipfile.ZipFile(egg_path) as egg: - egg.extractall(dir) - else: - # support buildout-style installed eggs directories - for pth in os.listdir(egg_path): - src = os.path.join(egg_path, pth) - if os.path.isfile(src): - shutil.copy2(src, dir) - else: - shutil.copytree(src, os.path.join(dir, pth)) - - pyver = egg_info['pyver'] - if pyver: - pyver = egg_info['pyver'] = pyver.replace('.', '') - - arch = (egg_info['arch'] or 'any').replace('.', '_').replace('-', '_') - - # assume all binary eggs are for CPython - abi = 'cp' + pyver[2:] if arch != 'any' else 'none' - - root_is_purelib = egg_info['arch'] is None - if root_is_purelib: - bw = bdist_wheel(dist.Distribution()) - else: - bw = _bdist_wheel_tag(dist.Distribution()) - - bw.root_is_pure = root_is_purelib - bw.python_tag = pyver - bw.plat_name_supplied = True - bw.plat_name = egg_info['arch'] or 'any' - if not root_is_purelib: - bw.full_tag_supplied = True - bw.full_tag = (pyver, abi, arch) - - dist_info_dir = os.path.join(dir, '{name}-{ver}.dist-info'.format(**egg_info)) - bw.egg2dist(os.path.join(dir, 'EGG-INFO'), dist_info_dir) - bw.write_wheelfile(dist_info_dir, generator='egg2wheel') - wheel_name = '{name}-{ver}-{pyver}-{}-{}.whl'.format(abi, arch, **egg_info) - with WheelFile(os.path.join(dest_dir, wheel_name), 'w') as wf: - wf.write_files(dir) - - shutil.rmtree(dir) - - -def parse_wininst_info(wininfo_name, egginfo_name): - """Extract metadata from filenames. - - Extracts the 4 metadataitems needed (name, version, pyversion, arch) from - the installer filename and the name of the egg-info directory embedded in - the zipfile (if any). - - The egginfo filename has the format:: - - name-ver(-pyver)(-arch).egg-info - - The installer filename has the format:: - - name-ver.arch(-pyver).exe - - Some things to note: - - 1. The installer filename is not definitive. An installer can be renamed - and work perfectly well as an installer. So more reliable data should - be used whenever possible. - 2. The egg-info data should be preferred for the name and version, because - these come straight from the distutils metadata, and are mandatory. - 3. The pyver from the egg-info data should be ignored, as it is - constructed from the version of Python used to build the installer, - which is irrelevant - the installer filename is correct here (even to - the point that when it's not there, any version is implied). - 4. The architecture must be taken from the installer filename, as it is - not included in the egg-info data. - 5. Architecture-neutral installers still have an architecture because the - installer format itself (being executable) is architecture-specific. We - should therefore ignore the architecture if the content is pure-python. - """ - - egginfo = None - if egginfo_name: - egginfo = egg_info_re.search(egginfo_name) - if not egginfo: - raise ValueError("Egg info filename %s is not valid" % (egginfo_name,)) - - # Parse the wininst filename - # 1. Distribution name (up to the first '-') - w_name, sep, rest = wininfo_name.partition('-') - if not sep: - raise ValueError("Installer filename %s is not valid" % (wininfo_name,)) - - # Strip '.exe' - rest = rest[:-4] - # 2. Python version (from the last '-', must start with 'py') - rest2, sep, w_pyver = rest.rpartition('-') - if sep and w_pyver.startswith('py'): - rest = rest2 - w_pyver = w_pyver.replace('.', '') - else: - # Not version specific - use py2.py3. While it is possible that - # pure-Python code is not compatible with both Python 2 and 3, there - # is no way of knowing from the wininst format, so we assume the best - # here (the user can always manually rename the wheel to be more - # restrictive if needed). - w_pyver = 'py2.py3' - # 3. Version and architecture - w_ver, sep, w_arch = rest.rpartition('.') - if not sep: - raise ValueError("Installer filename %s is not valid" % (wininfo_name,)) - - if egginfo: - w_name = egginfo.group('name') - w_ver = egginfo.group('ver') - - return {'name': w_name, 'ver': w_ver, 'arch': w_arch, 'pyver': w_pyver} - - -def wininst2wheel(path, dest_dir): - with zipfile.ZipFile(path) as bdw: - # Search for egg-info in the archive - egginfo_name = None - for filename in bdw.namelist(): - if '.egg-info' in filename: - egginfo_name = filename - break - - info = parse_wininst_info(os.path.basename(path), egginfo_name) - - root_is_purelib = True - for zipinfo in bdw.infolist(): - if zipinfo.filename.startswith('PLATLIB'): - root_is_purelib = False - break - if root_is_purelib: - paths = {'purelib': ''} - else: - paths = {'platlib': ''} - - dist_info = "%(name)s-%(ver)s" % info - datadir = "%s.data/" % dist_info - - # rewrite paths to trick ZipFile into extracting an egg - # XXX grab wininst .ini - between .exe, padding, and first zip file. - members = [] - egginfo_name = '' - for zipinfo in bdw.infolist(): - key, basename = zipinfo.filename.split('/', 1) - key = key.lower() - basepath = paths.get(key, None) - if basepath is None: - basepath = datadir + key.lower() + '/' - oldname = zipinfo.filename - newname = basepath + basename - zipinfo.filename = newname - del bdw.NameToInfo[oldname] - bdw.NameToInfo[newname] = zipinfo - # Collect member names, but omit '' (from an entry like "PLATLIB/" - if newname: - members.append(newname) - # Remember egg-info name for the egg2dist call below - if not egginfo_name: - if newname.endswith('.egg-info'): - egginfo_name = newname - elif '.egg-info/' in newname: - egginfo_name, sep, _ = newname.rpartition('/') - dir = tempfile.mkdtemp(suffix="_b2w") - bdw.extractall(dir, members) - - # egg2wheel - abi = 'none' - pyver = info['pyver'] - arch = (info['arch'] or 'any').replace('.', '_').replace('-', '_') - # Wininst installers always have arch even if they are not - # architecture-specific (because the format itself is). - # So, assume the content is architecture-neutral if root is purelib. - if root_is_purelib: - arch = 'any' - # If the installer is architecture-specific, it's almost certainly also - # CPython-specific. - if arch != 'any': - pyver = pyver.replace('py', 'cp') - wheel_name = '-'.join((dist_info, pyver, abi, arch)) - if root_is_purelib: - bw = bdist_wheel(dist.Distribution()) - else: - bw = _bdist_wheel_tag(dist.Distribution()) - - bw.root_is_pure = root_is_purelib - bw.python_tag = pyver - bw.plat_name_supplied = True - bw.plat_name = info['arch'] or 'any' - - if not root_is_purelib: - bw.full_tag_supplied = True - bw.full_tag = (pyver, abi, arch) - - dist_info_dir = os.path.join(dir, '%s.dist-info' % dist_info) - bw.egg2dist(os.path.join(dir, egginfo_name), dist_info_dir) - bw.write_wheelfile(dist_info_dir, generator='wininst2wheel') - - wheel_path = os.path.join(dest_dir, wheel_name) - with WheelFile(wheel_path, 'w') as wf: - wf.write_files(dir) - - shutil.rmtree(dir) - - -def convert(files, dest_dir, verbose): - # Only support wheel convert if pkg_resources is present - require_pkgresources('wheel convert') - - for pat in files: - for installer in iglob(pat): - if os.path.splitext(installer)[1] == '.egg': - conv = egg2wheel - else: - conv = wininst2wheel - - if verbose: - print("{}... ".format(installer)) - sys.stdout.flush() - - conv(installer, dest_dir) - if verbose: - print("OK") diff --git a/venv2/lib/python2.7/site-packages/wheel/cli/pack.py b/venv2/lib/python2.7/site-packages/wheel/cli/pack.py deleted file mode 100644 index af6e81c..0000000 --- a/venv2/lib/python2.7/site-packages/wheel/cli/pack.py +++ /dev/null @@ -1,58 +0,0 @@ -from __future__ import print_function - -import os.path -import re -import sys - -from wheel.cli import WheelError -from wheel.wheelfile import WheelFile - -DIST_INFO_RE = re.compile(r"^(?P(?P.+?)-(?P\d.*?))\.dist-info$") - - -def pack(directory, dest_dir, build_number): - """Repack a previously unpacked wheel directory into a new wheel file. - - The .dist-info/WHEEL file must contain one or more tags so that the target - wheel file name can be determined. - - :param directory: The unpacked wheel directory - :param dest_dir: Destination directory (defaults to the current directory) - """ - # Find the .dist-info directory - dist_info_dirs = [fn for fn in os.listdir(directory) - if os.path.isdir(os.path.join(directory, fn)) and DIST_INFO_RE.match(fn)] - if len(dist_info_dirs) > 1: - raise WheelError('Multiple .dist-info directories found in {}'.format(directory)) - elif not dist_info_dirs: - raise WheelError('No .dist-info directories found in {}'.format(directory)) - - # Determine the target wheel filename - dist_info_dir = dist_info_dirs[0] - name_version = DIST_INFO_RE.match(dist_info_dir).group('namever') - - # Add the build number if specific - if build_number: - name_version += '-' + build_number - - # Read the tags from .dist-info/WHEEL - with open(os.path.join(directory, dist_info_dir, 'WHEEL')) as f: - tags = [line.split(' ')[1].rstrip() for line in f if line.startswith('Tag: ')] - if not tags: - raise WheelError('No tags present in {}/WHEEL; cannot determine target wheel filename' - .format(dist_info_dir)) - - # Reassemble the tags for the wheel file - impls = sorted({tag.split('-')[0] for tag in tags}) - abivers = sorted({tag.split('-')[1] for tag in tags}) - platforms = sorted({tag.split('-')[2] for tag in tags}) - tagline = '-'.join(['.'.join(impls), '.'.join(abivers), '.'.join(platforms)]) - - # Repack the wheel - wheel_path = os.path.join(dest_dir, '{}-{}.whl'.format(name_version, tagline)) - with WheelFile(wheel_path, 'w') as wf: - print("Repacking wheel as {}...".format(wheel_path), end='') - sys.stdout.flush() - wf.write_files(directory) - - print('OK') diff --git a/venv2/lib/python2.7/site-packages/wheel/cli/unpack.py b/venv2/lib/python2.7/site-packages/wheel/cli/unpack.py deleted file mode 100644 index 2e9857a..0000000 --- a/venv2/lib/python2.7/site-packages/wheel/cli/unpack.py +++ /dev/null @@ -1,25 +0,0 @@ -from __future__ import print_function - -import os.path -import sys - -from ..wheelfile import WheelFile - - -def unpack(path, dest='.'): - """Unpack a wheel. - - Wheel content will be unpacked to {dest}/{name}-{ver}, where {name} - is the package name and {ver} its version. - - :param path: The path to the wheel. - :param dest: Destination directory (default to current directory). - """ - with WheelFile(path) as wf: - namever = wf.parsed_filename.group('namever') - destination = os.path.join(dest, namever) - print("Unpacking to: {}...".format(destination), end='') - sys.stdout.flush() - wf.extractall(destination) - - print('OK') diff --git a/venv2/lib/python2.7/site-packages/wheel/metadata.py b/venv2/lib/python2.7/site-packages/wheel/metadata.py deleted file mode 100644 index ab0c07e..0000000 --- a/venv2/lib/python2.7/site-packages/wheel/metadata.py +++ /dev/null @@ -1,141 +0,0 @@ -""" -Tools for converting old- to new-style metadata. -""" - -import os.path -import re -import textwrap - -import pkg_resources - -from .pkginfo import read_pkg_info - -# Wheel itself is probably the only program that uses non-extras markers -# in METADATA/PKG-INFO. Support its syntax with the extra at the end only. -EXTRA_RE = re.compile( - r"""^(?P.*?)(;\s*(?P.*?)(extra == '(?P.*?)')?)$""") - - -def requires_to_requires_dist(requirement): - """Return the version specifier for a requirement in PEP 345/566 fashion.""" - if getattr(requirement, 'url', None): - return " @ " + requirement.url - - requires_dist = [] - for op, ver in requirement.specs: - requires_dist.append(op + ver) - if not requires_dist: - return '' - return " (%s)" % ','.join(sorted(requires_dist)) - - -def convert_requirements(requirements): - """Yield Requires-Dist: strings for parsed requirements strings.""" - for req in requirements: - parsed_requirement = pkg_resources.Requirement.parse(req) - spec = requires_to_requires_dist(parsed_requirement) - extras = ",".join(sorted(parsed_requirement.extras)) - if extras: - extras = "[%s]" % extras - yield (parsed_requirement.project_name + extras + spec) - - -def generate_requirements(extras_require): - """ - Convert requirements from a setup()-style dictionary to ('Requires-Dist', 'requirement') - and ('Provides-Extra', 'extra') tuples. - - extras_require is a dictionary of {extra: [requirements]} as passed to setup(), - using the empty extra {'': [requirements]} to hold install_requires. - """ - for extra, depends in extras_require.items(): - condition = '' - extra = extra or '' - if ':' in extra: # setuptools extra:condition syntax - extra, condition = extra.split(':', 1) - - extra = pkg_resources.safe_extra(extra) - if extra: - yield 'Provides-Extra', extra - if condition: - condition = "(" + condition + ") and " - condition += "extra == '%s'" % extra - - if condition: - condition = ' ; ' + condition - - for new_req in convert_requirements(depends): - yield 'Requires-Dist', new_req + condition - - -def pkginfo_to_metadata(egg_info_path, pkginfo_path): - """ - Convert .egg-info directory with PKG-INFO to the Metadata 2.1 format - """ - pkg_info = read_pkg_info(pkginfo_path) - pkg_info.replace_header('Metadata-Version', '2.1') - # Those will be regenerated from `requires.txt`. - del pkg_info['Provides-Extra'] - del pkg_info['Requires-Dist'] - requires_path = os.path.join(egg_info_path, 'requires.txt') - if os.path.exists(requires_path): - with open(requires_path) as requires_file: - requires = requires_file.read() - - parsed_requirements = sorted(pkg_resources.split_sections(requires), - key=lambda x: x[0] or '') - for extra, reqs in parsed_requirements: - for key, value in generate_requirements({extra: reqs}): - if (key, value) not in pkg_info.items(): - pkg_info[key] = value - - description = pkg_info['Description'] - if description: - pkg_info.set_payload(dedent_description(pkg_info)) - del pkg_info['Description'] - - return pkg_info - - -def pkginfo_unicode(pkg_info, field): - """Hack to coax Unicode out of an email Message() - Python 3.3+""" - text = pkg_info[field] - field = field.lower() - if not isinstance(text, str): - if not hasattr(pkg_info, 'raw_items'): # Python 3.2 - return str(text) - for item in pkg_info.raw_items(): - if item[0].lower() == field: - text = item[1].encode('ascii', 'surrogateescape') \ - .decode('utf-8') - break - - return text - - -def dedent_description(pkg_info): - """ - Dedent and convert pkg_info['Description'] to Unicode. - """ - description = pkg_info['Description'] - - # Python 3 Unicode handling, sorta. - surrogates = False - if not isinstance(description, str): - surrogates = True - description = pkginfo_unicode(pkg_info, 'Description') - - description_lines = description.splitlines() - description_dedent = '\n'.join( - # if the first line of long_description is blank, - # the first line here will be indented. - (description_lines[0].lstrip(), - textwrap.dedent('\n'.join(description_lines[1:])), - '\n')) - - if surrogates: - description_dedent = description_dedent \ - .encode("utf8") \ - .decode("ascii", "surrogateescape") - - return description_dedent diff --git a/venv2/lib/python2.7/site-packages/wheel/pep425tags.py b/venv2/lib/python2.7/site-packages/wheel/pep425tags.py deleted file mode 100644 index 13b5073..0000000 --- a/venv2/lib/python2.7/site-packages/wheel/pep425tags.py +++ /dev/null @@ -1,185 +0,0 @@ -"""Generate and work with PEP 425 Compatibility Tags.""" - -import distutils.util -import platform -import sys -import sysconfig -import warnings - -try: - from importlib.machinery import get_all_suffixes -except ImportError: - from imp import get_suffixes as get_all_suffixes - - -def get_config_var(var): - try: - return sysconfig.get_config_var(var) - except IOError as e: # pip Issue #1074 - warnings.warn("{0}".format(e), RuntimeWarning) - return None - - -def get_abbr_impl(): - """Return abbreviated implementation name.""" - impl = platform.python_implementation() - if impl == 'PyPy': - return 'pp' - elif impl == 'Jython': - return 'jy' - elif impl == 'IronPython': - return 'ip' - elif impl == 'CPython': - return 'cp' - - raise LookupError('Unknown Python implementation: ' + impl) - - -def get_impl_ver(): - """Return implementation version.""" - impl_ver = get_config_var("py_version_nodot") - if not impl_ver or get_abbr_impl() == 'pp': - impl_ver = ''.join(map(str, get_impl_version_info())) - return impl_ver - - -def get_impl_version_info(): - """Return sys.version_info-like tuple for use in decrementing the minor - version.""" - if get_abbr_impl() == 'pp': - # as per https://github.com/pypa/pip/issues/2882 - return (sys.version_info[0], sys.pypy_version_info.major, - sys.pypy_version_info.minor) - else: - return sys.version_info[0], sys.version_info[1] - - -def get_flag(var, fallback, expected=True, warn=True): - """Use a fallback method for determining SOABI flags if the needed config - var is unset or unavailable.""" - val = get_config_var(var) - if val is None: - if warn: - warnings.warn("Config variable '{0}' is unset, Python ABI tag may " - "be incorrect".format(var), RuntimeWarning, 2) - return fallback() - return val == expected - - -def get_abi_tag(): - """Return the ABI tag based on SOABI (if available) or emulate SOABI - (CPython 2, PyPy).""" - soabi = get_config_var('SOABI') - impl = get_abbr_impl() - if not soabi and impl in ('cp', 'pp') and hasattr(sys, 'maxunicode'): - d = '' - m = '' - u = '' - if get_flag('Py_DEBUG', - lambda: hasattr(sys, 'gettotalrefcount'), - warn=(impl == 'cp')): - d = 'd' - if get_flag('WITH_PYMALLOC', - lambda: impl == 'cp', - warn=(impl == 'cp')): - m = 'm' - if get_flag('Py_UNICODE_SIZE', - lambda: sys.maxunicode == 0x10ffff, - expected=4, - warn=(impl == 'cp' and - sys.version_info < (3, 3))) \ - and sys.version_info < (3, 3): - u = 'u' - abi = '%s%s%s%s%s' % (impl, get_impl_ver(), d, m, u) - elif soabi and soabi.startswith('cpython-'): - abi = 'cp' + soabi.split('-')[1] - elif soabi: - abi = soabi.replace('.', '_').replace('-', '_') - else: - abi = None - return abi - - -def get_platform(): - """Return our platform name 'win32', 'linux_x86_64'""" - # XXX remove distutils dependency - result = distutils.util.get_platform().replace('.', '_').replace('-', '_') - if result == "linux_x86_64" and sys.maxsize == 2147483647: - # pip pull request #3497 - result = "linux_i686" - return result - - -def get_supported(versions=None, supplied_platform=None): - """Return a list of supported tags for each version specified in - `versions`. - - :param versions: a list of string versions, of the form ["33", "32"], - or None. The first version will be assumed to support our ABI. - """ - supported = [] - - # Versions must be given with respect to the preference - if versions is None: - versions = [] - version_info = get_impl_version_info() - major = version_info[:-1] - # Support all previous minor Python versions. - for minor in range(version_info[-1], -1, -1): - versions.append(''.join(map(str, major + (minor,)))) - - impl = get_abbr_impl() - - abis = [] - - abi = get_abi_tag() - if abi: - abis[0:0] = [abi] - - abi3s = set() - for suffix in get_all_suffixes(): - if suffix[0].startswith('.abi'): - abi3s.add(suffix[0].split('.', 2)[1]) - - abis.extend(sorted(list(abi3s))) - - abis.append('none') - - platforms = [] - if supplied_platform: - platforms.append(supplied_platform) - platforms.append(get_platform()) - - # Current version, current API (built specifically for our Python): - for abi in abis: - for arch in platforms: - supported.append(('%s%s' % (impl, versions[0]), abi, arch)) - - # abi3 modules compatible with older version of Python - for version in versions[1:]: - # abi3 was introduced in Python 3.2 - if version in ('31', '30'): - break - for abi in abi3s: # empty set if not Python 3 - for arch in platforms: - supported.append(("%s%s" % (impl, version), abi, arch)) - - # No abi / arch, but requires our implementation: - for i, version in enumerate(versions): - supported.append(('%s%s' % (impl, version), 'none', 'any')) - if i == 0: - # Tagged specifically as being cross-version compatible - # (with just the major version specified) - supported.append(('%s%s' % (impl, versions[0][0]), 'none', 'any')) - - # Major Python version + platform; e.g. binaries not using the Python API - for arch in platforms: - supported.append(('py%s' % (versions[0][0]), 'none', arch)) - - # No abi / arch, generic Python - for i, version in enumerate(versions): - supported.append(('py%s' % (version,), 'none', 'any')) - if i == 0: - supported.append(('py%s' % (version[0]), 'none', 'any')) - - return supported diff --git a/venv2/lib/python2.7/site-packages/wheel/pkginfo.py b/venv2/lib/python2.7/site-packages/wheel/pkginfo.py deleted file mode 100644 index 115be45..0000000 --- a/venv2/lib/python2.7/site-packages/wheel/pkginfo.py +++ /dev/null @@ -1,43 +0,0 @@ -"""Tools for reading and writing PKG-INFO / METADATA without caring -about the encoding.""" - -from email.parser import Parser - -try: - unicode - _PY3 = False -except NameError: - _PY3 = True - -if not _PY3: - from email.generator import Generator - - def read_pkg_info_bytes(bytestr): - return Parser().parsestr(bytestr) - - def read_pkg_info(path): - with open(path, "r") as headers: - message = Parser().parse(headers) - return message - - def write_pkg_info(path, message): - with open(path, 'w') as metadata: - Generator(metadata, mangle_from_=False, maxheaderlen=0).flatten(message) -else: - from email.generator import BytesGenerator - - def read_pkg_info_bytes(bytestr): - headers = bytestr.decode(encoding="ascii", errors="surrogateescape") - message = Parser().parsestr(headers) - return message - - def read_pkg_info(path): - with open(path, "r", - encoding="ascii", - errors="surrogateescape") as headers: - message = Parser().parse(headers) - return message - - def write_pkg_info(path, message): - with open(path, "wb") as out: - BytesGenerator(out, mangle_from_=False, maxheaderlen=0).flatten(message) diff --git a/venv2/lib/python2.7/site-packages/wheel/util.py b/venv2/lib/python2.7/site-packages/wheel/util.py deleted file mode 100644 index 0afb54a..0000000 --- a/venv2/lib/python2.7/site-packages/wheel/util.py +++ /dev/null @@ -1,46 +0,0 @@ -import base64 -import io -import sys - - -if sys.version_info[0] < 3: - text_type = unicode # noqa: F821 - - StringIO = io.BytesIO - - def native(s, encoding='utf-8'): - if isinstance(s, unicode): - return s.encode(encoding) - return s -else: - text_type = str - - StringIO = io.StringIO - - def native(s, encoding='utf-8'): - if isinstance(s, bytes): - return s.decode(encoding) - return s - - -def urlsafe_b64encode(data): - """urlsafe_b64encode without padding""" - return base64.urlsafe_b64encode(data).rstrip(b'=') - - -def urlsafe_b64decode(data): - """urlsafe_b64decode without padding""" - pad = b'=' * (4 - (len(data) & 3)) - return base64.urlsafe_b64decode(data + pad) - - -def as_unicode(s): - if isinstance(s, bytes): - return s.decode('utf-8') - return s - - -def as_bytes(s): - if isinstance(s, text_type): - return s.encode('utf-8') - return s diff --git a/venv2/lib/python2.7/site-packages/wheel/wheelfile.py b/venv2/lib/python2.7/site-packages/wheel/wheelfile.py deleted file mode 100644 index ddf8509..0000000 --- a/venv2/lib/python2.7/site-packages/wheel/wheelfile.py +++ /dev/null @@ -1,169 +0,0 @@ -from __future__ import print_function - -import csv -import hashlib -import os.path -import re -import stat -import time -from collections import OrderedDict -from distutils import log as logger -from zipfile import ZIP_DEFLATED, ZipInfo, ZipFile - -from wheel.cli import WheelError -from wheel.util import urlsafe_b64decode, as_unicode, native, urlsafe_b64encode, as_bytes, StringIO - -# Non-greedy matching of an optional build number may be too clever (more -# invalid wheel filenames will match). Separate regex for .dist-info? -WHEEL_INFO_RE = re.compile( - r"""^(?P(?P.+?)-(?P.+?))(-(?P\d[^-]*))? - -(?P.+?)-(?P.+?)-(?P.+?)\.whl$""", - re.VERBOSE) - - -def get_zipinfo_datetime(timestamp=None): - # Some applications need reproducible .whl files, but they can't do this without forcing - # the timestamp of the individual ZipInfo objects. See issue #143. - timestamp = int(os.environ.get('SOURCE_DATE_EPOCH', timestamp or time.time())) - return time.gmtime(timestamp)[0:6] - - -class WheelFile(ZipFile): - """A ZipFile derivative class that also reads SHA-256 hashes from - .dist-info/RECORD and checks any read files against those. - """ - - _default_algorithm = hashlib.sha256 - - def __init__(self, file, mode='r'): - basename = os.path.basename(file) - self.parsed_filename = WHEEL_INFO_RE.match(basename) - if not basename.endswith('.whl') or self.parsed_filename is None: - raise WheelError("Bad wheel filename {!r}".format(basename)) - - ZipFile.__init__(self, file, mode, compression=ZIP_DEFLATED, allowZip64=True) - - self.dist_info_path = '{}.dist-info'.format(self.parsed_filename.group('namever')) - self.record_path = self.dist_info_path + '/RECORD' - self._file_hashes = OrderedDict() - self._file_sizes = {} - if mode == 'r': - # Ignore RECORD and any embedded wheel signatures - self._file_hashes[self.record_path] = None, None - self._file_hashes[self.record_path + '.jws'] = None, None - self._file_hashes[self.record_path + '.p7s'] = None, None - - # Fill in the expected hashes by reading them from RECORD - try: - record = self.open(self.record_path) - except KeyError: - raise WheelError('Missing {} file'.format(self.record_path)) - - with record: - for line in record: - line = line.decode('utf-8') - path, hash_sum, size = line.rsplit(u',', 2) - if hash_sum: - algorithm, hash_sum = hash_sum.split(u'=') - try: - hashlib.new(algorithm) - except ValueError: - raise WheelError('Unsupported hash algorithm: {}'.format(algorithm)) - - if algorithm.lower() in {'md5', 'sha1'}: - raise WheelError( - 'Weak hash algorithm ({}) is not permitted by PEP 427' - .format(algorithm)) - - self._file_hashes[path] = ( - algorithm, urlsafe_b64decode(hash_sum.encode('ascii'))) - - def open(self, name_or_info, mode="r", pwd=None): - def _update_crc(newdata, eof=None): - if eof is None: - eof = ef._eof - update_crc_orig(newdata) - else: # Python 2 - update_crc_orig(newdata, eof) - - running_hash.update(newdata) - if eof and running_hash.digest() != expected_hash: - raise WheelError("Hash mismatch for file '{}'".format(native(ef_name))) - - ef = ZipFile.open(self, name_or_info, mode, pwd) - ef_name = as_unicode(name_or_info.filename if isinstance(name_or_info, ZipInfo) - else name_or_info) - if mode == 'r' and not ef_name.endswith('/'): - if ef_name not in self._file_hashes: - raise WheelError("No hash found for file '{}'".format(native(ef_name))) - - algorithm, expected_hash = self._file_hashes[ef_name] - if expected_hash is not None: - # Monkey patch the _update_crc method to also check for the hash from RECORD - running_hash = hashlib.new(algorithm) - update_crc_orig, ef._update_crc = ef._update_crc, _update_crc - - return ef - - def write_files(self, base_dir): - logger.info("creating '%s' and adding '%s' to it", self.filename, base_dir) - deferred = [] - for root, dirnames, filenames in os.walk(base_dir): - # Sort the directory names so that `os.walk` will walk them in a - # defined order on the next iteration. - dirnames.sort() - for name in sorted(filenames): - path = os.path.normpath(os.path.join(root, name)) - if os.path.isfile(path): - arcname = os.path.relpath(path, base_dir) - if arcname == self.record_path: - pass - elif root.endswith('.dist-info'): - deferred.append((path, arcname)) - else: - self.write(path, arcname) - - deferred.sort() - for path, arcname in deferred: - self.write(path, arcname) - - def write(self, filename, arcname=None, compress_type=None): - with open(filename, 'rb') as f: - st = os.fstat(f.fileno()) - data = f.read() - - zinfo = ZipInfo(arcname or filename, date_time=get_zipinfo_datetime(st.st_mtime)) - zinfo.external_attr = (stat.S_IMODE(st.st_mode) | stat.S_IFMT(st.st_mode)) << 16 - zinfo.compress_type = ZIP_DEFLATED - self.writestr(zinfo, data, compress_type) - - def writestr(self, zinfo_or_arcname, bytes, compress_type=None): - ZipFile.writestr(self, zinfo_or_arcname, bytes, compress_type) - fname = (zinfo_or_arcname.filename if isinstance(zinfo_or_arcname, ZipInfo) - else zinfo_or_arcname) - logger.info("adding '%s'", fname) - if fname != self.record_path: - hash_ = self._default_algorithm(bytes) - self._file_hashes[fname] = hash_.name, native(urlsafe_b64encode(hash_.digest())) - self._file_sizes[fname] = len(bytes) - - def close(self): - # Write RECORD - if self.fp is not None and self.mode == 'w' and self._file_hashes: - data = StringIO() - writer = csv.writer(data, delimiter=',', quotechar='"', lineterminator='\n') - writer.writerows(( - ( - fname, - algorithm + "=" + hash_, - self._file_sizes[fname] - ) - for fname, (algorithm, hash_) in self._file_hashes.items() - )) - writer.writerow((format(self.record_path), "", "")) - zinfo = ZipInfo(native(self.record_path), date_time=get_zipinfo_datetime()) - zinfo.compress_type = ZIP_DEFLATED - zinfo.external_attr = 0o664 << 16 - self.writestr(zinfo, as_bytes(data.getvalue())) - - ZipFile.close(self) diff --git a/venv2/lib/python2.7/site.py b/venv2/lib/python2.7/site.py deleted file mode 100644 index ede3ca3..0000000 --- a/venv2/lib/python2.7/site.py +++ /dev/null @@ -1,851 +0,0 @@ -"""Append module search paths for third-party packages to sys.path. - -**************************************************************** -* This module is automatically imported during initialization. * -**************************************************************** - -In earlier versions of Python (up to 1.5a3), scripts or modules that -needed to use site-specific modules would place ``import site'' -somewhere near the top of their code. Because of the automatic -import, this is no longer necessary (but code that does it still -works). - -This will append site-specific paths to the module search path. On -Unix, it starts with sys.prefix and sys.exec_prefix (if different) and -appends lib/python/site-packages as well as lib/site-python. -It also supports the Debian convention of -lib/python/dist-packages. On other platforms (mainly Mac and -Windows), it uses just sys.prefix (and sys.exec_prefix, if different, -but this is unlikely). The resulting directories, if they exist, are -appended to sys.path, and also inspected for path configuration files. - -FOR DEBIAN, this sys.path is augmented with directories in /usr/local. -Local addons go into /usr/local/lib/python/site-packages -(resp. /usr/local/lib/site-python), Debian addons install into -/usr/{lib,share}/python/dist-packages. - -A path configuration file is a file whose name has the form -.pth; its contents are additional directories (one per line) -to be added to sys.path. Non-existing directories (or -non-directories) are never added to sys.path; no directory is added to -sys.path more than once. Blank lines and lines beginning with -'#' are skipped. Lines starting with 'import' are executed. - -For example, suppose sys.prefix and sys.exec_prefix are set to -/usr/local and there is a directory /usr/local/lib/python2.X/site-packages -with three subdirectories, foo, bar and spam, and two path -configuration files, foo.pth and bar.pth. Assume foo.pth contains the -following: - - # foo package configuration - foo - bar - bletch - -and bar.pth contains: - - # bar package configuration - bar - -Then the following directories are added to sys.path, in this order: - - /usr/local/lib/python2.X/site-packages/bar - /usr/local/lib/python2.X/site-packages/foo - -Note that bletch is omitted because it doesn't exist; bar precedes foo -because bar.pth comes alphabetically before foo.pth; and spam is -omitted because it is not mentioned in either path configuration file. - -After these path manipulations, an attempt is made to import a module -named sitecustomize, which can perform arbitrary additional -site-specific customizations. If this import fails with an -ImportError exception, it is silently ignored. - -""" - -import os -import sys - -try: - import __builtin__ as builtins -except ImportError: - import builtins -try: - set -except NameError: - from sets import Set as set - -# Prefixes for site-packages; add additional prefixes like /usr/local here -PREFIXES = [sys.prefix, sys.exec_prefix] -# Enable per user site-packages directory -# set it to False to disable the feature or True to force the feature -ENABLE_USER_SITE = None -# for distutils.commands.install -USER_SITE = None -USER_BASE = None - -_is_64bit = (getattr(sys, "maxsize", None) or getattr(sys, "maxint")) > 2 ** 32 -_is_pypy = hasattr(sys, "pypy_version_info") -_is_jython = sys.platform[:4] == "java" -if _is_jython: - ModuleType = type(os) - - -def makepath(*paths): - dir = os.path.join(*paths) - if _is_jython and (dir == "__classpath__" or dir.startswith("__pyclasspath__")): - return dir, dir - dir = os.path.abspath(dir) - return dir, os.path.normcase(dir) - - -def abs__file__(): - """Set all module' __file__ attribute to an absolute path""" - for m in sys.modules.values(): - if (_is_jython and not isinstance(m, ModuleType)) or hasattr(m, "__loader__"): - # only modules need the abspath in Jython. and don't mess - # with a PEP 302-supplied __file__ - continue - f = getattr(m, "__file__", None) - if f is None: - continue - m.__file__ = os.path.abspath(f) - - -def removeduppaths(): - """ Remove duplicate entries from sys.path along with making them - absolute""" - # This ensures that the initial path provided by the interpreter contains - # only absolute pathnames, even if we're running from the build directory. - L = [] - known_paths = set() - for dir in sys.path: - # Filter out duplicate paths (on case-insensitive file systems also - # if they only differ in case); turn relative paths into absolute - # paths. - dir, dircase = makepath(dir) - if not dircase in known_paths: - L.append(dir) - known_paths.add(dircase) - sys.path[:] = L - return known_paths - - -# XXX This should not be part of site.py, since it is needed even when -# using the -S option for Python. See http://www.python.org/sf/586680 -def addbuilddir(): - """Append ./build/lib. in case we're running in the build dir - (especially for Guido :-)""" - from distutils.util import get_platform - - s = "build/lib.{}-{:.3}".format(get_platform(), sys.version) - if hasattr(sys, "gettotalrefcount"): - s += "-pydebug" - s = os.path.join(os.path.dirname(sys.path[-1]), s) - sys.path.append(s) - - -def _init_pathinfo(): - """Return a set containing all existing directory entries from sys.path""" - d = set() - for dir in sys.path: - try: - if os.path.isdir(dir): - dir, dircase = makepath(dir) - d.add(dircase) - except TypeError: - continue - return d - - -def addpackage(sitedir, name, known_paths): - """Add a new path to known_paths by combining sitedir and 'name' or execute - sitedir if it starts with 'import'""" - if known_paths is None: - _init_pathinfo() - reset = 1 - else: - reset = 0 - fullname = os.path.join(sitedir, name) - try: - f = open(fullname, "r") - except IOError: - return - try: - for line in f: - if line.startswith("#"): - continue - if line.startswith("import"): - exec(line) - continue - line = line.rstrip() - dir, dircase = makepath(sitedir, line) - if not dircase in known_paths and os.path.exists(dir): - sys.path.append(dir) - known_paths.add(dircase) - finally: - f.close() - if reset: - known_paths = None - return known_paths - - -def addsitedir(sitedir, known_paths=None): - """Add 'sitedir' argument to sys.path if missing and handle .pth files in - 'sitedir'""" - if known_paths is None: - known_paths = _init_pathinfo() - reset = 1 - else: - reset = 0 - sitedir, sitedircase = makepath(sitedir) - if not sitedircase in known_paths: - sys.path.append(sitedir) # Add path component - try: - names = os.listdir(sitedir) - except os.error: - return - names.sort() - for name in names: - if name.endswith(os.extsep + "pth"): - addpackage(sitedir, name, known_paths) - if reset: - known_paths = None - return known_paths - - -def addsitepackages(known_paths, sys_prefix=sys.prefix, exec_prefix=sys.exec_prefix): - """Add site-packages (and possibly site-python) to sys.path""" - prefixes = [os.path.join(sys_prefix, "local"), sys_prefix] - if exec_prefix != sys_prefix: - prefixes.append(os.path.join(exec_prefix, "local")) - - for prefix in prefixes: - if prefix: - if sys.platform in ("os2emx", "riscos") or _is_jython: - sitedirs = [os.path.join(prefix, "Lib", "site-packages")] - elif _is_pypy: - sitedirs = [os.path.join(prefix, "site-packages")] - elif sys.platform == "darwin" and prefix == sys_prefix: - - if prefix.startswith("/System/Library/Frameworks/"): # Apple's Python - - sitedirs = [ - os.path.join("/Library/Python", sys.version[:3], "site-packages"), - os.path.join(prefix, "Extras", "lib", "python"), - ] - - else: # any other Python distros on OSX work this way - sitedirs = [os.path.join(prefix, "lib", "python" + sys.version[:3], "site-packages")] - - elif os.sep == "/": - sitedirs = [ - os.path.join(prefix, "lib", "python" + sys.version[:3], "site-packages"), - os.path.join(prefix, "lib", "site-python"), - os.path.join(prefix, "python" + sys.version[:3], "lib-dynload"), - ] - lib64_dir = os.path.join(prefix, "lib64", "python" + sys.version[:3], "site-packages") - if os.path.exists(lib64_dir) and os.path.realpath(lib64_dir) not in [ - os.path.realpath(p) for p in sitedirs - ]: - if _is_64bit: - sitedirs.insert(0, lib64_dir) - else: - sitedirs.append(lib64_dir) - try: - # sys.getobjects only available in --with-pydebug build - sys.getobjects - sitedirs.insert(0, os.path.join(sitedirs[0], "debug")) - except AttributeError: - pass - # Debian-specific dist-packages directories: - sitedirs.append(os.path.join(prefix, "local/lib", "python" + sys.version[:3], "dist-packages")) - if sys.version[0] == "2": - sitedirs.append(os.path.join(prefix, "lib", "python" + sys.version[:3], "dist-packages")) - else: - sitedirs.append(os.path.join(prefix, "lib", "python" + sys.version[0], "dist-packages")) - sitedirs.append(os.path.join(prefix, "lib", "dist-python")) - else: - sitedirs = [prefix, os.path.join(prefix, "lib", "site-packages")] - if sys.platform == "darwin": - # for framework builds *only* we add the standard Apple - # locations. Currently only per-user, but /Library and - # /Network/Library could be added too - if "Python.framework" in prefix: - home = os.environ.get("HOME") - if home: - sitedirs.append(os.path.join(home, "Library", "Python", sys.version[:3], "site-packages")) - for sitedir in sitedirs: - if os.path.isdir(sitedir): - addsitedir(sitedir, known_paths) - return None - - -def check_enableusersite(): - """Check if user site directory is safe for inclusion - - The function tests for the command line flag (including environment var), - process uid/gid equal to effective uid/gid. - - None: Disabled for security reasons - False: Disabled by user (command line option) - True: Safe and enabled - """ - if hasattr(sys, "flags") and getattr(sys.flags, "no_user_site", False): - return False - - if hasattr(os, "getuid") and hasattr(os, "geteuid"): - # check process uid == effective uid - if os.geteuid() != os.getuid(): - return None - if hasattr(os, "getgid") and hasattr(os, "getegid"): - # check process gid == effective gid - if os.getegid() != os.getgid(): - return None - - return True - - -def addusersitepackages(known_paths): - """Add a per user site-package to sys.path - - Each user has its own python directory with site-packages in the - home directory. - - USER_BASE is the root directory for all Python versions - - USER_SITE is the user specific site-packages directory - - USER_SITE/.. can be used for data. - """ - global USER_BASE, USER_SITE, ENABLE_USER_SITE - env_base = os.environ.get("PYTHONUSERBASE", None) - - def joinuser(*args): - return os.path.expanduser(os.path.join(*args)) - - # if sys.platform in ('os2emx', 'riscos'): - # # Don't know what to put here - # USER_BASE = '' - # USER_SITE = '' - if os.name == "nt": - base = os.environ.get("APPDATA") or "~" - if env_base: - USER_BASE = env_base - else: - USER_BASE = joinuser(base, "Python") - USER_SITE = os.path.join(USER_BASE, "Python" + sys.version[0] + sys.version[2], "site-packages") - else: - if env_base: - USER_BASE = env_base - else: - USER_BASE = joinuser("~", ".local") - USER_SITE = os.path.join(USER_BASE, "lib", "python" + sys.version[:3], "site-packages") - - if ENABLE_USER_SITE and os.path.isdir(USER_SITE): - addsitedir(USER_SITE, known_paths) - if ENABLE_USER_SITE: - for dist_libdir in ("lib", "local/lib"): - user_site = os.path.join(USER_BASE, dist_libdir, "python" + sys.version[:3], "dist-packages") - if os.path.isdir(user_site): - addsitedir(user_site, known_paths) - return known_paths - - -def setBEGINLIBPATH(): - """The OS/2 EMX port has optional extension modules that do double duty - as DLLs (and must use the .DLL file extension) for other extensions. - The library search path needs to be amended so these will be found - during module import. Use BEGINLIBPATH so that these are at the start - of the library search path. - - """ - dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload") - libpath = os.environ["BEGINLIBPATH"].split(";") - if libpath[-1]: - libpath.append(dllpath) - else: - libpath[-1] = dllpath - os.environ["BEGINLIBPATH"] = ";".join(libpath) - - -def setquit(): - """Define new built-ins 'quit' and 'exit'. - These are simply strings that display a hint on how to exit. - - """ - if os.sep == ":": - eof = "Cmd-Q" - elif os.sep == "\\": - eof = "Ctrl-Z plus Return" - else: - eof = "Ctrl-D (i.e. EOF)" - - class Quitter(object): - def __init__(self, name): - self.name = name - - def __repr__(self): - return "Use {}() or {} to exit".format(self.name, eof) - - def __call__(self, code=None): - # Shells like IDLE catch the SystemExit, but listen when their - # stdin wrapper is closed. - try: - sys.stdin.close() - except: - pass - raise SystemExit(code) - - builtins.quit = Quitter("quit") - builtins.exit = Quitter("exit") - - -class _Printer(object): - """interactive prompt objects for printing the license text, a list of - contributors and the copyright notice.""" - - MAXLINES = 23 - - def __init__(self, name, data, files=(), dirs=()): - self.__name = name - self.__data = data - self.__files = files - self.__dirs = dirs - self.__lines = None - - def __setup(self): - if self.__lines: - return - data = None - for dir in self.__dirs: - for filename in self.__files: - filename = os.path.join(dir, filename) - try: - fp = open(filename, "r") - data = fp.read() - fp.close() - break - except IOError: - pass - if data: - break - if not data: - data = self.__data - self.__lines = data.split("\n") - self.__linecnt = len(self.__lines) - - def __repr__(self): - self.__setup() - if len(self.__lines) <= self.MAXLINES: - return "\n".join(self.__lines) - else: - return "Type %s() to see the full %s text" % ((self.__name,) * 2) - - def __call__(self): - self.__setup() - prompt = "Hit Return for more, or q (and Return) to quit: " - lineno = 0 - while 1: - try: - for i in range(lineno, lineno + self.MAXLINES): - print(self.__lines[i]) - except IndexError: - break - else: - lineno += self.MAXLINES - key = None - while key is None: - try: - key = raw_input(prompt) - except NameError: - key = input(prompt) - if key not in ("", "q"): - key = None - if key == "q": - break - - -def setcopyright(): - """Set 'copyright' and 'credits' in __builtin__""" - builtins.copyright = _Printer("copyright", sys.copyright) - if _is_jython: - builtins.credits = _Printer("credits", "Jython is maintained by the Jython developers (www.jython.org).") - elif _is_pypy: - builtins.credits = _Printer("credits", "PyPy is maintained by the PyPy developers: http://pypy.org/") - else: - builtins.credits = _Printer( - "credits", - """\ - Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands - for supporting Python development. See www.python.org for more information.""", - ) - here = os.path.dirname(os.__file__) - builtins.license = _Printer( - "license", - "See https://www.python.org/psf/license/", - ["LICENSE.txt", "LICENSE"], - [sys.prefix, os.path.join(here, os.pardir), here, os.curdir], - ) - - -class _Helper(object): - """Define the built-in 'help'. - This is a wrapper around pydoc.help (with a twist). - - """ - - def __repr__(self): - return "Type help() for interactive help, " "or help(object) for help about object." - - def __call__(self, *args, **kwds): - import pydoc - - return pydoc.help(*args, **kwds) - - -def sethelper(): - builtins.help = _Helper() - - -def aliasmbcs(): - """On Windows, some default encodings are not provided by Python, - while they are always available as "mbcs" in each locale. Make - them usable by aliasing to "mbcs" in such a case.""" - if sys.platform == "win32": - import locale, codecs - - enc = locale.getdefaultlocale()[1] - if enc.startswith("cp"): # "cp***" ? - try: - codecs.lookup(enc) - except LookupError: - import encodings - - encodings._cache[enc] = encodings._unknown - encodings.aliases.aliases[enc] = "mbcs" - - -def setencoding(): - """Set the string encoding used by the Unicode implementation. The - default is 'ascii', but if you're willing to experiment, you can - change this.""" - encoding = "ascii" # Default value set by _PyUnicode_Init() - if 0: - # Enable to support locale aware default string encodings. - import locale - - loc = locale.getdefaultlocale() - if loc[1]: - encoding = loc[1] - if 0: - # Enable to switch off string to Unicode coercion and implicit - # Unicode to string conversion. - encoding = "undefined" - if encoding != "ascii": - # On Non-Unicode builds this will raise an AttributeError... - sys.setdefaultencoding(encoding) # Needs Python Unicode build ! - - -def execsitecustomize(): - """Run custom site specific code, if available.""" - try: - import sitecustomize - except ImportError: - pass - - -def virtual_install_main_packages(): - f = open(os.path.join(os.path.dirname(__file__), "orig-prefix.txt")) - sys.real_prefix = f.read().strip() - f.close() - pos = 2 - hardcoded_relative_dirs = [] - if sys.path[0] == "": - pos += 1 - if _is_jython: - paths = [os.path.join(sys.real_prefix, "Lib")] - elif _is_pypy: - if sys.version_info > (3, 2): - cpyver = "%d" % sys.version_info[0] - elif sys.pypy_version_info >= (1, 5): - cpyver = "%d.%d" % sys.version_info[:2] - else: - cpyver = "%d.%d.%d" % sys.version_info[:3] - paths = [os.path.join(sys.real_prefix, "lib_pypy"), os.path.join(sys.real_prefix, "lib-python", cpyver)] - if sys.pypy_version_info < (1, 9): - paths.insert(1, os.path.join(sys.real_prefix, "lib-python", "modified-%s" % cpyver)) - hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below - # - # This is hardcoded in the Python executable, but relative to sys.prefix: - for path in paths[:]: - plat_path = os.path.join(path, "plat-%s" % sys.platform) - if os.path.exists(plat_path): - paths.append(plat_path) - elif sys.platform == "win32": - paths = [os.path.join(sys.real_prefix, "Lib"), os.path.join(sys.real_prefix, "DLLs")] - else: - paths = [os.path.join(sys.real_prefix, "lib", "python" + sys.version[:3])] - hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below - lib64_path = os.path.join(sys.real_prefix, "lib64", "python" + sys.version[:3]) - if os.path.exists(lib64_path): - if _is_64bit: - paths.insert(0, lib64_path) - else: - paths.append(lib64_path) - # This is hardcoded in the Python executable, but relative to - # sys.prefix. Debian change: we need to add the multiarch triplet - # here, which is where the real stuff lives. As per PEP 421, in - # Python 3.3+, this lives in sys.implementation, while in Python 2.7 - # it lives in sys. - try: - arch = getattr(sys, "implementation", sys)._multiarch - except AttributeError: - # This is a non-multiarch aware Python. Fallback to the old way. - arch = sys.platform - plat_path = os.path.join(sys.real_prefix, "lib", "python" + sys.version[:3], "plat-%s" % arch) - if os.path.exists(plat_path): - paths.append(plat_path) - # This is hardcoded in the Python executable, but - # relative to sys.prefix, so we have to fix up: - for path in list(paths): - tk_dir = os.path.join(path, "lib-tk") - if os.path.exists(tk_dir): - paths.append(tk_dir) - - # These are hardcoded in the Apple's Python executable, - # but relative to sys.prefix, so we have to fix them up: - if sys.platform == "darwin": - hardcoded_paths = [ - os.path.join(relative_dir, module) - for relative_dir in hardcoded_relative_dirs - for module in ("plat-darwin", "plat-mac", "plat-mac/lib-scriptpackages") - ] - - for path in hardcoded_paths: - if os.path.exists(path): - paths.append(path) - - sys.path.extend(paths) - - -def force_global_eggs_after_local_site_packages(): - """ - Force easy_installed eggs in the global environment to get placed - in sys.path after all packages inside the virtualenv. This - maintains the "least surprise" result that packages in the - virtualenv always mask global packages, never the other way - around. - - """ - egginsert = getattr(sys, "__egginsert", 0) - for i, path in enumerate(sys.path): - if i > egginsert and path.startswith(sys.prefix): - egginsert = i - sys.__egginsert = egginsert + 1 - - -def virtual_addsitepackages(known_paths): - force_global_eggs_after_local_site_packages() - return addsitepackages(known_paths, sys_prefix=sys.real_prefix) - - -def fixclasspath(): - """Adjust the special classpath sys.path entries for Jython. These - entries should follow the base virtualenv lib directories. - """ - paths = [] - classpaths = [] - for path in sys.path: - if path == "__classpath__" or path.startswith("__pyclasspath__"): - classpaths.append(path) - else: - paths.append(path) - sys.path = paths - sys.path.extend(classpaths) - - -def execusercustomize(): - """Run custom user specific code, if available.""" - try: - import usercustomize - except ImportError: - pass - - -def enablerlcompleter(): - """Enable default readline configuration on interactive prompts, by - registering a sys.__interactivehook__. - If the readline module can be imported, the hook will set the Tab key - as completion key and register ~/.python_history as history file. - This can be overridden in the sitecustomize or usercustomize module, - or in a PYTHONSTARTUP file. - """ - - def register_readline(): - import atexit - - try: - import readline - import rlcompleter - except ImportError: - return - - # Reading the initialization (config) file may not be enough to set a - # completion key, so we set one first and then read the file. - readline_doc = getattr(readline, "__doc__", "") - if readline_doc is not None and "libedit" in readline_doc: - readline.parse_and_bind("bind ^I rl_complete") - else: - readline.parse_and_bind("tab: complete") - - try: - readline.read_init_file() - except OSError: - # An OSError here could have many causes, but the most likely one - # is that there's no .inputrc file (or .editrc file in the case of - # Mac OS X + libedit) in the expected location. In that case, we - # want to ignore the exception. - pass - - if readline.get_current_history_length() == 0: - # If no history was loaded, default to .python_history. - # The guard is necessary to avoid doubling history size at - # each interpreter exit when readline was already configured - # through a PYTHONSTARTUP hook, see: - # http://bugs.python.org/issue5845#msg198636 - history = os.path.join(os.path.expanduser("~"), ".python_history") - try: - readline.read_history_file(history) - except OSError: - pass - - def write_history(): - try: - readline.write_history_file(history) - except (FileNotFoundError, PermissionError): - # home directory does not exist or is not writable - # https://bugs.python.org/issue19891 - pass - - atexit.register(write_history) - - sys.__interactivehook__ = register_readline - - -if _is_pypy: - - def import_builtin_stuff(): - """PyPy specific: some built-in modules should be pre-imported because - some programs expect them to be in sys.modules on startup. This is ported - from PyPy's site.py. - """ - import encodings - - if "exceptions" in sys.builtin_module_names: - import exceptions - - if "zipimport" in sys.builtin_module_names: - import zipimport - - -def main(): - global ENABLE_USER_SITE - virtual_install_main_packages() - if _is_pypy: - import_builtin_stuff() - abs__file__() - paths_in_sys = removeduppaths() - if os.name == "posix" and sys.path and os.path.basename(sys.path[-1]) == "Modules": - addbuilddir() - if _is_jython: - fixclasspath() - GLOBAL_SITE_PACKAGES = not os.path.exists(os.path.join(os.path.dirname(__file__), "no-global-site-packages.txt")) - if not GLOBAL_SITE_PACKAGES: - ENABLE_USER_SITE = False - if ENABLE_USER_SITE is None: - ENABLE_USER_SITE = check_enableusersite() - paths_in_sys = addsitepackages(paths_in_sys) - paths_in_sys = addusersitepackages(paths_in_sys) - if GLOBAL_SITE_PACKAGES: - paths_in_sys = virtual_addsitepackages(paths_in_sys) - if sys.platform == "os2emx": - setBEGINLIBPATH() - setquit() - setcopyright() - sethelper() - if sys.version_info[0] == 3: - enablerlcompleter() - aliasmbcs() - setencoding() - execsitecustomize() - if ENABLE_USER_SITE: - execusercustomize() - # Remove sys.setdefaultencoding() so that users cannot change the - # encoding after initialization. The test for presence is needed when - # this module is run as a script, because this code is executed twice. - if hasattr(sys, "setdefaultencoding"): - del sys.setdefaultencoding - - -main() - - -def _script(): - help = """\ - %s [--user-base] [--user-site] - - Without arguments print some useful information - With arguments print the value of USER_BASE and/or USER_SITE separated - by '%s'. - - Exit codes with --user-base or --user-site: - 0 - user site directory is enabled - 1 - user site directory is disabled by user - 2 - uses site directory is disabled by super user - or for security reasons - >2 - unknown error - """ - args = sys.argv[1:] - if not args: - print("sys.path = [") - for dir in sys.path: - print(" {!r},".format(dir)) - print("]") - - def exists(path): - if os.path.isdir(path): - return "exists" - else: - return "doesn't exist" - - print("USER_BASE: {!r} ({})".format(USER_BASE, exists(USER_BASE))) - print("USER_SITE: {!r} ({})".format(USER_SITE, exists(USER_SITE))) - print("ENABLE_USER_SITE: %r" % ENABLE_USER_SITE) - sys.exit(0) - - buffer = [] - if "--user-base" in args: - buffer.append(USER_BASE) - if "--user-site" in args: - buffer.append(USER_SITE) - - if buffer: - print(os.pathsep.join(buffer)) - if ENABLE_USER_SITE: - sys.exit(0) - elif ENABLE_USER_SITE is False: - sys.exit(1) - elif ENABLE_USER_SITE is None: - sys.exit(2) - else: - sys.exit(3) - else: - import textwrap - - print(textwrap.dedent(help % (sys.argv[0], os.pathsep))) - sys.exit(10) - - -if __name__ == "__main__": - _script() diff --git a/venv2/lib/python2.7/sre.py b/venv2/lib/python2.7/sre.py deleted file mode 120000 index 27f81b9..0000000 --- a/venv2/lib/python2.7/sre.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/sre.py \ No newline at end of file diff --git a/venv2/lib/python2.7/sre_compile.py b/venv2/lib/python2.7/sre_compile.py deleted file mode 120000 index dce5da4..0000000 --- a/venv2/lib/python2.7/sre_compile.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/sre_compile.py \ No newline at end of file diff --git a/venv2/lib/python2.7/sre_constants.py b/venv2/lib/python2.7/sre_constants.py deleted file mode 120000 index b9c9797..0000000 --- a/venv2/lib/python2.7/sre_constants.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/sre_constants.py \ No newline at end of file diff --git a/venv2/lib/python2.7/sre_parse.py b/venv2/lib/python2.7/sre_parse.py deleted file mode 120000 index f33a572..0000000 --- a/venv2/lib/python2.7/sre_parse.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/sre_parse.py \ No newline at end of file diff --git a/venv2/lib/python2.7/stat.py b/venv2/lib/python2.7/stat.py deleted file mode 120000 index c1d654c..0000000 --- a/venv2/lib/python2.7/stat.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/stat.py \ No newline at end of file diff --git a/venv2/lib/python2.7/types.py b/venv2/lib/python2.7/types.py deleted file mode 120000 index 5546478..0000000 --- a/venv2/lib/python2.7/types.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/types.py \ No newline at end of file diff --git a/venv2/lib/python2.7/warnings.py b/venv2/lib/python2.7/warnings.py deleted file mode 120000 index a9c4730..0000000 --- a/venv2/lib/python2.7/warnings.py +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/python2.7/warnings.py \ No newline at end of file diff --git a/venv2/local/bin b/venv2/local/bin deleted file mode 120000 index 9cec038..0000000 --- a/venv2/local/bin +++ /dev/null @@ -1 +0,0 @@ -/home/sean/Downloads/BMS-View/venv2/bin \ No newline at end of file diff --git a/venv2/local/lib b/venv2/local/lib deleted file mode 120000 index 8ebdbfe..0000000 --- a/venv2/local/lib +++ /dev/null @@ -1 +0,0 @@ -/home/sean/Downloads/BMS-View/venv2/lib \ No newline at end of file

    J0ec%{X00Gw zMrkzY6|W+2m%4$O;{M;ZCg746Z_*h1P!3<-=|a`@;C!REUK-)jaRJ5&e+B&8s3X>Q zQ(P($)p1MuHGj#Cthfr;=_oB7mM)kh`?tC_qdtoUYYmxn zWB>NNiz27`w~F=ScI!ty^TUE%+>h%iV&iDuLBNlPH_#=xWW>4xnOTj|F=2$bH#%mV zNXHnR4)d0wzy>f;G%tCvY+mcGsz-!w6a0BoLMG}i3uHqRa=Bv6^@kN?3bO=cR|(0f z`~Ah>>^=BnR9$M0?(Q$iKK;c&@CUO5f@VaJH#u3qxsPFHa1WIxh9fsi5t;!g7(faq zm_T#+D{pd&zQ4BtqK;~rLQjd>?m`)(A46IA_+R{9B#`m`Yp4f8+3Pa+L3K;Ca;WkCw*K9}E|RrD_E0Z~@B_6PKbOWBRof zO@ckv5gc8iJD-b)R3(u!8E*I``nCmU%#n6hOcXg;Xs~*LrWh$=OAX1uodd+fg;BB- z_`t_##^H!FWh-TX57vtZLhK@#baA3|Ofl_^@OMK{sw+6Q0p8Jx@O=!%H7&o5Gc>e_ zBXFxD&>4t31Mv$$JOPMf*CCpDa5PfJC+T(PiSw{RFUSewJzsmzr8HQ7m#P8w?y*63O@eyus*aPpQ`QHEBV0h-5-M8Gp#FbDk%Q0DsxKQJ60x)a0k{GP~g zd`=JrtvBaHWK2Y6>)F3bt@lu8H5^j~A)JTC;FmEbL>M>m7DFJjykULuz)ENqszH^9 z@U6dSsq(sTB|(+-EL9$1q8Nrlm&q!(z_ml{krpybXn;gXY@+^0C_=0VXf7aID#*D8 z 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%0DV7S>p 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%0AV0`Urr17lttc{8M!DE5<#+=py>(02^-rE?I}oo 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

iML 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