From 56cf3716c06986a76aca042c284b73a2eb574cda Mon Sep 17 00:00:00 2001 From: dntrinh <55397489+dntrinh@users.noreply.github.com> Date: Tue, 17 Sep 2019 22:19:22 -0600 Subject: [PATCH 1/4] Add files via upload --- helloworld.py | 42 ++++++++++++++++++++++++++++++++++++++++++ output.txt | 25 +++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 helloworld.py create mode 100644 output.txt diff --git a/helloworld.py b/helloworld.py new file mode 100644 index 0000000..32148d8 --- /dev/null +++ b/helloworld.py @@ -0,0 +1,42 @@ +def helloworld(): + + def greeting(): + + print("What is your name?") + Name = input() + print("Hello World, my name is", Name) + + greeting() + + def fibonacci(): + + num_1 = 0 + num_2 = 1 + + import time + time.sleep(1) + print(num_1) + import time + time.sleep(1) + print(num_2) + import time + time.sleep(1) + + for i in range(1, 20): + new_num = num_1 + num_2 + num_1 = num_2 + num_2 = new_num + print(new_num) + + import time + time.sleep(1) + + fibonacci() + + import time + time.sleep(1) + + print("Task Complete!") + + +helloworld() \ No newline at end of file diff --git a/output.txt b/output.txt new file mode 100644 index 0000000..0210bf6 --- /dev/null +++ b/output.txt @@ -0,0 +1,25 @@ +What is your name? +Daren +Hello World, my name is Daren +0 +1 +1 +2 +3 +5 +8 +13 +21 +34 +55 +89 +144 +233 +377 +610 +987 +1597 +2584 +4181 +6765 +Task Complete! \ No newline at end of file From 5e1739c991e74f8e3716832d9dabf9b0ef046d0d Mon Sep 17 00:00:00 2001 From: dntrinh Date: Tue, 17 Sep 2019 23:00:23 -0600 Subject: [PATCH 2/4] Assignment done! --- .idea/.name | 1 + .idea/helloworld1.iml | 13 + .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/workspace.xml | 114 + helloworld.py | 42 + output.txt | 25 + tutorial | 1 + venv/Lib/site-packages/easy-install.pth | 2 + .../pip-19.0.3-py3.7.egg/EGG-INFO/PKG-INFO | 73 + .../pip-19.0.3-py3.7.egg/EGG-INFO/SOURCES.txt | 391 + .../EGG-INFO/dependency_links.txt | 1 + .../EGG-INFO/entry_points.txt | 5 + .../EGG-INFO/not-zip-safe | 1 + .../EGG-INFO/top_level.txt | 1 + .../pip-19.0.3-py3.7.egg/pip/__init__.py | 1 + .../pip-19.0.3-py3.7.egg/pip/__main__.py | 19 + .../pip/_internal/__init__.py | 78 + .../pip/_internal/build_env.py | 215 + .../pip/_internal/cache.py | 224 + .../pip/_internal/cli/__init__.py | 4 + .../pip/_internal/cli/autocompletion.py | 152 + .../pip/_internal/cli/base_command.py | 341 + .../pip/_internal/cli/cmdoptions.py | 809 ++ .../pip/_internal/cli/main_parser.py | 104 + .../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 | 227 + .../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 | 566 ++ .../pip/_internal/commands/list.py | 301 + .../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 | 387 + .../pip/_internal/download.py | 971 ++ .../pip/_internal/exceptions.py | 274 + .../pip/_internal/index.py | 990 ++ .../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 | 413 + .../pip/_internal/pep425tags.py | 381 + .../pip/_internal/pyproject.py | 171 + .../pip/_internal/req/__init__.py | 77 + .../pip/_internal/req/constructors.py | 339 + .../pip/_internal/req/req_file.py | 382 + .../pip/_internal/req/req_install.py | 1021 ++ .../pip/_internal/req/req_set.py | 197 + .../pip/_internal/req/req_tracker.py | 88 + .../pip/_internal/req/req_uninstall.py | 596 ++ .../pip/_internal/resolve.py | 393 + .../pip/_internal/utils/__init__.py | 0 .../pip/_internal/utils/appdirs.py | 270 + .../pip/_internal/utils/compat.py | 264 + .../pip/_internal/utils/deprecation.py | 90 + .../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 | 318 + .../pip/_internal/utils/misc.py | 1040 +++ .../pip/_internal/utils/models.py | 40 + .../pip/_internal/utils/outdated.py | 164 + .../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 + .../pip/_internal/utils/ui.py | 441 + .../pip/_internal/vcs/__init__.py | 534 ++ .../pip/_internal/vcs/bazaar.py | 114 + .../pip/_internal/vcs/git.py | 369 + .../pip/_internal/vcs/mercurial.py | 103 + .../pip/_internal/vcs/subversion.py | 200 + .../pip/_internal/wheel.py | 1095 +++ .../pip/_vendor/__init__.py | 111 + .../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 | 4512 +++++++++ .../pip/_vendor/certifi/core.py | 20 + .../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 + .../pip/_vendor/distlib/t32.exe | Bin 0 -> 92672 bytes .../pip/_vendor/distlib/t64.exe | Bin 0 -> 102400 bytes .../pip/_vendor/distlib/util.py | 1756 ++++ .../pip/_vendor/distlib/version.py | 736 ++ .../pip/_vendor/distlib/w32.exe | Bin 0 -> 89088 bytes .../pip/_vendor/distlib/w64.exe | Bin 0 -> 99328 bytes .../pip/_vendor/distlib/wheel.py | 988 ++ .../pip/_vendor/distro.py | 1197 +++ .../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 + .../pip/_vendor/idna/codec.py | 118 + .../pip/_vendor/idna/compat.py | 12 + .../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 +++++++++++++++++ .../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 + .../pip/_vendor/pep517/build.py | 108 + .../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 | 3171 +++++++ .../pip/_vendor/pkg_resources/py31compat.py | 23 + .../pip/_vendor/progress/__init__.py | 127 + .../pip/_vendor/progress/bar.py | 94 + .../pip/_vendor/progress/counter.py | 48 + .../pip/_vendor/progress/helpers.py | 91 + .../pip/_vendor/progress/spinner.py | 44 + .../pip/_vendor/pyparsing.py | 6452 +++++++++++++ .../pip/_vendor/pytoml/__init__.py | 4 + .../pip/_vendor/pytoml/core.py | 13 + .../pip/_vendor/pytoml/parser.py | 341 + .../pip/_vendor/pytoml/test.py | 30 + .../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 ++ .../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 ++ .../pip/_vendor/retrying.py | 267 + .../pip-19.0.3-py3.7.egg/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/setuptools-40.8.0-py3.7.egg | Bin 0 -> 571910 bytes venv/Lib/site-packages/setuptools.pth | 1 + venv/Scripts/Activate.ps1 | 51 + venv/Scripts/activate | 76 + venv/Scripts/activate.bat | 45 + venv/Scripts/deactivate.bat | 21 + venv/Scripts/easy_install-3.7-script.py | 12 + venv/Scripts/easy_install-3.7.exe | Bin 0 -> 65536 bytes venv/Scripts/easy_install-3.7.exe.manifest | 15 + venv/Scripts/easy_install-script.py | 12 + venv/Scripts/easy_install.exe | Bin 0 -> 65536 bytes venv/Scripts/easy_install.exe.manifest | 15 + venv/Scripts/pip-script.py | 12 + venv/Scripts/pip.exe | Bin 0 -> 65536 bytes venv/Scripts/pip.exe.manifest | 15 + venv/Scripts/pip3-script.py | 12 + venv/Scripts/pip3.7-script.py | 12 + venv/Scripts/pip3.7.exe | Bin 0 -> 65536 bytes venv/Scripts/pip3.7.exe.manifest | 15 + venv/Scripts/pip3.exe | Bin 0 -> 65536 bytes venv/Scripts/pip3.exe.manifest | 15 + venv/Scripts/python.exe | Bin 0 -> 415248 bytes venv/Scripts/pythonw.exe | Bin 0 -> 414736 bytes venv/pyvenv.cfg | 3 + 348 files changed, 106751 insertions(+) create mode 100644 .idea/.name create mode 100644 .idea/helloworld1.iml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/workspace.xml create mode 100644 helloworld.py create mode 100644 output.txt create mode 160000 tutorial create mode 100644 venv/Lib/site-packages/easy-install.pth create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/PKG-INFO create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/SOURCES.txt create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/dependency_links.txt create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/entry_points.txt create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/not-zip-safe create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/top_level.txt create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/__main__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/build_env.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cache.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/autocompletion.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/base_command.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/cmdoptions.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/main_parser.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/parser.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/status_codes.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/check.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/completion.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/configuration.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/download.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/freeze.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/hash.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/help.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/install.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/list.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/search.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/show.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/uninstall.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/wheel.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/configuration.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/download.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/exceptions.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/index.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/locations.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/candidate.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/format_control.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/index.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/link.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/operations/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/operations/check.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/operations/freeze.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/operations/prepare.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/pep425tags.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/pyproject.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/constructors.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_file.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_install.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_set.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_tracker.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_uninstall.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/resolve.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/appdirs.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/compat.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/deprecation.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/encoding.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/filesystem.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/glibc.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/hashes.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/logging.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/misc.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/models.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/outdated.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/packaging.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/setuptools_build.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/temp_dir.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/typing.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/ui.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/bazaar.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/git.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/mercurial.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/subversion.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/wheel.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/appdirs.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/_cmd.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/adapter.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/cache.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/caches/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/caches/file_cache.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/caches/redis_cache.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/compat.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/controller.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/filewrapper.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/heuristics.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/serialize.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/wrapper.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/certifi/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/certifi/__main__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/certifi/cacert.pem create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/certifi/core.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/big5freq.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/big5prober.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/chardistribution.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/charsetgroupprober.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/charsetprober.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/cli/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/cli/chardetect.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/codingstatemachine.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/compat.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/cp949prober.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/enums.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/escprober.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/escsm.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/eucjpprober.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/euckrfreq.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/euckrprober.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/euctwfreq.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/euctwprober.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/gb2312freq.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/gb2312prober.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/hebrewprober.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/jisfreq.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/jpcntx.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langbulgarianmodel.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langcyrillicmodel.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langgreekmodel.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langhebrewmodel.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langhungarianmodel.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langthaimodel.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langturkishmodel.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/latin1prober.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/mbcharsetprober.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/mbcsgroupprober.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/mbcssm.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/sbcharsetprober.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/sbcsgroupprober.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/sjisprober.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/universaldetector.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/utf8prober.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/version.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/ansi.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/ansitowin32.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/initialise.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/win32.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/winterm.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/misc.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/shutil.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/sysconfig.cfg create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/sysconfig.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/tarfile.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/compat.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/database.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/index.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/locators.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/manifest.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/markers.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/metadata.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/resources.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/scripts.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/t32.exe create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/t64.exe create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/util.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/version.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/w32.exe create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/w64.exe create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/wheel.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distro.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_ihatexml.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_inputstream.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_tokenizer.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_trie/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_trie/_base.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_trie/datrie.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_trie/py.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_utils.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/constants.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/alphabeticalattributes.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/base.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/inject_meta_charset.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/lint.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/optionaltags.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/sanitizer.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/whitespace.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/html5parser.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/serializer.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treeadapters/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treeadapters/genshi.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treeadapters/sax.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/base.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/dom.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/etree.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/etree_lxml.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/base.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/dom.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/etree.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/etree_lxml.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/genshi.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/codec.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/compat.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/core.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/idnadata.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/intranges.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/package_data.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/uts46data.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/ipaddress.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/linklockfile.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/mkdirlockfile.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/pidlockfile.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/sqlitelockfile.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/symlinklockfile.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/msgpack/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/msgpack/_version.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/msgpack/exceptions.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/msgpack/fallback.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/__about__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/_compat.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/_structures.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/markers.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/requirements.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/specifiers.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/utils.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/version.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/_in_process.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/build.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/check.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/colorlog.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/compat.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/envbuild.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/wrappers.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pkg_resources/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pkg_resources/py31compat.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/bar.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/counter.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/helpers.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/spinner.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pyparsing.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/core.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/parser.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/test.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/utils.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/writer.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/__version__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/_internal_utils.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/adapters.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/api.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/auth.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/certs.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/compat.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/cookies.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/exceptions.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/help.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/hooks.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/models.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/packages.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/sessions.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/status_codes.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/structures.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/utils.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/retrying.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/six.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/_collections.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/connection.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/connectionpool.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/_appengine_environ.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/_securetransport/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/_securetransport/bindings.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/_securetransport/low_level.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/appengine.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/ntlmpool.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/pyopenssl.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/securetransport.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/socks.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/exceptions.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/fields.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/filepost.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/backports/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/backports/makefile.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/six.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/poolmanager.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/request.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/response.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/connection.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/queue.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/request.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/response.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/retry.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/ssl_.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/timeout.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/url.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/wait.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/__init__.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/labels.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/mklabels.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/tests.py create mode 100644 venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/x_user_defined.py create mode 100644 venv/Lib/site-packages/setuptools-40.8.0-py3.7.egg create mode 100644 venv/Lib/site-packages/setuptools.pth create mode 100644 venv/Scripts/Activate.ps1 create mode 100644 venv/Scripts/activate create mode 100644 venv/Scripts/activate.bat create mode 100644 venv/Scripts/deactivate.bat create mode 100644 venv/Scripts/easy_install-3.7-script.py create mode 100644 venv/Scripts/easy_install-3.7.exe create mode 100644 venv/Scripts/easy_install-3.7.exe.manifest create mode 100644 venv/Scripts/easy_install-script.py create mode 100644 venv/Scripts/easy_install.exe create mode 100644 venv/Scripts/easy_install.exe.manifest create mode 100644 venv/Scripts/pip-script.py create mode 100644 venv/Scripts/pip.exe create mode 100644 venv/Scripts/pip.exe.manifest create mode 100644 venv/Scripts/pip3-script.py create mode 100644 venv/Scripts/pip3.7-script.py create mode 100644 venv/Scripts/pip3.7.exe create mode 100644 venv/Scripts/pip3.7.exe.manifest create mode 100644 venv/Scripts/pip3.exe create mode 100644 venv/Scripts/pip3.exe.manifest create mode 100644 venv/Scripts/python.exe create mode 100644 venv/Scripts/pythonw.exe create mode 100644 venv/pyvenv.cfg diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..4d539b4 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +helloworld1 \ No newline at end of file diff --git a/.idea/helloworld1.iml b/.idea/helloworld1.iml new file mode 100644 index 0000000..85c7612 --- /dev/null +++ b/.idea/helloworld1.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..6670658 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..2fa3dd7 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..365788d --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1568683078989 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/helloworld.py b/helloworld.py new file mode 100644 index 0000000..758d3fe --- /dev/null +++ b/helloworld.py @@ -0,0 +1,42 @@ +def helloworld(): + + def greeting(): + + print("What is your name?") + Name = input() + print("Hello World, my name is", Name) + + greeting() + + def fibonacci(): + + num_1 = 0 + num_2 = 1 + + import time + time.sleep(1) + print(num_1) + import time + time.sleep(1) + print(num_2) + import time + time.sleep(1) + + for i in range(1, 20): + new_num = num_1 + num_2 + num_1 = num_2 + num_2 = new_num + print(new_num) + + import time + time.sleep(1) + + fibonacci() + + import time + time.sleep(1) + + print("Task Complete!") + + +helloworld() \ No newline at end of file diff --git a/output.txt b/output.txt new file mode 100644 index 0000000..da96741 --- /dev/null +++ b/output.txt @@ -0,0 +1,25 @@ +What is your name? +Daren +Hello World, my name is Daren +0 +1 +1 +2 +3 +5 +8 +13 +21 +34 +55 +89 +144 +233 +377 +610 +987 +1597 +2584 +4181 +6765 +Task Complete! \ No newline at end of file diff --git a/tutorial b/tutorial new file mode 160000 index 0000000..0e9d49d --- /dev/null +++ b/tutorial @@ -0,0 +1 @@ +Subproject commit 0e9d49df9f548d402e1888a5c79ee5fa250b0a0a diff --git a/venv/Lib/site-packages/easy-install.pth b/venv/Lib/site-packages/easy-install.pth new file mode 100644 index 0000000..b74fe2e --- /dev/null +++ b/venv/Lib/site-packages/easy-install.pth @@ -0,0 +1,2 @@ +./setuptools-40.8.0-py3.7.egg +./pip-19.0.3-py3.7.egg diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/PKG-INFO b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/PKG-INFO new file mode 100644 index 0000000..0b410a2 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/PKG-INFO @@ -0,0 +1,73 @@ +Metadata-Version: 1.2 +Name: pip +Version: 19.0.3 +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 +Description: 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/ + +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.* diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/SOURCES.txt b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/SOURCES.txt new file mode 100644 index 0000000..eb4810d --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/SOURCES.txt @@ -0,0 +1,391 @@ +AUTHORS.txt +LICENSE.txt +MANIFEST.in +NEWS.rst +README.rst +pyproject.toml +setup.cfg +setup.py +docs/pip_sphinxext.py +docs/html/conf.py +docs/html/cookbook.rst +docs/html/index.rst +docs/html/installing.rst +docs/html/logic.rst +docs/html/news.rst +docs/html/quickstart.rst +docs/html/usage.rst +docs/html/user_guide.rst +docs/html/development/configuration.rst +docs/html/development/contributing.rst +docs/html/development/getting-started.rst +docs/html/development/index.rst +docs/html/development/release-process.rst +docs/html/development/vendoring-policy.rst +docs/html/reference/index.rst +docs/html/reference/pip.rst +docs/html/reference/pip_check.rst +docs/html/reference/pip_config.rst +docs/html/reference/pip_download.rst +docs/html/reference/pip_freeze.rst +docs/html/reference/pip_hash.rst +docs/html/reference/pip_install.rst +docs/html/reference/pip_list.rst +docs/html/reference/pip_search.rst +docs/html/reference/pip_show.rst +docs/html/reference/pip_uninstall.rst +docs/html/reference/pip_wheel.rst +docs/man/index.rst +docs/man/commands/check.rst +docs/man/commands/config.rst +docs/man/commands/download.rst +docs/man/commands/freeze.rst +docs/man/commands/hash.rst +docs/man/commands/help.rst +docs/man/commands/install.rst +docs/man/commands/list.rst +docs/man/commands/search.rst +docs/man/commands/show.rst +docs/man/commands/uninstall.rst +docs/man/commands/wheel.rst +src/pip/__init__.py +src/pip/__main__.py +src/pip.egg-info/PKG-INFO +src/pip.egg-info/SOURCES.txt +src/pip.egg-info/dependency_links.txt +src/pip.egg-info/entry_points.txt +src/pip.egg-info/not-zip-safe +src/pip.egg-info/top_level.txt +src/pip/_internal/__init__.py +src/pip/_internal/build_env.py +src/pip/_internal/cache.py +src/pip/_internal/configuration.py +src/pip/_internal/download.py +src/pip/_internal/exceptions.py +src/pip/_internal/index.py +src/pip/_internal/locations.py +src/pip/_internal/pep425tags.py +src/pip/_internal/pyproject.py +src/pip/_internal/resolve.py +src/pip/_internal/wheel.py +src/pip/_internal/cli/__init__.py +src/pip/_internal/cli/autocompletion.py +src/pip/_internal/cli/base_command.py +src/pip/_internal/cli/cmdoptions.py +src/pip/_internal/cli/main_parser.py +src/pip/_internal/cli/parser.py +src/pip/_internal/cli/status_codes.py +src/pip/_internal/commands/__init__.py +src/pip/_internal/commands/check.py +src/pip/_internal/commands/completion.py +src/pip/_internal/commands/configuration.py +src/pip/_internal/commands/download.py +src/pip/_internal/commands/freeze.py +src/pip/_internal/commands/hash.py +src/pip/_internal/commands/help.py +src/pip/_internal/commands/install.py +src/pip/_internal/commands/list.py +src/pip/_internal/commands/search.py +src/pip/_internal/commands/show.py +src/pip/_internal/commands/uninstall.py +src/pip/_internal/commands/wheel.py +src/pip/_internal/models/__init__.py +src/pip/_internal/models/candidate.py +src/pip/_internal/models/format_control.py +src/pip/_internal/models/index.py +src/pip/_internal/models/link.py +src/pip/_internal/operations/__init__.py +src/pip/_internal/operations/check.py +src/pip/_internal/operations/freeze.py +src/pip/_internal/operations/prepare.py +src/pip/_internal/req/__init__.py +src/pip/_internal/req/constructors.py +src/pip/_internal/req/req_file.py +src/pip/_internal/req/req_install.py +src/pip/_internal/req/req_set.py +src/pip/_internal/req/req_tracker.py +src/pip/_internal/req/req_uninstall.py +src/pip/_internal/utils/__init__.py +src/pip/_internal/utils/appdirs.py +src/pip/_internal/utils/compat.py +src/pip/_internal/utils/deprecation.py +src/pip/_internal/utils/encoding.py +src/pip/_internal/utils/filesystem.py +src/pip/_internal/utils/glibc.py +src/pip/_internal/utils/hashes.py +src/pip/_internal/utils/logging.py +src/pip/_internal/utils/misc.py +src/pip/_internal/utils/models.py +src/pip/_internal/utils/outdated.py +src/pip/_internal/utils/packaging.py +src/pip/_internal/utils/setuptools_build.py +src/pip/_internal/utils/temp_dir.py +src/pip/_internal/utils/typing.py +src/pip/_internal/utils/ui.py +src/pip/_internal/vcs/__init__.py +src/pip/_internal/vcs/bazaar.py +src/pip/_internal/vcs/git.py +src/pip/_internal/vcs/mercurial.py +src/pip/_internal/vcs/subversion.py +src/pip/_vendor/README.rst +src/pip/_vendor/__init__.py +src/pip/_vendor/appdirs.LICENSE.txt +src/pip/_vendor/appdirs.py +src/pip/_vendor/distro.LICENSE +src/pip/_vendor/distro.py +src/pip/_vendor/ipaddress.LICENSE +src/pip/_vendor/ipaddress.py +src/pip/_vendor/pyparsing.LICENSE +src/pip/_vendor/pyparsing.py +src/pip/_vendor/retrying.LICENSE +src/pip/_vendor/retrying.py +src/pip/_vendor/six.LICENSE +src/pip/_vendor/six.py +src/pip/_vendor/vendor.txt +src/pip/_vendor/cachecontrol/LICENSE.txt +src/pip/_vendor/cachecontrol/__init__.py +src/pip/_vendor/cachecontrol/_cmd.py +src/pip/_vendor/cachecontrol/adapter.py +src/pip/_vendor/cachecontrol/cache.py +src/pip/_vendor/cachecontrol/compat.py +src/pip/_vendor/cachecontrol/controller.py +src/pip/_vendor/cachecontrol/filewrapper.py +src/pip/_vendor/cachecontrol/heuristics.py +src/pip/_vendor/cachecontrol/serialize.py +src/pip/_vendor/cachecontrol/wrapper.py +src/pip/_vendor/cachecontrol/caches/__init__.py +src/pip/_vendor/cachecontrol/caches/file_cache.py +src/pip/_vendor/cachecontrol/caches/redis_cache.py +src/pip/_vendor/certifi/LICENSE +src/pip/_vendor/certifi/__init__.py +src/pip/_vendor/certifi/__main__.py +src/pip/_vendor/certifi/cacert.pem +src/pip/_vendor/certifi/core.py +src/pip/_vendor/chardet/LICENSE +src/pip/_vendor/chardet/__init__.py +src/pip/_vendor/chardet/big5freq.py +src/pip/_vendor/chardet/big5prober.py +src/pip/_vendor/chardet/chardistribution.py +src/pip/_vendor/chardet/charsetgroupprober.py +src/pip/_vendor/chardet/charsetprober.py +src/pip/_vendor/chardet/codingstatemachine.py +src/pip/_vendor/chardet/compat.py +src/pip/_vendor/chardet/cp949prober.py +src/pip/_vendor/chardet/enums.py +src/pip/_vendor/chardet/escprober.py +src/pip/_vendor/chardet/escsm.py +src/pip/_vendor/chardet/eucjpprober.py +src/pip/_vendor/chardet/euckrfreq.py +src/pip/_vendor/chardet/euckrprober.py +src/pip/_vendor/chardet/euctwfreq.py +src/pip/_vendor/chardet/euctwprober.py +src/pip/_vendor/chardet/gb2312freq.py +src/pip/_vendor/chardet/gb2312prober.py +src/pip/_vendor/chardet/hebrewprober.py +src/pip/_vendor/chardet/jisfreq.py +src/pip/_vendor/chardet/jpcntx.py +src/pip/_vendor/chardet/langbulgarianmodel.py +src/pip/_vendor/chardet/langcyrillicmodel.py +src/pip/_vendor/chardet/langgreekmodel.py +src/pip/_vendor/chardet/langhebrewmodel.py +src/pip/_vendor/chardet/langhungarianmodel.py +src/pip/_vendor/chardet/langthaimodel.py +src/pip/_vendor/chardet/langturkishmodel.py +src/pip/_vendor/chardet/latin1prober.py +src/pip/_vendor/chardet/mbcharsetprober.py +src/pip/_vendor/chardet/mbcsgroupprober.py +src/pip/_vendor/chardet/mbcssm.py +src/pip/_vendor/chardet/sbcharsetprober.py +src/pip/_vendor/chardet/sbcsgroupprober.py +src/pip/_vendor/chardet/sjisprober.py +src/pip/_vendor/chardet/universaldetector.py +src/pip/_vendor/chardet/utf8prober.py +src/pip/_vendor/chardet/version.py +src/pip/_vendor/chardet/cli/__init__.py +src/pip/_vendor/chardet/cli/chardetect.py +src/pip/_vendor/colorama/LICENSE.txt +src/pip/_vendor/colorama/__init__.py +src/pip/_vendor/colorama/ansi.py +src/pip/_vendor/colorama/ansitowin32.py +src/pip/_vendor/colorama/initialise.py +src/pip/_vendor/colorama/win32.py +src/pip/_vendor/colorama/winterm.py +src/pip/_vendor/distlib/LICENSE.txt +src/pip/_vendor/distlib/__init__.py +src/pip/_vendor/distlib/compat.py +src/pip/_vendor/distlib/database.py +src/pip/_vendor/distlib/index.py +src/pip/_vendor/distlib/locators.py +src/pip/_vendor/distlib/manifest.py +src/pip/_vendor/distlib/markers.py +src/pip/_vendor/distlib/metadata.py +src/pip/_vendor/distlib/resources.py +src/pip/_vendor/distlib/scripts.py +src/pip/_vendor/distlib/t32.exe +src/pip/_vendor/distlib/t64.exe +src/pip/_vendor/distlib/util.py +src/pip/_vendor/distlib/version.py +src/pip/_vendor/distlib/w32.exe +src/pip/_vendor/distlib/w64.exe +src/pip/_vendor/distlib/wheel.py +src/pip/_vendor/distlib/_backport/__init__.py +src/pip/_vendor/distlib/_backport/misc.py +src/pip/_vendor/distlib/_backport/shutil.py +src/pip/_vendor/distlib/_backport/sysconfig.cfg +src/pip/_vendor/distlib/_backport/sysconfig.py +src/pip/_vendor/distlib/_backport/tarfile.py +src/pip/_vendor/html5lib/LICENSE +src/pip/_vendor/html5lib/__init__.py +src/pip/_vendor/html5lib/_ihatexml.py +src/pip/_vendor/html5lib/_inputstream.py +src/pip/_vendor/html5lib/_tokenizer.py +src/pip/_vendor/html5lib/_utils.py +src/pip/_vendor/html5lib/constants.py +src/pip/_vendor/html5lib/html5parser.py +src/pip/_vendor/html5lib/serializer.py +src/pip/_vendor/html5lib/_trie/__init__.py +src/pip/_vendor/html5lib/_trie/_base.py +src/pip/_vendor/html5lib/_trie/datrie.py +src/pip/_vendor/html5lib/_trie/py.py +src/pip/_vendor/html5lib/filters/__init__.py +src/pip/_vendor/html5lib/filters/alphabeticalattributes.py +src/pip/_vendor/html5lib/filters/base.py +src/pip/_vendor/html5lib/filters/inject_meta_charset.py +src/pip/_vendor/html5lib/filters/lint.py +src/pip/_vendor/html5lib/filters/optionaltags.py +src/pip/_vendor/html5lib/filters/sanitizer.py +src/pip/_vendor/html5lib/filters/whitespace.py +src/pip/_vendor/html5lib/treeadapters/__init__.py +src/pip/_vendor/html5lib/treeadapters/genshi.py +src/pip/_vendor/html5lib/treeadapters/sax.py +src/pip/_vendor/html5lib/treebuilders/__init__.py +src/pip/_vendor/html5lib/treebuilders/base.py +src/pip/_vendor/html5lib/treebuilders/dom.py +src/pip/_vendor/html5lib/treebuilders/etree.py +src/pip/_vendor/html5lib/treebuilders/etree_lxml.py +src/pip/_vendor/html5lib/treewalkers/__init__.py +src/pip/_vendor/html5lib/treewalkers/base.py +src/pip/_vendor/html5lib/treewalkers/dom.py +src/pip/_vendor/html5lib/treewalkers/etree.py +src/pip/_vendor/html5lib/treewalkers/etree_lxml.py +src/pip/_vendor/html5lib/treewalkers/genshi.py +src/pip/_vendor/idna/LICENSE.rst +src/pip/_vendor/idna/__init__.py +src/pip/_vendor/idna/codec.py +src/pip/_vendor/idna/compat.py +src/pip/_vendor/idna/core.py +src/pip/_vendor/idna/idnadata.py +src/pip/_vendor/idna/intranges.py +src/pip/_vendor/idna/package_data.py +src/pip/_vendor/idna/uts46data.py +src/pip/_vendor/lockfile/LICENSE +src/pip/_vendor/lockfile/__init__.py +src/pip/_vendor/lockfile/linklockfile.py +src/pip/_vendor/lockfile/mkdirlockfile.py +src/pip/_vendor/lockfile/pidlockfile.py +src/pip/_vendor/lockfile/sqlitelockfile.py +src/pip/_vendor/lockfile/symlinklockfile.py +src/pip/_vendor/msgpack/COPYING +src/pip/_vendor/msgpack/__init__.py +src/pip/_vendor/msgpack/_version.py +src/pip/_vendor/msgpack/exceptions.py +src/pip/_vendor/msgpack/fallback.py +src/pip/_vendor/packaging/LICENSE +src/pip/_vendor/packaging/LICENSE.APACHE +src/pip/_vendor/packaging/LICENSE.BSD +src/pip/_vendor/packaging/__about__.py +src/pip/_vendor/packaging/__init__.py +src/pip/_vendor/packaging/_compat.py +src/pip/_vendor/packaging/_structures.py +src/pip/_vendor/packaging/markers.py +src/pip/_vendor/packaging/requirements.py +src/pip/_vendor/packaging/specifiers.py +src/pip/_vendor/packaging/utils.py +src/pip/_vendor/packaging/version.py +src/pip/_vendor/pep517/LICENSE +src/pip/_vendor/pep517/__init__.py +src/pip/_vendor/pep517/_in_process.py +src/pip/_vendor/pep517/build.py +src/pip/_vendor/pep517/check.py +src/pip/_vendor/pep517/colorlog.py +src/pip/_vendor/pep517/compat.py +src/pip/_vendor/pep517/envbuild.py +src/pip/_vendor/pep517/wrappers.py +src/pip/_vendor/pkg_resources/LICENSE +src/pip/_vendor/pkg_resources/__init__.py +src/pip/_vendor/pkg_resources/py31compat.py +src/pip/_vendor/progress/LICENSE +src/pip/_vendor/progress/__init__.py +src/pip/_vendor/progress/bar.py +src/pip/_vendor/progress/counter.py +src/pip/_vendor/progress/helpers.py +src/pip/_vendor/progress/spinner.py +src/pip/_vendor/pytoml/LICENSE +src/pip/_vendor/pytoml/__init__.py +src/pip/_vendor/pytoml/core.py +src/pip/_vendor/pytoml/parser.py +src/pip/_vendor/pytoml/test.py +src/pip/_vendor/pytoml/utils.py +src/pip/_vendor/pytoml/writer.py +src/pip/_vendor/requests/LICENSE +src/pip/_vendor/requests/__init__.py +src/pip/_vendor/requests/__version__.py +src/pip/_vendor/requests/_internal_utils.py +src/pip/_vendor/requests/adapters.py +src/pip/_vendor/requests/api.py +src/pip/_vendor/requests/auth.py +src/pip/_vendor/requests/certs.py +src/pip/_vendor/requests/compat.py +src/pip/_vendor/requests/cookies.py +src/pip/_vendor/requests/exceptions.py +src/pip/_vendor/requests/help.py +src/pip/_vendor/requests/hooks.py +src/pip/_vendor/requests/models.py +src/pip/_vendor/requests/packages.py +src/pip/_vendor/requests/sessions.py +src/pip/_vendor/requests/status_codes.py +src/pip/_vendor/requests/structures.py +src/pip/_vendor/requests/utils.py +src/pip/_vendor/urllib3/LICENSE.txt +src/pip/_vendor/urllib3/__init__.py +src/pip/_vendor/urllib3/_collections.py +src/pip/_vendor/urllib3/connection.py +src/pip/_vendor/urllib3/connectionpool.py +src/pip/_vendor/urllib3/exceptions.py +src/pip/_vendor/urllib3/fields.py +src/pip/_vendor/urllib3/filepost.py +src/pip/_vendor/urllib3/poolmanager.py +src/pip/_vendor/urllib3/request.py +src/pip/_vendor/urllib3/response.py +src/pip/_vendor/urllib3/contrib/__init__.py +src/pip/_vendor/urllib3/contrib/_appengine_environ.py +src/pip/_vendor/urllib3/contrib/appengine.py +src/pip/_vendor/urllib3/contrib/ntlmpool.py +src/pip/_vendor/urllib3/contrib/pyopenssl.py +src/pip/_vendor/urllib3/contrib/securetransport.py +src/pip/_vendor/urllib3/contrib/socks.py +src/pip/_vendor/urllib3/contrib/_securetransport/__init__.py +src/pip/_vendor/urllib3/contrib/_securetransport/bindings.py +src/pip/_vendor/urllib3/contrib/_securetransport/low_level.py +src/pip/_vendor/urllib3/packages/__init__.py +src/pip/_vendor/urllib3/packages/six.py +src/pip/_vendor/urllib3/packages/backports/__init__.py +src/pip/_vendor/urllib3/packages/backports/makefile.py +src/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py +src/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py +src/pip/_vendor/urllib3/util/__init__.py +src/pip/_vendor/urllib3/util/connection.py +src/pip/_vendor/urllib3/util/queue.py +src/pip/_vendor/urllib3/util/request.py +src/pip/_vendor/urllib3/util/response.py +src/pip/_vendor/urllib3/util/retry.py +src/pip/_vendor/urllib3/util/ssl_.py +src/pip/_vendor/urllib3/util/timeout.py +src/pip/_vendor/urllib3/util/url.py +src/pip/_vendor/urllib3/util/wait.py +src/pip/_vendor/webencodings/LICENSE +src/pip/_vendor/webencodings/__init__.py +src/pip/_vendor/webencodings/labels.py +src/pip/_vendor/webencodings/mklabels.py +src/pip/_vendor/webencodings/tests.py +src/pip/_vendor/webencodings/x_user_defined.py \ No newline at end of file diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/dependency_links.txt b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/entry_points.txt b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/entry_points.txt new file mode 100644 index 0000000..f5809cb --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/entry_points.txt @@ -0,0 +1,5 @@ +[console_scripts] +pip = pip._internal:main +pip3 = pip._internal:main +pip3.7 = pip._internal:main + diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/not-zip-safe b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/not-zip-safe new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/not-zip-safe @@ -0,0 +1 @@ + diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/top_level.txt b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/top_level.txt new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/EGG-INFO/top_level.txt @@ -0,0 +1 @@ +pip diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/__init__.py new file mode 100644 index 0000000..f48c1ca --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/__init__.py @@ -0,0 +1 @@ +__version__ = "19.0.3" diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/__main__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/__main__.py new file mode 100644 index 0000000..0c223f8 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/__main__.py @@ -0,0 +1,19 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/__init__.py new file mode 100644 index 0000000..276124d --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/__init__.py @@ -0,0 +1,78 @@ +#!/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-stder +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/build_env.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/build_env.py new file mode 100644 index 0000000..d744cc7 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/build_env.py @@ -0,0 +1,215 @@ +"""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 # noqa: F401 + from pip._internal.index import PackageFinder # noqa: F401 + +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, show_stdout=False, 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cache.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cache.py new file mode 100644 index 0000000..eb295c4 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cache.py @@ -0,0 +1,224 @@ +"""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 # noqa: F401 + from pip._internal.index import FormatControl # noqa: F401 + +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/__init__.py new file mode 100644 index 0000000..e589bb9 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/__init__.py @@ -0,0 +1,4 @@ +"""Subpackage containing all of pip's command line interface related code +""" + +# This file intentionally does not import submodules diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/autocompletion.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/autocompletion.py new file mode 100644 index 0000000..0a04199 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/autocompletion.py @@ -0,0 +1,152 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/base_command.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/base_command.py new file mode 100644 index 0000000..3ceea49 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/base_command.py @@ -0,0 +1,341 @@ +"""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 # noqa: F401 + from optparse import Values # noqa: F401 + from pip._internal.cache import WheelCache # noqa: F401 + from pip._internal.req.req_set import RequirementSet # noqa: F401 + +__all__ = ['Command'] + +logger = logging.getLogger(__name__) + + +class Command(object): + name = None # type: Optional[str] + usage = None # type: Optional[str] + hidden = False # type: bool + 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('ERROR: %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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/cmdoptions.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/cmdoptions.py new file mode 100644 index 0000000..5cf5ee9 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/cmdoptions.py @@ -0,0 +1,809 @@ +""" +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, List, Optional, Union # noqa: F401 + from optparse import OptionParser, Values # noqa: F401 + from pip._internal.cli.parser import ConfigOptionParser # noqa: F401 + + +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 + # gauranteed 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 = {} # type: ignore + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/main_parser.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/main_parser.py new file mode 100644 index 0000000..b17c749 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/main_parser.py @@ -0,0 +1,104 @@ +"""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 # noqa: F401 + + +__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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/parser.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/parser.py new file mode 100644 index 0000000..e1eaac4 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/parser.py @@ -0,0 +1,261 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/status_codes.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/status_codes.py new file mode 100644 index 0000000..275360a --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/cli/status_codes.py @@ -0,0 +1,8 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/__init__.py new file mode 100644 index 0000000..c7d1da3 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/__init__.py @@ -0,0 +1,79 @@ +""" +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 # noqa: F401 + from pip._internal.cli.base_command import Command # noqa: F401 + +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/check.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/check.py new file mode 100644 index 0000000..801cecc --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/check.py @@ -0,0 +1,41 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/completion.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/completion.py new file mode 100644 index 0000000..2fcdd39 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/completion.py @@ -0,0 +1,94 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/configuration.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/configuration.py new file mode 100644 index 0000000..826c08d --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/configuration.py @@ -0,0 +1,227 @@ +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 venv_config_file +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 --venv 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( + '--venv', + dest='venv_file', + action='store_true', + default=False, + help='Use the virtualenv configuration file 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): + file_options = { + kinds.USER: options.user_file, + kinds.GLOBAL: options.global_file, + kinds.VENV: options.venv_file + } + + if sum(file_options.values()) == 0: + if not need_value: + return None + # Default to user, unless there's a virtualenv file. + elif os.path.exists(venv_config_file): + return kinds.VENV + else: + return kinds.USER + elif sum(file_options.values()) == 1: + # There's probably a better expression for this. + return [key for key in file_options if file_options[key]][0] + + raise PipError( + "Need exactly one file to operate upon " + "(--user, --venv, --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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/download.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/download.py new file mode 100644 index 0000000..a57e4bc --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/download.py @@ -0,0 +1,176 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/freeze.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/freeze.py new file mode 100644 index 0000000..dc9c53a --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/freeze.py @@ -0,0 +1,96 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/hash.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/hash.py new file mode 100644 index 0000000..423440e --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/hash.py @@ -0,0 +1,57 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/help.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/help.py new file mode 100644 index 0000000..49a81cb --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/help.py @@ -0,0 +1,37 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/install.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/install.py new file mode 100644 index 0000000..1c244d2 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/install.py @@ -0,0 +1,566 @@ +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__) + + +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) + + # We don't build wheels for legacy requirements if we + # don't have wheel installed or we don't have a cache dir + try: + import wheel # noqa: F401 + build_legacy = bool(options.cache_dir) + except ImportError: + build_legacy = False + + wb = WheelBuilder( + finder, preparer, wheel_cache, + build_options=[], global_options=[], + ) + + # Always build PEP 517 requirements + build_failures = wb.build( + pep517_requirements, + session=session, autobuilding=True + ) + + if build_legacy: + # We don't care about failures building legacy + # requirements, as we'll fall through to a direct + # install for those. + wb.build( + legacy_requirements, + session=session, autobuilding=True + ) + + # 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/list.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/list.py new file mode 100644 index 0000000..a640274 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/list.py @@ -0,0 +1,301 @@ +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] + + if not all_candidates: + continue + best_candidate = max(all_candidates, + key=finder._candidate_sort_key) + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/search.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/search.py new file mode 100644 index 0000000..c157a31 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/search.py @@ -0,0 +1,135 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/show.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/show.py new file mode 100644 index 0000000..f92c9bc --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/show.py @@ -0,0 +1,168 @@ +from __future__ import absolute_import + +import logging +import os +from email.parser import FeedParser # type: ignore + +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/uninstall.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/uninstall.py new file mode 100644 index 0000000..0cd6f54 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/uninstall.py @@ -0,0 +1,78 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/wheel.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/wheel.py new file mode 100644 index 0000000..cd72a3d --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/commands/wheel.py @@ -0,0 +1,186 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/configuration.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/configuration.py new file mode 100644 index 0000000..fe6df9b --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/configuration.py @@ -0,0 +1,387 @@ +"""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 import six +from pip._vendor.six.moves import configparser + +from pip._internal.exceptions import ( + ConfigurationError, ConfigurationFileCouldNotBeLoaded, +) +from pip._internal.locations import ( + legacy_config_file, new_config_file, running_under_virtualenv, + site_config_files, venv_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 ( # noqa: F401 + 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 + VENV="venv", # 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.VENV, 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.VENV, 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 = six.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 currentin-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) # type: ignore + + # + # 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(site_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 + if running_under_virtualenv(): + yield kinds.VENV, [venv_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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/download.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/download.py new file mode 100644 index 0000000..2bbe176 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/download.py @@ -0,0 +1,971 @@ +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.logging import indent_log +from pip._internal.utils.misc import ( + ARCHIVE_EXTENSIONS, ask_path_exists, backup_dir, call_subprocess, consume, + display_path, format_size, get_installed_version, rmtree, + split_auth_from_netloc, splitext, unpack_file, +) +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 DownloadProgressProvider +from pip._internal.vcs import vcs + +if MYPY_CHECK_RUNNING: + from typing import ( # noqa: F401 + Optional, Tuple, Dict, IO, Text, Union + ) + from pip._internal.models.link import Link # noqa: F401 + from pip._internal.utils.hashes import Hashes # noqa: F401 + from pip._internal.vcs import AuthInfo # noqa: F401 + +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__) + + +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 + + 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 we have a UNC path, prepend UNC share notation + if netloc: + netloc = '\\\\' + netloc + + 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) + + +def _copy_dist_from_dir(link_path, location): + """Copy distribution files in `link_path` to `location`. + + Invoked when user requests to install a local directory. E.g.: + + pip install . + pip install ~/dev/git-repos/python-prompt-toolkit + + """ + + # Note: This is currently VERY SLOW if you have a lot of data in the + # directory, because it copies everything with `shutil.copytree`. + # What it should really do is build an sdist and install that. + # See https://github.com/pypa/pip/issues/2195 + + if os.path.isdir(location): + rmtree(location) + + # build an sdist + setup_py = 'setup.py' + sdist_args = [sys.executable] + sdist_args.append('-c') + sdist_args.append(SETUPTOOLS_SHIM % setup_py) + sdist_args.append('sdist') + sdist_args += ['--dist-dir', location] + logger.info('Running setup.py sdist for %s', link_path) + + with indent_log(): + call_subprocess(sdist_args, cwd=link_path, show_stdout=False) + + # unpack sdist into `location` + sdist = os.path.join(location, os.listdir(location)[0]) + logger.info('Unpacking sdist %s into %s', sdist, location) + unpack_file(sdist, location, content_type=None, link=None) + + +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/exceptions.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/exceptions.py new file mode 100644 index 0000000..38ceeea --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/exceptions.py @@ -0,0 +1,274 @@ +"""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 # noqa: F401 + from pip._internal.req.req_install import InstallRequirement # noqa: F401 + + +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/index.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/index.py new file mode 100644 index 0000000..9eda3a3 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/index.py @@ -0,0 +1,990 @@ +"""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 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 # noqa: F401 + from typing import ( # noqa: F401 + Tuple, Optional, Any, List, Union, Callable, Set, Sequence, + Iterable, MutableMapping + ) + from pip._vendor.packaging.version import _BaseVersion # noqa: F401 + from pip._vendor.requests import Response # noqa: F401 + from pip._internal.req import InstallRequirement # noqa: F401 + from pip._internal.download import PipSession # noqa: F401 + + SecureOrigin = Tuple[str, str, Optional[str]] + BuildTag = Tuple[Any, ...] # either emply tuple or Tuple[int, str] + CandidateSortingKey = Tuple[int, _BaseVersion, BuildTag, Optional[int]] + +__all__ = ['FormatControl', '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', 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 as exc: + 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 requests.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 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. + """ + 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 + self.valid_tags = get_supported( + versions=versions, + platform=platform, + abi=abi, + impl=implementation, + ) + + # Do we prefer old, but valid, binary dist over new source dist + self.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 _candidate_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 _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_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 + """ + all_candidates = self.find_all_candidates(req.name) + + # Filter out anything which doesn't match our specifier + compatible_versions = set( + req.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 all_candidates], + prereleases=( + self.allow_all_prereleases + if self.allow_all_prereleases else None + ), + ) + ) + applicable_candidates = [ + # Again, converting to str to deal with debundling. + c for c in all_candidates if str(c.version) in compatible_versions + ] + + if applicable_candidates: + best_candidate = max(applicable_candidates, + key=self._candidate_sort_key) + else: + best_candidate = None + + if req.satisfied_by is not None: + installed_version = parse_version(req.satisfied_by.version) + else: + installed_version = 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, + ', '.join( + sorted( + {str(c.version) for c in all_candidates}, + key=parse_version, + ) + ) + ) + + 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, + ', '.join(sorted(compatible_versions, key=parse_version)) or + "none", + ) + raise BestVersionAlreadyInstalled + + logger.debug( + 'Using version %s (newest of versions: %s)', + best_candidate.version, + ', '.join(sorted(compatible_versions, key=parse_version)) + ) + 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 wheel.supported(self.valid_tags): + 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 + + +_CLEAN_LINK_RE = re.compile(r'[^a-z0-9$&+,/:;=?@.#%_\\|-]', re.I) + + +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).""" + return _CLEAN_LINK_RE.sub(lambda match: '%%%2x' % ord(match.group(0)), url) + + +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/locations.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/locations.py new file mode 100644 index 0000000..c6e2a3e --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/locations.py @@ -0,0 +1,211 @@ +"""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 # noqa: F401 + + +# 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' + +site_config_files = [ + os.path.join(path, config_basename) + for path in appdirs.site_config_dirs('pip') +] + +venv_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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/__init__.py new file mode 100644 index 0000000..7855226 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/__init__.py @@ -0,0 +1,2 @@ +"""A package that contains models that represent entities. +""" diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/candidate.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/candidate.py new file mode 100644 index 0000000..4475458 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/candidate.py @@ -0,0 +1,31 @@ +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 # noqa: F401 + from pip._internal.models.link import Link # noqa: F401 + from typing import Any, Union # noqa: F401 + + +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/format_control.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/format_control.py new file mode 100644 index 0000000..971a391 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/format_control.py @@ -0,0 +1,73 @@ +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 # noqa: F401 + + +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/index.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/index.py new file mode 100644 index 0000000..ead1efb --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/index.py @@ -0,0 +1,31 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/link.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/link.py new file mode 100644 index 0000000..ad2f93e --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/models/link.py @@ -0,0 +1,163 @@ +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, Text # noqa: F401 + from pip._internal.index import HTMLPage # noqa: F401 + + +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/operations/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/operations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/operations/check.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/operations/check.py new file mode 100644 index 0000000..0b56eda --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/operations/check.py @@ -0,0 +1,155 @@ +"""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 # noqa: F401 + from typing import ( # noqa: F401 + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/operations/freeze.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/operations/freeze.py new file mode 100644 index 0000000..388bb73 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/operations/freeze.py @@ -0,0 +1,247 @@ +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 ( # noqa: F401 + Iterator, Optional, List, Container, Set, Dict, Tuple, Iterable, Union + ) + from pip._internal.cache import WheelCache # noqa: F401 + from pip._vendor.pkg_resources import ( # noqa: F401 + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/operations/prepare.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/operations/prepare.py new file mode 100644 index 0000000..4f31dd5 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/operations/prepare.py @@ -0,0 +1,413 @@ +"""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 +from pip._internal.vcs import vcs + +if MYPY_CHECK_RUNNING: + from typing import Any, Optional # noqa: F401 + from pip._internal.req.req_install import InstallRequirement # noqa: F401 + from pip._internal.index import PackageFinder # noqa: F401 + from pip._internal.download import PipSession # noqa: F401 + from pip._internal.req.req_tracker import RequirementTracker # noqa: F401 + +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 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 + + def _raise_conflicts(conflicting_with, conflicting_reqs): + raise InstallationError( + "Some build dependencies for %s conflict with %s: %s." % ( + self.req, conflicting_with, ', '.join( + '%s is incompatible with %s' % (installed, wanted) + for installed, wanted in sorted(conflicting)))) + + 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: + _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. + with self.req.build_env: + # We need to have the env active when calling the hook. + self.req.spin_message = "Getting requirements to build wheel" + reqs = self.req.pep517_backend.get_requires_for_build_wheel() + conflicting, missing = self.req.build_env.check_requirements(reqs) + if conflicting: + _raise_conflicts("the backend dependencies", conflicting) + self.req.build_env.install_requirements( + finder, missing, 'normal', + "Installing backend dependencies" + ) + + 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 req.link.scheme in vcs.all_schemes: + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/pep425tags.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/pep425tags.py new file mode 100644 index 0000000..1e782d1 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/pep425tags.py @@ -0,0 +1,381 @@ +"""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 ( # noqa: F401 + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/pyproject.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/pyproject.py new file mode 100644 index 0000000..8d739a6 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/pyproject.py @@ -0,0 +1,171 @@ +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 # noqa: F401 + + +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/__init__.py new file mode 100644 index 0000000..5e4eb92 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/__init__.py @@ -0,0 +1,77 @@ +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 List, Sequence # noqa: F401 + +__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, **kwargs +): + # 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/constructors.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/constructors.py new file mode 100644 index 0000000..1eed1dd --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/constructors.py @@ -0,0 +1,339 @@ +"""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 ( # noqa: F401 + Optional, Tuple, Set, Any, Union, Text, Dict, + ) + from pip._internal.cache import WheelCache # noqa: F401 + + +__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) + + domains_not_allowed = [ + PyPI.file_storage_domain, + TestPyPI.file_storage_domain, + ] + if req.url 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_file.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_file.py new file mode 100644 index 0000000..726f2f6 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_file.py @@ -0,0 +1,382 @@ +""" +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 ( # noqa: F401 + Iterator, Tuple, Optional, List, Callable, Text + ) + from pip._internal.req import InstallRequirement # noqa: F401 + from pip._internal.cache import WheelCache # noqa: F401 + from pip._internal.index import PackageFinder # noqa: F401 + from pip._internal.download import PipSession # noqa: F401 + + 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): + # 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 discusssion 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_install.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_install.py new file mode 100644 index 0000000..a4834b0 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_install.py @@ -0,0 +1,1021 @@ +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 ( # noqa: F401 + Optional, Iterable, List, Union, Any, Text, Sequence, Dict + ) + from pip._internal.build_env import BuildEnvironment # noqa: F401 + from pip._internal.cache import WheelCache # noqa: F401 + from pip._internal.index import PackageFinder # noqa: F401 + from pip._vendor.pkg_resources import Distribution # noqa: F401 + from pip._vendor.packaging.specifiers import SpecifierSet # noqa: F401 + from pip._vendor.packaging.markers import Marker # noqa: F401 + + +logger = logging.getLogger(__name__) + + +class InstallRequirement(object): + """ + Represents something that may be installed later on, may have information + about where to fetch the relavant 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): + 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): + 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): + 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, cwd=None, extra_environ=None): + with open_spinner(self.spin_message) as spinner: + call_subprocess( + cmd, + cwd=cwd, + extra_environ=extra_environ, + show_stdout=False, + 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, + show_stdout=False, + 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): + 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, + show_stdout=False, + ) + + 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. + 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, + show_stdout=False, + 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): + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_set.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_set.py new file mode 100644 index 0000000..d1410e9 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_set.py @@ -0,0 +1,197 @@ +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 Optional, List, Tuple, Dict, Iterable # noqa: F401 + from pip._internal.req.req_install import InstallRequirement # noqa: F401 + + +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): + 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): + 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 + + @property + def has_requirements(self): + # type: () -> List[InstallRequirement] + return list(req for req in self.requirements.values() if not + req.constraint) or self.unnamed_requirements + + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_tracker.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_tracker.py new file mode 100644 index 0000000..82e084a --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_tracker.py @@ -0,0 +1,88 @@ +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 typing import Set, Iterator # noqa: F401 + from pip._internal.req.req_install import InstallRequirement # noqa: F401 + from pip._internal.models.link import Link # noqa: F401 + +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): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_uninstall.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_uninstall.py new file mode 100644 index 0000000..c80959e --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/req/req_uninstall.py @@ -0,0 +1,596 @@ +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 + +logger = logging.getLogger(__name__) + + +def _script_names(dist, script_name, is_gui): + """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): + @functools.wraps(fn) + def unique(*args, **kw): + seen = set() + for item in fn(*args, **kw): + if item not in seen: + seen.add(item) + yield item + return unique + + +@_unique +def uninstallation_paths(dist): + """ + 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): + """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() + 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): + """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() + + def norm_join(*a): + 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() + all_subdirs = set() + 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): + """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 = list(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) + + _normcased_files = set(map(os.path.normcase, files)) + + 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): + # Mapping from source file root to [Adjacent]TempDirectory + # for files under that directory. + self._save_dirs = {} + # (old path, new path) tuples for each move that may need + # to be undone. + self._moves = [] + + def _get_directory_stash(self, path): + """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) + 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): + """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): + """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): + """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): + """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): + 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): + self.paths = set() + self._refuse = set() + self.pth = {} + self.dist = dist + self._moved_paths = StashedUninstallPathSet() + + def _permitted(self, path): + """ + Return True if the given path is one we are permitted to + remove/modify, False otherwise. + + """ + return is_local(path) + + def add(self, path): + 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): + 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): + """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): + """Display which files would be deleted and prompt for confirmation + """ + + def _display(msg, paths): + 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 = list(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): + """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 False + 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): + """Remove temporary save dir: rollback will no longer be possible.""" + self._moved_paths.commit() + + @classmethod + def from_dist(cls, dist): + 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): + 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() + self._saved_lines = None + + def add(self, entry): + 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): + 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): + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/resolve.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/resolve.py new file mode 100644 index 0000000..33f572f --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/resolve.py @@ -0,0 +1,393 @@ +"""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 # noqa: F401 + from pip._internal.download import PipSession # noqa: F401 + from pip._internal.req.req_install import InstallRequirement # noqa: F401 + from pip._internal.index import PackageFinder # noqa: F401 + from pip._internal.req.req_set import RequirementSet # noqa: F401 + from pip._internal.operations.prepare import ( # noqa: F401 + DistAbstraction, RequirementPreparer + ) + from pip._internal.cache import WheelCache # noqa: F401 + +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/appdirs.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/appdirs.py new file mode 100644 index 0000000..9af9fa7 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/appdirs.py @@ -0,0 +1,270 @@ +""" +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 ( # noqa: F401 + List, Union + ) + + +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/compat.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/compat.py new file mode 100644 index 0000000..2d8b3bf --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/compat.py @@ -0,0 +1,264 @@ +"""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 # noqa: F401 + +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/deprecation.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/deprecation.py new file mode 100644 index 0000000..0beaf74 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/deprecation.py @@ -0,0 +1,90 @@ +""" +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 # noqa: F401 + + +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: " + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/encoding.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/encoding.py new file mode 100644 index 0000000..d36defa --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/encoding.py @@ -0,0 +1,39 @@ +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 # noqa: F401 + +BOMS = [ + (codecs.BOM_UTF8, 'utf8'), + (codecs.BOM_UTF16, 'utf16'), + (codecs.BOM_UTF16_BE, 'utf16-be'), + (codecs.BOM_UTF16_LE, 'utf16-le'), + (codecs.BOM_UTF32, 'utf32'), + (codecs.BOM_UTF32_BE, 'utf32-be'), + (codecs.BOM_UTF32_LE, 'utf32-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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/filesystem.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/filesystem.py new file mode 100644 index 0000000..1e6b033 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/filesystem.py @@ -0,0 +1,30 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/glibc.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/glibc.py new file mode 100644 index 0000000..8a51f69 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/glibc.py @@ -0,0 +1,93 @@ +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 # noqa: F401 + + +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/hashes.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/hashes.py new file mode 100644 index 0000000..c6df7a1 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/hashes.py @@ -0,0 +1,115 @@ +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 ( # noqa: F401 + Dict, List, BinaryIO, NoReturn, Iterator + ) + from pip._vendor.six import PY3 + if PY3: + from hashlib import _Hash # noqa: F401 + else: + from hashlib import _hash as _Hash # noqa: F401 + + +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/logging.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/logging.py new file mode 100644 index 0000000..579d696 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/logging.py @@ -0,0 +1,318 @@ +from __future__ import absolute_import + +import contextlib +import errno +import logging +import logging.handlers +import os +import sys + +from pip._vendor.six import PY2 + +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.misc import ensure_dir + +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 obeying containing indent_log contexts. + + :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 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) + 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(logging.Filter): + + def __init__(self, level): + self.level = level + + def filter(self, record): + return record.levelno < self.level + + +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", + } + + logging.config.dictConfig({ + "version": 1, + "disable_existing_loggers": False, + "filters": { + "exclude_warnings": { + "()": "pip._internal.utils.logging.MaxLevelFilter", + "level": logging.WARNING, + }, + }, + "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_warnings"], + "formatter": "indent", + }, + "console_errors": { + "level": "WARNING", + "class": handler_classes["stream"], + "no_color": no_color, + "stream": log_streams["stderr"], + "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": ["console", "console_errors"] + ( + ["user_log"] if include_user_log else [] + ), + }, + "loggers": { + "pip._vendor": { + "level": vendored_log_level + } + }, + }) + + return level_number diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/misc.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/misc.py new file mode 100644 index 0000000..84605ee --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/misc.py @@ -0,0 +1,1040 @@ +from __future__ import absolute_import + +import contextlib +import errno +import io +import locale +# 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 +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 ( # noqa: F401 + Optional, Tuple, Iterable, List, Match, Union, Any, Mapping, Text, + AnyStr, Container + ) + from pip._vendor.pkg_resources import Distribution # noqa: F401 + from pip._internal.models.link import Link # noqa: F401 + from pip._internal.utils.ui import SpinnerInterface # noqa: F401 + + +__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__) + +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 call_subprocess( + 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]] + unset_environ=None, # type: Optional[Iterable[str]] + spinner=None # type: Optional[SpinnerInterface] +): + # type: (...) -> Optional[Text] + """ + Args: + 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 = [] + # This function's handling of subprocess output is confusing and I + # previously broke it terribly, so as penance I will write a long comment + # explaining things. + # + # The obvious thing that affects output is the show_stdout= + # kwarg. show_stdout=True means, let the subprocess write directly to our + # stdout. Even though it is nominally the default, it is almost never used + # inside pip (and should not be used in new code without a very good + # reason); as of 2016-02-22 it is only used in a few places inside the VCS + # wrapper code. Ideally we should get rid of it entirely, because it + # creates a lot of complexity here for a rarely used feature. + # + # Most places in pip set show_stdout=False. What this means is: + # - We connect the child stdout to a pipe, which we read. + # - By default, we hide the output but show a spinner -- unless the + # subprocess exits with an error, in which case we show the output. + # - If the --verbose option was passed (= loglevel is DEBUG), then we show + # the output unconditionally. (But in this case we don't want to show + # the output a second time if it turns out that there was an error.) + # + # stderr is always merged with stdout (even if show_stdout=True). + if show_stdout: + stdout = None + else: + stdout = subprocess.PIPE + if command_desc is None: + cmd_parts = [] + for part in cmd: + if ' ' in part or '\n' in part or '"' in part or "'" in part: + part = '"%s"' % part.replace('"', '\\"') + cmd_parts.append(part) + command_desc = ' '.join(cmd_parts) + logger.debug("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=stdout, cwd=cwd, env=env, + ) + proc.stdin.close() + except Exception as exc: + logger.critical( + "Error %s while executing command %s", exc, command_desc, + ) + raise + all_output = [] + if stdout is not None: + while True: + line = console_to_str(proc.stdout.readline()) + if not line: + break + line = line.rstrip() + all_output.append(line + '\n') + if logger.getEffectiveLevel() <= std_logging.DEBUG: + # Show the line immediately + logger.debug(line) + else: + # Update the spinner + if spinner is not None: + spinner.spin() + try: + proc.wait() + finally: + if proc.stdout: + proc.stdout.close() + if spinner is not None: + if proc.returncode: + spinner.finish("error") + else: + spinner.finish("done") + if proc.returncode and proc.returncode not in extra_ok_returncodes: + if on_returncode == 'raise': + if (logger.getEffectiveLevel() > std_logging.DEBUG and + not show_stdout): + logger.info( + 'Complete output from command %s:', command_desc, + ) + logger.info( + ''.join(all_output) + + '\n----------------------------------------' + ) + raise InstallationError( + 'Command "%s" failed with error code %s in %s' + % (command_desc, proc.returncode, cwd)) + elif on_returncode == 'warn': + 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)) + if not show_stdout: + return ''.join(all_output) + return None + + +def read_text_file(filename): + # type: (str) -> str + """Return the contents of *filename*. + + Try to decode the file contents with utf-8, the preferred system encoding + (e.g., cp1252 on some Windows machines), and latin1, in that order. + Decoding a byte string with latin1 will never raise an error. In the worst + case, the returned string will contain some garbage characters. + + """ + with open(filename, 'rb') as fp: + data = fp.read() + + encodings = ['utf-8', locale.getpreferredencoding(False), 'latin1'] + for enc in encodings: + try: + # https://github.com/python/mypy/issues/1174 + data = data.decode(enc) # type: ignore + except UnicodeDecodeError: + continue + break + + assert not isinstance(data, bytes) # Latin1 should have worked. + return data + + +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 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 + + +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/models.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/models.py new file mode 100644 index 0000000..d5cb80a --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/models.py @@ -0,0 +1,40 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/outdated.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/outdated.py new file mode 100644 index 0000000..37c47a4 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/outdated.py @@ -0,0 +1,164 @@ +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 # noqa: F401 + from typing import Any, Dict # noqa: F401 + from pip._internal.download import PipSession # noqa: F401 + + +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, + ) + all_candidates = finder.find_all_candidates("pip") + if not all_candidates: + return + pypi_version = str( + max(all_candidates, key=lambda c: c.version).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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/packaging.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/packaging.py new file mode 100644 index 0000000..7aaf7b5 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/packaging.py @@ -0,0 +1,85 @@ +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 # noqa: F401 + from email.message import Message # noqa: F401 + from pip._vendor.pkg_resources import Distribution # noqa: F401 + + +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/setuptools_build.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/setuptools_build.py new file mode 100644 index 0000000..03973e9 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/setuptools_build.py @@ -0,0 +1,8 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/temp_dir.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/temp_dir.py new file mode 100644 index 0000000..2c81ad5 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/temp_dir.py @@ -0,0 +1,155 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/typing.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/typing.py new file mode 100644 index 0000000..e085cdf --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/typing.py @@ -0,0 +1,29 @@ +"""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 ... # noqa: F401 + +Ref: https://github.com/python/mypy/issues/3216 +""" + +MYPY_CHECK_RUNNING = False diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/ui.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/ui.py new file mode 100644 index 0000000..433675d --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/utils/ui.py @@ -0,0 +1,441 @@ +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.bar import ( + Bar, ChargingBar, FillingCirclesBar, FillingSquaresBar, IncrementalBar, + ShadyBar, +) +from pip._vendor.progress.helpers import HIDE_CURSOR, SHOW_CURSOR, WritelnMixin +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 # noqa: F401 + +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 neds 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 DownloadChargingBar(BaseDownloadProgressBar, # type: ignore + ChargingBar): + pass + + +class DownloadShadyBar(BaseDownloadProgressBar, ShadyBar): # type: ignore + pass + + +class DownloadFillingSquaresBar(BaseDownloadProgressBar, # type: ignore + FillingSquaresBar): + pass + + +class DownloadFillingCirclesBar(BaseDownloadProgressBar, # type: ignore + FillingCirclesBar): + pass + + +class DownloadBlueEmojiProgressBar(BaseDownloadProgressBar, # type: ignore + BlueEmojiBar): + pass + + +class DownloadProgressSpinner(WindowsMixin, InterruptibleMixin, + DownloadProgressMixin, WritelnMixin, 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/__init__.py new file mode 100644 index 0000000..9cba764 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/__init__.py @@ -0,0 +1,534 @@ +"""Handles all VCS (version control) support""" +from __future__ import absolute_import + +import errno +import logging +import os +import shutil +import sys + +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.exceptions import BadCommand +from pip._internal.utils.misc import ( + display_path, backup_dir, call_subprocess, rmtree, ask_path_exists, +) +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import ( # noqa: F401 + Any, Dict, Iterable, List, Mapping, Optional, Text, Tuple, Type + ) + from pip._internal.utils.ui import SpinnerInterface # noqa: F401 + + AuthInfo = Tuple[Optional[str], Optional[str]] + +__all__ = ['vcs'] + + +logger = logging.getLogger(__name__) + + +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, vcs, rev=None, extra_args=None): + # type: (VersionControl, Optional[str], Optional[List[str]]) -> None + """ + Args: + vcs: a VersionControl object. + 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.vcs = vcs + + def __repr__(self): + return '<RevOptions {}: rev={!r}>'.format(self.vcs.name, self.rev) + + @property + def arg_rev(self): + # type: () -> Optional[str] + if self.rev is None: + return self.vcs.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.vcs.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.vcs.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] + + def __init__(self, url=None, *args, **kwargs): + self.url = url + super(VersionControl, self).__init__(*args, **kwargs) + + def get_base_rev_args(self, rev): + """ + Return the base revision arguments for a vcs command. + + Args: + rev: the name of a revision to install. Cannot be None. + """ + raise NotImplementedError + + def make_rev_options(self, 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(self, 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 + + def get_netloc_and_auth(self, 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) + + def get_url_rev_and_auth(self, 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 = self.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 + + def make_rev_args(self, 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 + + def normalize_url(self, url): + # type: (str) -> str + """ + Normalize a URL for comparison by unquoting it and removing any + trailing slash. + """ + return urllib_parse.unquote(url).rstrip('/') + + def compare_urls(self, url1, url2): + # type: (str, str) -> bool + """ + Compare two repo URLs for identity, ignoring incidental differences. + """ + return (self.normalize_url(url1) == self.normalize_url(url2)) + + def fetch_new(self, 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 + + def is_commit_id_equal(self, 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_src_requirement(cls, location, project_name): + """ + Return a string representing the requirement needed to + redownload the files currently present in location, something + like: + {repository_url}@{revision}#egg={project_name}-{version_identifier} + """ + raise NotImplementedError + + @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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/bazaar.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/bazaar.py new file mode 100644 index 0000000..4c6ac79 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/bazaar.py @@ -0,0 +1,114 @@ +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, make_vcs_requirement_url, rmtree, +) +from pip._internal.utils.temp_dir import TempDirectory +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']) + + def get_base_rev_args(self, 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) + + with TempDirectory(kind="export") as temp_dir: + self.unpack(temp_dir.path) + + self.run_command( + ['export', location], + cwd=temp_dir.path, show_stdout=False, + ) + + def fetch_new(self, 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] + self.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) + + def get_url_rev_and_auth(self, url): + # hotfix the URL scheme after removing bzr+ from bzr+ssh:// readd it + url, rev, user_pass = super(Bazaar, self).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 get_src_requirement(cls, location, project_name): + repo = cls.get_remote_url(location) + if not repo: + return None + if not repo.lower().startswith('bzr:'): + repo = 'bzr+' + repo + current_rev = cls.get_revision(location) + return make_vcs_requirement_url(repo, current_rev, project_name) + + def is_commit_id_equal(self, dest, name): + """Always assume the versions don't match""" + return False + + +vcs.register(Bazaar) diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/git.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/git.py new file mode 100644 index 0000000..dd2bd61 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/git.py @@ -0,0 +1,369 @@ +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, make_vcs_requirement_url, 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) + + def get_base_rev_args(self, 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 becasue + # 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) + + def get_current_branch(self, 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 = self.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 + ) + + def get_revision_sha(self, 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 = self.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) + + def resolve_revision(self, 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 = self.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. + self.run_command( + ['fetch', '-q', url] + rev_options.to_args(), + cwd=dest, + ) + # Change the revision to the SHA of the ref we fetched + sha = self.get_revision(dest, rev='FETCH_HEAD') + rev_options = rev_options.make_new(sha) + + return rev_options + + def is_commit_id_equal(self, 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 self.get_revision(dest) == name + + def fetch_new(self, 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), + ) + self.run_command(['clone', '-q', url, dest]) + + if rev_options.rev: + # Then a specific revision was requested. + rev_options = self.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 self.is_commit_id_equal(dest, rev_options.rev): + cmd_args = ['checkout', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) + elif self.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, + ] + self.run_command(cmd_args, cwd=dest) + + #: repo may contain submodules + self.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): + """Return the relative path of setup.py to the git repo root.""" + # 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_src_requirement(cls, location, project_name): + repo = cls.get_remote_url(location) + if not repo.lower().startswith('git:'): + repo = 'git+' + repo + current_rev = cls.get_revision(location) + subdir = cls._get_subdirectory(location) + req = make_vcs_requirement_url(repo, current_rev, project_name, + subdir=subdir) + + return req + + def get_url_rev_and_auth(self, 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, self).get_url_rev_and_auth(url) + url = url.replace('ssh://', '') + else: + url, rev, user_pass = super(Git, self).get_url_rev_and_auth(url) + + return url, rev, user_pass + + def update_submodules(self, location): + if not os.path.exists(os.path.join(location, '.gitmodules')): + return + self.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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/mercurial.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/mercurial.py new file mode 100644 index 0000000..26e75de --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/mercurial.py @@ -0,0 +1,103 @@ +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, make_vcs_requirement_url +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') + + def get_base_rev_args(self, 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 + ) + + def fetch_new(self, dest, url, rev_options): + rev_display = rev_options.to_display() + logger.info( + 'Cloning hg %s%s to %s', + url, + rev_display, + display_path(dest), + ) + self.run_command(['clone', '--noupdate', '-q', url, dest]) + cmd_args = ['update', '-q'] + rev_options.to_args() + self.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): + current_revision = cls.run_command( + ['parents', '--template={rev}'], + show_stdout=False, cwd=location).strip() + return current_revision + + @classmethod + def get_revision_hash(cls, location): + current_rev_hash = cls.run_command( + ['parents', '--template={node}'], + show_stdout=False, cwd=location).strip() + return current_rev_hash + + @classmethod + def get_src_requirement(cls, location, project_name): + repo = cls.get_remote_url(location) + if not repo.lower().startswith('hg:'): + repo = 'hg+' + repo + current_rev_hash = cls.get_revision_hash(location) + return make_vcs_requirement_url(repo, current_rev_hash, project_name) + + def is_commit_id_equal(self, dest, name): + """Always assume the versions don't match""" + return False + + +vcs.register(Mercurial) diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/subversion.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/subversion.py new file mode 100644 index 0000000..42ac5ac --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/vcs/subversion.py @@ -0,0 +1,200 @@ +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, make_vcs_requirement_url, rmtree, split_auth_from_netloc, +) +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>') + + +logger = logging.getLogger(__name__) + + +class Subversion(VersionControl): + name = 'svn' + dirname = '.svn' + repo_name = 'checkout' + schemes = ('svn', 'svn+ssh', 'svn+http', 'svn+https', 'svn+svn') + + def get_base_rev_args(self, rev): + return ['-r', rev] + + 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) + + def fetch_new(self, 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] + self.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 + + def get_netloc_and_auth(self, 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, self).get_netloc_and_auth( + netloc, scheme) + + return split_auth_from_netloc(netloc) + + def get_url_rev_and_auth(self, url): + # hotfix the URL scheme after removing svn+ from svn+ssh:// readd it + url, rev, user_pass = super(Subversion, self).get_url_rev_and_auth(url) + if url.startswith('ssh://'): + url = 'svn+' + url + return url, rev, user_pass + + def make_rev_args(self, 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 get_src_requirement(cls, location, project_name): + repo = cls.get_remote_url(location) + if repo is None: + return None + repo = 'svn+' + repo + rev = cls.get_revision(location) + return make_vcs_requirement_url(repo, rev, project_name) + + def is_commit_id_equal(self, dest, name): + """Always assume the versions don't match""" + return False + + +vcs.register(Subversion) diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/wheel.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/wheel.py new file mode 100644 index 0000000..67bcc7f --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_internal/wheel.py @@ -0,0 +1,1095 @@ +""" +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 ( + call_subprocess, captured_stdout, ensure_dir, 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 ( # noqa: F401 + Dict, List, Optional, Sequence, Mapping, Tuple, IO, Text, Any, + Union, Iterable + ) + from pip._vendor.packaging.requirements import Requirement # noqa: F401 + from pip._internal.req.req_install import InstallRequirement # noqa: F401 + from pip._internal.download import PipSession # noqa: F401 + from pip._internal.index import FormatControl, PackageFinder # noqa: F401 + from pip._internal.operations.prepare import ( # noqa: F401 + RequirementPreparer + ) + from pip._internal.cache import WheelCache # noqa: F401 + from pip._internal.pep425tags import Pep425Tag # noqa: F401 + + 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(): + scripts = sorted(scripts) + if len(scripts) == 1: + start_text = "script {} is".format(scripts[0]) + else: + start_text = "scripts {} are".format( + ", ".join(scripts[:-1]) + " and " + 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( + command_args, # type: List[str] + command_output, # type: str +): + # type: (...) -> str + """ + Format command information for logging. + """ + text = 'Command arguments: {}\n'.format(command_args) + + 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) + + 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(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(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 + 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, + show_stdout=False, 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, show_stdout=False) + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/__init__.py new file mode 100644 index 0000000..b919b54 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/__init__.py @@ -0,0 +1,111 @@ +""" +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__(vendored_name, globals(), locals(), level=0) + except ImportError: + 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.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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/appdirs.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/appdirs.py new file mode 100644 index 0000000..2bd3911 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/appdirs.py @@ -0,0 +1,604 @@ +#!/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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/__init__.py new file mode 100644 index 0000000..8fdee66 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/__init__.py @@ -0,0 +1,11 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/_cmd.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/_cmd.py new file mode 100644 index 0000000..f1e0ad9 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/_cmd.py @@ -0,0 +1,57 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/adapter.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/adapter.py new file mode 100644 index 0000000..780eb28 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/adapter.py @@ -0,0 +1,133 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/cache.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/cache.py new file mode 100644 index 0000000..94e0773 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/cache.py @@ -0,0 +1,39 @@ +""" +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/caches/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/caches/__init__.py new file mode 100644 index 0000000..0e1658f --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/caches/__init__.py @@ -0,0 +1,2 @@ +from .file_cache import FileCache # noqa +from .redis_cache import RedisCache # noqa diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/caches/file_cache.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/caches/file_cache.py new file mode 100644 index 0000000..1ba0080 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/caches/file_cache.py @@ -0,0 +1,146 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/caches/redis_cache.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/caches/redis_cache.py new file mode 100644 index 0000000..ed705ce --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/caches/redis_cache.py @@ -0,0 +1,33 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/compat.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/compat.py new file mode 100644 index 0000000..33b5aed --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/compat.py @@ -0,0 +1,29 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/controller.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/controller.py new file mode 100644 index 0000000..1b2b943 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/controller.py @@ -0,0 +1,367 @@ +""" +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/filewrapper.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/filewrapper.py new file mode 100644 index 0000000..30ed4c5 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/filewrapper.py @@ -0,0 +1,80 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/heuristics.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/heuristics.py new file mode 100644 index 0000000..6c0e979 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/heuristics.py @@ -0,0 +1,135 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/serialize.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/serialize.py new file mode 100644 index 0000000..ec43ff2 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/serialize.py @@ -0,0 +1,186 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/wrapper.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/wrapper.py new file mode 100644 index 0000000..265bfc8 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/cachecontrol/wrapper.py @@ -0,0 +1,29 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/certifi/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/certifi/__init__.py new file mode 100644 index 0000000..ef71f3a --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/certifi/__init__.py @@ -0,0 +1,3 @@ +from .core import where + +__version__ = "2018.11.29" diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/certifi/__main__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/certifi/__main__.py new file mode 100644 index 0000000..ae2aff5 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/certifi/__main__.py @@ -0,0 +1,2 @@ +from pip._vendor.certifi import where +print(where()) diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/certifi/cacert.pem b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/certifi/cacert.pem new file mode 100644 index 0000000..db68797 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/certifi/cacert.pem @@ -0,0 +1,4512 @@ + +# 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----- diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/certifi/core.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/certifi/core.py new file mode 100644 index 0000000..2d02ea4 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/certifi/core.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# -*- 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') + + +if __name__ == '__main__': + print(where()) diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/__init__.py new file mode 100644 index 0000000..0f9f820 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/__init__.py @@ -0,0 +1,39 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/big5freq.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/big5freq.py new file mode 100644 index 0000000..38f3251 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/big5freq.py @@ -0,0 +1,386 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/big5prober.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/big5prober.py new file mode 100644 index 0000000..98f9970 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/big5prober.py @@ -0,0 +1,47 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/chardistribution.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/chardistribution.py new file mode 100644 index 0000000..c0395f4 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/chardistribution.py @@ -0,0 +1,233 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/charsetgroupprober.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/charsetgroupprober.py new file mode 100644 index 0000000..8b3738e --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/charsetgroupprober.py @@ -0,0 +1,106 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/charsetprober.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/charsetprober.py new file mode 100644 index 0000000..eac4e59 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/charsetprober.py @@ -0,0 +1,145 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/cli/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/cli/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/cli/__init__.py @@ -0,0 +1 @@ + diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/cli/chardetect.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/cli/chardetect.py new file mode 100644 index 0000000..c61136b --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/cli/chardetect.py @@ -0,0 +1,85 @@ +#!/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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/codingstatemachine.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/codingstatemachine.py new file mode 100644 index 0000000..68fba44 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/codingstatemachine.py @@ -0,0 +1,88 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/compat.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/compat.py new file mode 100644 index 0000000..ddd7468 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/compat.py @@ -0,0 +1,34 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/cp949prober.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/cp949prober.py new file mode 100644 index 0000000..efd793a --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/cp949prober.py @@ -0,0 +1,49 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/enums.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/enums.py new file mode 100644 index 0000000..0451207 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/enums.py @@ -0,0 +1,76 @@ +""" +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/escprober.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/escprober.py new file mode 100644 index 0000000..c70493f --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/escprober.py @@ -0,0 +1,101 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/escsm.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/escsm.py new file mode 100644 index 0000000..0069523 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/escsm.py @@ -0,0 +1,246 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/eucjpprober.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/eucjpprober.py new file mode 100644 index 0000000..20ce8f7 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/eucjpprober.py @@ -0,0 +1,92 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/euckrfreq.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/euckrfreq.py new file mode 100644 index 0000000..b68078c --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/euckrfreq.py @@ -0,0 +1,195 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/euckrprober.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/euckrprober.py new file mode 100644 index 0000000..345a060 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/euckrprober.py @@ -0,0 +1,47 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/euctwfreq.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/euctwfreq.py new file mode 100644 index 0000000..ed7a995 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/euctwfreq.py @@ -0,0 +1,387 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/euctwprober.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/euctwprober.py new file mode 100644 index 0000000..35669cc --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/euctwprober.py @@ -0,0 +1,46 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/gb2312freq.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/gb2312freq.py new file mode 100644 index 0000000..697837b --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/gb2312freq.py @@ -0,0 +1,283 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/gb2312prober.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/gb2312prober.py new file mode 100644 index 0000000..8446d2d --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/gb2312prober.py @@ -0,0 +1,46 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/hebrewprober.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/hebrewprober.py new file mode 100644 index 0000000..b0e1bf4 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/hebrewprober.py @@ -0,0 +1,292 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/jisfreq.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/jisfreq.py new file mode 100644 index 0000000..83fc082 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/jisfreq.py @@ -0,0 +1,325 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/jpcntx.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/jpcntx.py new file mode 100644 index 0000000..20044e4 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/jpcntx.py @@ -0,0 +1,233 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langbulgarianmodel.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langbulgarianmodel.py new file mode 100644 index 0000000..2aa4fb2 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langbulgarianmodel.py @@ -0,0 +1,228 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langcyrillicmodel.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langcyrillicmodel.py new file mode 100644 index 0000000..e5f9a1f --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langcyrillicmodel.py @@ -0,0 +1,333 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langgreekmodel.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langgreekmodel.py new file mode 100644 index 0000000..5332221 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langgreekmodel.py @@ -0,0 +1,225 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langhebrewmodel.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langhebrewmodel.py new file mode 100644 index 0000000..58f4c87 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langhebrewmodel.py @@ -0,0 +1,200 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langhungarianmodel.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langhungarianmodel.py new file mode 100644 index 0000000..bb7c095 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langhungarianmodel.py @@ -0,0 +1,225 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langthaimodel.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langthaimodel.py new file mode 100644 index 0000000..15f94c2 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langthaimodel.py @@ -0,0 +1,199 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langturkishmodel.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langturkishmodel.py new file mode 100644 index 0000000..a427a45 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/langturkishmodel.py @@ -0,0 +1,193 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/latin1prober.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/latin1prober.py new file mode 100644 index 0000000..7d1e8c2 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/latin1prober.py @@ -0,0 +1,145 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/mbcharsetprober.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/mbcharsetprober.py new file mode 100644 index 0000000..6256ecf --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/mbcharsetprober.py @@ -0,0 +1,91 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/mbcsgroupprober.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/mbcsgroupprober.py new file mode 100644 index 0000000..530abe7 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/mbcsgroupprober.py @@ -0,0 +1,54 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/mbcssm.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/mbcssm.py new file mode 100644 index 0000000..8360d0f --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/mbcssm.py @@ -0,0 +1,572 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/sbcharsetprober.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/sbcharsetprober.py new file mode 100644 index 0000000..0adb51d --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/sbcharsetprober.py @@ -0,0 +1,132 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/sbcsgroupprober.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/sbcsgroupprober.py new file mode 100644 index 0000000..98e95dc --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/sbcsgroupprober.py @@ -0,0 +1,73 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/sjisprober.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/sjisprober.py new file mode 100644 index 0000000..9e29623 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/sjisprober.py @@ -0,0 +1,92 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/universaldetector.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/universaldetector.py new file mode 100644 index 0000000..7b4e92d --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/universaldetector.py @@ -0,0 +1,286 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/utf8prober.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/utf8prober.py new file mode 100644 index 0000000..6c3196c --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/utf8prober.py @@ -0,0 +1,82 @@ +######################## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/version.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/version.py new file mode 100644 index 0000000..bb2a34a --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/chardet/version.py @@ -0,0 +1,9 @@ +""" +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/__init__.py new file mode 100644 index 0000000..2a3bf47 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/__init__.py @@ -0,0 +1,6 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/ansi.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/ansi.py new file mode 100644 index 0000000..7877658 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/ansi.py @@ -0,0 +1,102 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/ansitowin32.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/ansitowin32.py new file mode 100644 index 0000000..359c92b --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/ansitowin32.py @@ -0,0 +1,257 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/initialise.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/initialise.py new file mode 100644 index 0000000..430d066 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/initialise.py @@ -0,0 +1,80 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/win32.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/win32.py new file mode 100644 index 0000000..c2d8360 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/win32.py @@ -0,0 +1,152 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/winterm.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/winterm.py new file mode 100644 index 0000000..0fdb4ec --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/colorama/winterm.py @@ -0,0 +1,169 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/__init__.py new file mode 100644 index 0000000..a786b4d --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/__init__.py @@ -0,0 +1,23 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/__init__.py new file mode 100644 index 0000000..f7dbf4c --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/__init__.py @@ -0,0 +1,6 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/misc.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/misc.py new file mode 100644 index 0000000..cfb318d --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/misc.py @@ -0,0 +1,41 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/shutil.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/shutil.py new file mode 100644 index 0000000..159e49e --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/shutil.py @@ -0,0 +1,761 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/sysconfig.cfg b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/sysconfig.cfg new file mode 100644 index 0000000..1746bd0 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/sysconfig.cfg @@ -0,0 +1,84 @@ +[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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/sysconfig.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/sysconfig.py new file mode 100644 index 0000000..1df3aba --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/sysconfig.py @@ -0,0 +1,788 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/tarfile.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/tarfile.py new file mode 100644 index 0000000..d66d856 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/_backport/tarfile.py @@ -0,0 +1,2607 @@ +#------------------------------------------------------------------- +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/compat.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/compat.py new file mode 100644 index 0000000..ff328c8 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/compat.py @@ -0,0 +1,1120 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/database.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/database.py new file mode 100644 index 0000000..b13cdac --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/database.py @@ -0,0 +1,1339 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/index.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/index.py new file mode 100644 index 0000000..2406be2 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/index.py @@ -0,0 +1,516 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/locators.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/locators.py new file mode 100644 index 0000000..5c655c3 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/locators.py @@ -0,0 +1,1295 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/manifest.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/manifest.py new file mode 100644 index 0000000..ca0fe44 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/manifest.py @@ -0,0 +1,393 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/markers.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/markers.py new file mode 100644 index 0000000..ee1f3e2 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/markers.py @@ -0,0 +1,131 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/metadata.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/metadata.py new file mode 100644 index 0000000..77eed7f --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/metadata.py @@ -0,0 +1,1094 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/resources.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/resources.py new file mode 100644 index 0000000..1884016 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/resources.py @@ -0,0 +1,355 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/scripts.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/scripts.py new file mode 100644 index 0000000..8e22cb9 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/scripts.py @@ -0,0 +1,417 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/t32.exe b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/t32.exe new file mode 100644 index 0000000000000000000000000000000000000000..a09d926872d84ae22a617dfe9ebb560d420b37de GIT binary patch literal 92672 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/t64.exe b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/t64.exe new file mode 100644 index 0000000000000000000000000000000000000000..9da9b40de922fb203df6b9a1d0ad4139af536850 GIT binary patch literal 102400 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�vlnW`{LoXpTySn$@;x8yoz96jn?+Kk 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�?dYNUd4WaURX_A__M4W}D0!0n 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/util.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/util.py new file mode 100644 index 0000000..9d4bfd3 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/util.py @@ -0,0 +1,1756 @@ +# +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/version.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/version.py new file mode 100644 index 0000000..3eebe18 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/version.py @@ -0,0 +1,736 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/w32.exe b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/w32.exe new file mode 100644 index 0000000000000000000000000000000000000000..732215a9d34ccb7b417d637a7646d9b843ecafa8 GIT binary patch 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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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/w64.exe b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/w64.exe new file mode 100644 index 0000000000000000000000000000000000000000..c41bd0a011fd760ce20ba795d9e535e0d2c39876 GIT binary patch literal 99328 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 B=L-M; literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/wheel.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/wheel.py new file mode 100644 index 0000000..b04bfae --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distlib/wheel.py @@ -0,0 +1,988 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distro.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distro.py new file mode 100644 index 0000000..aa4defc --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/distro.py @@ -0,0 +1,1197 @@ +# 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 a renewed alternative implementation 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.7 is expected to remove it +altogether. Its predecessor function :py:func:`platform.dist` was already +deprecated since Python 2.6 and is also expected to be removed in Python 3.7. +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 = {} + +#: 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`. + """ + return self.os_release_attr('codename') \ + or 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`. + """ + + 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 + if k == 'VERSION': + # this handles cases in which the codename is in + # the `(CODENAME)` (rhel, centos, fedora) format + # or in the `, CODENAME` format (Ubuntu). + codename = re.search(r'(\(\D+\))|,(\s+)?\D+', v) + if codename: + codename = codename.group() + codename = codename.strip('()') + codename = codename.strip(',') + codename = codename.strip() + # codename appears within paranthese. + props['codename'] = codename + else: + props['codename'] = '' + else: + # Ignore any tokens that are not variable assignments + pass + 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 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) + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/__init__.py new file mode 100644 index 0000000..0491234 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/__init__.py @@ -0,0 +1,35 @@ +""" +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_ihatexml.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_ihatexml.py new file mode 100644 index 0000000..4c77717 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_ihatexml.py @@ -0,0 +1,288 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_inputstream.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_inputstream.py new file mode 100644 index 0000000..a65e55f --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_inputstream.py @@ -0,0 +1,923 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_tokenizer.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_tokenizer.py new file mode 100644 index 0000000..178f6e7 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_tokenizer.py @@ -0,0 +1,1721 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_trie/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_trie/__init__.py new file mode 100644 index 0000000..a5ba4bf --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_trie/__init__.py @@ -0,0 +1,14 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_trie/_base.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_trie/_base.py new file mode 100644 index 0000000..a1158bb --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_trie/_base.py @@ -0,0 +1,37 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_trie/datrie.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_trie/datrie.py new file mode 100644 index 0000000..e2e5f86 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_trie/datrie.py @@ -0,0 +1,44 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_trie/py.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_trie/py.py new file mode 100644 index 0000000..c178b21 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_trie/py.py @@ -0,0 +1,67 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_utils.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_utils.py new file mode 100644 index 0000000..0703afb --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/_utils.py @@ -0,0 +1,124 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/constants.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/constants.py new file mode 100644 index 0000000..1ff8041 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/constants.py @@ -0,0 +1,2947 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/alphabeticalattributes.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/alphabeticalattributes.py new file mode 100644 index 0000000..5ba926e --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/alphabeticalattributes.py @@ -0,0 +1,29 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/base.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/base.py new file mode 100644 index 0000000..c7dbaed --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/base.py @@ -0,0 +1,12 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/inject_meta_charset.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/inject_meta_charset.py new file mode 100644 index 0000000..aefb5c8 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/inject_meta_charset.py @@ -0,0 +1,73 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/lint.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/lint.py new file mode 100644 index 0000000..fcc07ee --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/lint.py @@ -0,0 +1,93 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/optionaltags.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/optionaltags.py new file mode 100644 index 0000000..4a86501 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/optionaltags.py @@ -0,0 +1,207 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/sanitizer.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/sanitizer.py new file mode 100644 index 0000000..af8e77b --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/sanitizer.py @@ -0,0 +1,896 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/whitespace.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/whitespace.py new file mode 100644 index 0000000..0d12584 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/filters/whitespace.py @@ -0,0 +1,38 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/html5parser.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/html5parser.py new file mode 100644 index 0000000..ae41a13 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/html5parser.py @@ -0,0 +1,2791 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/serializer.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/serializer.py new file mode 100644 index 0000000..53f4d44 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/serializer.py @@ -0,0 +1,409 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treeadapters/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treeadapters/__init__.py new file mode 100644 index 0000000..7ef5959 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treeadapters/__init__.py @@ -0,0 +1,30 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treeadapters/genshi.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treeadapters/genshi.py new file mode 100644 index 0000000..61d5fb6 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treeadapters/genshi.py @@ -0,0 +1,54 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treeadapters/sax.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treeadapters/sax.py new file mode 100644 index 0000000..f4ccea5 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treeadapters/sax.py @@ -0,0 +1,50 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/__init__.py new file mode 100644 index 0000000..d44447e --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/__init__.py @@ -0,0 +1,88 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/base.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/base.py new file mode 100644 index 0000000..73973db --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/base.py @@ -0,0 +1,417 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/dom.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/dom.py new file mode 100644 index 0000000..dcfac22 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/dom.py @@ -0,0 +1,236 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/etree.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/etree.py new file mode 100644 index 0000000..0dedf44 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/etree.py @@ -0,0 +1,340 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/etree_lxml.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/etree_lxml.py new file mode 100644 index 0000000..ca12a99 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treebuilders/etree_lxml.py @@ -0,0 +1,366 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/__init__.py new file mode 100644 index 0000000..9bec207 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/__init__.py @@ -0,0 +1,154 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/base.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/base.py new file mode 100644 index 0000000..80c474c --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/base.py @@ -0,0 +1,252 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/dom.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/dom.py new file mode 100644 index 0000000..b0c89b0 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/dom.py @@ -0,0 +1,43 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/etree.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/etree.py new file mode 100644 index 0000000..95fc0c1 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/etree.py @@ -0,0 +1,130 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/etree_lxml.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/etree_lxml.py new file mode 100644 index 0000000..e81ddf3 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/etree_lxml.py @@ -0,0 +1,213 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/genshi.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/genshi.py new file mode 100644 index 0000000..7483be2 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/html5lib/treewalkers/genshi.py @@ -0,0 +1,69 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/__init__.py new file mode 100644 index 0000000..847bf93 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/__init__.py @@ -0,0 +1,2 @@ +from .package_data import __version__ +from .core import * diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/codec.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/codec.py new file mode 100644 index 0000000..98c65ea --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/codec.py @@ -0,0 +1,118 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/compat.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/compat.py new file mode 100644 index 0000000..4d47f33 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/compat.py @@ -0,0 +1,12 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/core.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/core.py new file mode 100644 index 0000000..104624a --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/core.py @@ -0,0 +1,396 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/idnadata.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/idnadata.py new file mode 100644 index 0000000..a80c959 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/idnadata.py @@ -0,0 +1,1979 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/intranges.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/intranges.py new file mode 100644 index 0000000..fa8a735 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/intranges.py @@ -0,0 +1,53 @@ +""" +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/package_data.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/package_data.py new file mode 100644 index 0000000..257e898 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/package_data.py @@ -0,0 +1,2 @@ +__version__ = '2.8' + diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/uts46data.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/uts46data.py new file mode 100644 index 0000000..a68ed4c --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/idna/uts46data.py @@ -0,0 +1,8205 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/ipaddress.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/ipaddress.py new file mode 100644 index 0000000..f2d0766 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/ipaddress.py @@ -0,0 +1,2419 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/__init__.py new file mode 100644 index 0000000..a6f44a5 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/__init__.py @@ -0,0 +1,347 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/linklockfile.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/linklockfile.py new file mode 100644 index 0000000..2ca9be0 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/linklockfile.py @@ -0,0 +1,73 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/mkdirlockfile.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/mkdirlockfile.py new file mode 100644 index 0000000..05a8c96 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/mkdirlockfile.py @@ -0,0 +1,84 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/pidlockfile.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/pidlockfile.py new file mode 100644 index 0000000..069e85b --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/pidlockfile.py @@ -0,0 +1,190 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/sqlitelockfile.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/sqlitelockfile.py new file mode 100644 index 0000000..f997e24 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/sqlitelockfile.py @@ -0,0 +1,156 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/symlinklockfile.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/symlinklockfile.py new file mode 100644 index 0000000..23b41f5 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/lockfile/symlinklockfile.py @@ -0,0 +1,70 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/msgpack/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/msgpack/__init__.py new file mode 100644 index 0000000..2afca5a --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/msgpack/__init__.py @@ -0,0 +1,66 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/msgpack/_version.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/msgpack/_version.py new file mode 100644 index 0000000..d28f0de --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/msgpack/_version.py @@ -0,0 +1 @@ +version = (0, 5, 6) diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/msgpack/exceptions.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/msgpack/exceptions.py new file mode 100644 index 0000000..9766881 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/msgpack/exceptions.py @@ -0,0 +1,41 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/msgpack/fallback.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/msgpack/fallback.py new file mode 100644 index 0000000..9418421 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/msgpack/fallback.py @@ -0,0 +1,977 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/__about__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/__about__.py new file mode 100644 index 0000000..7481c9e --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/__about__.py @@ -0,0 +1,27 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/__init__.py new file mode 100644 index 0000000..a0cf67d --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/__init__.py @@ -0,0 +1,26 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/_compat.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/_compat.py new file mode 100644 index 0000000..25da473 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/_compat.py @@ -0,0 +1,31 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/_structures.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/_structures.py new file mode 100644 index 0000000..68dcca6 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/_structures.py @@ -0,0 +1,68 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/markers.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/markers.py new file mode 100644 index 0000000..5482476 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/markers.py @@ -0,0 +1,296 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/requirements.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/requirements.py new file mode 100644 index 0000000..dbc5f11 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/requirements.py @@ -0,0 +1,138 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/specifiers.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/specifiers.py new file mode 100644 index 0000000..743576a --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/specifiers.py @@ -0,0 +1,749 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/utils.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/utils.py new file mode 100644 index 0000000..8841878 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/utils.py @@ -0,0 +1,57 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/version.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/version.py new file mode 100644 index 0000000..95157a1 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/packaging/version.py @@ -0,0 +1,420 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/__init__.py new file mode 100644 index 0000000..9c1a098 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/__init__.py @@ -0,0 +1,4 @@ +"""Wrappers to build Python packages using PEP 517 hooks +""" + +__version__ = '0.5.0' diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/_in_process.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/_in_process.py new file mode 100644 index 0000000..d6524b6 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/_in_process.py @@ -0,0 +1,207 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/build.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/build.py new file mode 100644 index 0000000..ac6c949 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/build.py @@ -0,0 +1,108 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/check.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/check.py new file mode 100644 index 0000000..f4cdc6b --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/check.py @@ -0,0 +1,202 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/colorlog.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/colorlog.py new file mode 100644 index 0000000..69c8a59 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/colorlog.py @@ -0,0 +1,115 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/compat.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/compat.py new file mode 100644 index 0000000..01c66fc --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/compat.py @@ -0,0 +1,23 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/envbuild.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/envbuild.py new file mode 100644 index 0000000..f7ac5f4 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/envbuild.py @@ -0,0 +1,158 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/wrappers.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/wrappers.py new file mode 100644 index 0000000..b14b899 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pep517/wrappers.py @@ -0,0 +1,163 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pkg_resources/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pkg_resources/__init__.py new file mode 100644 index 0000000..9c4fd8e --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pkg_resources/__init__.py @@ -0,0 +1,3171 @@ +# 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 +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 has_metadata(self, name): + return self.egg_info and self._has(self._fn(self.egg_info, name)) + + 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): + if resource_name: + return os.path.join(base, *resource_name.split('/')) + return base + + 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 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 = _version_from_file(self._get_metadata(self.PKG_INFO)) + if version is None: + tmpl = "Missing 'Version:' header and/or %s file" + raise ValueError(tmpl % self.PKG_INFO, 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(self, name): + if self.has_metadata(name): + for line in self.get_metadata_lines(name): + yield line + + 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 = _version_from_file(self._get_metadata(self.PKG_INFO)) + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pkg_resources/py31compat.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pkg_resources/py31compat.py new file mode 100644 index 0000000..a2d3007 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pkg_resources/py31compat.py @@ -0,0 +1,23 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/__init__.py new file mode 100644 index 0000000..a41f65d --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/__init__.py @@ -0,0 +1,127 @@ +# 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 + +from collections import deque +from datetime import timedelta +from math import ceil +from sys import stderr +from time import time + + +__version__ = '1.4' + + +class Infinite(object): + file = stderr + sma_window = 10 # Simple Moving Average window + + def __init__(self, *args, **kwargs): + self.index = 0 + self.start_ts = time() + self.avg = 0 + self._ts = self.start_ts + self._xput = deque(maxlen=self.sma_window) + for key, val in kwargs.items(): + setattr(self, key, val) + + def __getitem__(self, key): + if key.startswith('_'): + return None + return getattr(self, key, None) + + @property + def elapsed(self): + return int(time() - self.start_ts) + + @property + def elapsed_td(self): + return timedelta(seconds=self.elapsed) + + def update_avg(self, n, dt): + if n > 0: + self._xput.append(dt / n) + self.avg = sum(self._xput) / len(self._xput) + + def update(self): + pass + + def start(self): + pass + + def finish(self): + pass + + def next(self, n=1): + now = time() + dt = now - self._ts + self.update_avg(n, dt) + self._ts = now + self.index = self.index + n + self.update() + + def iter(self, it): + try: + for x in it: + yield x + self.next() + finally: + 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 + + try: + for x in it: + yield x + self.next() + finally: + self.finish() diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/bar.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/bar.py new file mode 100644 index 0000000..025e61c --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/bar.py @@ -0,0 +1,94 @@ +# -*- 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 +from .helpers import WritelnMixin + + +class Bar(WritelnMixin, Progress): + width = 32 + message = '' + suffix = '%(index)d/%(max)d' + bar_prefix = ' |' + bar_suffix = '| ' + empty_fill = ' ' + fill = '#' + hide_cursor = True + + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/counter.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/counter.py new file mode 100644 index 0000000..6b45a1e --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/counter.py @@ -0,0 +1,48 @@ +# -*- 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 +from .helpers import WriteMixin + + +class Counter(WriteMixin, Infinite): + message = '' + hide_cursor = True + + def update(self): + self.write(str(self.index)) + + +class Countdown(WriteMixin, Progress): + hide_cursor = True + + def update(self): + self.write(str(self.remaining)) + + +class Stack(WriteMixin, Progress): + phases = (' ', '▁', '▂', '▃', '▄', '▅', '▆', '▇', '█') + hide_cursor = True + + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/helpers.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/helpers.py new file mode 100644 index 0000000..0cde44e --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/helpers.py @@ -0,0 +1,91 @@ +# 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 print_function + + +HIDE_CURSOR = '\x1b[?25l' +SHOW_CURSOR = '\x1b[?25h' + + +class WriteMixin(object): + hide_cursor = False + + def __init__(self, message=None, **kwargs): + super(WriteMixin, self).__init__(**kwargs) + self._width = 0 + if message: + self.message = message + + if self.file and self.file.isatty(): + if self.hide_cursor: + print(HIDE_CURSOR, end='', file=self.file) + print(self.message, end='', file=self.file) + self.file.flush() + + def write(self, s): + if self.file and self.file.isatty(): + b = '\b' * self._width + c = s.ljust(self._width) + print(b + c, end='', file=self.file) + self._width = max(self._width, len(s)) + self.file.flush() + + def finish(self): + if self.file and self.file.isatty() and self.hide_cursor: + print(SHOW_CURSOR, end='', file=self.file) + + +class WritelnMixin(object): + hide_cursor = False + + def __init__(self, message=None, **kwargs): + super(WritelnMixin, self).__init__(**kwargs) + if message: + self.message = message + + if self.file and self.file.isatty() and self.hide_cursor: + print(HIDE_CURSOR, end='', file=self.file) + + def clearln(self): + if self.file and self.file.isatty(): + print('\r\x1b[K', end='', file=self.file) + + def writeln(self, line): + if self.file and self.file.isatty(): + self.clearln() + print(line, end='', file=self.file) + self.file.flush() + + def finish(self): + if self.file and self.file.isatty(): + print(file=self.file) + if self.hide_cursor: + print(SHOW_CURSOR, end='', file=self.file) + + +from signal import signal, SIGINT +from sys import exit + + +class SigIntMixin(object): + """Registers a signal handler that calls finish on SIGINT""" + + def __init__(self, *args, **kwargs): + super(SigIntMixin, self).__init__(*args, **kwargs) + signal(SIGINT, self._sigint_handler) + + def _sigint_handler(self, signum, frame): + self.finish() + exit(0) diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/spinner.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/spinner.py new file mode 100644 index 0000000..464c7b2 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/progress/spinner.py @@ -0,0 +1,44 @@ +# -*- 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 +from .helpers import WriteMixin + + +class Spinner(WriteMixin, Infinite): + message = '' + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pyparsing.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pyparsing.py new file mode 100644 index 0000000..bea4d9c --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pyparsing.py @@ -0,0 +1,6452 @@ +#-*- 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.3.1" +__versionTime__ = "09 Jan 2019 23:26 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 + + +#~ 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', +'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.frame + + 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 += 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 + t = t.replace(r'\n','\n').lstrip('\ufeff') + 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: + 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 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): + super(Char, self).__init__(charset, exact=1) + 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 + + 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() + if self.asMatch: + ret = result + elif self.asGroupList: + ret = result.groups() + else: + ret = ParseResults(result.group()) + d = result.groupdict() + if d: + for k, v in d.items(): + ret[k] = v + 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): + """ + 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 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 + ``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 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 :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() + 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) + # self.saveAsList = any(e.saveAsList for e in self.exprs) + else: + self.mayReturnEmpty = True + + def streamline(self): + super(MatchFirst, self).streamline() + 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 + 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 :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 = expr.saveAsList + + 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).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 ``<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): + """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="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']]]]]]] + """ + 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 ``/* ... */``" + +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/__init__.py new file mode 100644 index 0000000..8ed060f --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/__init__.py @@ -0,0 +1,4 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/core.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/core.py new file mode 100644 index 0000000..c182734 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/core.py @@ -0,0 +1,13 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/parser.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/parser.py new file mode 100644 index 0000000..3493aa6 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/parser.py @@ -0,0 +1,341 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/test.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/test.py new file mode 100644 index 0000000..ec8abfc --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/test.py @@ -0,0 +1,30 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/utils.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/utils.py new file mode 100644 index 0000000..636a680 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/utils.py @@ -0,0 +1,67 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/writer.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/writer.py new file mode 100644 index 0000000..73b5089 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/pytoml/writer.py @@ -0,0 +1,106 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/__init__.py new file mode 100644 index 0000000..80c4ce1 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/__init__.py @@ -0,0 +1,133 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/__version__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/__version__.py new file mode 100644 index 0000000..f5b5d03 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/__version__.py @@ -0,0 +1,14 @@ +# .-. .-. .-. . . .-. .-. .-. .-. +# |( |- |.| | | |- `-. | `-. +# ' ' `-' `-`.`-' `-' `-' ' `-' + +__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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/_internal_utils.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/_internal_utils.py new file mode 100644 index 0000000..759d9a5 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/_internal_utils.py @@ -0,0 +1,42 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/adapters.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/adapters.py new file mode 100644 index 0000000..c30e7c9 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/adapters.py @@ -0,0 +1,533 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/api.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/api.py new file mode 100644 index 0000000..abada96 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/api.py @@ -0,0 +1,158 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/auth.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/auth.py new file mode 100644 index 0000000..bdde51c --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/auth.py @@ -0,0 +1,305 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/certs.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/certs.py new file mode 100644 index 0000000..06a594e --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/certs.py @@ -0,0 +1,18 @@ +#!/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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/compat.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/compat.py new file mode 100644 index 0000000..6a86893 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/compat.py @@ -0,0 +1,74 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/cookies.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/cookies.py new file mode 100644 index 0000000..56fccd9 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/cookies.py @@ -0,0 +1,549 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/exceptions.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/exceptions.py new file mode 100644 index 0000000..a91e1fd --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/exceptions.py @@ -0,0 +1,126 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/help.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/help.py new file mode 100644 index 0000000..3c3072b --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/help.py @@ -0,0 +1,119 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/hooks.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/hooks.py new file mode 100644 index 0000000..7a51f21 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/hooks.py @@ -0,0 +1,34 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/models.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/models.py new file mode 100644 index 0000000..0839957 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/models.py @@ -0,0 +1,953 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/packages.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/packages.py new file mode 100644 index 0000000..9582fa7 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/packages.py @@ -0,0 +1,16 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/sessions.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/sessions.py new file mode 100644 index 0000000..d73d700 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/sessions.py @@ -0,0 +1,770 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/status_codes.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/status_codes.py new file mode 100644 index 0000000..813e8c4 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/status_codes.py @@ -0,0 +1,120 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/structures.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/structures.py new file mode 100644 index 0000000..da930e2 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/structures.py @@ -0,0 +1,103 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/utils.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/utils.py new file mode 100644 index 0000000..8170a8d --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/requests/utils.py @@ -0,0 +1,977 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/retrying.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/retrying.py new file mode 100644 index 0000000..6d1e627 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/retrying.py @@ -0,0 +1,267 @@ +## 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/six.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/six.py new file mode 100644 index 0000000..89b2188 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/six.py @@ -0,0 +1,952 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/__init__.py new file mode 100644 index 0000000..148a9c3 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/__init__.py @@ -0,0 +1,92 @@ +""" +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/_collections.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/_collections.py new file mode 100644 index 0000000..34f2381 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/_collections.py @@ -0,0 +1,329 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/connection.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/connection.py new file mode 100644 index 0000000..02b3665 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/connection.py @@ -0,0 +1,391 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/connectionpool.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/connectionpool.py new file mode 100644 index 0000000..f7a8f19 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/connectionpool.py @@ -0,0 +1,896 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/_appengine_environ.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/_appengine_environ.py new file mode 100644 index 0000000..f3e0094 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/_appengine_environ.py @@ -0,0 +1,30 @@ +""" +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/_securetransport/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/_securetransport/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/_securetransport/bindings.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/_securetransport/bindings.py new file mode 100644 index 0000000..bcf41c0 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/_securetransport/bindings.py @@ -0,0 +1,593 @@ +""" +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/_securetransport/low_level.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/_securetransport/low_level.py new file mode 100644 index 0000000..b13cd9e --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/_securetransport/low_level.py @@ -0,0 +1,346 @@ +""" +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/appengine.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/appengine.py new file mode 100644 index 0000000..9b42952 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/appengine.py @@ -0,0 +1,289 @@ +""" +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/ntlmpool.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/ntlmpool.py new file mode 100644 index 0000000..8ea127c --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/ntlmpool.py @@ -0,0 +1,111 @@ +""" +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/pyopenssl.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/pyopenssl.py new file mode 100644 index 0000000..363667c --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/pyopenssl.py @@ -0,0 +1,466 @@ +""" +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/securetransport.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/securetransport.py new file mode 100644 index 0000000..77cb59e --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/securetransport.py @@ -0,0 +1,804 @@ +""" +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/socks.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/socks.py new file mode 100644 index 0000000..811e312 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/contrib/socks.py @@ -0,0 +1,192 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/exceptions.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/exceptions.py new file mode 100644 index 0000000..7bbaa98 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/exceptions.py @@ -0,0 +1,246 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/fields.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/fields.py new file mode 100644 index 0000000..37fe64a --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/fields.py @@ -0,0 +1,178 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/filepost.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/filepost.py new file mode 100644 index 0000000..78f1e19 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/filepost.py @@ -0,0 +1,98 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/__init__.py new file mode 100644 index 0000000..170e974 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/__init__.py @@ -0,0 +1,5 @@ +from __future__ import absolute_import + +from . import ssl_match_hostname + +__all__ = ('ssl_match_hostname', ) diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/backports/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/backports/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/backports/makefile.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/backports/makefile.py new file mode 100644 index 0000000..740db37 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/backports/makefile.py @@ -0,0 +1,53 @@ +# -*- 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/six.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/six.py new file mode 100644 index 0000000..190c023 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/six.py @@ -0,0 +1,868 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py new file mode 100644 index 0000000..d6594eb --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py @@ -0,0 +1,19 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py new file mode 100644 index 0000000..970cf65 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py @@ -0,0 +1,156 @@ +"""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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/poolmanager.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/poolmanager.py new file mode 100644 index 0000000..fe5491c --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/poolmanager.py @@ -0,0 +1,450 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/request.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/request.py new file mode 100644 index 0000000..8f2f44b --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/request.py @@ -0,0 +1,150 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/response.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/response.py new file mode 100644 index 0000000..c112690 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/response.py @@ -0,0 +1,705 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/__init__.py new file mode 100644 index 0000000..2f2770b --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/__init__.py @@ -0,0 +1,54 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/connection.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/connection.py new file mode 100644 index 0000000..5ad70b2 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/connection.py @@ -0,0 +1,134 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/queue.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/queue.py new file mode 100644 index 0000000..d3d379a --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/queue.py @@ -0,0 +1,21 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/request.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/request.py new file mode 100644 index 0000000..3ddfcd5 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/request.py @@ -0,0 +1,118 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/response.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/response.py new file mode 100644 index 0000000..3d54864 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/response.py @@ -0,0 +1,87 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/retry.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/retry.py new file mode 100644 index 0000000..e7d0abd --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/retry.py @@ -0,0 +1,411 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/ssl_.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/ssl_.py new file mode 100644 index 0000000..dfc553f --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/ssl_.py @@ -0,0 +1,381 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/timeout.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/timeout.py new file mode 100644 index 0000000..cec817e --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/timeout.py @@ -0,0 +1,242 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/url.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/url.py new file mode 100644 index 0000000..6b6f996 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/url.py @@ -0,0 +1,230 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/wait.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/wait.py new file mode 100644 index 0000000..4db71ba --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/urllib3/util/wait.py @@ -0,0 +1,150 @@ +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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/__init__.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/__init__.py new file mode 100644 index 0000000..d21d697 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/__init__.py @@ -0,0 +1,342 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/labels.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/labels.py new file mode 100644 index 0000000..29cbf91 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/labels.py @@ -0,0 +1,231 @@ +""" + + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/mklabels.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/mklabels.py new file mode 100644 index 0000000..295dc92 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/mklabels.py @@ -0,0 +1,59 @@ +""" + + 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/tests.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/tests.py new file mode 100644 index 0000000..e12c10d --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/tests.py @@ -0,0 +1,153 @@ +# 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/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/x_user_defined.py b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/x_user_defined.py new file mode 100644 index 0000000..d16e326 --- /dev/null +++ b/venv/Lib/site-packages/pip-19.0.3-py3.7.egg/pip/_vendor/webencodings/x_user_defined.py @@ -0,0 +1,325 @@ +# 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/venv/Lib/site-packages/setuptools-40.8.0-py3.7.egg b/venv/Lib/site-packages/setuptools-40.8.0-py3.7.egg new file mode 100644 index 0000000000000000000000000000000000000000..3464fb65cb9df3b165488579cf7e14fd40c94c5b GIT binary patch literal 571910 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Ý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 p6O9&Oh=U1DuDpEL)M9}p{RUGX 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools.pth b/venv/Lib/site-packages/setuptools.pth new file mode 100644 index 0000000..ca49991 --- /dev/null +++ b/venv/Lib/site-packages/setuptools.pth @@ -0,0 +1 @@ +./setuptools-40.8.0-py3.7.egg diff --git a/venv/Scripts/Activate.ps1 b/venv/Scripts/Activate.ps1 new file mode 100644 index 0000000..342b0ee --- /dev/null +++ b/venv/Scripts/Activate.ps1 @@ -0,0 +1,51 @@ +function global:deactivate ([switch]$NonDestructive) { + # Revert to original values + if (Test-Path function:_OLD_VIRTUAL_PROMPT) { + copy-item function:_OLD_VIRTUAL_PROMPT function:prompt + remove-item function:_OLD_VIRTUAL_PROMPT + } + + if (Test-Path env:_OLD_VIRTUAL_PYTHONHOME) { + copy-item env:_OLD_VIRTUAL_PYTHONHOME env:PYTHONHOME + remove-item env:_OLD_VIRTUAL_PYTHONHOME + } + + if (Test-Path env:_OLD_VIRTUAL_PATH) { + copy-item env:_OLD_VIRTUAL_PATH env:PATH + remove-item env:_OLD_VIRTUAL_PATH + } + + if (Test-Path env:VIRTUAL_ENV) { + remove-item env:VIRTUAL_ENV + } + + if (!$NonDestructive) { + # Self destruct! + remove-item function:deactivate + } +} + +deactivate -nondestructive + +$env:VIRTUAL_ENV="C:\Users\Daren\PycharmProjects\helloworld\venv" + +if (! $env:VIRTUAL_ENV_DISABLE_PROMPT) { + # Set the prompt to include the env name + # Make sure _OLD_VIRTUAL_PROMPT is global + function global:_OLD_VIRTUAL_PROMPT {""} + copy-item function:prompt function:_OLD_VIRTUAL_PROMPT + function global:prompt { + Write-Host -NoNewline -ForegroundColor Green '(venv) ' + _OLD_VIRTUAL_PROMPT + } +} + +# Clear PYTHONHOME +if (Test-Path env:PYTHONHOME) { + copy-item env:PYTHONHOME env:_OLD_VIRTUAL_PYTHONHOME + remove-item env:PYTHONHOME +} + +# Add the venv to the PATH +copy-item env:PATH env:_OLD_VIRTUAL_PATH +$env:PATH = "$env:VIRTUAL_ENV\Scripts;$env:PATH" diff --git a/venv/Scripts/activate b/venv/Scripts/activate new file mode 100644 index 0000000..0b222be --- /dev/null +++ b/venv/Scripts/activate @@ -0,0 +1,76 @@ +# This file must be used with "source bin/activate" *from bash* +# you cannot run it directly + +deactivate () { + # reset old environment variables + if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then + PATH="${_OLD_VIRTUAL_PATH:-}" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if [ -n "${_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:-}" -o -n "${ZSH_VERSION:-}" ] ; then + hash -r + fi + + if [ -n "${_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="C:\Users\Daren\PycharmProjects\helloworld\venv" +export VIRTUAL_ENV + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/Scripts:$PATH" +export PATH + +# unset PYTHONHOME if set +# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) +# could use `if (set -u; : $PYTHONHOME) ;` in bash +if [ -n "${PYTHONHOME:-}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1:-}" + if [ "x(venv) " != x ] ; then + PS1="(venv) ${PS1:-}" + else + if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then + # special case for Aspen magic directories + # see http://www.zetadev.com/software/aspen/ + PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1" + else + PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1" + fi + fi + export PS1 +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:-}" -o -n "${ZSH_VERSION:-}" ] ; then + hash -r +fi diff --git a/venv/Scripts/activate.bat b/venv/Scripts/activate.bat new file mode 100644 index 0000000..0da2166 --- /dev/null +++ b/venv/Scripts/activate.bat @@ -0,0 +1,45 @@ +@echo off + +rem This file is UTF-8 encoded, so we need to update the current code page while executing it +for /f "tokens=2 delims=:." %%a in ('"%SystemRoot%\System32\chcp.com"') do ( + set "_OLD_CODEPAGE=%%a" +) +if defined _OLD_CODEPAGE ( + "%SystemRoot%\System32\chcp.com" 65001 > nul +) + +set "VIRTUAL_ENV=C:\Users\Daren\PycharmProjects\helloworld\venv" + +if not defined PROMPT ( + set "PROMPT=$P$G" +) + +if defined _OLD_VIRTUAL_PROMPT ( + set "PROMPT=%_OLD_VIRTUAL_PROMPT%" +) + +if defined _OLD_VIRTUAL_PYTHONHOME ( + set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" +) + +set "_OLD_VIRTUAL_PROMPT=%PROMPT%" +set "PROMPT=(venv) %PROMPT%" + +if defined PYTHONHOME ( + set "_OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME%" + set PYTHONHOME= +) + +if defined _OLD_VIRTUAL_PATH ( + set "PATH=%_OLD_VIRTUAL_PATH%" +) else ( + set "_OLD_VIRTUAL_PATH=%PATH%" +) + +set "PATH=%VIRTUAL_ENV%\Scripts;%PATH%" + +:END +if defined _OLD_CODEPAGE ( + "%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul + set "_OLD_CODEPAGE=" +) diff --git a/venv/Scripts/deactivate.bat b/venv/Scripts/deactivate.bat new file mode 100644 index 0000000..1205c61 --- /dev/null +++ b/venv/Scripts/deactivate.bat @@ -0,0 +1,21 @@ +@echo off + +if defined _OLD_VIRTUAL_PROMPT ( + set "PROMPT=%_OLD_VIRTUAL_PROMPT%" +) +set _OLD_VIRTUAL_PROMPT= + +if defined _OLD_VIRTUAL_PYTHONHOME ( + set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" + set _OLD_VIRTUAL_PYTHONHOME= +) + +if defined _OLD_VIRTUAL_PATH ( + set "PATH=%_OLD_VIRTUAL_PATH%" +) + +set _OLD_VIRTUAL_PATH= + +set VIRTUAL_ENV= + +:END diff --git a/venv/Scripts/easy_install-3.7-script.py b/venv/Scripts/easy_install-3.7-script.py new file mode 100644 index 0000000..551dcaa --- /dev/null +++ b/venv/Scripts/easy_install-3.7-script.py @@ -0,0 +1,12 @@ +#!C:\Users\Daren\PycharmProjects\helloworld\venv\Scripts\python.exe +# EASY-INSTALL-ENTRY-SCRIPT: 'setuptools==40.8.0','console_scripts','easy_install-3.7' +__requires__ = 'setuptools==40.8.0' +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('setuptools==40.8.0', 'console_scripts', 'easy_install-3.7')() + ) diff --git a/venv/Scripts/easy_install-3.7.exe b/venv/Scripts/easy_install-3.7.exe new file mode 100644 index 0000000000000000000000000000000000000000..b1487b7819e7286577a043c7726fbe0ca1543083 GIT binary patch literal 65536 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[c}i<OXTz6k>I#RErv3nvcIClH@!{vM)zJ_weD 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 literal 0 HcmV?d00001 diff --git a/venv/Scripts/easy_install-3.7.exe.manifest b/venv/Scripts/easy_install-3.7.exe.manifest new file mode 100644 index 0000000..a3dcdf2 --- /dev/null +++ b/venv/Scripts/easy_install-3.7.exe.manifest @@ -0,0 +1,15 @@ +<?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="easy_install-3.7" + 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/venv/Scripts/easy_install-script.py b/venv/Scripts/easy_install-script.py new file mode 100644 index 0000000..d5d60ec --- /dev/null +++ b/venv/Scripts/easy_install-script.py @@ -0,0 +1,12 @@ +#!C:\Users\Daren\PycharmProjects\helloworld\venv\Scripts\python.exe +# EASY-INSTALL-ENTRY-SCRIPT: 'setuptools==40.8.0','console_scripts','easy_install' +__requires__ = 'setuptools==40.8.0' +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('setuptools==40.8.0', 'console_scripts', 'easy_install')() + ) diff --git a/venv/Scripts/easy_install.exe b/venv/Scripts/easy_install.exe new file mode 100644 index 0000000000000000000000000000000000000000..b1487b7819e7286577a043c7726fbe0ca1543083 GIT binary patch literal 65536 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[c}i<OXTz6k>I#RErv3nvcIClH@!{vM)zJ_weD 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 literal 0 HcmV?d00001 diff --git a/venv/Scripts/easy_install.exe.manifest b/venv/Scripts/easy_install.exe.manifest new file mode 100644 index 0000000..9c19e18 --- /dev/null +++ b/venv/Scripts/easy_install.exe.manifest @@ -0,0 +1,15 @@ +<?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="easy_install" + 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/venv/Scripts/pip-script.py b/venv/Scripts/pip-script.py new file mode 100644 index 0000000..518f9d9 --- /dev/null +++ b/venv/Scripts/pip-script.py @@ -0,0 +1,12 @@ +#!C:\Users\Daren\PycharmProjects\helloworld\venv\Scripts\python.exe +# EASY-INSTALL-ENTRY-SCRIPT: 'pip==19.0.3','console_scripts','pip' +__requires__ = 'pip==19.0.3' +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('pip==19.0.3', 'console_scripts', 'pip')() + ) diff --git a/venv/Scripts/pip.exe b/venv/Scripts/pip.exe new file mode 100644 index 0000000000000000000000000000000000000000..b1487b7819e7286577a043c7726fbe0ca1543083 GIT binary patch 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 literal 0 HcmV?d00001 diff --git a/venv/Scripts/pip.exe.manifest b/venv/Scripts/pip.exe.manifest new file mode 100644 index 0000000..dd6f562 --- /dev/null +++ b/venv/Scripts/pip.exe.manifest @@ -0,0 +1,15 @@ +<?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="pip" + 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/venv/Scripts/pip3-script.py b/venv/Scripts/pip3-script.py new file mode 100644 index 0000000..c0af0bc --- /dev/null +++ b/venv/Scripts/pip3-script.py @@ -0,0 +1,12 @@ +#!C:\Users\Daren\PycharmProjects\helloworld\venv\Scripts\python.exe +# EASY-INSTALL-ENTRY-SCRIPT: 'pip==19.0.3','console_scripts','pip3' +__requires__ = 'pip==19.0.3' +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('pip==19.0.3', 'console_scripts', 'pip3')() + ) diff --git a/venv/Scripts/pip3.7-script.py b/venv/Scripts/pip3.7-script.py new file mode 100644 index 0000000..dcd20c5 --- /dev/null +++ b/venv/Scripts/pip3.7-script.py @@ -0,0 +1,12 @@ +#!C:\Users\Daren\PycharmProjects\helloworld\venv\Scripts\python.exe +# EASY-INSTALL-ENTRY-SCRIPT: 'pip==19.0.3','console_scripts','pip3.7' +__requires__ = 'pip==19.0.3' +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('pip==19.0.3', 'console_scripts', 'pip3.7')() + ) diff --git a/venv/Scripts/pip3.7.exe b/venv/Scripts/pip3.7.exe new file mode 100644 index 0000000000000000000000000000000000000000..b1487b7819e7286577a043c7726fbe0ca1543083 GIT binary patch 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 literal 0 HcmV?d00001 diff --git a/venv/Scripts/pip3.7.exe.manifest b/venv/Scripts/pip3.7.exe.manifest new file mode 100644 index 0000000..991cd51 --- /dev/null +++ b/venv/Scripts/pip3.7.exe.manifest @@ -0,0 +1,15 @@ +<?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="pip3.7" + 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/venv/Scripts/pip3.exe b/venv/Scripts/pip3.exe new file mode 100644 index 0000000000000000000000000000000000000000..b1487b7819e7286577a043c7726fbe0ca1543083 GIT binary patch literal 65536 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[c}i<OXTz6k>I#RErv3nvcIClH@!{vM)zJ_weD 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 literal 0 HcmV?d00001 diff --git a/venv/Scripts/pip3.exe.manifest b/venv/Scripts/pip3.exe.manifest new file mode 100644 index 0000000..cdf9df4 --- /dev/null +++ b/venv/Scripts/pip3.exe.manifest @@ -0,0 +1,15 @@ +<?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="pip3" + 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/venv/Scripts/python.exe b/venv/Scripts/python.exe new file mode 100644 index 0000000000000000000000000000000000000000..87bc9ee8afe085c6839a5c043090a215b32ef1a3 GIT binary patch literal 415248 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Μ`C<08PLZil3Mdr5pMMeaVwEHhur#t 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�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 literal 0 HcmV?d00001 diff --git a/venv/Scripts/pythonw.exe b/venv/Scripts/pythonw.exe new file mode 100644 index 0000000000000000000000000000000000000000..cd3ecd248da898dcca840de9125db072205b704f GIT binary patch literal 414736 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%0D+x>hAqSFh2DyXg!C_=$#(@*^=6iHV?X1 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 N$e0u$ZwLMr^dDz|9UK4v literal 0 HcmV?d00001 diff --git a/venv/pyvenv.cfg b/venv/pyvenv.cfg new file mode 100644 index 0000000..c971d68 --- /dev/null +++ b/venv/pyvenv.cfg @@ -0,0 +1,3 @@ +home = C:\Users\Daren\AppData\Local\Programs\Python\Python37-32 +include-system-site-packages = false +version = 3.7.4 From d92dbfc1705f434e09ae8995c412f9075f3a51c9 Mon Sep 17 00:00:00 2001 From: dntrinh <dntrinh@ualberta.ca> Date: Tue, 17 Sep 2019 23:51:07 -0600 Subject: [PATCH 3/4] assignment done! --- helloworld.py | 42 ++++++++++++++++++++++++++++++++++++++++++ output.txt | 25 +++++++++++++++++++++++++ tutorial | 1 + 3 files changed, 68 insertions(+) create mode 100644 helloworld.py create mode 100644 output.txt create mode 160000 tutorial diff --git a/helloworld.py b/helloworld.py new file mode 100644 index 0000000..758d3fe --- /dev/null +++ b/helloworld.py @@ -0,0 +1,42 @@ +def helloworld(): + + def greeting(): + + print("What is your name?") + Name = input() + print("Hello World, my name is", Name) + + greeting() + + def fibonacci(): + + num_1 = 0 + num_2 = 1 + + import time + time.sleep(1) + print(num_1) + import time + time.sleep(1) + print(num_2) + import time + time.sleep(1) + + for i in range(1, 20): + new_num = num_1 + num_2 + num_1 = num_2 + num_2 = new_num + print(new_num) + + import time + time.sleep(1) + + fibonacci() + + import time + time.sleep(1) + + print("Task Complete!") + + +helloworld() \ No newline at end of file diff --git a/output.txt b/output.txt new file mode 100644 index 0000000..da96741 --- /dev/null +++ b/output.txt @@ -0,0 +1,25 @@ +What is your name? +Daren +Hello World, my name is Daren +0 +1 +1 +2 +3 +5 +8 +13 +21 +34 +55 +89 +144 +233 +377 +610 +987 +1597 +2584 +4181 +6765 +Task Complete! \ No newline at end of file diff --git a/tutorial b/tutorial new file mode 160000 index 0000000..0e9d49d --- /dev/null +++ b/tutorial @@ -0,0 +1 @@ +Subproject commit 0e9d49df9f548d402e1888a5c79ee5fa250b0a0a From 34de60f8b16ac90b4d55a6267536d47165a46750 Mon Sep 17 00:00:00 2001 From: dntrinh <dntrinh@ualberta.ca> Date: Wed, 18 Sep 2019 00:16:58 -0600 Subject: [PATCH 4/4] assignment done! --- .idea/vcs.xml | 8 ++++++++ .idea/workspace.xml | 23 ++++++++++++++++++++- README.md | 18 ---------------- helloworld.py | 50 --------------------------------------------- output.txt | 33 ------------------------------ 5 files changed, 30 insertions(+), 102 deletions(-) create mode 100644 .idea/vcs.xml delete mode 100644 README.md diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..866150c --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="VcsDirectoryMappings"> + <mapping directory="$PROJECT_DIR$" vcs="Git" /> + <mapping directory="$PROJECT_DIR$/tutorial" vcs="Git" /> + <mapping directory="$PROJECT_DIR$/tutorial/tutorial" vcs="Git" /> + </component> +</project> \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 365788d..3bb0c82 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,7 +1,12 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> <component name="ChangeListManager"> - <list default="true" id="ea0247ab-b1f1-487d-8e24-9585d6a9c631" name="Default Changelist" comment="" /> + <list default="true" id="ea0247ab-b1f1-487d-8e24-9585d6a9c631" name="Default Changelist" comment=""> + <change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/helloworld.py" beforeDir="false" afterPath="$PROJECT_DIR$/helloworld.py" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/output.txt" beforeDir="false" afterPath="$PROJECT_DIR$/output.txt" afterDir="false" /> + </list> <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" /> <option name="SHOW_DIALOG" value="false" /> <option name="HIGHLIGHT_CONFLICTS" value="true" /> @@ -15,8 +20,13 @@ </list> </option> </component> + <component name="Git.Settings"> + <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" /> + </component> <component name="ProjectId" id="1QwYMaM0SiiDczZxzU0RbSk0yaR" /> + <component name="ProjectLevelVcsManager" settingsEditedManually="true" /> <component name="PropertiesComponent"> + <property name="SHARE_PROJECT_CONFIGURATION_FILES" value="true" /> <property name="com.intellij.ide.scratch.LRUPopupBuilder$1/New Scratch File" value="Python" /> <property name="last_opened_file_path" value="$PROJECT_DIR$" /> </component> @@ -100,6 +110,17 @@ </task> <servers /> </component> + <component name="Vcs.Log.Tabs.Properties"> + <option name="TAB_STATES"> + <map> + <entry key="MAIN"> + <value> + <State /> + </value> + </entry> + </map> + </option> + </component> <component name="XDebuggerManager"> <breakpoint-manager> <default-breakpoints> diff --git a/README.md b/README.md deleted file mode 100644 index 1fc37cc..0000000 --- a/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# tutorial -This repository is used for new members to complete the assigned task below to be granted full access to the ALEX repository and begin work on the exoskelton project. - -# The task -1. Find and clone the “tutorial” repository from the UAlberta Biomed GitHub organization to your local computer -2. Create a new branch with your name (firstname-lastname) -3. Create either a new C++ file or Python file (i.e. helloworld.cpp or helloworld.py) -4. Write a simple program that does the following: - - Call a function from main that asks the user for their name and prints to the terminal “Hello World, my name is <name>” - - Then, call a function that iteratively computes the first 20 numbers in the Fibonacci sequence. Add a delay (you decide how long) after each computation and print each number on a new line in the terminal - - Print “Task Complete!” after the first 20 numbers have been printed. -(Note: you cannot hard code these numbers into your program) - - Test your code - - Check to see if it compiles, you should not get any errors - - Pipe the terminal output into a text file (output.txt) in the same directory - - Add/commit your program and output file; use an appropriate commit message -5. Once you have completed all the steps, push your branch to the tutorial repo -6. Message your team lead that you have completed this exercise diff --git a/helloworld.py b/helloworld.py index 922f01a..758d3fe 100644 --- a/helloworld.py +++ b/helloworld.py @@ -1,7 +1,3 @@ -<<<<<<< HEAD -======= -<<<<<<< HEAD ->>>>>>> 0859c73712267c7b47c717177e309b36dbae841c def helloworld(): def greeting(): @@ -43,50 +39,4 @@ def fibonacci(): print("Task Complete!") -<<<<<<< HEAD -======= -======= -def helloworld(): - - def greeting(): - - print("What is your name?") - Name = input() - print("Hello World, my name is", Name) - - greeting() - - def fibonacci(): - - num_1 = 0 - num_2 = 1 - - import time - time.sleep(1) - print(num_1) - import time - time.sleep(1) - print(num_2) - import time - time.sleep(1) - - for i in range(1, 20): - new_num = num_1 + num_2 - num_1 = num_2 - num_2 = new_num - print(new_num) - - import time - time.sleep(1) - - fibonacci() - - import time - time.sleep(1) - - print("Task Complete!") - - ->>>>>>> 56cf3716c06986a76aca042c284b73a2eb574cda ->>>>>>> 0859c73712267c7b47c717177e309b36dbae841c helloworld() \ No newline at end of file diff --git a/output.txt b/output.txt index 87f1312..da96741 100644 --- a/output.txt +++ b/output.txt @@ -1,7 +1,3 @@ -<<<<<<< HEAD -======= -<<<<<<< HEAD ->>>>>>> 0859c73712267c7b47c717177e309b36dbae841c What is your name? Daren Hello World, my name is Daren @@ -26,33 +22,4 @@ Hello World, my name is Daren 2584 4181 6765 -<<<<<<< HEAD -======= -======= -What is your name? -Daren -Hello World, my name is Daren -0 -1 -1 -2 -3 -5 -8 -13 -21 -34 -55 -89 -144 -233 -377 -610 -987 -1597 -2584 -4181 -6765 ->>>>>>> 56cf3716c06986a76aca042c284b73a2eb574cda ->>>>>>> 0859c73712267c7b47c717177e309b36dbae841c Task Complete! \ No newline at end of file