From 81ae2628e5af35fe0f8eb56a2ca25128a36e2864 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Fri, 18 May 2018 00:46:20 -0400 Subject: [PATCH] Update to pip 10.0.1 and update imports Signed-off-by: Dan Ryan --- pipenv/patched/notpip/LICENSE.txt | 40 +- pipenv/patched/notpip/__init__.py | 347 +- pipenv/patched/notpip/__main__.py | 6 +- pipenv/patched/notpip/_internal/__init__.py | 246 + .../notpip/{ => _internal}/basecommand.py | 198 +- .../notpip/{ => _internal}/baseparser.py | 141 +- pipenv/patched/notpip/_internal/build_env.py | 92 + pipenv/patched/notpip/_internal/cache.py | 202 + .../notpip/{ => _internal}/cmdoptions.py | 274 +- .../{ => _internal}/commands/__init__.py | 49 +- .../notpip/_internal/commands/check.py | 42 + .../{ => _internal}/commands/completion.py | 67 +- .../_internal/commands/configuration.py | 227 + .../{ => _internal}/commands/download.py | 91 +- .../notpip/{ => _internal}/commands/freeze.py | 31 +- .../notpip/{ => _internal}/commands/hash.py | 10 +- .../notpip/{ => _internal}/commands/help.py | 9 +- .../notpip/_internal/commands/install.py | 502 ++ .../notpip/{ => _internal}/commands/list.py | 116 +- .../notpip/{ => _internal}/commands/search.py | 32 +- .../notpip/{ => _internal}/commands/show.py | 22 +- .../{ => _internal}/commands/uninstall.py | 45 +- .../notpip/{ => _internal}/commands/wheel.py | 137 +- pipenv/patched/notpip/_internal/compat.py | 235 + .../patched/notpip/_internal/configuration.py | 378 ++ .../notpip/{ => _internal}/download.py | 174 +- .../notpip/{ => _internal}/exceptions.py | 9 +- .../patched/notpip/{ => _internal}/index.py | 142 +- .../notpip/{ => _internal}/locations.py | 38 +- .../notpip/_internal/models/__init__.py | 4 + .../notpip/{ => _internal}/models/index.py | 3 +- .../{ => _internal}/operations/__init__.py | 0 .../notpip/_internal/operations/check.py | 106 + .../notpip/_internal/operations/freeze.py | 252 + .../notpip/_internal/operations/prepare.py | 380 ++ .../notpip/{ => _internal}/pep425tags.py | 35 +- .../patched/notpip/_internal/req/__init__.py | 69 + .../notpip/{ => _internal}/req/req_file.py | 108 +- .../notpip/{ => _internal}/req/req_install.py | 670 ++- .../patched/notpip/_internal/req/req_set.py | 165 + .../notpip/_internal/req/req_uninstall.py | 455 ++ pipenv/patched/notpip/_internal/resolve.py | 381 ++ .../notpip/{ => _internal}/status_codes.py | 0 .../notpip/_internal/utils/__init__.py | 0 .../notpip/{ => _internal}/utils/appdirs.py | 18 +- .../{ => _internal}/utils/deprecation.py | 21 +- .../notpip/{ => _internal}/utils/encoding.py | 8 +- .../{ => _internal}/utils/filesystem.py | 2 +- .../notpip/{ => _internal}/utils/glibc.py | 11 +- .../notpip/{ => _internal}/utils/hashes.py | 8 +- .../notpip/{ => _internal}/utils/logging.py | 16 +- .../__init__.py => _internal/utils/misc.py} | 101 +- .../notpip/{ => _internal}/utils/outdated.py | 51 +- .../notpip/{ => _internal}/utils/packaging.py | 31 +- .../{ => _internal}/utils/setuptools_build.py | 0 .../notpip/_internal/utils/temp_dir.py | 82 + .../patched/notpip/_internal/utils/typing.py | 29 + .../notpip/{ => _internal}/utils/ui.py | 113 +- .../notpip/{ => _internal}/vcs/__init__.py | 135 +- .../notpip/{ => _internal}/vcs/bazaar.py | 59 +- .../patched/notpip/{ => _internal}/vcs/git.py | 231 +- .../notpip/{ => _internal}/vcs/mercurial.py | 46 +- .../notpip/{ => _internal}/vcs/subversion.py | 66 +- .../patched/notpip/{ => _internal}/wheel.py | 388 +- pipenv/patched/notpip/_vendor/__init__.py | 10 +- pipenv/patched/notpip/_vendor/appdirs.py | 116 +- .../notpip/_vendor/cachecontrol/__init__.py | 2 +- .../notpip/_vendor/cachecontrol/_cmd.py | 8 +- .../notpip/_vendor/cachecontrol/adapter.py | 21 +- .../_vendor/cachecontrol/caches/__init__.py | 20 +- .../_vendor/cachecontrol/caches/file_cache.py | 35 +- .../cachecontrol/caches/redis_cache.py | 12 +- .../notpip/_vendor/cachecontrol/compat.py | 17 +- .../notpip/_vendor/cachecontrol/controller.py | 106 +- .../notpip/_vendor/cachecontrol/heuristics.py | 2 +- .../notpip/_vendor/cachecontrol/serialize.py | 84 +- .../notpip/_vendor/cachecontrol/wrapper.py | 10 +- .../notpip/_vendor/chardet/cli/chardetect.py | 6 +- .../notpip/_vendor/colorama/__init__.py | 2 +- .../notpip/_vendor/colorama/ansitowin32.py | 4 +- .../patched/notpip/_vendor/colorama/win32.py | 10 +- .../notpip/_vendor/distlib/__init__.py | 4 +- .../_vendor/distlib/_backport/sysconfig.cfg | 168 +- .../_vendor/distlib/_backport/sysconfig.py | 14 +- .../patched/notpip/_vendor/distlib/compat.py | 41 +- .../notpip/_vendor/distlib/database.py | 92 +- .../patched/notpip/_vendor/distlib/index.py | 9 +- .../notpip/_vendor/distlib/locators.py | 55 +- .../notpip/_vendor/distlib/manifest.py | 2 +- .../patched/notpip/_vendor/distlib/markers.py | 239 +- .../notpip/_vendor/distlib/metadata.py | 35 +- .../notpip/_vendor/distlib/resources.py | 2 +- .../patched/notpip/_vendor/distlib/scripts.py | 37 +- pipenv/patched/notpip/_vendor/distlib/t32.exe | Bin 89088 -> 92672 bytes pipenv/patched/notpip/_vendor/distlib/t64.exe | Bin 97792 -> 102400 bytes pipenv/patched/notpip/_vendor/distlib/util.py | 306 +- .../patched/notpip/_vendor/distlib/version.py | 40 +- pipenv/patched/notpip/_vendor/distlib/w32.exe | Bin 85504 -> 89088 bytes pipenv/patched/notpip/_vendor/distlib/w64.exe | Bin 94208 -> 99328 bytes .../patched/notpip/_vendor/distlib/wheel.py | 38 +- pipenv/patched/notpip/_vendor/distro.py | 135 +- .../notpip/_vendor/html5lib/__init__.py | 26 +- .../notpip/_vendor/html5lib/_ihatexml.py | 2 +- .../notpip/_vendor/html5lib/_inputstream.py | 14 +- .../notpip/_vendor/html5lib/_tokenizer.py | 2 +- .../notpip/_vendor/html5lib/_trie/_base.py | 3 +- .../notpip/_vendor/html5lib/_trie/datrie.py | 2 +- .../notpip/_vendor/html5lib/_trie/py.py | 2 +- .../patched/notpip/_vendor/html5lib/_utils.py | 7 +- .../notpip/_vendor/html5lib/constants.py | 8 +- .../filters/alphabeticalattributes.py | 19 +- .../html5lib/filters/inject_meta_charset.py | 8 + .../notpip/_vendor/html5lib/filters/lint.py | 14 +- .../_vendor/html5lib/filters/optionaltags.py | 1 + .../_vendor/html5lib/filters/sanitizer.py | 59 +- .../_vendor/html5lib/filters/whitespace.py | 2 +- .../notpip/_vendor/html5lib/html5parser.py | 140 +- .../notpip/_vendor/html5lib/serializer.py | 159 +- .../_vendor/html5lib/treeadapters/__init__.py | 18 + .../_vendor/html5lib/treeadapters/genshi.py | 7 + .../_vendor/html5lib/treeadapters/sax.py | 8 +- .../_vendor/html5lib/treebuilders/__init__.py | 80 +- .../_vendor/html5lib/treebuilders/base.py | 70 +- .../_vendor/html5lib/treebuilders/etree.py | 2 +- .../html5lib/treebuilders/etree_lxml.py | 1 - .../_vendor/html5lib/treewalkers/__init__.py | 39 +- .../_vendor/html5lib/treewalkers/base.py | 102 + .../_vendor/html5lib/treewalkers/etree.py | 11 +- .../html5lib/treewalkers/etree_lxml.py | 2 +- pipenv/patched/notpip/_vendor/ipaddress.py | 56 +- .../notpip/_vendor/msgpack/__init__.py | 66 + .../notpip/_vendor/msgpack/_version.py | 1 + .../notpip/_vendor/msgpack/exceptions.py | 41 + .../notpip/_vendor/msgpack/fallback.py | 977 ++++ pipenv/patched/notpip/_vendor/ordereddict.py | 127 - .../notpip/_vendor/packaging/__about__.py | 2 +- .../notpip/_vendor/packaging/_structures.py | 2 + .../notpip/_vendor/packaging/markers.py | 8 +- .../notpip/_vendor/packaging/requirements.py | 17 +- .../notpip/_vendor/packaging/specifiers.py | 2 +- .../patched/notpip/_vendor/packaging/utils.py | 49 + .../notpip/_vendor/packaging/version.py | 100 +- .../notpip/_vendor/pkg_resources/__init__.py | 544 +- .../_vendor/pkg_resources/py31compat.py | 22 + .../notpip/_vendor/progress/__init__.py | 46 +- pipenv/patched/notpip/_vendor/progress/bar.py | 33 +- .../notpip/_vendor/progress/counter.py | 5 +- .../notpip/_vendor/progress/spinner.py | 10 +- pipenv/patched/notpip/_vendor/pyparsing.py | 58 +- .../patched/notpip/_vendor/pytoml/__init__.py | 3 + pipenv/patched/notpip/_vendor/pytoml/core.py | 13 + .../patched/notpip/_vendor/pytoml/parser.py | 374 ++ .../patched/notpip/_vendor/pytoml/writer.py | 127 + pipenv/patched/notpip/_vendor/re-vendor.py | 34 - .../notpip/_vendor/requests/__init__.py | 18 +- .../notpip/_vendor/requests/adapters.py | 30 +- .../notpip/_vendor/requests/cacert.pem | 4433 ----------------- .../patched/notpip/_vendor/requests/certs.py | 2 +- .../patched/notpip/_vendor/requests/compat.py | 10 +- .../notpip/_vendor/requests/exceptions.py | 2 +- .../patched/notpip/_vendor/requests/help.py | 6 +- .../patched/notpip/_vendor/requests/models.py | 10 +- .../notpip/_vendor/requests/packages.py | 6 +- pipenv/patched/notpip/_vendor/retrying.py | 2 +- pipenv/patched/notpip/_vendor/six.py | 55 +- .../_vendor/urllib3/contrib/appengine.py | 4 +- .../_vendor/urllib3/contrib/pyopenssl.py | 2 +- .../ssl_match_hostname/_implementation.py | 2 +- .../notpip/_vendor/urllib3/util/ssl_.py | 2 +- .../notpip/_vendor/webencodings/__init__.py | 4 +- .../notpip/_vendor/webencodings/tests.py | 2 +- .../_vendor/webencodings/x_user_defined.py | 2 +- pipenv/patched/notpip/commands/check.py | 39 - pipenv/patched/notpip/commands/install.py | 437 -- pipenv/patched/notpip/compat/__init__.py | 169 - pipenv/patched/notpip/compat/dictconfig.py | 565 --- pipenv/patched/notpip/models/__init__.py | 4 - pipenv/patched/notpip/operations/check.py | 49 - pipenv/patched/notpip/operations/freeze.py | 132 - pipenv/patched/notpip/req/__init__.py | 10 - pipenv/patched/notpip/req/req_set.py | 838 ---- pipenv/patched/notpip/req/req_uninstall.py | 195 - pipenv/patched/notpip/utils/build.py | 42 - pipenv/patched/piptools/cache.py | 2 +- pipenv/patched/piptools/locations.py | 2 +- pipenv/patched/piptools/repositories/pypi.py | 12 +- pipenv/patched/piptools/resolver.py | 2 +- pipenv/patched/safety/cli.py | 4 +- pipenv/vendor/pipdeptree.py | 6 +- pipenv/vendor/requirements/fragment.py | 2 +- 190 files changed, 9661 insertions(+), 10594 deletions(-) create mode 100644 pipenv/patched/notpip/_internal/__init__.py rename pipenv/patched/notpip/{ => _internal}/basecommand.py (61%) rename pipenv/patched/notpip/{ => _internal}/baseparser.py (67%) create mode 100644 pipenv/patched/notpip/_internal/build_env.py create mode 100644 pipenv/patched/notpip/_internal/cache.py rename pipenv/patched/notpip/{ => _internal}/cmdoptions.py (77%) rename pipenv/patched/notpip/{ => _internal}/commands/__init__.py (53%) create mode 100644 pipenv/patched/notpip/_internal/commands/check.py rename pipenv/patched/notpip/{ => _internal}/commands/completion.py (54%) create mode 100644 pipenv/patched/notpip/_internal/commands/configuration.py rename pipenv/patched/notpip/{ => _internal}/commands/download.py (71%) rename pipenv/patched/notpip/{ => _internal}/commands/freeze.py (75%) rename pipenv/patched/notpip/{ => _internal}/commands/hash.py (85%) rename pipenv/patched/notpip/{ => _internal}/commands/help.py (71%) create mode 100644 pipenv/patched/notpip/_internal/commands/install.py rename pipenv/patched/notpip/{ => _internal}/commands/list.py (77%) rename pipenv/patched/notpip/{ => _internal}/commands/search.py (79%) rename pipenv/patched/notpip/{ => _internal}/commands/show.py (90%) rename pipenv/patched/notpip/{ => _internal}/commands/uninstall.py (61%) rename pipenv/patched/notpip/{ => _internal}/commands/wheel.py (56%) create mode 100644 pipenv/patched/notpip/_internal/compat.py create mode 100644 pipenv/patched/notpip/_internal/configuration.py rename pipenv/patched/notpip/{ => _internal}/download.py (85%) rename pipenv/patched/notpip/{ => _internal}/exceptions.py (97%) rename pipenv/patched/notpip/{ => _internal}/index.py (92%) rename pipenv/patched/notpip/{ => _internal}/locations.py (82%) create mode 100644 pipenv/patched/notpip/_internal/models/__init__.py rename pipenv/patched/notpip/{ => _internal}/models/index.py (73%) rename pipenv/patched/notpip/{ => _internal}/operations/__init__.py (100%) create mode 100644 pipenv/patched/notpip/_internal/operations/check.py create mode 100644 pipenv/patched/notpip/_internal/operations/freeze.py create mode 100644 pipenv/patched/notpip/_internal/operations/prepare.py rename pipenv/patched/notpip/{ => _internal}/pep425tags.py (93%) create mode 100644 pipenv/patched/notpip/_internal/req/__init__.py rename pipenv/patched/notpip/{ => _internal}/req/req_file.py (81%) rename pipenv/patched/notpip/{ => _internal}/req/req_install.py (66%) create mode 100644 pipenv/patched/notpip/_internal/req/req_set.py create mode 100644 pipenv/patched/notpip/_internal/req/req_uninstall.py create mode 100644 pipenv/patched/notpip/_internal/resolve.py rename pipenv/patched/notpip/{ => _internal}/status_codes.py (100%) create mode 100644 pipenv/patched/notpip/_internal/utils/__init__.py rename pipenv/patched/notpip/{ => _internal}/utils/appdirs.py (94%) rename pipenv/patched/notpip/{ => _internal}/utils/deprecation.py (80%) rename pipenv/patched/notpip/{ => _internal}/utils/encoding.py (83%) rename pipenv/patched/notpip/{ => _internal}/utils/filesystem.py (94%) rename pipenv/patched/notpip/{ => _internal}/utils/glibc.py (93%) rename pipenv/patched/notpip/{ => _internal}/utils/hashes.py (92%) rename pipenv/patched/notpip/{ => _internal}/utils/logging.py (88%) rename pipenv/patched/notpip/{utils/__init__.py => _internal/utils/misc.py} (93%) rename pipenv/patched/notpip/{ => _internal}/utils/outdated.py (76%) rename pipenv/patched/notpip/{ => _internal}/utils/packaging.py (78%) rename pipenv/patched/notpip/{ => _internal}/utils/setuptools_build.py (100%) create mode 100644 pipenv/patched/notpip/_internal/utils/temp_dir.py create mode 100644 pipenv/patched/notpip/_internal/utils/typing.py rename pipenv/patched/notpip/{ => _internal}/utils/ui.py (79%) rename pipenv/patched/notpip/{ => _internal}/vcs/__init__.py (76%) rename pipenv/patched/notpip/{ => _internal}/vcs/bazaar.py (67%) rename pipenv/patched/notpip/{ => _internal}/vcs/git.py (61%) rename pipenv/patched/notpip/{ => _internal}/vcs/mercurial.py (72%) rename pipenv/patched/notpip/{ => _internal}/vcs/subversion.py (83%) rename pipenv/patched/notpip/{ => _internal}/wheel.py (74%) mode change 100644 => 100755 pipenv/patched/notpip/_vendor/distlib/t32.exe mode change 100644 => 100755 pipenv/patched/notpip/_vendor/distlib/t64.exe mode change 100644 => 100755 pipenv/patched/notpip/_vendor/distlib/w32.exe mode change 100644 => 100755 pipenv/patched/notpip/_vendor/distlib/w64.exe create mode 100644 pipenv/patched/notpip/_vendor/msgpack/__init__.py create mode 100644 pipenv/patched/notpip/_vendor/msgpack/_version.py create mode 100644 pipenv/patched/notpip/_vendor/msgpack/exceptions.py create mode 100644 pipenv/patched/notpip/_vendor/msgpack/fallback.py delete mode 100644 pipenv/patched/notpip/_vendor/ordereddict.py create mode 100644 pipenv/patched/notpip/_vendor/pkg_resources/py31compat.py create mode 100644 pipenv/patched/notpip/_vendor/pytoml/__init__.py create mode 100644 pipenv/patched/notpip/_vendor/pytoml/core.py create mode 100644 pipenv/patched/notpip/_vendor/pytoml/parser.py create mode 100644 pipenv/patched/notpip/_vendor/pytoml/writer.py delete mode 100644 pipenv/patched/notpip/_vendor/re-vendor.py delete mode 100644 pipenv/patched/notpip/_vendor/requests/cacert.pem delete mode 100644 pipenv/patched/notpip/commands/check.py delete mode 100644 pipenv/patched/notpip/commands/install.py delete mode 100644 pipenv/patched/notpip/compat/__init__.py delete mode 100644 pipenv/patched/notpip/compat/dictconfig.py delete mode 100644 pipenv/patched/notpip/models/__init__.py delete mode 100644 pipenv/patched/notpip/operations/check.py delete mode 100644 pipenv/patched/notpip/operations/freeze.py delete mode 100644 pipenv/patched/notpip/req/__init__.py delete mode 100644 pipenv/patched/notpip/req/req_set.py delete mode 100644 pipenv/patched/notpip/req/req_uninstall.py delete mode 100644 pipenv/patched/notpip/utils/build.py diff --git a/pipenv/patched/notpip/LICENSE.txt b/pipenv/patched/notpip/LICENSE.txt index f63eac3d..049480f8 100644 --- a/pipenv/patched/notpip/LICENSE.txt +++ b/pipenv/patched/notpip/LICENSE.txt @@ -1,20 +1,20 @@ -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. +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. diff --git a/pipenv/patched/notpip/__init__.py b/pipenv/patched/notpip/__init__.py index 5957d31f..ab649641 100644 --- a/pipenv/patched/notpip/__init__.py +++ b/pipenv/patched/notpip/__init__.py @@ -1,346 +1 @@ -#!/usr/bin/env python -from __future__ import absolute_import - -import locale -import logging -import os -import optparse -import warnings - -import sys -import re - -# 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 pip9.vcs. -from pip9._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: - if (sys.platform == "darwin" and - getattr(ssl, "OPENSSL_VERSION_NUMBER", 0) < 0x1000100f): # OpenSSL 1.0.1 - try: - from pip9._vendor.urllib3.contrib import securetransport - except (ImportError, OSError): - pass - else: - securetransport.inject_into_urllib3() - -from pip9.exceptions import InstallationError, CommandError, PipError -from pip9.utils import get_installed_distributions, get_prog -from pip9.utils import deprecation, dist_is_editable -from pip9.vcs import git, mercurial, subversion, bazaar # noqa -from pip9.baseparser import ConfigOptionParser, UpdatingDefaultsHelpFormatter -from pip9.commands import get_summaries, get_similar_commands -from pip9.commands import commands_dict -from pip9._vendor.urllib3.exceptions import InsecureRequestWarning - - -# assignment for flake8 to be happy - -# This fixes a peculiarity when importing via __import__ - as we are -# initialising the pip module, "from pip9.import cmdoptions" is recursive -# and appears not to work properly in that situation. -import pip9.cmdoptions -cmdoptions = pip9.cmdoptions - -# The version as used in the setup.py and the docs conf.py -__version__ = "9.0.3" - - -logger = logging.getLogger(__name__) - -# Hide the InsecureRequestWarning from urllib3 -warnings.filterwarnings("ignore", category=InsecureRequestWarning) - - -def autocomplete(): - """Command and option completion for the main option parser (and options) - and its subcommands (and options). - - Enable by sourcing one of the completion shell scripts (bash, zsh or fish). - """ - # 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 uninstall command - if subcommand_name == 'uninstall' and not current.startswith('-'): - 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]() - options += [(opt.get_opt_string(), opt.nargs) - for opt in subcommand.parser.option_list_all - if opt.help != optparse.SUPPRESS_HELP] - - # 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)] - for option in options: - opt_label = option[0] - # append '=' to options which require args - if option[1]: - opt_label += '=' - print(opt_label) - else: - # show main parser options only when necessary - if current.startswith('-') or current.startswith('--'): - 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) - - subcommands += [i.get_opt_string() for i in opts - if i.help != optparse.SUPPRESS_HELP] - - print(' '.join([x for x in subcommands if x.startswith(current)])) - sys.exit(1) - - -def create_main_parser(): - 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.dirname(os.path.dirname(os.path.abspath(__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) - - parser.main = True # so the help formatter knows - - # 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 parseopts(args): - 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) - 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 - - -def check_isolated(args): - isolated = False - - if "--isolated" in args: - isolated = True - - return isolated - - -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 = parseopts(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 pip9.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=check_isolated(cmd_args)) - return command.main(cmd_args) - - -# ########################################################### -# # Writing freeze files - -class FrozenRequirement(object): - - def __init__(self, name, req, editable, comments=()): - self.name = name - self.req = req - self.editable = editable - self.comments = comments - - _rev_re = re.compile(r'-r(\d+)$') - _date_re = re.compile(r'-(20\d\d\d\d\d\d)$') - - @classmethod - def from_dist(cls, dist, dependency_links): - location = os.path.normcase(os.path.abspath(dist.location)) - comments = [] - from pip9.vcs import vcs, get_src_requirement - if dist_is_editable(dist) and vcs.get_backend_name(location): - editable = True - try: - req = get_src_requirement(dist, location) - except InstallationError as exc: - logger.warning( - "Error when trying to get requirement for VCS system %s, " - "falling back to uneditable format", exc - ) - req = None - if req is None: - logger.warning( - 'Could not determine repository location of %s', location - ) - comments.append( - '## !! Could not determine repository location' - ) - req = dist.as_requirement() - editable = False - else: - editable = False - req = dist.as_requirement() - specs = req.specs - assert len(specs) == 1 and specs[0][0] in ["==", "==="], \ - 'Expected 1 spec with == or ===; specs = %r; dist = %r' % \ - (specs, dist) - version = specs[0][1] - ver_match = cls._rev_re.search(version) - date_match = cls._date_re.search(version) - if ver_match or date_match: - svn_backend = vcs.get_backend('svn') - if svn_backend: - svn_location = svn_backend().get_location( - dist, - dependency_links, - ) - if not svn_location: - logger.warning( - 'Warning: cannot find svn location for %s', req) - comments.append( - '## FIXME: could not find svn URL in dependency_links ' - 'for this package:' - ) - else: - comments.append( - '# Installing as editable to satisfy requirement %s:' % - req - ) - if ver_match: - rev = ver_match.group(1) - else: - rev = '{%s}' % date_match.group(1) - editable = True - req = '%s@%s#egg=%s' % ( - svn_location, - rev, - cls.egg_name(dist) - ) - return cls(dist.project_name, req, editable, comments) - - @staticmethod - def egg_name(dist): - name = dist.egg_name() - match = re.search(r'-py\d\.\d$', name) - if match: - name = name[:match.start()] - return name - - def __str__(self): - req = self.req - if self.editable: - req = '-e %s' % req - return '\n'.join(list(self.comments) + [str(req)]) + '\n' - - -if __name__ == '__main__': - sys.exit(main()) +__version__ = "10.0.1" diff --git a/pipenv/patched/notpip/__main__.py b/pipenv/patched/notpip/__main__.py index 9849a65c..28cfefb3 100644 --- a/pipenv/patched/notpip/__main__.py +++ b/pipenv/patched/notpip/__main__.py @@ -9,11 +9,11 @@ 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 pip9 + # Add that to sys.path so we can import notpip path = os.path.dirname(os.path.dirname(__file__)) sys.path.insert(0, path) -import pip9 # noqa +from notpip._internal import main as _main # noqa if __name__ == '__main__': - sys.exit(pip9.main()) + sys.exit(_main()) diff --git a/pipenv/patched/notpip/_internal/__init__.py b/pipenv/patched/notpip/_internal/__init__.py new file mode 100644 index 00000000..753f8879 --- /dev/null +++ b/pipenv/patched/notpip/_internal/__init__.py @@ -0,0 +1,246 @@ +#!/usr/bin/env python +from __future__ import absolute_import + +import locale +import logging +import os +import optparse +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 notpip._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 notpip._vendor.urllib3.contrib import securetransport + except (ImportError, OSError): + pass + else: + securetransport.inject_into_urllib3() + +from notpip import __version__ +from notpip._internal import cmdoptions +from notpip._internal.exceptions import CommandError, PipError +from notpip._internal.utils.misc import get_installed_distributions, get_prog +from notpip._internal.utils import deprecation +from notpip._internal.vcs import git, mercurial, subversion, bazaar # noqa +from notpip._internal.baseparser import ( + ConfigOptionParser, UpdatingDefaultsHelpFormatter, +) +from notpip._internal.commands import get_summaries, get_similar_commands +from notpip._internal.commands import commands_dict +from notpip._vendor.urllib3.exceptions import InsecureRequestWarning + +logger = logging.getLogger(__name__) + +# Hide the InsecureRequestWarning from urllib3 +warnings.filterwarnings("ignore", category=InsecureRequestWarning) + + +def autocomplete(): + """Command and option completion for the main option parser (and options) + and its subcommands (and options). + + Enable by sourcing one of the completion shell scripts (bash, zsh or fish). + """ + # 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)] + 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 + if current.startswith('-') or current.startswith('--'): + 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) + + for opt in opts: + if opt.help != optparse.SUPPRESS_HELP: + subcommands += opt._long_opts + opt._short_opts + + print(' '.join([x for x in subcommands if x.startswith(current)])) + sys.exit(1) + + +def create_main_parser(): + 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.dirname(os.path.dirname(os.path.abspath(__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) + + parser.main = True # so the help formatter knows + + # 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 parseopts(args): + 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) + 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 + + +def check_isolated(args): + isolated = False + + if "--isolated" in args: + isolated = True + + return isolated + + +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 = parseopts(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=check_isolated(cmd_args)) + return command.main(cmd_args) diff --git a/pipenv/patched/notpip/basecommand.py b/pipenv/patched/notpip/_internal/basecommand.py similarity index 61% rename from pipenv/patched/notpip/basecommand.py rename to pipenv/patched/notpip/_internal/basecommand.py index 8e11f179..e81ea9db 100644 --- a/pipenv/patched/notpip/basecommand.py +++ b/pipenv/patched/notpip/_internal/basecommand.py @@ -2,40 +2,49 @@ from __future__ import absolute_import import logging +import logging.config +import optparse import os import sys -import optparse import warnings -from pip9 import cmdoptions -from pip9.index import PackageFinder -from pip9.locations import running_under_virtualenv -from pip9.download import pip9Session -from pip9.exceptions import (BadCommand, InstallationError, UninstallationError, - CommandError, PreviousBuildDirError) - -from pip9.compat import logging_dictConfig -from pip9.baseparser import ConfigOptionParser, UpdatingDefaultsHelpFormatter -from pip9.req import InstallRequirement, parse_requirements -from pip9.status_codes import ( - SUCCESS, ERROR, UNKNOWN_ERROR, VIRTUALENV_NOT_FOUND, - PREVIOUS_BUILD_DIR_ERROR, +from notpip._internal import cmdoptions +from notpip._internal.baseparser import ( + ConfigOptionParser, UpdatingDefaultsHelpFormatter, ) -from pip9.utils import deprecation, get_prog, normalize_path -from pip9.utils.logging import IndentingFormatter -from pip9.utils.outdated import pip9_version_check +from notpip._internal.compat import WINDOWS +from notpip._internal.download import PipSession +from notpip._internal.exceptions import ( + BadCommand, CommandError, InstallationError, PreviousBuildDirError, + UninstallationError, +) +from notpip._internal.index import PackageFinder +from notpip._internal.locations import running_under_virtualenv +from notpip._internal.req.req_file import parse_requirements +from notpip._internal.req.req_install import InstallRequirement +from notpip._internal.status_codes import ( + ERROR, PREVIOUS_BUILD_DIR_ERROR, SUCCESS, UNKNOWN_ERROR, + VIRTUALENV_NOT_FOUND, +) +from notpip._internal.utils import deprecation +from notpip._internal.utils.logging import IndentingFormatter +from notpip._internal.utils.misc import get_prog, normalize_path +from notpip._internal.utils.outdated import pip_version_check +from notpip._internal.utils.typing import MYPY_CHECK_RUNNING +if MYPY_CHECK_RUNNING: + from typing import Optional __all__ = ['Command'] - logger = logging.getLogger(__name__) class Command(object): - name = None - usage = None - hidden = False + name = None # type: Optional[str] + usage = None # type: Optional[str] + hidden = False # type: bool + ignore_require_venv = False # type: bool log_streams = ("ext://sys.stdout", "ext://sys.stderr") def __init__(self, isolated=False): @@ -105,15 +114,17 @@ class Command(object): def main(self, args): options, args = self.parse_args(args) - if options.quiet: - if options.quiet == 1: - level = "WARNING" - if options.quiet == 2: - level = "ERROR" - else: - level = "CRITICAL" - elif options.verbose: + # Set verbosity so that it can be used elsewhere. + self.verbosity = options.verbose - options.quiet + + if self.verbosity >= 1: level = "DEBUG" + elif self.verbosity == -1: + level = "WARNING" + elif self.verbosity == -2: + level = "ERROR" + elif self.verbosity <= -3: + level = "CRITICAL" else: level = "INFO" @@ -123,12 +134,15 @@ class Command(object): if options.log: root_level = "DEBUG" - logging_dictConfig({ + logger_class = "pip._internal.utils.logging.ColorizedStreamHandler" + handler_class = "pip._internal.utils.logging.BetterRotatingFileHandler" + + logging.config.dictConfig({ "version": 1, "disable_existing_loggers": False, "filters": { "exclude_warnings": { - "()": "pip9.utils.logging.MaxLevelFilter", + "()": "pip._internal.utils.logging.MaxLevelFilter", "level": logging.WARNING, }, }, @@ -141,20 +155,22 @@ class Command(object): "handlers": { "console": { "level": level, - "class": "pip9.utils.logging.ColorizedStreamHandler", + "class": logger_class, + "no_color": options.no_color, "stream": self.log_streams[0], "filters": ["exclude_warnings"], "formatter": "indent", }, "console_errors": { "level": "WARNING", - "class": "pip9.utils.logging.ColorizedStreamHandler", + "class": logger_class, + "no_color": options.no_color, "stream": self.log_streams[1], "formatter": "indent", }, "user_log": { "level": "DEBUG", - "class": "pip9.utils.logging.BetterRotatingFileHandler", + "class": handler_class, "filename": options.log or "/dev/null", "delay": True, "formatter": "indent", @@ -169,29 +185,24 @@ class Command(object): ])), }, # Disable any logging besides WARNING unless we have DEBUG level - # logging enabled. These use both pip9._vendor and the bare names + # logging enabled. These use both pip._vendor and the bare names # for the case where someone unbundles our libraries. - "loggers": dict( - ( - name, - { - "level": ( - "WARNING" - if level in ["INFO", "ERROR"] - else "DEBUG" - ), - }, - ) - for name in ["pip9._vendor", "distlib", "requests", "urllib3"] - ), + "loggers": { + name: { + "level": ( + "WARNING" if level in ["INFO", "ERROR"] else "DEBUG" + ) + } for name in [ + "pip._vendor", "distlib", "requests", "urllib3" + ] + }, }) - if sys.version_info[:2] == (2, 6): + if sys.version_info[:2] == (3, 3): warnings.warn( - "Python 2.6 is no longer supported by the Python core team, " - "please upgrade your Python. A future version of pip will " - "drop support for Python 2.6", - deprecation.Python26DeprecationWarning + "Python 3.3 supported has been deprecated and support for it " + "will be dropped in the future. Please upgrade your Python.", + deprecation.RemovedInPip11Warning, ) # TODO: try to get these passing down from the command? @@ -203,7 +214,7 @@ class Command(object): if options.exists_action: os.environ['PIP_EXISTS_ACTION'] = ' '.join(options.exists_action) - if options.require_venv: + 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( @@ -211,6 +222,8 @@ class Command(object): ) sys.exit(VIRTUALENV_NOT_FOUND) + original_root_handlers = set(logging.root.handlers) + try: status = self.run(options, args) # FIXME: all commands should return an exit status @@ -249,7 +262,11 @@ class Command(object): options, retries=0, timeout=min(5, options.timeout)) as session: - pip_version_check(session) + pip_version_check(session, options) + # Avoid leaking loggers + for handler in set(logging.root.handlers) - original_root_handlers: + # this method benefit from the Logger class internal lock + logging.root.removeHandler(handler) return SUCCESS @@ -262,54 +279,73 @@ class RequirementCommand(Command): """ 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 in parse_requirements( + for req_to_add in parse_requirements( filename, constraint=True, finder=finder, options=options, session=session, wheel_cache=wheel_cache): - requirement_set.add_requirement(req) + req_to_add.is_direct = True + requirement_set.add_requirement(req_to_add) for req in args: - requirement_set.add_requirement( - InstallRequirement.from_line( - req, None, isolated=options.isolated_mode, - wheel_cache=wheel_cache - ) + req_to_add = InstallRequirement.from_line( + req, None, isolated=options.isolated_mode, + wheel_cache=wheel_cache ) + req_to_add.is_direct = True + requirement_set.add_requirement(req_to_add) for req in options.editables: - requirement_set.add_requirement( - InstallRequirement.from_editable( - req, - default_vcs=options.default_vcs, - isolated=options.isolated_mode, - wheel_cache=wheel_cache - ) + req_to_add = InstallRequirement.from_editable( + req, + isolated=options.isolated_mode, + wheel_cache=wheel_cache ) + req_to_add.is_direct = True + requirement_set.add_requirement(req_to_add) - found_req_in_file = False for filename in options.requirements: - for req in parse_requirements( + for req_to_add in parse_requirements( filename, finder=finder, options=options, session=session, wheel_cache=wheel_cache): - found_req_in_file = True - requirement_set.add_requirement(req) + 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 found_req_in_file): + if not (args or options.editables or options.requirements): opts = {'name': name} if options.find_links: - msg = ('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))) + 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: - msg = ('You must give at least one requirement ' - 'to %(name)s (see "pip help %(name)s")' % opts) - logger.warning(msg) + raise CommandError( + 'You must give at least one requirement to %(name)s ' + '(see "pip help %(name)s")' % opts) + + # On Windows, any operation modifying pip should be run as: + # python -m pip ... + # See https://github.com/pypa/pip/issues/1299 for more discussion + should_show_use_python_msg = ( + WINDOWS and + requirement_set.has_requirement("pip") and + os.path.basename(sys.argv[0]).startswith("pip") + ) + 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)) + ) def _build_package_finder(self, options, session, platform=None, python_versions=None, diff --git a/pipenv/patched/notpip/baseparser.py b/pipenv/patched/notpip/_internal/baseparser.py similarity index 67% rename from pipenv/patched/notpip/baseparser.py rename to pipenv/patched/notpip/_internal/baseparser.py index dc28d4cf..888f837a 100644 --- a/pipenv/patched/notpip/baseparser.py +++ b/pipenv/patched/notpip/_internal/baseparser.py @@ -1,23 +1,18 @@ """Base option parser setup""" from __future__ import absolute_import -import sys +import logging import optparse -import os -import re +import sys import textwrap from distutils.util import strtobool -from pip9._vendor.six import string_types -from pip9._vendor.six.moves import configparser -from pip9.locations import ( - legacy_config_file, config_basename, running_under_virtualenv, - site_config_files -) -from pip9.utils import appdirs, get_terminal_size +from notpip._vendor.six import string_types +from notpip._internal.compat import get_terminal_size +from notpip._internal.configuration import Configuration, ConfigurationError -_environ_prefix_re = re.compile(r"^PIP_", re.I) +logger = logging.getLogger(__name__) class PrettyHelpFormatter(optparse.IndentedHelpFormatter): @@ -137,58 +132,15 @@ class ConfigOptionParser(CustomOptionParser): """Custom option parser which updates its defaults by checking the configuration files and environmental variables""" - isolated = False - def __init__(self, *args, **kwargs): - self.config = configparser.RawConfigParser() self.name = kwargs.pop('name') - self.isolated = kwargs.pop("isolated", False) - self.files = self.get_config_files() - if self.files: - self.config.read(self.files) + + isolated = kwargs.pop("isolated", False) + self.config = Configuration(isolated) + assert self.name optparse.OptionParser.__init__(self, *args, **kwargs) - def get_config_files(self): - # the files returned by this method will be parsed in order with the - # first files listed being overridden by later files in standard - # ConfigParser fashion - config_file = os.environ.get('PIP_CONFIG_FILE', False) - if config_file == os.devnull: - return [] - - # at the base we have any site-wide configuration - files = list(site_config_files) - - # per-user configuration next - if not self.isolated: - if config_file and os.path.exists(config_file): - files.append(config_file) - else: - # This is the legacy config file, we consider it to be a lower - # priority than the new file location. - files.append(legacy_config_file) - - # This is the new config file, we consider it to be a higher - # priority than the legacy file. - files.append( - os.path.join( - appdirs.user_config_dir("pip"), - config_basename, - ) - ) - - # finally virtualenv configuration first trumping others - if running_under_virtualenv(): - venv_config_file = os.path.join( - sys.prefix, - config_basename, - ) - if os.path.exists(venv_config_file): - files.append(venv_config_file) - - return files - def check_default(self, option, key, val): try: return option.check_value(key, val) @@ -196,30 +148,43 @@ class ConfigOptionParser(CustomOptionParser): 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).""" - # Then go and look for the other sources of configuration: - config = {} - # 1. config files - for section in ('global', self.name): - config.update( - self.normalize_keys(self.get_config_section(section)) - ) - # 2. environmental variables - if not self.isolated: - config.update(self.normalize_keys(self.get_environ_vars())) + # Accumulate complex default state. self.values = optparse.Values(self.defaults) late_eval = set() # Then set the options with those values - for key, val in config.items(): - # ignore empty values - if not val: - continue + for key, val in self._get_ordered_configuration_items(): + # '--' because configuration supports only long names + option = self.get_option('--' + key) - 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. @@ -249,30 +214,6 @@ class ConfigOptionParser(CustomOptionParser): self.values = None return defaults - def normalize_keys(self, items): - """Return a config dictionary with normalized keys regardless of - whether the keys were specified in environment variables or in config - files""" - normalized = {} - for key, val in items: - key = key.replace('_', '-') - if not key.startswith('--'): - key = '--%s' % key # only prefer long opts - normalized[key] = val - return normalized - - def get_config_section(self, name): - """Get a section of a configuration""" - if self.config.has_section(name): - return self.config.items(name) - return [] - - def get_environ_vars(self): - """Returns a generator with all environmental vars with prefix PIP_""" - for key, val in os.environ.items(): - if _environ_prefix_re.search(key): - yield (_environ_prefix_re.sub("", key).lower(), val) - def get_default_values(self): """Overriding to make updating the defaults after instantiation of the option parser possible, _update_defaults() does the dirty work.""" @@ -280,6 +221,12 @@ class ConfigOptionParser(CustomOptionParser): # 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(2, err.args[0]) + defaults = self._update_defaults(self.defaults.copy()) # ours for option in self._get_all_options(): default = defaults.get(option.dest) diff --git a/pipenv/patched/notpip/_internal/build_env.py b/pipenv/patched/notpip/_internal/build_env.py new file mode 100644 index 00000000..ea2b5a08 --- /dev/null +++ b/pipenv/patched/notpip/_internal/build_env.py @@ -0,0 +1,92 @@ +"""Build Environment used for isolation during sdist building +""" + +import os +from distutils.sysconfig import get_python_lib +from sysconfig import get_paths + +from notpip._internal.utils.temp_dir import TempDirectory + + +class BuildEnvironment(object): + """Creates and manages an isolated environment to install build deps + """ + + def __init__(self, no_clean): + self._temp_dir = TempDirectory(kind="build-env") + self._no_clean = no_clean + + @property + def path(self): + return self._temp_dir.path + + def __enter__(self): + self._temp_dir.create() + + self.save_path = os.environ.get('PATH', None) + self.save_pythonpath = os.environ.get('PYTHONPATH', None) + self.save_nousersite = os.environ.get('PYTHONNOUSERSITE', 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 + + # Note: prefer distutils' sysconfig to get the + # library paths so PyPy is correctly supported. + purelib = get_python_lib(plat_specific=0, prefix=self.path) + platlib = get_python_lib(plat_specific=1, prefix=self.path) + if purelib == platlib: + lib_dirs = purelib + else: + lib_dirs = purelib + os.pathsep + platlib + if self.save_pythonpath: + os.environ['PYTHONPATH'] = lib_dirs + os.pathsep + \ + self.save_pythonpath + else: + os.environ['PYTHONPATH'] = lib_dirs + + os.environ['PYTHONNOUSERSITE'] = '1' + + return self.path + + def __exit__(self, exc_type, exc_val, exc_tb): + if not self._no_clean: + self._temp_dir.cleanup() + + def restore_var(varname, old_value): + if old_value is None: + os.environ.pop(varname, None) + else: + os.environ[varname] = old_value + + restore_var('PATH', self.save_path) + restore_var('PYTHONPATH', self.save_pythonpath) + restore_var('PYTHONNOUSERSITE', self.save_nousersite) + + def cleanup(self): + self._temp_dir.cleanup() + + +class NoOpBuildEnvironment(BuildEnvironment): + """A no-op drop-in replacement for BuildEnvironment + """ + + def __init__(self, no_clean): + pass + + def __enter__(self): + pass + + def __exit__(self, exc_type, exc_val, exc_tb): + pass + + def cleanup(self): + pass diff --git a/pipenv/patched/notpip/_internal/cache.py b/pipenv/patched/notpip/_internal/cache.py new file mode 100644 index 00000000..2d5873a3 --- /dev/null +++ b/pipenv/patched/notpip/_internal/cache.py @@ -0,0 +1,202 @@ +"""Cache Management +""" + +import errno +import hashlib +import logging +import os + +from notpip._vendor.packaging.utils import canonicalize_name + +from notpip._internal import index +from notpip._internal.compat import expanduser +from notpip._internal.download import path_to_url +from notpip._internal.utils.temp_dir import TempDirectory +from notpip._internal.wheel import InvalidWheelFilename, Wheel + +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: A pip.index.FormatControl object 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): + 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): + """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): + 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 = index.fmt_ctl_formats( + self.format_control, 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): + """Return a directory to store cached items in for link. + """ + raise NotImplementedError() + + def get(self, link, package_name): + """Returns a link to a cached item if it exists, otherwise returns the + passed link. + """ + raise NotImplementedError() + + def _link_for_candidate(self, link, candidate): + root = self.get_path_for_link(link) + path = os.path.join(root, candidate) + + return index.Link(path_to_url(path)) + + def cleanup(self): + pass + + +class SimpleWheelCache(Cache): + """A cache of wheels for future installs. + """ + + def __init__(self, cache_dir, format_control): + super(SimpleWheelCache, self).__init__( + cache_dir, format_control, {"binary"} + ) + + def get_path_for_link(self, link): + """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): + 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): + 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): + 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): + 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): + return self._wheel_cache.get_path_for_link(link) + + def get_ephem_path_for_link(self, link): + return self._ephem_cache.get_path_for_link(link) + + def get(self, link, package_name): + 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): + self._wheel_cache.cleanup() + self._ephem_cache.cleanup() diff --git a/pipenv/patched/notpip/cmdoptions.py b/pipenv/patched/notpip/_internal/cmdoptions.py similarity index 77% rename from pipenv/patched/notpip/cmdoptions.py rename to pipenv/patched/notpip/_internal/cmdoptions.py index fd1864e8..3fd940fe 100644 --- a/pipenv/patched/notpip/cmdoptions.py +++ b/pipenv/patched/notpip/_internal/cmdoptions.py @@ -9,16 +9,21 @@ pass on state. To be consistent, all options will follow this design. """ from __future__ import absolute_import -from functools import partial -from optparse import OptionGroup, SUPPRESS_HELP, Option import warnings +from functools import partial +from optparse import SUPPRESS_HELP, Option, OptionGroup -from pip9.index import ( +from notpip._internal.index import ( FormatControl, fmt_ctl_handle_mutual_exclude, fmt_ctl_no_binary, - fmt_ctl_no_use_wheel) -from pip9.models import PyPI -from pip9.locations import USER_CACHE_DIR, src_prefix -from pip9.utils.hashes import STRONG_HASHES +) +from notpip._internal.locations import USER_CACHE_DIR, src_prefix +from notpip._internal.models import PyPI +from notpip._internal.utils.hashes import STRONG_HASHES +from notpip._internal.utils.typing import MYPY_CHECK_RUNNING +from notpip._internal.utils.ui import BAR_TYPES + +if MYPY_CHECK_RUNNING: + from typing import Any def make_option_group(group, parser): @@ -33,12 +38,6 @@ def make_option_group(group, parser): return option_group -def resolve_wheel_no_use_binary(options): - if not options.use_wheel: - control = options.format_control - fmt_ctl_no_use_wheel(control) - - def check_install_build_global(options, check_options=None): """Disable wheels if per-setup.py call options are set. @@ -57,7 +56,8 @@ def check_install_build_global(options, check_options=None): fmt_ctl_no_binary(control) warnings.warn( 'Disabling all use of wheels due to the use of --build-options ' - '/ --global-options / --install-options.', stacklevel=2) + '/ --global-options / --install-options.', stacklevel=2, + ) ########### @@ -69,7 +69,8 @@ help_ = partial( '-h', '--help', dest='help', action='help', - help='Show help.') + help='Show help.', +) # type: Any isolated_mode = partial( Option, @@ -90,7 +91,8 @@ require_virtualenv = partial( dest='require_venv', action='store_true', default=False, - help=SUPPRESS_HELP) + help=SUPPRESS_HELP +) # type: Any verbose = partial( Option, @@ -101,12 +103,22 @@ verbose = partial( help='Give more output. Option is additive, and can be used up to 3 times.' ) +no_color = partial( + Option, + '--no-color', + dest='no_color', + action='store_true', + default=False, + help="Suppress colored output", +) + version = partial( Option, '-V', '--version', dest='version', action='store_true', - help='Show version and exit.') + help='Show version and exit.', +) # type: Any quiet = partial( Option, @@ -114,10 +126,25 @@ quiet = partial( 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).') -) + help=( + 'Give less output. Option is additive, and can be used up to 3' + ' times (corresponding to WARNING, ERROR, and CRITICAL logging' + ' levels).' + ), +) # type: Any + +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: Any log = partial( Option, @@ -125,7 +152,7 @@ log = partial( dest="log", metavar="path", help="Path to a verbose appending log." -) +) # type: Any no_input = partial( Option, @@ -134,7 +161,8 @@ no_input = partial( dest='no_input', action='store_true', default=False, - help=SUPPRESS_HELP) + help=SUPPRESS_HELP +) # type: Any proxy = partial( Option, @@ -142,7 +170,8 @@ proxy = partial( dest='proxy', type='str', default='', - help="Specify a proxy in the form [user:passwd@]proxy.server:port.") + help="Specify a proxy in the form [user:passwd@]proxy.server:port." +) # type: Any retries = partial( Option, @@ -151,7 +180,8 @@ retries = partial( type='int', default=5, help="Maximum number of retries each connection should attempt " - "(default %default times).") + "(default %default times).", +) # type: Any timeout = partial( Option, @@ -160,16 +190,8 @@ timeout = partial( dest='timeout', type='float', default=15, - help='Set the socket timeout (default %default seconds).') - -default_vcs = partial( - Option, - # The default version control system for editables, e.g. 'svn' - '--default-vcs', - dest='default_vcs', - type='str', - default='', - help=SUPPRESS_HELP) + help='Set the socket timeout (default %default seconds).', +) # type: Any skip_requirements_regex = partial( Option, @@ -178,7 +200,8 @@ skip_requirements_regex = partial( dest='skip_requirements_regex', type='str', default='', - help=SUPPRESS_HELP) + help=SUPPRESS_HELP, +) # type: Any def exists_action(): @@ -192,7 +215,8 @@ def exists_action(): action='append', metavar='action', help="Default action when a path already exists: " - "(s)witch, (i)gnore, (w)ipe, (b)ackup, (a)bort.") + "(s)witch, (i)gnore, (w)ipe, (b)ackup, (a)bort).", + ) cert = partial( @@ -201,7 +225,8 @@ cert = partial( dest='cert', type='str', metavar='path', - help="Path to alternate CA bundle.") + help="Path to alternate CA bundle.", +) # type: Any client_cert = partial( Option, @@ -211,7 +236,8 @@ client_cert = partial( default=None, metavar='path', help="Path to SSL client certificate, a single file containing the " - "private key and the certificate in PEM format.") + "private key and the certificate in PEM format.", +) # type: Any index_url = partial( Option, @@ -222,7 +248,8 @@ index_url = partial( 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.") + "in the same format.", +) # type: Any def extra_index_url(): @@ -234,7 +261,7 @@ def extra_index_url(): default=[], help="Extra URLs of package indexes to use in addition to " "--index-url. Should follow the same rules as " - "--index-url." + "--index-url.", ) @@ -244,7 +271,8 @@ no_index = partial( dest='no_index', action='store_true', default=False, - help='Ignore package index (only looking at --find-links URLs instead).') + help='Ignore package index (only looking at --find-links URLs instead).', +) # type: Any def find_links(): @@ -256,30 +284,10 @@ def find_links(): 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 allow_external(): - return Option( - "--allow-external", - dest="allow_external", - action="append", - default=[], - metavar="PACKAGE", - help=SUPPRESS_HELP, + "then look for archives in the directory listing.", ) -allow_all_external = partial( - Option, - "--allow-all-external", - dest="allow_all_external", - action="store_true", - default=False, - help=SUPPRESS_HELP, -) - - def trusted_host(): return Option( "--trusted-host", @@ -292,38 +300,6 @@ def trusted_host(): ) -# Remove after 7.0 -no_allow_external = partial( - Option, - "--no-allow-external", - dest="allow_all_external", - action="store_false", - default=False, - help=SUPPRESS_HELP, -) - - -# Remove --allow-insecure after 7.0 -def allow_unsafe(): - return Option( - "--allow-unverified", "--allow-insecure", - dest="allow_unverified", - action="append", - default=[], - metavar="PACKAGE", - help=SUPPRESS_HELP, - ) - -# Remove after 7.0 -no_allow_unsafe = partial( - Option, - "--no-allow-insecure", - dest="allow_all_insecure", - action="store_false", - default=False, - help=SUPPRESS_HELP -) - # Remove after 1.5 process_dependency_links = partial( Option, @@ -332,7 +308,7 @@ process_dependency_links = partial( action="store_true", default=False, help="Enable the processing of dependency links.", -) +) # type: Any def constraints(): @@ -343,7 +319,8 @@ def constraints(): default=[], metavar='file', help='Constrain versions using the given constraints file. ' - 'This option can be used multiple times.') + 'This option can be used multiple times.' + ) def requirements(): @@ -354,7 +331,8 @@ def requirements(): default=[], metavar='file', help='Install from the given requirements file. ' - 'This option can be used multiple times.') + 'This option can be used multiple times.' + ) def editable(): @@ -368,6 +346,7 @@ def editable(): '"develop mode") from a local project path or a VCS url.'), ) + src = partial( Option, '--src', '--source', '--source-dir', '--source-directory', @@ -377,28 +356,7 @@ src = partial( help='Directory to check out editable projects into. ' 'The default in a virtualenv is "/src". ' 'The default for global installs is "/src".' -) - -# XXX: deprecated, remove in 9.0 -use_wheel = partial( - Option, - '--use-wheel', - dest='use_wheel', - action='store_true', - default=True, - help=SUPPRESS_HELP, -) - -# XXX: deprecated, remove in 9.0 -no_use_wheel = partial( - Option, - '--no-use-wheel', - dest='use_wheel', - action='store_false', - default=True, - help=('Do not Find and prefer wheel archives when searching indexes and ' - 'find-links locations. DEPRECATED in favour of --no-binary.'), -) +) # type: Any def _get_format_control(values, option): @@ -409,13 +367,15 @@ def _get_format_control(values, option): def _handle_no_binary(option, opt_str, value, parser): existing = getattr(parser.values, option.dest) fmt_ctl_handle_mutual_exclude( - value, existing.no_binary, existing.only_binary) + value, existing.no_binary, existing.only_binary, + ) def _handle_only_binary(option, opt_str, value, parser): existing = getattr(parser.values, option.dest) fmt_ctl_handle_mutual_exclude( - value, existing.only_binary, existing.no_binary) + value, existing.only_binary, existing.no_binary, + ) def no_binary(): @@ -428,7 +388,8 @@ def no_binary(): "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.") + "this option is used on them.", + ) def only_binary(): @@ -441,7 +402,8 @@ def only_binary(): "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.") + "used on them.", + ) cache_dir = partial( @@ -467,22 +429,39 @@ no_deps = partial( dest='ignore_dependencies', action='store_true', default=False, - help="Don't install package dependencies.") + help="Don't install package dependencies.", +) # type: Any build_dir = partial( Option, '-b', '--build', '--build-dir', '--build-directory', dest='build_dir', metavar='dir', - help='Directory to unpack packages into and build in.' -) + 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: Any ignore_requires_python = partial( Option, '--ignore-requires-python', dest='ignore_requires_python', action='store_true', - help='Ignore the Requires-Python information.') + help='Ignore the Requires-Python information.' +) # type: Any + +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: Any install_options = partial( Option, @@ -494,7 +473,8 @@ install_options = partial( "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.") + "directory path, be sure to use absolute path.", +) # type: Any global_options = partial( Option, @@ -503,14 +483,16 @@ global_options = partial( action='append', metavar='options', help="Extra global options to be supplied to the setup.py " - "call before the install command.") + "call before the install command.", +) # type: Any no_clean = partial( Option, '--no-clean', action='store_true', default=False, - help="Don't clean up build directories.") + help="Don't clean up build directories)." +) # type: Any pre = partial( Option, @@ -518,7 +500,8 @@ pre = partial( action='store_true', default=False, help="Include pre-release and development versions. By default, " - "pip only finds stable versions.") + "pip only finds stable versions.", +) # type: Any disable_pip_version_check = partial( Option, @@ -527,7 +510,9 @@ disable_pip_version_check = partial( 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.") + "of pip is available for download. Implied with --no-index.", +) # type: Any + # Deprecated, Remove later always_unzip = partial( @@ -536,7 +521,7 @@ always_unzip = partial( dest='always_unzip', action='store_true', help=SUPPRESS_HELP, -) +) # type: Any def _merge_hash(option, opt_str, value, parser): @@ -566,7 +551,8 @@ hash = partial( callback=_merge_hash, type='string', help="Verify that the package's archive matches this " - 'hash before installing. Example: --hash=sha256:abcdef...') + 'hash before installing. Example: --hash=sha256:abcdef...', +) # type: Any require_hashes = partial( @@ -577,7 +563,8 @@ require_hashes = partial( 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.') + 'requirements file has a --hash option.', +) # type: Any ########## @@ -598,7 +585,6 @@ general_group = { proxy, retries, timeout, - default_vcs, skip_requirements_regex, exists_action, trusted_host, @@ -607,10 +593,11 @@ general_group = { cache_dir, no_cache, disable_pip_version_check, + no_color, ] } -non_deprecated_index_group = { +index_group = { 'name': 'Package Index Options', 'options': [ index_url, @@ -620,14 +607,3 @@ non_deprecated_index_group = { process_dependency_links, ] } - -index_group = { - 'name': 'Package Index Options (including deprecated options)', - 'options': non_deprecated_index_group['options'] + [ - allow_external, - allow_all_external, - no_allow_external, - allow_unsafe, - no_allow_unsafe, - ] -} diff --git a/pipenv/patched/notpip/commands/__init__.py b/pipenv/patched/notpip/_internal/commands/__init__.py similarity index 53% rename from pipenv/patched/notpip/commands/__init__.py rename to pipenv/patched/notpip/_internal/commands/__init__.py index 646c8a15..580f87ee 100644 --- a/pipenv/patched/notpip/commands/__init__.py +++ b/pipenv/patched/notpip/_internal/commands/__init__.py @@ -3,35 +3,25 @@ Package containing all pip commands """ from __future__ import absolute_import -from pip9.commands.completion import CompletionCommand -from pip9.commands.download import DownloadCommand -from pip9.commands.freeze import FreezeCommand -from pip9.commands.hash import HashCommand -from pip9.commands.help import HelpCommand -from pip9.commands.list import ListCommand -from pip9.commands.check import CheckCommand -from pip9.commands.search import SearchCommand -from pip9.commands.show import ShowCommand -from pip9.commands.install import InstallCommand -from pip9.commands.uninstall import UninstallCommand -from pip9.commands.wheel import WheelCommand +from notpip._internal.commands.completion import CompletionCommand +from notpip._internal.commands.configuration import ConfigurationCommand +from notpip._internal.commands.download import DownloadCommand +from notpip._internal.commands.freeze import FreezeCommand +from notpip._internal.commands.hash import HashCommand +from notpip._internal.commands.help import HelpCommand +from notpip._internal.commands.list import ListCommand +from notpip._internal.commands.check import CheckCommand +from notpip._internal.commands.search import SearchCommand +from notpip._internal.commands.show import ShowCommand +from notpip._internal.commands.install import InstallCommand +from notpip._internal.commands.uninstall import UninstallCommand +from notpip._internal.commands.wheel import WheelCommand +from notpip._internal.utils.typing import MYPY_CHECK_RUNNING -commands_dict = { - CompletionCommand.name: CompletionCommand, - FreezeCommand.name: FreezeCommand, - HashCommand.name: HashCommand, - HelpCommand.name: HelpCommand, - SearchCommand.name: SearchCommand, - ShowCommand.name: ShowCommand, - InstallCommand.name: InstallCommand, - UninstallCommand.name: UninstallCommand, - DownloadCommand.name: DownloadCommand, - ListCommand.name: ListCommand, - CheckCommand.name: CheckCommand, - WheelCommand.name: WheelCommand, -} - +if MYPY_CHECK_RUNNING: + from typing import List, Type + from notpip._internal.basecommand import Command commands_order = [ InstallCommand, @@ -41,12 +31,15 @@ commands_order = [ 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): diff --git a/pipenv/patched/notpip/_internal/commands/check.py b/pipenv/patched/notpip/_internal/commands/check.py new file mode 100644 index 00000000..278f6ba6 --- /dev/null +++ b/pipenv/patched/notpip/_internal/commands/check.py @@ -0,0 +1,42 @@ +import logging + +from notpip._internal.basecommand import Command +from notpip._internal.operations.check import ( + check_package_set, create_package_set_from_installed, +) +from notpip._internal.utils.misc import get_installed_distributions + +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 = 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: + return 1 + else: + logger.info("No broken requirements found.") diff --git a/pipenv/patched/notpip/commands/completion.py b/pipenv/patched/notpip/_internal/commands/completion.py similarity index 54% rename from pipenv/patched/notpip/commands/completion.py rename to pipenv/patched/notpip/_internal/commands/completion.py index 4aaec4a9..6e2cb586 100644 --- a/pipenv/patched/notpip/commands/completion.py +++ b/pipenv/patched/notpip/_internal/commands/completion.py @@ -1,7 +1,10 @@ from __future__ import absolute_import import sys -from pip9.basecommand import Command +import textwrap + +from notpip._internal.basecommand import Command +from notpip._internal.utils.misc import get_prog BASE_COMPLETION = """ # pip %(shell)s completion start%(script)s# pip %(shell)s completion end @@ -9,38 +12,44 @@ BASE_COMPLETION = """ COMPLETION_SCRIPTS = { 'bash': """ -_pip_completion() -{ - COMPREPLY=( $( COMP_WORDS="${COMP_WORDS[*]}" \\ - COMP_CWORD=$COMP_CWORD \\ - PIP_AUTO_COMPLETE=1 $1 ) ) + _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 + """, } -complete -o default -F _pip_completion pip -""", '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 pip -""", '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 pip -"""} 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) @@ -73,7 +82,11 @@ class CompletionCommand(Command): shells = COMPLETION_SCRIPTS.keys() shell_options = ['--' + shell for shell in sorted(shells)] if options.shell in shells: - script = COMPLETION_SCRIPTS.get(options.shell, '') + script = textwrap.dedent( + COMPLETION_SCRIPTS.get(options.shell, '') % { + 'prog': get_prog(), + } + ) print(BASE_COMPLETION % {'script': script, 'shell': options.shell}) else: sys.stderr.write( diff --git a/pipenv/patched/notpip/_internal/commands/configuration.py b/pipenv/patched/notpip/_internal/commands/configuration.py new file mode 100644 index 00000000..d76a0212 --- /dev/null +++ b/pipenv/patched/notpip/_internal/commands/configuration.py @@ -0,0 +1,227 @@ +import logging +import os +import subprocess + +from notpip._internal.basecommand import Command +from notpip._internal.configuration import Configuration, kinds +from notpip._internal.exceptions import PipError +from notpip._internal.locations import venv_config_file +from notpip._internal.status_codes import ERROR, SUCCESS +from notpip._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/pipenv/patched/notpip/commands/download.py b/pipenv/patched/notpip/_internal/commands/download.py similarity index 71% rename from pipenv/patched/notpip/commands/download.py rename to pipenv/patched/notpip/_internal/commands/download.py index f7cfe95f..95e69325 100644 --- a/pipenv/patched/notpip/commands/download.py +++ b/pipenv/patched/notpip/_internal/commands/download.py @@ -3,15 +3,16 @@ from __future__ import absolute_import import logging import os -from pip9.exceptions import CommandError -from pip9.index import FormatControl -from pip9.req import RequirementSet -from pip9.basecommand import RequirementCommand -from pip9 import cmdoptions -from pip9.utils import ensure_dir, normalize_path -from pip9.utils.build import BuildDirectory -from pip9.utils.filesystem import check_path_owner - +from notpip._internal import cmdoptions +from notpip._internal.basecommand import RequirementCommand +from notpip._internal.exceptions import CommandError +from notpip._internal.index import FormatControl +from notpip._internal.operations.prepare import RequirementPreparer +from notpip._internal.req import RequirementSet +from notpip._internal.resolve import Resolver +from notpip._internal.utils.filesystem import check_path_owner +from notpip._internal.utils.misc import ensure_dir, normalize_path +from notpip._internal.utils.temp_dir import TempDirectory logger = logging.getLogger(__name__) @@ -33,8 +34,8 @@ class DownloadCommand(RequirementCommand): usage = """ %prog [options] [package-index-options] ... %prog [options] -r [package-index-options] ... - %prog [options] [-e] ... - %prog [options] [-e] ... + %prog [options] ... + %prog [options] ... %prog [options] ...""" summary = 'Download packages.' @@ -45,7 +46,6 @@ class DownloadCommand(RequirementCommand): cmd_opts = self.cmd_opts cmd_opts.add_option(cmdoptions.constraints()) - cmd_opts.add_option(cmdoptions.editable()) cmd_opts.add_option(cmdoptions.requirements()) cmd_opts.add_option(cmdoptions.build_dir()) cmd_opts.add_option(cmdoptions.no_deps()) @@ -56,6 +56,8 @@ class DownloadCommand(RequirementCommand): 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( '-d', '--dest', '--destination-dir', '--destination-directory', @@ -113,7 +115,7 @@ class DownloadCommand(RequirementCommand): ) index_opts = cmdoptions.make_option_group( - cmdoptions.non_deprecated_index_group, + cmdoptions.index_group, self.parser, ) @@ -122,6 +124,9 @@ class DownloadCommand(RequirementCommand): 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] @@ -134,13 +139,18 @@ class DownloadCommand(RequirementCommand): options.abi, options.implementation, ]) - binary_only = FormatControl(set(), set([':all:'])) - if dist_restriction_set and options.format_control != binary_only: + binary_only = FormatControl(set(), {':all:'}) + no_sdist_dependencies = ( + options.format_control != binary_only and + not options.ignore_dependencies + ) + if dist_restriction_set and no_sdist_dependencies: raise CommandError( - "--only-binary=:all: must be set and --no-binary must not " - "be set (or must be set to :none:) when restricting platform " - "and interpreter constraints using --python-version, " - "--platform, --abi, or --implementation." + "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:)." ) options.src_dir = os.path.abspath(options.src_dir) @@ -169,18 +179,12 @@ class DownloadCommand(RequirementCommand): ) options.cache_dir = None - with BuildDirectory(options.build_dir, - delete=build_delete) as build_dir: + with TempDirectory( + options.build_dir, delete=build_delete, kind="download" + ) as directory: requirement_set = RequirementSet( - build_dir=build_dir, - src_dir=options.src_dir, - download_dir=options.download_dir, - ignore_installed=True, - ignore_dependencies=options.ignore_dependencies, - session=session, - isolated=options.isolated_mode, - require_hashes=options.require_hashes + require_hashes=options.require_hashes, ) self.populate_requirement_set( requirement_set, @@ -192,18 +196,35 @@ class DownloadCommand(RequirementCommand): None ) - if not requirement_set.has_requirements: - return + 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, + ) - requirement_set.prepare_files(finder) + 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 - ) + logger.info('Successfully downloaded %s', downloaded) # Clean up if not options.no_clean: diff --git a/pipenv/patched/notpip/commands/freeze.py b/pipenv/patched/notpip/_internal/commands/freeze.py similarity index 75% rename from pipenv/patched/notpip/commands/freeze.py rename to pipenv/patched/notpip/_internal/commands/freeze.py index 5a6deb9e..f0fcbaae 100644 --- a/pipenv/patched/notpip/commands/freeze.py +++ b/pipenv/patched/notpip/_internal/commands/freeze.py @@ -2,14 +2,13 @@ from __future__ import absolute_import import sys -import pip9 -from pip9.compat import stdlib_pkgs -from pip9.basecommand import Command -from pip9.operations.freeze import freeze -from pip9.wheel import WheelCache +from notpip._internal import index +from notpip._internal.basecommand import Command +from notpip._internal.cache import WheelCache +from notpip._internal.compat import stdlib_pkgs +from notpip._internal.operations.freeze import freeze - -DEV_PKGS = ('pip', 'setuptools', 'distribute', 'wheel') +DEV_PKGS = {'pip', 'setuptools', 'distribute', 'wheel'} class FreezeCommand(Command): @@ -63,11 +62,16 @@ class FreezeCommand(Command): 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 = pip9.index.FormatControl(set(), set()) + format_control = index.FormatControl(set(), set()) wheel_cache = WheelCache(options.cache_dir, format_control) skip = set(stdlib_pkgs) if not options.freeze_all: @@ -81,7 +85,12 @@ class FreezeCommand(Command): skip_regex=options.skip_requirements_regex, isolated=options.isolated_mode, wheel_cache=wheel_cache, - skip=skip) + skip=skip, + exclude_editable=options.exclude_editable, + ) - for line in freeze(**freeze_kwargs): - sys.stdout.write(line + '\n') + try: + for line in freeze(**freeze_kwargs): + sys.stdout.write(line + '\n') + finally: + wheel_cache.cleanup() diff --git a/pipenv/patched/notpip/commands/hash.py b/pipenv/patched/notpip/_internal/commands/hash.py similarity index 85% rename from pipenv/patched/notpip/commands/hash.py rename to pipenv/patched/notpip/_internal/commands/hash.py index b3eb1732..37aedc47 100644 --- a/pipenv/patched/notpip/commands/hash.py +++ b/pipenv/patched/notpip/_internal/commands/hash.py @@ -4,11 +4,10 @@ import hashlib import logging import sys -from pip9.basecommand import Command -from pip9.status_codes import ERROR -from pip9.utils import read_chunks -from pip9.utils.hashes import FAVORITE_HASH, STRONG_HASHES - +from notpip._internal.basecommand import Command +from notpip._internal.status_codes import ERROR +from notpip._internal.utils.hashes import FAVORITE_HASH, STRONG_HASHES +from notpip._internal.utils.misc import read_chunks logger = logging.getLogger(__name__) @@ -24,6 +23,7 @@ class HashCommand(Command): 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) diff --git a/pipenv/patched/notpip/commands/help.py b/pipenv/patched/notpip/_internal/commands/help.py similarity index 71% rename from pipenv/patched/notpip/commands/help.py rename to pipenv/patched/notpip/_internal/commands/help.py index 0c6bf171..ed461ae8 100644 --- a/pipenv/patched/notpip/commands/help.py +++ b/pipenv/patched/notpip/_internal/commands/help.py @@ -1,7 +1,7 @@ from __future__ import absolute_import -from pip9.basecommand import Command, SUCCESS -from pip9.exceptions import CommandError +from notpip._internal.basecommand import SUCCESS, Command +from notpip._internal.exceptions import CommandError class HelpCommand(Command): @@ -10,12 +10,13 @@ class HelpCommand(Command): usage = """ %prog """ summary = 'Show help for commands.' + ignore_require_venv = True def run(self, options, args): - from pip9.commands import commands_dict, get_similar_commands + from notpip._internal.commands import commands_dict, get_similar_commands try: - # 'pip help' with no args is handled by pip9.__init__.parseopt() + # '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 diff --git a/pipenv/patched/notpip/_internal/commands/install.py b/pipenv/patched/notpip/_internal/commands/install.py new file mode 100644 index 00000000..ffd40a61 --- /dev/null +++ b/pipenv/patched/notpip/_internal/commands/install.py @@ -0,0 +1,502 @@ +from __future__ import absolute_import + +import errno +import logging +import operator +import os +import shutil +from optparse import SUPPRESS_HELP + +from notpip._internal import cmdoptions +from notpip._internal.basecommand import RequirementCommand +from notpip._internal.cache import WheelCache +from notpip._internal.exceptions import ( + CommandError, InstallationError, PreviousBuildDirError, +) +from notpip._internal.locations import distutils_scheme, virtualenv_no_global +from notpip._internal.operations.check import check_install_conflicts +from notpip._internal.operations.prepare import RequirementPreparer +from notpip._internal.req import RequirementSet, install_given_reqs +from notpip._internal.resolve import Resolver +from notpip._internal.status_codes import ERROR +from notpip._internal.utils.filesystem import check_path_owner +from notpip._internal.utils.misc import ensure_dir, get_installed_version +from notpip._internal.utils.temp_dir import TempDirectory +from notpip._internal.wheel import WheelBuilder + +try: + import wheel +except ImportError: + wheel = None + + +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( + '--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.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.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) + + 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, session) + 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 TempDirectory( + options.build_dir, delete=build_delete, kind="install" + ) 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=None, + progress_bar=options.progress_bar, + build_isolation=options.build_isolation, + ) + + 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, + ) + resolver.resolve(requirement_set) + + # If caching is disabled or wheel is not installed don't + # try to build wheels. + if wheel and options.cache_dir: + # build wheels before install. + wb = WheelBuilder( + finder, preparer, wheel_cache, + build_options=[], global_options=[], + ) + # Ignore the result: a failed wheel will be + # installed from the sdist/vcs whatever. + wb.build( + requirement_set.requirements.values(), + session=session, autobuilding=True + ) + + 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, + ) + + possible_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, + ) + reqs = sorted(installed, key=operator.attrgetter('name')) + items = [] + for req in reqs: + item = req.name + try: + installed_version = get_installed_version( + req.name, possible_lib_locations + ) + 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): + package_set, _dep_info = check_install_conflicts(to_install) + missing, conflicting = _dep_info + + # NOTE: There is some duplication here from notpip 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/pipenv/patched/notpip/commands/list.py b/pipenv/patched/notpip/_internal/commands/list.py similarity index 77% rename from pipenv/patched/notpip/commands/list.py rename to pipenv/patched/notpip/_internal/commands/list.py index 9f36140e..2bb460b5 100644 --- a/pipenv/patched/notpip/commands/list.py +++ b/pipenv/patched/notpip/_internal/commands/list.py @@ -3,20 +3,19 @@ from __future__ import absolute_import import json import logging import warnings -try: - from itertools import zip_longest -except ImportError: - from itertools import izip_longest as zip_longest -from pip9._vendor import six +from notpip._vendor import six +from notpip._vendor.six.moves import zip_longest -from pip9.basecommand import Command -from pip9.exceptions import CommandError -from pip9.index import PackageFinder -from pip9.utils import ( - get_installed_distributions, dist_is_editable) -from pip9.utils.deprecation import RemovedInPip10Warning -from pip9.cmdoptions import make_option_group, index_group +from notpip._internal.basecommand import Command +from notpip._internal.cmdoptions import index_group, make_option_group +from notpip._internal.exceptions import CommandError +from notpip._internal.index import PackageFinder +from notpip._internal.utils.deprecation import RemovedInPip11Warning +from notpip._internal.utils.misc import ( + dist_is_editable, get_installed_distributions, +) +from notpip._internal.utils.packaging import get_installer logger = logging.getLogger(__name__) @@ -78,9 +77,10 @@ class ListCommand(Command): '--format', action='store', dest='list_format', + default="columns", choices=('legacy', 'columns', 'freeze', 'json'), - help="Select the output format among: legacy (default), columns, " - "freeze or json.", + help="Select the output format among: columns (default), freeze, " + "json, or legacy.", ) cmd_opts.add_option( @@ -91,6 +91,19 @@ class ListCommand(Command): "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 = make_option_group(index_group, self.parser) self.parser.insert_option_group(0, index_opts) @@ -110,37 +123,11 @@ class ListCommand(Command): ) def run(self, options, args): - if options.allow_external: + if options.list_format == "legacy": warnings.warn( - "--allow-external has been deprecated and will be removed in " - "the future. Due to changes in the repository protocol, it no " - "longer has any effect.", - RemovedInPip10Warning, - ) - - if options.allow_all_external: - warnings.warn( - "--allow-all-external has been deprecated and will be removed " - "in the future. Due to changes in the repository protocol, it " - "no longer has any effect.", - RemovedInPip10Warning, - ) - - if options.allow_unverified: - warnings.warn( - "--allow-unverified has been deprecated and will be removed " - "in the future. Due to changes in the repository protocol, it " - "no longer has any effect.", - RemovedInPip10Warning, - ) - - if options.list_format is None: - warnings.warn( - "The default format will switch to columns in the future. " - "You can use --format=(legacy|columns) (or define a " - "format=(legacy|columns) in your pip9.conf under the [list] " - "section) to disable this warning.", - RemovedInPip10Warning, + "The legacy format has been deprecated and will be removed " + "in the future.", + RemovedInPip11Warning, ) if options.outdated and options.uptodate: @@ -151,6 +138,7 @@ class ListCommand(Command): local_only=options.local, user_only=options.user, editables_only=options.editable, + include_editables=options.include_editable, ) if options.outdated: @@ -179,7 +167,7 @@ class ListCommand(Command): dep_keys = set() for dist in packages: dep_keys.update(requirement.key for requirement in dist.requires()) - return set(pkg for pkg in packages if pkg.key not in dep_keys) + 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 @@ -220,8 +208,15 @@ class ListCommand(Command): dist.latest_filetype = typ yield dist - def output_legacy(self, dist): - if dist_is_editable(dist): + def output_legacy(self, dist, options): + if options.verbose >= 1: + return '%s (%s, %s, %s)' % ( + dist.project_name, + dist.version, + dist.location, + get_installer(dist), + ) + elif dist_is_editable(dist): return '%s (%s, %s)' % ( dist.project_name, dist.version, @@ -230,9 +225,9 @@ class ListCommand(Command): else: return '%s (%s)' % (dist.project_name, dist.version) - def output_legacy_latest(self, dist): + def output_legacy_latest(self, dist, options): return '%s - Latest: %s [%s]' % ( - self.output_legacy(dist), + self.output_legacy(dist, options), dist.latest_version, dist.latest_filetype, ) @@ -247,15 +242,19 @@ class ListCommand(Command): self.output_package_listing_columns(data, header) elif options.list_format == 'freeze': for dist in packages: - logger.info("%s==%s", dist.project_name, dist.version) + 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)) - else: # legacy + elif options.list_format == "legacy": for dist in packages: if options.outdated: - logger.info(self.output_legacy_latest(dist)) + logger.info(self.output_legacy_latest(dist, options)) else: - logger.info(self.output_legacy(dist)) + logger.info(self.output_legacy(dist, options)) def output_package_listing_columns(self, data, header): # insert the header first: we need to know the size of column names @@ -303,8 +302,10 @@ def format_for_columns(pkgs, options): header = ["Package", "Version"] data = [] - if any(dist_is_editable(x) for x in pkgs): + 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 @@ -315,8 +316,10 @@ def format_for_columns(pkgs, options): row.append(proj.latest_version) row.append(proj.latest_filetype) - if dist_is_editable(proj): + 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) @@ -330,6 +333,9 @@ def format_for_json(packages, options): '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 diff --git a/pipenv/patched/notpip/commands/search.py b/pipenv/patched/notpip/_internal/commands/search.py similarity index 79% rename from pipenv/patched/notpip/commands/search.py rename to pipenv/patched/notpip/_internal/commands/search.py index 30fa54cd..58b9acd8 100644 --- a/pipenv/patched/notpip/commands/search.py +++ b/pipenv/patched/notpip/_internal/commands/search.py @@ -3,19 +3,21 @@ from __future__ import absolute_import import logging import sys import textwrap +from collections import OrderedDict -from pip9.basecommand import Command, SUCCESS -from pip9.compat import OrderedDict -from pip9.download import pip9XmlrpcTransport -from pip9.models import PyPI -from pip9.utils import get_terminal_size -from pip9.utils.logging import indent_log -from pip9.exceptions import CommandError -from pip9.status_codes import NO_MATCHES_FOUND -from pip9._vendor.packaging.version import parse as parse_version -from pip9._vendor import pkg_resources -from pip9._vendor.six.moves import xmlrpc_client +from notpip._vendor import pkg_resources +from notpip._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 notpip._vendor.six.moves import xmlrpc_client # type: ignore +from notpip._internal.basecommand import SUCCESS, Command +from notpip._internal.compat import get_terminal_size +from notpip._internal.download import PipXmlrpcTransport +from notpip._internal.exceptions import CommandError +from notpip._internal.models import PyPI +from notpip._internal.status_codes import NO_MATCHES_FOUND +from notpip._internal.utils.logging import indent_log logger = logging.getLogger(__name__) @@ -26,6 +28,7 @@ class SearchCommand(Command): usage = """ %prog [options] """ summary = 'Search PyPI for packages.' + ignore_require_venv = True def __init__(self, *args, **kw): super(SearchCommand, self).__init__(*args, **kw) @@ -96,7 +99,7 @@ def print_results(hits, name_column_width=None, terminal_width=None): return if name_column_width is None: name_column_width = max([ - len(hit['name']) + len(hit.get('versions', ['-'])[-1]) + len(hit['name']) + len(highest_version(hit.get('versions', ['-']))) for hit in hits ]) + 4 @@ -104,7 +107,7 @@ def print_results(hits, name_column_width=None, terminal_width=None): for hit in hits: name = hit['name'] summary = hit['summary'] or '' - version = hit.get('versions', ['-'])[-1] + latest = highest_version(hit.get('versions', ['-'])) if terminal_width is not None: target_width = terminal_width - name_column_width - 5 if target_width > 10: @@ -113,13 +116,12 @@ def print_results(hits, name_column_width=None, terminal_width=None): summary = ('\n' + ' ' * (name_column_width + 3)).join(summary) line = '%-*s - %s' % (name_column_width, - '%s (%s)' % (name, version), summary) + '%s (%s)' % (name, latest), summary) try: logger.info(line) if name in installed_packages: dist = pkg_resources.get_distribution(name) with indent_log(): - latest = highest_version(hit['versions']) if dist.version == latest: logger.info('INSTALLED: %s (latest)', dist.version) else: diff --git a/pipenv/patched/notpip/commands/show.py b/pipenv/patched/notpip/_internal/commands/show.py similarity index 90% rename from pipenv/patched/notpip/commands/show.py rename to pipenv/patched/notpip/_internal/commands/show.py index 056e466c..f761b08f 100644 --- a/pipenv/patched/notpip/commands/show.py +++ b/pipenv/patched/notpip/_internal/commands/show.py @@ -1,14 +1,14 @@ from __future__ import absolute_import -from email.parser import FeedParser import logging import os +from email.parser import FeedParser # type: ignore -from pip9.basecommand import Command -from pip9.status_codes import SUCCESS, ERROR -from pip9._vendor import pkg_resources -from pip9._vendor.packaging.utils import canonicalize_name +from notpip._vendor import pkg_resources +from notpip._vendor.packaging.utils import canonicalize_name +from notpip._internal.basecommand import Command +from notpip._internal.status_codes import ERROR, SUCCESS logger = logging.getLogger(__name__) @@ -19,6 +19,7 @@ class ShowCommand(Command): usage = """ %prog [options] ...""" summary = 'Show information about installed packages.' + ignore_require_venv = True def __init__(self, *args, **kw): super(ShowCommand, self).__init__(*args, **kw) @@ -126,7 +127,14 @@ def print_results(distributions, list_files=False, verbose=False): results_printed = True if i > 0: logger.info("---") - logger.info("Name: %s", dist.get('name', '')) + + 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', '')) @@ -135,6 +143,8 @@ def print_results(distributions, list_files=False, verbose=False): 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', '')) diff --git a/pipenv/patched/notpip/commands/uninstall.py b/pipenv/patched/notpip/_internal/commands/uninstall.py similarity index 61% rename from pipenv/patched/notpip/commands/uninstall.py rename to pipenv/patched/notpip/_internal/commands/uninstall.py index 03465821..cb4207f2 100644 --- a/pipenv/patched/notpip/commands/uninstall.py +++ b/pipenv/patched/notpip/_internal/commands/uninstall.py @@ -1,10 +1,10 @@ from __future__ import absolute_import -import pip9 -from pip9.wheel import WheelCache -from pip9.req import InstallRequirement, RequirementSet, parse_requirements -from pip9.basecommand import Command -from pip9.exceptions import InstallationError +from notpip._vendor.packaging.utils import canonicalize_name + +from notpip._internal.basecommand import Command +from notpip._internal.exceptions import InstallationError +from notpip._internal.req import InstallRequirement, parse_requirements class UninstallCommand(Command): @@ -44,33 +44,28 @@ class UninstallCommand(Command): def run(self, options, args): with self._build_session(options) as session: - format_control = pip9.index.FormatControl(set(), set()) - wheel_cache = WheelCache(options.cache_dir, format_control) - requirement_set = RequirementSet( - build_dir=None, - src_dir=None, - download_dir=None, - isolated=options.isolated_mode, - session=session, - wheel_cache=wheel_cache, - ) + reqs_to_uninstall = {} for name in args: - requirement_set.add_requirement( - InstallRequirement.from_line( - name, isolated=options.isolated_mode, - wheel_cache=wheel_cache - ) + req = InstallRequirement.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, - wheel_cache=wheel_cache): - requirement_set.add_requirement(req) - if not requirement_set.has_requirements: + 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) ) - requirement_set.uninstall(auto_confirm=options.yes) + 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/pipenv/patched/notpip/commands/wheel.py b/pipenv/patched/notpip/_internal/commands/wheel.py similarity index 56% rename from pipenv/patched/notpip/commands/wheel.py rename to pipenv/patched/notpip/_internal/commands/wheel.py index 8140f608..e3db0b9d 100644 --- a/pipenv/patched/notpip/commands/wheel.py +++ b/pipenv/patched/notpip/_internal/commands/wheel.py @@ -3,17 +3,16 @@ from __future__ import absolute_import import logging import os -import warnings - -from pip9.basecommand import RequirementCommand -from pip9.exceptions import CommandError, PreviousBuildDirError -from pip9.req import RequirementSet -from pip9.utils import import_or_raise -from pip9.utils.build import BuildDirectory -from pip9.utils.deprecation import RemovedInPip10Warning -from pip9.wheel import WheelCache, WheelBuilder -from pip9 import cmdoptions +from notpip._internal import cmdoptions +from notpip._internal.basecommand import RequirementCommand +from notpip._internal.cache import WheelCache +from notpip._internal.exceptions import CommandError, PreviousBuildDirError +from notpip._internal.operations.prepare import RequirementPreparer +from notpip._internal.req import RequirementSet +from notpip._internal.resolve import Resolver +from notpip._internal.utils.temp_dir import TempDirectory +from notpip._internal.wheel import WheelBuilder logger = logging.getLogger(__name__) @@ -56,8 +55,6 @@ class WheelCommand(RequirementCommand): help=("Build wheels into , where the default is the " "current working directory."), ) - cmd_opts.add_option(cmdoptions.use_wheel()) - cmd_opts.add_option(cmdoptions.no_use_wheel()) cmd_opts.add_option(cmdoptions.no_binary()) cmd_opts.add_option(cmdoptions.only_binary()) cmd_opts.add_option( @@ -65,7 +62,9 @@ class WheelCommand(RequirementCommand): dest='build_options', metavar='options', action='append', - help="Extra arguments to be supplied to 'setup.py bdist_wheel'.") + help="Extra arguments to be supplied to 'setup.py bdist_wheel'.", + ) + cmd_opts.add_option(cmdoptions.no_build_isolation()) cmd_opts.add_option(cmdoptions.constraints()) cmd_opts.add_option(cmdoptions.editable()) cmd_opts.add_option(cmdoptions.requirements()) @@ -73,6 +72,7 @@ class WheelCommand(RequirementCommand): 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', @@ -101,55 +101,9 @@ class WheelCommand(RequirementCommand): self.parser.insert_option_group(0, index_opts) self.parser.insert_option_group(0, cmd_opts) - def check_required_packages(self): - import_or_raise( - 'wheel.bdist_wheel', - CommandError, - "'pip wheel' requires the 'wheel' package. To fix this, run: " - "pip install wheel" - ) - pkg_resources = import_or_raise( - 'pkg_resources', - CommandError, - "'pip wheel' requires setuptools >= 0.8 for dist-info support." - " To fix this, run: pip install --upgrade setuptools" - ) - if not hasattr(pkg_resources, 'DistInfoDistribution'): - raise CommandError( - "'pip wheel' requires setuptools >= 0.8 for dist-info " - "support. To fix this, run: pip install --upgrade " - "setuptools" - ) - def run(self, options, args): - self.check_required_packages() - cmdoptions.resolve_wheel_no_use_binary(options) cmdoptions.check_install_build_global(options) - if options.allow_external: - warnings.warn( - "--allow-external has been deprecated and will be removed in " - "the future. Due to changes in the repository protocol, it no " - "longer has any effect.", - RemovedInPip10Warning, - ) - - if options.allow_all_external: - warnings.warn( - "--allow-all-external has been deprecated and will be removed " - "in the future. Due to changes in the repository protocol, it " - "no longer has any effect.", - RemovedInPip10Warning, - ) - - if options.allow_unverified: - warnings.warn( - "--allow-unverified has been deprecated and will be removed " - "in the future. Due to changes in the repository protocol, it " - "no longer has any effect.", - RemovedInPip10Warning, - ) - index_urls = [options.index_url] + options.extra_index_urls if options.no_index: logger.debug('Ignoring indexes: %s', ','.join(index_urls)) @@ -164,39 +118,55 @@ class WheelCommand(RequirementCommand): 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 BuildDirectory(options.build_dir, - delete=build_delete) as build_dir: + + with TempDirectory( + options.build_dir, delete=build_delete, kind="wheel" + ) as directory: requirement_set = RequirementSet( - build_dir=build_dir, - src_dir=options.src_dir, - download_dir=None, - ignore_dependencies=options.ignore_dependencies, - ignore_installed=True, - ignore_requires_python=options.ignore_requires_python, - isolated=options.isolated_mode, - session=session, - wheel_cache=wheel_cache, - wheel_download_dir=options.wheel_dir, - require_hashes=options.require_hashes + require_hashes=options.require_hashes, ) - self.populate_requirement_set( - requirement_set, args, options, finder, session, self.name, - wheel_cache - ) - - if not requirement_set.has_requirements: - return - 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, + ) + + 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, + ) + resolver.resolve(requirement_set) + # build wheels wb = WheelBuilder( - requirement_set, - finder, + finder, preparer, wheel_cache, build_options=options.build_options or [], global_options=options.global_options or [], + no_clean=options.no_clean, ) - if not wb.build(): + wheels_built_successfully = wb.build( + requirement_set.requirements.values(), session=session, + ) + if not wheels_built_successfully: raise CommandError( "Failed to build one or more wheels" ) @@ -206,3 +176,4 @@ class WheelCommand(RequirementCommand): finally: if not options.no_clean: requirement_set.cleanup_files() + wheel_cache.cleanup() diff --git a/pipenv/patched/notpip/_internal/compat.py b/pipenv/patched/notpip/_internal/compat.py new file mode 100644 index 00000000..c99a737e --- /dev/null +++ b/pipenv/patched/notpip/_internal/compat.py @@ -0,0 +1,235 @@ +"""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 notpip._vendor.six import text_type + +try: + import ipaddress +except ImportError: + try: + from notpip._vendor import ipaddress # type: ignore + except ImportError: + import ipaddr as ipaddress # type: ignore + ipaddress.ip_address = ipaddress.IPAddress + ipaddress.ip_network = ipaddress.IPNetwork + + +__all__ = [ + "ipaddress", "uses_pycache", "console_to_str", "native_str", + "get_path_uid", "stdlib_pkgs", "WINDOWS", "samefile", "get_terminal_size", +] + + +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): + """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: + s = data.decode(encoding) + except UnicodeDecodeError: + logger.warning( + "Subprocess output does not appear to be encoded as %s", + encoding, + ) + s = 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: + s = s.encode(output_encoding, errors="backslashreplace") + s = s.decode(output_encoding) + + return s + + +if sys.version_info >= (3,): + def native_str(s, replace=False): + if isinstance(s, bytes): + return s.decode('utf-8', 'replace' if replace else 'strict') + return s + +else: + def native_str(s, replace=False): + # 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): + """ + 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 + + +def expanduser(path): + """ + Expand ~ and ~user constructions. + + Includes a workaround for http://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): + """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(): + """ + 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()) +else: + def get_terminal_size(): + """ + 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: + 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: + 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/pipenv/patched/notpip/_internal/configuration.py b/pipenv/patched/notpip/_internal/configuration.py new file mode 100644 index 00000000..0aa53c7c --- /dev/null +++ b/pipenv/patched/notpip/_internal/configuration.py @@ -0,0 +1,378 @@ +"""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 notpip._vendor import six +from notpip._vendor.six.moves import configparser + +from notpip._internal.exceptions import ConfigurationError +from notpip._internal.locations import ( + legacy_config_file, new_config_file, running_under_virtualenv, + site_config_files, venv_config_file, +) +from notpip._internal.utils.misc import ensure_dir, enum +from notpip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any, Dict, Iterable, List, NewType, Optional, Tuple + + RawConfigParser = configparser.RawConfigParser # Shorthand + Kind = NewType("Kind", str) + +logger = logging.getLogger(__name__) + + +# NOTE: Maybe use the optionx attribute to normalize keynames. +def _normalize_name(name): + # type: (str) -> str + """Make a name consistent regardless of source (environment or file) + """ + name = name.lower().replace('_', '-') + if name.startswith('--'): + name = name[2:] # only prefer long opts + return name + + +def _disassemble_key(name): + # type: (str) -> List[str] + return name.split(".", 1) + + +# The kinds of configurations there are. +kinds = enum( + USER="user", # User Specific + GLOBAL="global", # System Wide + 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: + raise ConfigurationError(( + "ERROR: " + "Configuration file contains invalid %s characters.\n" + "Please fix your configuration, located at %s\n" + ) % (locale.getpreferredencoding(False), fname)) + 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/pipenv/patched/notpip/download.py b/pipenv/patched/notpip/_internal/download.py similarity index 85% rename from pipenv/patched/notpip/download.py rename to pipenv/patched/notpip/_internal/download.py index 52c4366f..0ecdf14a 100644 --- a/pipenv/patched/notpip/download.py +++ b/pipenv/patched/notpip/_internal/download.py @@ -11,44 +11,49 @@ import platform import re import shutil import sys -import tempfile + +from notpip._vendor import requests, six, urllib3 +from notpip._vendor.cachecontrol import CacheControlAdapter +from notpip._vendor.cachecontrol.caches import FileCache +from notpip._vendor.lockfile import LockError +from notpip._vendor.requests.adapters import BaseAdapter, HTTPAdapter +from notpip._vendor.requests.auth import AuthBase, HTTPBasicAuth +from notpip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response +from notpip._vendor.requests.structures import CaseInsensitiveDict +from notpip._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 notpip._vendor.six.moves import xmlrpc_client # type: ignore +from notpip._vendor.six.moves.urllib import parse as urllib_parse +from notpip._vendor.six.moves.urllib import request as urllib_request +from notpip._vendor.six.moves.urllib.parse import unquote as urllib_unquote +from notpip._vendor.urllib3.util import IS_PYOPENSSL + +import notpip +from notpip._internal.compat import WINDOWS +from notpip._internal.exceptions import HashMismatch, InstallationError +from notpip._internal.locations import write_delete_marker_file +from notpip._internal.models import PyPI +from notpip._internal.utils.encoding import auto_decode +from notpip._internal.utils.filesystem import check_path_owner +from notpip._internal.utils.glibc import libc_ver +from notpip._internal.utils.logging import indent_log +from notpip._internal.utils.misc import ( + ARCHIVE_EXTENSIONS, ask_path_exists, backup_dir, call_subprocess, consume, + display_path, format_size, get_installed_version, rmtree, splitext, + unpack_file, +) +from notpip._internal.utils.setuptools_build import SETUPTOOLS_SHIM +from notpip._internal.utils.temp_dir import TempDirectory +from notpip._internal.utils.ui import DownloadProgressProvider +from notpip._internal.vcs import vcs try: import ssl # noqa - HAS_TLS = True except ImportError: - HAS_TLS = False - -from pip9._vendor.six.moves.urllib import parse as urllib_parse -from pip9._vendor.six.moves.urllib import request as urllib_request - -import pip9 - -from pip9.exceptions import InstallationError, HashMismatch -from pip9.models import PyPI -from pip9.utils import (splitext, rmtree, format_size, display_path, - backup_dir, ask_path_exists, unpack_file, - ARCHIVE_EXTENSIONS, consume, call_subprocess) -from pip9.utils.encoding import auto_decode -from pip9.utils.filesystem import check_path_owner -from pip9.utils.logging import indent_log -from pip9.utils.setuptools_build import SETUPTOOLS_SHIM -from pip9.utils.glibc import libc_ver -from pip9.utils.ui import DownloadProgressBar, DownloadProgressSpinner -from pip9.locations import write_delete_marker_file -from pip9.vcs import vcs -from pip9._vendor import requests, six -from pip9._vendor.requests.adapters import BaseAdapter, HTTPAdapter -from pip9._vendor.requests.auth import AuthBase, HTTPBasicAuth -from pip9._vendor.requests.models import CONTENT_CHUNK_SIZE, Response -from pip9._vendor.requests.utils import get_netrc_auth -from pip9._vendor.requests.structures import CaseInsensitiveDict -from pip9._vendor import urllib3 -from pip9._vendor.cachecontrol import CacheControlAdapter -from pip9._vendor.cachecontrol.caches import FileCache -from pip9._vendor.lockfile import LockError -from pip9._vendor.six.moves import xmlrpc_client + ssl = None +HAS_TLS = (ssl is not None) or IS_PYOPENSSL __all__ = ['get_file_content', 'is_url', 'url_to_path', 'path_to_url', @@ -65,7 +70,7 @@ def user_agent(): Return a string representing the user agent. """ data = { - "installer": {"name": "pip", "version": pip9.__version__}, + "installer": {"name": "pip", "version": pip.__version__}, "python": platform.python_version(), "implementation": { "name": platform.python_implementation(), @@ -90,7 +95,7 @@ def user_agent(): data["implementation"]["version"] = platform.python_version() if sys.platform.startswith("linux"): - from pip9._vendor import distro + from notpip._vendor import distro distro_infos = dict(filter( lambda x: x[1], zip(["name", "version", "id"], distro.linux_distribution()), @@ -116,10 +121,13 @@ def user_agent(): if platform.machine(): data["cpu"] = platform.machine() - # Python 2.6 doesn't have ssl.OPENSSL_VERSION. - if HAS_TLS and sys.version_info[:2] > (2, 6): + 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), @@ -203,8 +211,9 @@ class MultiDomainBasicAuth(AuthBase): if "@" in netloc: userinfo = netloc.rsplit("@", 1)[0] if ":" in userinfo: - return userinfo.split(":", 1) - return userinfo, None + user, pwd = userinfo.split(":", 1) + return (urllib_unquote(user), urllib_unquote(pwd)) + return urllib_unquote(userinfo), None return None, None @@ -251,7 +260,7 @@ class SafeFileCache(FileCache): super(SafeFileCache, self).__init__(*args, **kwargs) # Check to ensure that the directory containing our cache directory - # is owned by the user current executing pip9. If it does not exist + # 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. @@ -342,7 +351,9 @@ class PipSession(requests.Session): # 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. - status_forcelist=[503], + # 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. @@ -376,7 +387,7 @@ class PipSession(requests.Session): # We want to use a non-validating adapter for any requests which are # deemed insecure. for host in insecure_hosts: - self.mount("https://{0}/".format(host), insecure_adapter) + self.mount("https://{}/".format(host), insecure_adapter) def request(self, method, url, *args, **kwargs): # Allow setting a default timeout on a session @@ -388,7 +399,12 @@ class PipSession(requests.Session): def get_file_content(url, comes_from=None, session=None): """Gets the content of a file; it may be a filename, file: URL, or - http: URL. Returns (location, content). Content is unicode.""" + 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'" @@ -509,14 +525,13 @@ def _progress_indicator(iterable, *args, **kwargs): return iterable -def _download_url(resp, link, content_file, hashes): +def _download_url(resp, link, content_file, hashes, progress_bar): 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: @@ -580,12 +595,12 @@ def _download_url(resp, link, content_file, hashes): 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)) - progress_indicator = DownloadProgressBar(max=total_length).iter else: logger.info("Downloading %s", url) - progress_indicator = DownloadProgressSpinner().iter elif cached_resp: logger.info("Using cached %s", url) else: @@ -633,42 +648,41 @@ def _copy_file(filename, location, link): def unpack_http_url(link, location, download_dir=None, - session=None, hashes=None): + session=None, hashes=None, progress_bar="on"): if session is None: raise TypeError( "unpack_http_url() missing 1 required keyword argument: 'session'" ) - temp_dir = tempfile.mkdtemp('-unpack', 'pip-') + 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 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) - 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, - hashes) + # 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) - # 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) - # 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) - rmtree(temp_dir) + if not already_downloaded_path: + os.unlink(from_path) def unpack_file_url(link, location, download_dir=None, hashes=None): @@ -739,7 +753,7 @@ def _copy_dist_from_dir(link_path, location): # build an sdist setup_py = 'setup.py' - sdist_args = [os.environ['PIP_PYTHON_PATH']] + sdist_args = [os.environ.get('PIP_PYTHON_PATH', sys.executable)] sdist_args.append('-c') sdist_args.append(SETUPTOOLS_SHIM % setup_py) sdist_args.append('sdist') @@ -785,7 +799,8 @@ class PipXmlrpcTransport(xmlrpc_client.Transport): def unpack_url(link, location, download_dir=None, - only_download=False, session=None, hashes=None): + only_download=False, session=None, hashes=None, + progress_bar="on"): """Unpack link. If link is a VCS link: if only_download, export into download_dir and ignore location @@ -818,13 +833,14 @@ def unpack_url(link, location, download_dir=None, location, download_dir, session, - hashes=hashes + hashes=hashes, + progress_bar=progress_bar ) if only_download: write_delete_marker_file(location) -def _download_http_url(link, session, temp_dir, hashes): +def _download_http_url(link, session, temp_dir, hashes, progress_bar): """Download link url into temp_dir using provided session""" target_url = link.url.split('#', 1)[0] try: @@ -879,7 +895,7 @@ def _download_http_url(link, session, temp_dir, hashes): 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) + _download_url(resp, link, content_file, hashes, progress_bar) return file_path, content_type diff --git a/pipenv/patched/notpip/exceptions.py b/pipenv/patched/notpip/_internal/exceptions.py similarity index 97% rename from pipenv/patched/notpip/exceptions.py rename to pipenv/patched/notpip/_internal/exceptions.py index e94d68c7..367a0e27 100644 --- a/pipenv/patched/notpip/exceptions.py +++ b/pipenv/patched/notpip/_internal/exceptions.py @@ -3,13 +3,17 @@ from __future__ import absolute_import from itertools import chain, groupby, repeat -from pip9._vendor.six import iteritems +from notpip._vendor.six import iteritems class PipError(Exception): """Base pip exception""" +class ConfigurationError(PipError): + """General exception in configuration""" + + class InstallationError(PipError): """General exception during installation""" @@ -158,7 +162,8 @@ class HashMissing(HashError): self.gotten_hash = gotten_hash def body(self): - from pip9.utils.hashes import FAVORITE_HASH # Dodge circular import. + # Dodge circular import. + from notpip._internal.utils.hashes import FAVORITE_HASH package = None if self.req: diff --git a/pipenv/patched/notpip/index.py b/pipenv/patched/notpip/_internal/index.py similarity index 92% rename from pipenv/patched/notpip/index.py rename to pipenv/patched/notpip/_internal/index.py index f452c8c4..5225dcab 100644 --- a/pipenv/patched/notpip/index.py +++ b/pipenv/patched/notpip/_internal/index.py @@ -1,42 +1,42 @@ """Routines related to PyPI, indexes""" from __future__ import absolute_import -import logging import cgi -from collections import namedtuple import itertools -import sys -import os -import re +import logging import mimetypes +import os import posixpath +import re +import sys import warnings +from collections import namedtuple -from pip9._vendor.six.moves.urllib import parse as urllib_parse -from pip9._vendor.six.moves.urllib import request as urllib_request +from notpip._vendor import html5lib, requests, six +from notpip._vendor.distlib.compat import unescape +from notpip._vendor.packaging import specifiers +from notpip._vendor.packaging.utils import canonicalize_name +from notpip._vendor.packaging.version import parse as parse_version +from notpip._vendor.requests.exceptions import SSLError +from notpip._vendor.six.moves.urllib import parse as urllib_parse +from notpip._vendor.six.moves.urllib import request as urllib_request -from pip9.compat import ipaddress -from pip9.utils import ( - cached_property, splitext, normalize_path, - ARCHIVE_EXTENSIONS, SUPPORTED_EXTENSIONS, -) -from pip9.utils.deprecation import RemovedInPip10Warning -from pip9.utils.logging import indent_log -from notpip.utils.packaging import check_requires_python -from pip9.exceptions import ( - DistributionNotFound, BestVersionAlreadyInstalled, InvalidWheelFilename, +from notpip._internal.compat import ipaddress +from notpip._internal.download import HAS_TLS, is_url, path_to_url, url_to_path +from notpip._internal.exceptions import ( + BestVersionAlreadyInstalled, DistributionNotFound, InvalidWheelFilename, UnsupportedWheel, ) -from pip9.download import HAS_TLS, is_url, path_to_url, url_to_path -from notpip.wheel import Wheel, wheel_ext -from pip9.pep425tags import get_supported -from notpip._vendor import html5lib, requests, six -from pip9._vendor.packaging.version import parse as parse_version -from pip9._vendor.packaging.utils import canonicalize_name -from notpip._vendor.packaging import specifiers -from pip9._vendor.requests.exceptions import SSLError, HTTPError -from pip9._vendor.distlib.compat import unescape - +from notpip._internal.models import PyPI +from notpip._internal.pep425tags import get_supported +from notpip._internal.utils.deprecation import RemovedInPip11Warning +from notpip._internal.utils.logging import indent_log +from notpip._internal.utils.misc import ( + ARCHIVE_EXTENSIONS, SUPPORTED_EXTENSIONS, cached_property, normalize_path, + splitext, +) +from notpip._internal.utils.packaging import check_requires_python +from notpip._internal.wheel import Wheel, wheel_ext __all__ = ['FormatControl', 'fmt_ctl_handle_mutual_exclude', 'PackageFinder'] @@ -67,8 +67,8 @@ class InstallationCandidate(object): self.requires_python = requires_python def __repr__(self): - return "".format( - self.project, self.version, self.location + return "".format( + self.project, self.version, self.location, ) def __hash__(self): @@ -193,6 +193,18 @@ class PackageFinder(object): ) break + def get_formatted_locations(self): + lines = [] + if self.index_urls and self.index_urls != [PyPI.simple_url]: + lines.append( + "Looking in indexes: {}".format(", ".join(self.index_urls)) + ) + if self.find_links: + lines.append( + "Looking in links: {}".format(", ".join(self.find_links)) + ) + return "\n".join(lines) + def add_dependency_links(self, links): # # FIXME: this shouldn't be global list this, it should only # # apply to requirements of the package that specifies the @@ -202,7 +214,7 @@ class PackageFinder(object): warnings.warn( "Dependency Links processing has been deprecated and will be " "removed in a future release.", - RemovedInPip10Warning, + RemovedInPip11Warning, ) self.dependency_links.extend(links) @@ -224,8 +236,6 @@ class PackageFinder(object): return extras - - @staticmethod def _sort_locations(locations, expand_dir=False): """ @@ -265,14 +275,16 @@ class PackageFinder(object): else: logger.warning( "Url '%s' is ignored: it is neither a file " - "nor a directory.", url) + "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) + "path or lacks a specific scheme.", url, + ) return files, urls @@ -290,6 +302,7 @@ class PackageFinder(object): with the same version, would have to be considered equal """ support_num = len(self.valid_tags) + build_tag = tuple() if candidate.location.is_wheel: # can raise InvalidWheelFilename wheel = Wheel(candidate.location.filename) @@ -304,9 +317,14 @@ class PackageFinder(object): pri = -(wheel.support_index_min(tags=tags)) except TypeError: pri = -(support_num) + + 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 (candidate.version, pri) + return (candidate.version, build_tag, pri) def _validate_secure_origin(self, logger, location): # Determine if this url used a secure transport mechanism @@ -370,9 +388,9 @@ class PackageFinder(object): # 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 it " - "is recommended to use HTTPS instead, otherwise you may silence " - "this warning and allow it anyways with '--trusted-host %s'.", + "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, ) @@ -412,13 +430,13 @@ class PackageFinder(object): 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) + self.find_links, expand_dir=True, + ) dep_file_loc, dep_url_loc = self._sort_locations(self.dependency_links) - file_locations = ( - Link(url) for url in itertools.chain( - index_file_loc, fl_file_loc, dep_file_loc) - ) + file_locations = (Link(url) for url in itertools.chain( + index_file_loc, fl_file_loc, dep_file_loc, + )) # We trust every url that the user has given us whether it was given # via --index-url or --find-links @@ -513,7 +531,6 @@ class PackageFinder(object): ) else: compatible_versions = [str(c.version) for c in all_candidates] - applicable_candidates = [ # Again, converting to str to deal with debundling. c for c in all_candidates if str(c.version) in compatible_versions @@ -537,7 +554,7 @@ class PackageFinder(object): req, ', '.join( sorted( - set(str(c.version) for c in all_candidates), + {str(c.version) for c in all_candidates}, key=parse_version, ) ) @@ -600,7 +617,7 @@ class PackageFinder(object): try: page = self._get_page(location) - except HTTPError as e: + except requests.HTTPError as e: page = None if page is None: continue @@ -652,11 +669,13 @@ class PackageFinder(object): # Always ignore unsupported extensions even when we ignore compatibility if ext not in SUPPORTED_EXTENSIONS: self._log_skipped_link( - link, 'unsupported archive format: %s' % ext) + link, 'unsupported archive format: %s' % ext, + ) return if "binary" not in search.formats and ext == wheel_ext and not ignore_compatibility: self._log_skipped_link( - link, 'No binaries permitted for %s' % search.supplied) + link, 'No binaries permitted for %s' % search.supplied, + ) return if "macosx10" in link.path and ext == '.zip' and not ignore_compatibility: self._log_skipped_link(link, 'macosx10 one') @@ -682,7 +701,8 @@ class PackageFinder(object): # This should be up by the search.ok_binary check, but see issue 2700. if "source" not in search.formats and ext != wheel_ext: self._log_skipped_link( - link, 'No sources permitted for %s' % search.supplied) + link, 'No sources permitted for %s' % search.supplied, + ) return if not version: @@ -713,6 +733,7 @@ class PackageFinder(object): link, link.requires_python) return logger.debug('Found link %s, version: %s', link, version) + return InstallationCandidate(search.supplied, version, link, link.requires_python) def _get_page(self, link): @@ -783,7 +804,7 @@ class HTMLPage(object): url = url.split('#', 1)[0] # Check for VCS schemes that do not support lookup as web pages. - from pip9.vcs import VcsSupport + from notpip._internal.vcs import VcsSupport for scheme in VcsSupport.schemes: if url.lower().startswith(scheme) and url[len(scheme)] in '+:': logger.debug('Cannot look at %s URL %s', scheme, link) @@ -848,8 +869,8 @@ class HTMLPage(object): except requests.HTTPError as exc: cls._handle_fail(link, exc, url) except SSLError as exc: - reason = ("There was a problem confirming the ssl certificate: " - "%s" % exc) + reason = "There was a problem confirming the ssl certificate: " + reason += str(exc) cls._handle_fail(link, reason, url, meth=logger.info) except requests.ConnectionError as exc: cls._handle_fail(link, "connection error: %s" % exc, url) @@ -869,7 +890,7 @@ class HTMLPage(object): def _get_content_type(url, session): """Get the Content-Type of the given url, using a HEAD request""" scheme, netloc, path, query, fragment = urllib_parse.urlsplit(url) - if scheme not in ('http', 'https'): + if scheme not in {'http', 'https'}: # FIXME: some warning or something? # assertion error? return '' @@ -1065,7 +1086,7 @@ class Link(object): 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 pip9.vcs import vcs + from notpip._internal.vcs import vcs if self.scheme in vcs.all_schemes: return False @@ -1103,7 +1124,7 @@ def fmt_ctl_handle_mutual_exclude(value, target, other): def fmt_ctl_formats(fmt_ctl, canonical_name): - result = set(["binary", "source"]) + result = {"binary", "source"} if canonical_name in fmt_ctl.only_binary: result.discard('source') elif canonical_name in fmt_ctl.no_binary: @@ -1117,15 +1138,8 @@ def fmt_ctl_formats(fmt_ctl, canonical_name): def fmt_ctl_no_binary(fmt_ctl): fmt_ctl_handle_mutual_exclude( - ':all:', fmt_ctl.no_binary, fmt_ctl.only_binary) - - -def fmt_ctl_no_use_wheel(fmt_ctl): - fmt_ctl_no_binary(fmt_ctl) - warnings.warn( - '--no-use-wheel is deprecated and will be removed in the future. ' - ' Please use --no-binary :all: instead.', RemovedInPip10Warning, - stacklevel=2) + ':all:', fmt_ctl.no_binary, fmt_ctl.only_binary, + ) Search = namedtuple('Search', 'supplied canonical formats') diff --git a/pipenv/patched/notpip/locations.py b/pipenv/patched/notpip/_internal/locations.py similarity index 82% rename from pipenv/patched/notpip/locations.py rename to pipenv/patched/notpip/_internal/locations.py index d43d157f..5ef8075d 100644 --- a/pipenv/patched/notpip/locations.py +++ b/pipenv/patched/notpip/_internal/locations.py @@ -3,15 +3,15 @@ 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, install # type: ignore -from distutils import sysconfig -from distutils.command.install import install, SCHEME_KEYS # noqa - -from pip9.compat import WINDOWS, expanduser -from pip9.utils import appdirs - +from notpip._internal.compat import WINDOWS, expanduser +from notpip._internal.utils import appdirs # Application Directories USER_CACHE_DIR = appdirs.user_cache_dir("pip") @@ -19,7 +19,7 @@ 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 pip9. +here by pip. Once this package is successfully installed this source code will be deleted (unless you remove this file). @@ -80,8 +80,18 @@ src_prefix = os.path.abspath(src_prefix) # FIXME doesn't account for venv linked to global site-packages -site_packages = sysconfig.get_python_lib() -user_site = site.USER_SITE +site_packages = sysconfig.get_path("purelib") +# 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') @@ -91,7 +101,7 @@ if WINDOWS: bin_py = os.path.join(sys.prefix, 'bin') bin_user = os.path.join(user_site, 'bin') - config_basename = 'pip9.ini' + config_basename = 'pip.ini' legacy_storage_dir = os.path.join(user_dir, 'pip') legacy_config_file = os.path.join( @@ -102,14 +112,13 @@ else: bin_py = os.path.join(sys.prefix, 'bin') bin_user = os.path.join(user_site, 'bin') - config_basename = 'pip9.conf' + 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/': @@ -120,6 +129,9 @@ site_config_files = [ 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): @@ -143,7 +155,7 @@ def distutils_scheme(dist_name, user=False, home=None, root=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={0} prefix={1}".format(user, prefix) + assert not (user and prefix), "user={} prefix={}".format(user, prefix) i.user = user or i.user if user: i.prefix = "" diff --git a/pipenv/patched/notpip/_internal/models/__init__.py b/pipenv/patched/notpip/_internal/models/__init__.py new file mode 100644 index 00000000..73edc8e5 --- /dev/null +++ b/pipenv/patched/notpip/_internal/models/__init__.py @@ -0,0 +1,4 @@ +from notpip._internal.models.index import Index, PyPI + + +__all__ = ["Index", "PyPI"] diff --git a/pipenv/patched/notpip/models/index.py b/pipenv/patched/notpip/_internal/models/index.py similarity index 73% rename from pipenv/patched/notpip/models/index.py rename to pipenv/patched/notpip/_internal/models/index.py index 25fd488d..564df119 100644 --- a/pipenv/patched/notpip/models/index.py +++ b/pipenv/patched/notpip/_internal/models/index.py @@ -1,4 +1,4 @@ -from pip9._vendor.six.moves.urllib import parse as urllib_parse +from notpip._vendor.six.moves.urllib import parse as urllib_parse class Index(object): @@ -7,7 +7,6 @@ class Index(object): self.netloc = urllib_parse.urlsplit(url).netloc self.simple_url = self.url_to_path('simple') self.pypi_url = self.url_to_path('pypi') - self.pip_json_url = self.url_to_path('pypi/pip/json') def url_to_path(self, path): return urllib_parse.urljoin(self.url, path) diff --git a/pipenv/patched/notpip/operations/__init__.py b/pipenv/patched/notpip/_internal/operations/__init__.py similarity index 100% rename from pipenv/patched/notpip/operations/__init__.py rename to pipenv/patched/notpip/_internal/operations/__init__.py diff --git a/pipenv/patched/notpip/_internal/operations/check.py b/pipenv/patched/notpip/_internal/operations/check.py new file mode 100644 index 00000000..c8a1928f --- /dev/null +++ b/pipenv/patched/notpip/_internal/operations/check.py @@ -0,0 +1,106 @@ +"""Validation of dependencies of packages +""" + +from collections import namedtuple + +from notpip._vendor.packaging.utils import canonicalize_name + +from notpip._internal.operations.prepare import make_abstract_dist + +from notpip._internal.utils.misc import get_installed_distributions +from notpip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from notpip._internal.req.req_install import InstallRequirement + from typing import Any, Dict, Iterator, 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) -> PackageSet + """Converts a list of distributions into a PackageSet. + """ + # Default to using all packages installed on the system + if kwargs == {}: + kwargs = {"local_only": False, "skip": ()} + retval = {} + for dist in get_installed_distributions(**kwargs): + name = canonicalize_name(dist.project_name) + retval[name] = PackageDetails(dist.version, dist.requires()) + return retval + + +def check_package_set(package_set): + # type: (PackageSet) -> CheckResult + """Check if a package set is consistent + """ + 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] + + 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)) + + def str_key(x): + return str(x) + + if missing_deps: + missing[package_name] = sorted(missing_deps, key=str_key) + if conflicting_deps: + conflicting[package_name] = sorted(conflicting_deps, key=str_key) + + 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 + state = create_package_set_from_installed() + _simulate_installation_of(to_install, state) + return state, check_package_set(state) + + +# NOTE from @pradyunsg +# This required a minor update in dependency link handling logic over at +# operations.prepare.IsSDist.dist() to get it working +def _simulate_installation_of(to_install, state): + # type: (List[InstallRequirement], PackageSet) -> None + """Computes the version of packages after installing to_install. + """ + + # Modify it as installing requirement_set would (assuming no errors) + for inst_req in to_install: + dist = make_abstract_dist(inst_req).dist(finder=None) + name = canonicalize_name(dist.key) + state[name] = PackageDetails(dist.version, dist.requires()) diff --git a/pipenv/patched/notpip/_internal/operations/freeze.py b/pipenv/patched/notpip/_internal/operations/freeze.py new file mode 100644 index 00000000..6cc259d4 --- /dev/null +++ b/pipenv/patched/notpip/_internal/operations/freeze.py @@ -0,0 +1,252 @@ +from __future__ import absolute_import + +import collections +import logging +import os +import re +import warnings + +from notpip._vendor import pkg_resources, six +from notpip._vendor.packaging.utils import canonicalize_name +from notpip._vendor.pkg_resources import RequirementParseError + +from notpip._internal.exceptions import InstallationError +from notpip._internal.req import InstallRequirement +from notpip._internal.req.req_file import COMMENT_RE +from notpip._internal.utils.deprecation import RemovedInPip11Warning +from notpip._internal.utils.misc import ( + dist_is_editable, get_installed_distributions, +) + +logger = logging.getLogger(__name__) + + +def freeze( + requirement=None, + find_links=None, local_only=None, user_only=None, skip_regex=None, + isolated=False, + wheel_cache=None, + exclude_editable=False, + skip=()): + find_links = find_links or [] + skip_match = None + + if skip_regex: + skip_match = re.compile(skip_regex).search + + dependency_links = [] + + for dist in pkg_resources.working_set: + if dist.has_metadata('dependency_links.txt'): + dependency_links.extend( + dist.get_metadata_lines('dependency_links.txt') + ) + for link in find_links: + if '#egg=' in link: + dependency_links.append(link) + for link in find_links: + yield '-f %s' % link + installations = {} + for dist in get_installed_distributions(local_only=local_only, + skip=(), + user_only=user_only): + try: + req = FrozenRequirement.from_dist( + dist, + dependency_links + ) + 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() + # 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) + 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 = InstallRequirement.from_editable( + line, + isolated=isolated, + wheel_cache=wheel_cache, + ) + else: + line_req = InstallRequirement.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 that " + "package is not installed", + req_file_path, + COMMENT_RE.sub('', line).strip(), + ) + 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() + + +class FrozenRequirement(object): + def __init__(self, name, req, editable, comments=()): + self.name = name + self.req = req + self.editable = editable + self.comments = comments + + _rev_re = re.compile(r'-r(\d+)$') + _date_re = re.compile(r'-(20\d\d\d\d\d\d)$') + + @classmethod + def from_dist(cls, dist, dependency_links): + location = os.path.normcase(os.path.abspath(dist.location)) + comments = [] + from notpip._internal.vcs import vcs, get_src_requirement + if dist_is_editable(dist) and vcs.get_backend_name(location): + editable = True + try: + req = get_src_requirement(dist, location) + except InstallationError as exc: + logger.warning( + "Error when trying to get requirement for VCS system %s, " + "falling back to uneditable format", exc + ) + req = None + if req is None: + logger.warning( + 'Could not determine repository location of %s', location + ) + comments.append( + '## !! Could not determine repository location' + ) + req = dist.as_requirement() + editable = False + else: + editable = False + req = dist.as_requirement() + specs = req.specs + assert len(specs) == 1 and specs[0][0] in ["==", "==="], \ + 'Expected 1 spec with == or ===; specs = %r; dist = %r' % \ + (specs, dist) + version = specs[0][1] + ver_match = cls._rev_re.search(version) + date_match = cls._date_re.search(version) + if ver_match or date_match: + svn_backend = vcs.get_backend('svn') + if svn_backend: + svn_location = svn_backend().get_location( + dist, + dependency_links, + ) + if not svn_location: + logger.warning( + 'Warning: cannot find svn location for %s', req, + ) + comments.append( + '## FIXME: could not find svn URL in dependency_links ' + 'for this package:' + ) + else: + warnings.warn( + "SVN editable detection based on dependency links " + "will be dropped in the future.", + RemovedInPip11Warning, + ) + comments.append( + '# Installing as editable to satisfy requirement %s:' % + req + ) + if ver_match: + rev = ver_match.group(1) + else: + rev = '{%s}' % date_match.group(1) + editable = True + req = '%s@%s#egg=%s' % ( + svn_location, + rev, + cls.egg_name(dist) + ) + return cls(dist.project_name, req, editable, comments) + + @staticmethod + def egg_name(dist): + name = dist.egg_name() + match = re.search(r'-py\d\.\d$', name) + if match: + name = name[:match.start()] + return name + + 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/pipenv/patched/notpip/_internal/operations/prepare.py b/pipenv/patched/notpip/_internal/operations/prepare.py new file mode 100644 index 00000000..f0ac1cbc --- /dev/null +++ b/pipenv/patched/notpip/_internal/operations/prepare.py @@ -0,0 +1,380 @@ +"""Prepares a distribution for installation +""" + +import itertools +import logging +import os +import sys +from copy import copy + +from notpip._vendor import pkg_resources, requests + +from notpip._internal.build_env import NoOpBuildEnvironment +from notpip._internal.compat import expanduser +from notpip._internal.download import ( + is_dir_url, is_file_url, is_vcs_url, unpack_url, url_to_path, +) +from notpip._internal.exceptions import ( + DirectoryUrlHashUnsupported, HashUnpinned, InstallationError, + PreviousBuildDirError, VcsHashUnsupported, +) +from notpip._internal.index import FormatControl +from notpip._internal.req.req_install import InstallRequirement +from notpip._internal.utils.hashes import MissingHashes +from notpip._internal.utils.logging import indent_log +from notpip._internal.utils.misc import ( + call_subprocess, display_path, normalize_path, +) +from notpip._internal.utils.ui import open_spinner +from notpip._internal.vcs import vcs + +logger = logging.getLogger(__name__) + + +def make_abstract_dist(req): + """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) + + +def _install_build_reqs(finder, prefix, build_requirements): + # NOTE: What follows is not a very good thing. + # Eventually, this should move into the BuildEnvironment class and + # that should handle all the isolation and sub-process invocation. + finder = copy(finder) + finder.format_control = FormatControl(set(), set([":all:"])) + urls = [ + finder.find_requirement( + InstallRequirement.from_line(r), upgrade=False).url + for r in build_requirements + ] + args = [ + sys.executable, '-m', 'pip', 'install', '--ignore-installed', + '--no-user', '--prefix', prefix, + ] + list(urls) + + with open_spinner("Installing build dependencies") as spinner: + call_subprocess(args, show_stdout=False, spinner=spinner) + + +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): + self.req = req + + def dist(self, finder): + """Return a setuptools Dist object.""" + raise NotImplementedError(self.dist) + + def prep_for_dist(self, finder): + """Ensure that we can get a Dist for this requirement.""" + raise NotImplementedError(self.dist) + + +class IsWheel(DistAbstraction): + + def dist(self, finder): + return list(pkg_resources.find_distributions( + self.req.source_dir))[0] + + def prep_for_dist(self, finder, build_isolation): + # FIXME:https://github.com/pypa/pip/issues/1112 + pass + + +class IsSDist(DistAbstraction): + + def dist(self, finder): + dist = self.req.get_dist() + # FIXME: shouldn't be globally added. + if finder and dist.has_metadata('dependency_links.txt'): + finder.add_dependency_links( + dist.get_metadata_lines('dependency_links.txt') + ) + return dist + + def prep_for_dist(self, finder, build_isolation): + # Before calling "setup.py egg_info", we need to set-up the build + # environment. + build_requirements, isolate = self.req.get_pep_518_info() + should_isolate = build_isolation and isolate + + minimum_requirements = ('setuptools', 'wheel') + missing_requirements = set(minimum_requirements) - set( + pkg_resources.Requirement(r).key + for r in build_requirements + ) + if missing_requirements: + def format_reqs(rs): + return ' and '.join(map(repr, sorted(rs))) + logger.warning( + "Missing build time requirements in pyproject.toml for %s: " + "%s.", self.req, format_reqs(missing_requirements) + ) + logger.warning( + "This version of pip does not implement PEP 517 so it cannot " + "build a wheel without %s.", format_reqs(minimum_requirements) + ) + + if should_isolate: + with self.req.build_env: + pass + _install_build_reqs(finder, self.req.build_env.path, + build_requirements) + else: + self.req.build_env = NoOpBuildEnvironment(no_clean=False) + + self.req.run_egg_info() + self.req.assert_source_matches_version() + + +class Installed(DistAbstraction): + + def dist(self, finder): + return self.req.satisfied_by + + def prep_for_dist(self, finder): + pass + + +class RequirementPreparer(object): + """Prepares a Requirement + """ + + def __init__(self, build_dir, download_dir, src_dir, wheel_download_dir, + progress_bar, build_isolation): + super(RequirementPreparer, self).__init__() + + self.src_dir = src_dir + self.build_dir = build_dir + + # 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): + # 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, session, finder, + upgrade_allowed, require_hashes): + """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) + 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, require_hashes, use_user_site, + finder): + """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) + 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): + """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/pipenv/patched/notpip/pep425tags.py b/pipenv/patched/notpip/_internal/pep425tags.py similarity index 93% rename from pipenv/patched/notpip/pep425tags.py rename to pipenv/patched/notpip/_internal/pep425tags.py index f2d65d4c..0cb2c709 100644 --- a/pipenv/patched/notpip/pep425tags.py +++ b/pipenv/patched/notpip/_internal/pep425tags.py @@ -1,21 +1,16 @@ """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 -import platform -import logging +from collections import OrderedDict -try: - import sysconfig -except ImportError: # pragma nocover - # Python < 2.7 - import distutils.sysconfig as sysconfig -import distutils.util - -from pip9.compat import OrderedDict -import pip9.utils.glibc +import notpip._internal.utils.glibc logger = logging.getLogger(__name__) @@ -26,7 +21,7 @@ def get_config_var(var): try: return sysconfig.get_config_var(var) except IOError as e: # Issue #1074 - warnings.warn("{0}".format(e), RuntimeWarning) + warnings.warn("{}".format(e), RuntimeWarning) return None @@ -66,7 +61,7 @@ def get_impl_tag(): """ Returns the Tag for this specific implementation. """ - return "{0}{1}".format(get_abbr_impl(), get_impl_ver()) + return "{}{}".format(get_abbr_impl(), get_impl_ver()) def get_flag(var, fallback, expected=True, warn=True): @@ -86,7 +81,7 @@ def get_abi_tag(): (CPython 2, PyPy).""" soabi = get_config_var('SOABI') impl = get_abbr_impl() - if not soabi and impl in ('cp', 'pp') and hasattr(sys, 'maxunicode'): + if not soabi and impl in {'cp', 'pp'} and hasattr(sys, 'maxunicode'): d = '' m = '' u = '' @@ -133,7 +128,7 @@ def get_platform(): elif machine == "ppc64" and _is_running_32bit(): machine = "ppc" - return 'macosx_{0}_{1}_{2}'.format(split_ver[0], split_ver[1], machine) + return 'macosx_{}_{}_{}'.format(split_ver[0], split_ver[1], machine) # XXX remove distutils dependency result = distutils.util.get_platform().replace('.', '_').replace('-', '_') @@ -147,7 +142,7 @@ def get_platform(): def is_manylinux1_compatible(): # Only Linux, and only x86-64 / i686 - if get_platform() not in ("linux_x86_64", "linux_i686"): + if get_platform() not in {"linux_x86_64", "linux_i686"}: return False # Check for presence of _manylinux module @@ -159,7 +154,7 @@ def is_manylinux1_compatible(): pass # Check glibc version. CentOS 5 uses glibc 2.5. - return pip9.utils.glibc.have_compatible_glibc(2, 5) + return pip._internal.utils.glibc.have_compatible_glibc(2, 5) def get_darwin_arches(major, minor, machine): @@ -273,7 +268,7 @@ def get_supported(versions=None, noarch=False, platform=None, match = _osx_arch_pat.match(arch) if match: name, major, minor, actual_arch = match.groups() - tpl = '{0}_{1}_%i_%s'.format(name, major) + 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): @@ -294,7 +289,7 @@ def get_supported(versions=None, noarch=False, platform=None, # 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'): + if version in {'31', '30'}: break for abi in abi3s: # empty set if not Python 3 for arch in arches: @@ -318,7 +313,5 @@ def get_supported(versions=None, noarch=False, platform=None, return supported -supported_tags = get_supported() -supported_tags_noarch = get_supported(noarch=True) implementation_tag = get_impl_tag() diff --git a/pipenv/patched/notpip/_internal/req/__init__.py b/pipenv/patched/notpip/_internal/req/__init__.py new file mode 100644 index 00000000..d4bb7e91 --- /dev/null +++ b/pipenv/patched/notpip/_internal/req/__init__.py @@ -0,0 +1,69 @@ +from __future__ import absolute_import + +import logging + +from .req_install import InstallRequirement +from .req_set import RequirementSet +from .req_file import parse_requirements +from notpip._internal.utils.logging import indent_log + + +__all__ = [ + "RequirementSet", "InstallRequirement", + "parse_requirements", "install_given_reqs", +] + +logger = logging.getLogger(__name__) + + +def install_given_reqs(to_install, install_options, global_options=(), + *args, **kwargs): + """ + 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: + 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/pipenv/patched/notpip/req/req_file.py b/pipenv/patched/notpip/_internal/req/req_file.py similarity index 81% rename from pipenv/patched/notpip/req/req_file.py rename to pipenv/patched/notpip/_internal/req/req_file.py index 5377cad6..274fcc65 100644 --- a/pipenv/patched/notpip/req/req_file.py +++ b/pipenv/patched/notpip/_internal/req/req_file.py @@ -4,28 +4,31 @@ Requirements file parsing from __future__ import absolute_import +import optparse import os import re import shlex import sys -import optparse -import warnings -from pip9._vendor.six.moves.urllib import parse as urllib_parse -from pip9._vendor.six.moves import filterfalse +from notpip._vendor.six.moves import filterfalse +from notpip._vendor.six.moves.urllib import parse as urllib_parse -import pip9 -from pip9.download import get_file_content -from pip9.req.req_install import InstallRequirement -from pip9.exceptions import (RequirementsFileParseError) -from pip9.utils.deprecation import RemovedInPip10Warning -from pip9 import cmdoptions +from notpip._internal import cmdoptions +from notpip._internal.download import get_file_content +from notpip._internal.exceptions import RequirementsFileParseError +from notpip._internal.req.req_install import InstallRequirement __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, @@ -34,13 +37,6 @@ SUPPORTED_OPTIONS = [ cmdoptions.index_url, cmdoptions.find_links, cmdoptions.extra_index_url, - cmdoptions.allow_external, - cmdoptions.allow_all_external, - cmdoptions.no_allow_external, - cmdoptions.allow_unsafe, - cmdoptions.no_allow_unsafe, - cmdoptions.use_wheel, - cmdoptions.no_use_wheel, cmdoptions.always_unzip, cmdoptions.no_binary, cmdoptions.only_binary, @@ -66,13 +62,13 @@ def parse_requirements(filename, finder=None, comes_from=None, options=None, """Parse a requirements file and yield InstallRequirement instances. :param filename: Path or url of requirements file. - :param finder: Instance of pip9.index.PackageFinder. + :param finder: Instance of pip.index.PackageFinder. :param comes_from: Origin description of requirements. :param options: cli options. - :param session: Instance of pip9.download.PipSession. + :param session: Instance of pip.download.PipSession. :param constraint: If true, parsing a constraint file rather than requirements file. - :param wheel_cache: Instance of pip9.wheel.WheelCache + :param wheel_cache: Instance of pip.wheel.WheelCache """ if session is None: raise TypeError( @@ -104,6 +100,7 @@ def preprocess(content, options): 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 @@ -127,7 +124,7 @@ def process_line(line, filename, line_number, finder=None, comes_from=None, :param constraint: If True, parsing a constraints file. :param options: OptionParser options that we may update """ - parser = build_parser() + parser = build_parser(line) defaults = parser.get_default_values() defaults.index_url = None if finder: @@ -141,7 +138,8 @@ def process_line(line, filename, line_number, finder=None, comes_from=None, # preserve for the nested code path line_comes_from = '%s %s (line %s)' % ( - '-c' if constraint else '-r', filename, line_number) + '-c' if constraint else '-r', filename, line_number, + ) # yield a line requirement if args_str: @@ -161,11 +159,9 @@ def process_line(line, filename, line_number, finder=None, comes_from=None, # yield an editable requirement elif opts.editables: isolated = options.isolated_mode if options else False - default_vcs = options.default_vcs if options else None yield InstallRequirement.from_editable( opts.editables[0], comes_from=line_comes_from, - constraint=constraint, default_vcs=default_vcs, isolated=isolated, - wheel_cache=wheel_cache + constraint=constraint, isolated=isolated, wheel_cache=wheel_cache ) # parse a nested requirements file @@ -198,35 +194,8 @@ def process_line(line, filename, line_number, finder=None, comes_from=None, # set finder options elif finder: - if opts.allow_external: - warnings.warn( - "--allow-external has been deprecated and will be removed in " - "the future. Due to changes in the repository protocol, it no " - "longer has any effect.", - RemovedInPip10Warning, - ) - - if opts.allow_all_external: - warnings.warn( - "--allow-all-external has been deprecated and will be removed " - "in the future. Due to changes in the repository protocol, it " - "no longer has any effect.", - RemovedInPip10Warning, - ) - - if opts.allow_unverified: - warnings.warn( - "--allow-unverified has been deprecated and will be removed " - "in the future. Due to changes in the repository protocol, it " - "no longer has any effect.", - RemovedInPip10Warning, - ) - if opts.index_url: finder.index_urls = [opts.index_url] - if opts.use_wheel is False: - finder.use_wheel = False - pip9.index.fmt_ctl_no_use_wheel(finder.format_control) if opts.no_index is True: finder.index_urls = [] if opts.extra_index_urls: @@ -267,7 +236,7 @@ def break_args_options(line): return ' '.join(args), ' '.join(options) -def build_parser(): +def build_parser(line): """ Return a parser for parsing requirement lines """ @@ -281,6 +250,8 @@ def build_parser(): # 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) parser.exit = parser_exit @@ -336,7 +307,32 @@ def skip_regex(lines_enum, options): 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) + lines_enum = filterfalse(lambda e: pattern.search(e[1]), lines_enum) return lines_enum + + +def expand_env_variables(lines_enum): + """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/pipenv/patched/notpip/req/req_install.py b/pipenv/patched/notpip/_internal/req/req_install.py similarity index 66% rename from pipenv/patched/notpip/req/req_install.py rename to pipenv/patched/notpip/_internal/req/req_install.py index 22964474..442bf3ad 100644 --- a/pipenv/patched/notpip/req/req_install.py +++ b/pipenv/patched/notpip/_internal/req/req_install.py @@ -5,54 +5,52 @@ import os import re import shutil import sys -import tempfile +import sysconfig import traceback import warnings import zipfile - -from distutils import sysconfig from distutils.util import change_root -from email.parser import FeedParser +from email.parser import FeedParser # type: ignore -from notpip._vendor import pkg_resources, six +from notpip._vendor import pkg_resources, pytoml, six from notpip._vendor.packaging import specifiers from notpip._vendor.packaging.markers import Marker -from pip9._vendor.packaging.requirements import InvalidRequirement, Requirement -from pip9._vendor.packaging.utils import canonicalize_name -from pip9._vendor.packaging.version import Version, parse as parse_version -from pip9._vendor.six.moves import configparser +from notpip._vendor.packaging.requirements import InvalidRequirement, Requirement +from notpip._vendor.packaging.utils import canonicalize_name +from notpip._vendor.packaging.version import parse as parse_version +from notpip._vendor.packaging.version import Version +from notpip._vendor.pkg_resources import RequirementParseError, parse_requirements -import pip9.wheel - -from pip9.compat import native_str, get_stdlib, WINDOWS -from pip9.download import is_url, url_to_path, path_to_url, is_archive_file -from pip9.exceptions import ( - InstallationError, UninstallationError, +from notpip._internal import wheel +from notpip._internal.build_env import BuildEnvironment +from notpip._internal.compat import native_str +from notpip._internal.download import ( + is_archive_file, is_url, path_to_url, url_to_path, ) -from pip9.locations import ( - bin_py, running_under_virtualenv, PIP_DELETE_MARKER_FILENAME, bin_user, +from notpip._internal.exceptions import InstallationError, UninstallationError +from notpip._internal.locations import ( + PIP_DELETE_MARKER_FILENAME, running_under_virtualenv, ) -from pip9.utils import ( - display_path, rmtree, ask_path_exists, backup_dir, is_installable_dir, - dist_in_usersite, dist_in_site_packages, egg_link_path, - call_subprocess, read_text_file, FakeFile, _make_build_dir, ensure_dir, - get_installed_version, normalize_path, dist_is_local, +from notpip._internal.req.req_uninstall import UninstallPathSet +from notpip._internal.utils.deprecation import RemovedInPip11Warning +from notpip._internal.utils.hashes import Hashes +from notpip._internal.utils.logging import indent_log +from notpip._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, is_installable_dir, read_text_file, rmtree, ) - -from pip9.utils.hashes import Hashes -from pip9.utils.deprecation import RemovedInPip10Warning -from pip9.utils.logging import indent_log -from pip9.utils.setuptools_build import SETUPTOOLS_SHIM -from pip9.utils.ui import open_spinner -from pip9.req.req_uninstall import UninstallPathSet -from pip9.vcs import vcs -from pip9.wheel import move_wheel_files, Wheel - +from notpip._internal.utils.setuptools_build import SETUPTOOLS_SHIM +from notpip._internal.utils.temp_dir import TempDirectory +from notpip._internal.utils.ui import open_spinner +from notpip._internal.vcs import vcs +from notpip._internal.wheel import Wheel, move_wheel_files logger = logging.getLogger(__name__) operators = specifiers.Specifier._operators.keys() + def _strip_extras(path): m = re.match(r'^(.+)(\[[^\]]+\])$', path) extras = None @@ -65,40 +63,42 @@ def _strip_extras(path): return path_no_extras, extras -def _safe_extras(extras): - return set(pkg_resources.safe_extra(extra) for extra in extras) - - 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, comes_from, source_dir=None, editable=False, - link=None, as_egg=False, update=True, - pycompile=True, markers=None, isolated=False, options=None, - wheel_cache=None, constraint=False): - self.extras = () - if isinstance(req, six.string_types): - try: - req = Requirement(req) - except InvalidRequirement: - if os.path.sep in req: - add_msg = "It looks like a path. Does it exist ?" - elif '=' in req and not any(op in req for op in operators): - add_msg = "= is not a valid operator. Did you mean == ?" - else: - add_msg = traceback.format_exc() - raise InstallationError( - "Invalid requirement: '%s'\n%s" % (req, add_msg)) - self.extras = _safe_extras(req.extras) - + link=None, update=True, markers=None, + isolated=False, options=None, wheel_cache=None, + constraint=False, extras=()): + assert req is None or isinstance(req, Requirement), req self.req = req self.comes_from = comes_from self.constraint = constraint - self.source_dir = source_dir + 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 - self.link = self.original_link = link - self.as_egg = as_egg + if link is not None: + self.link = self.original_link = link + else: + from notpip._internal.index import Link + self.link = self.original_link = req and req.url and Link(req.url) + + 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 not None: self.markers = markers else: @@ -111,7 +111,7 @@ class InstallRequirement(object): # conflicts with another installed distribution: self.conflicts_with = None # Temporary build location - self._temp_build_dir = None + 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 @@ -120,44 +120,56 @@ class InstallRequirement(object): # Set to True after successful installation self.install_succeeded = None # UninstallPathSet of uninstalled distribution (for possible rollback) - self.uninstalled = None - # Set True if a legitimate do-nothing-on-uninstall has happened - e.g. - # system site packages, stdlib packages. - self.nothing_to_uninstall = False - self.use_user_site = False - self.target_dir = None + self.uninstalled_pathset = None self.options = options if options else {} - self.pycompile = pycompile # Set to True after successful preparation of this requirement self.prepared = False + self.is_direct = False self.isolated = isolated + self.build_env = BuildEnvironment(no_clean=True) @classmethod - def from_editable(cls, editable_req, comes_from=None, default_vcs=None, - isolated=False, options=None, wheel_cache=None, - constraint=False): - from pip9.index import Link + def from_editable(cls, editable_req, comes_from=None, isolated=False, + options=None, wheel_cache=None, constraint=False): + from notpip._internal.index import Link - name, url, extras_override = parse_editable( - editable_req, default_vcs) + name, url, extras_override = parse_editable(editable_req) if url.startswith('file:'): source_dir = url_to_path(url) else: source_dir = None - res = cls(name, comes_from, source_dir=source_dir, - editable=True, - link=Link(url), - constraint=constraint, - isolated=isolated, - options=options if options else {}, - wheel_cache=wheel_cache) + if name is not None: + try: + req = Requirement(name) + except InvalidRequirement: + raise InstallationError("Invalid requirement: '%s'" % name) + else: + req = None + return cls( + req, comes_from, source_dir=source_dir, + editable=True, + link=Link(url), + constraint=constraint, + isolated=isolated, + options=options if options else {}, + wheel_cache=wheel_cache, + extras=extras_override or (), + ) - if extras_override is not None: - res.extras = _safe_extras(extras_override) - - return res + @classmethod + def from_req(cls, req, comes_from=None, isolated=False, wheel_cache=None): + try: + req = Requirement(req) + except InvalidRequirement: + raise InstallationError("Invalid requirement: '%s'" % req) + if req.url: + raise InstallationError( + "Direct url requirement (like %s) are not allowed for " + "dependencies" % req + ) + return cls(req, comes_from, isolated=isolated, wheel_cache=wheel_cache) @classmethod def from_line( @@ -166,7 +178,7 @@ class InstallRequirement(object): """Creates an InstallRequirement from a name, which might be a requirement, directory containing 'setup.py', filename, or URL. """ - from pip9.index import Link + from notpip._internal.index import Link if is_url(name): marker_sep = '; ' @@ -191,9 +203,12 @@ class InstallRequirement(object): link = Link(name) else: p, extras = _strip_extras(path) - if (os.path.isdir(p) and - (os.path.sep in name or name.startswith('.'))): - + 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. File 'setup.py' " @@ -228,16 +243,31 @@ class InstallRequirement(object): else: req = name - options = options if options else {} - res = cls(req, comes_from, link=link, markers=markers, - isolated=isolated, options=options, - wheel_cache=wheel_cache, constraint=constraint) - if extras: - res.extras = _safe_extras( - Requirement('placeholder' + extras).extras) - - return res + extras = Requirement("placeholder" + extras.lower()).extras + else: + extras = () + if req is not None: + try: + req = Requirement(req) + except InvalidRequirement: + if os.path.sep in req: + add_msg = "It looks like a path." + add_msg += deduce_helpful_msg(req) + elif '=' in req and not any(op in req for op in operators): + add_msg = "= is not a valid operator. Did you mean == ?" + else: + add_msg = traceback.format_exc() + raise InstallationError( + "Invalid requirement: '%s'\n%s" % (req, add_msg)) + return cls( + req, comes_from, link=link, markers=markers, + isolated=isolated, + options=options if options else {}, + wheel_cache=wheel_cache, + constraint=constraint, + extras=extras, + ) def __str__(self): if self.req: @@ -277,7 +307,7 @@ class InstallRequirement(object): 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.cached_wheel(self.link, self.name) + self.link = self._wheel_cache.get(self.link, self.name) if old_link != self.link: logger.debug('Using cached wheel link: %s', self.link) @@ -293,7 +323,7 @@ class InstallRequirement(object): """ specifiers = self.specifier return (len(specifiers) == 1 and - next(iter(specifiers)).operator in ('==', '===')) + next(iter(specifiers)).operator in {'==', '==='}) def from_path(self): if self.req is None: @@ -309,8 +339,9 @@ class InstallRequirement(object): return s def build_location(self, build_dir): - if self._temp_build_dir is not None: - return self._temp_build_dir + 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 @@ -319,11 +350,10 @@ class InstallRequirement(object): # 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 = os.path.realpath( - tempfile.mkdtemp('-build', 'pip-') - ) + self._temp_build_dir.create() self._ideal_build_dir = build_dir - return self._temp_build_dir + + return self._temp_build_dir.path if self.editable: name = self.name.lower() else: @@ -348,10 +378,11 @@ class InstallRequirement(object): if self.source_dir is not None: return assert self.req is not None - assert self._temp_build_dir - assert self._ideal_build_dir - old_location = self._temp_build_dir - self._temp_build_dir = None + assert self._temp_build_dir.path + assert self._ideal_build_dir.path + 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( @@ -362,9 +393,9 @@ class InstallRequirement(object): self, display_path(old_location), display_path(new_location), ) shutil.move(old_location, new_location) - self._temp_build_dir = new_location + self._temp_build_dir.path = new_location self._ideal_build_dir = None - self.source_dir = new_location + self.source_dir = os.path.normpath(os.path.abspath(new_location)) self._egg_info_path = None @property @@ -382,18 +413,6 @@ class InstallRequirement(object): @property def setup_py(self): assert self.source_dir, "No source dir for %s" % self - try: - import setuptools # noqa - except ImportError: - if get_installed_version('setuptools') is None: - add_msg = "Please install setuptools." - else: - add_msg = traceback.format_exc() - # Setuptools is not available - raise InstallationError( - "Could not import setuptools which is required to " - "install from a source distribution.\n%s" % add_msg - ) setup_py = os.path.join(self.setup_py_dir, 'setup.py') @@ -403,6 +422,34 @@ class InstallRequirement(object): return setup_py + @property + def pyproject_toml(self): + assert self.source_dir, "No source dir for %s" % self + + pp_toml = os.path.join(self.setup_py_dir, 'pyproject.toml') + + # Python2 __file__ should not be unicode + if six.PY2 and isinstance(pp_toml, six.text_type): + pp_toml = pp_toml.encode(sys.getfilesystemencoding()) + + return pp_toml + + def get_pep_518_info(self): + """Get a list of the packages required to build the project, if any, + and a flag indicating whether pyproject.toml is present, indicating + that the build should be isolated. + + Build requirements can be specified in a pyproject.toml, as described + in PEP 518. If this file exists but doesn't specify build + requirements, pip will default to installing setuptools and wheel. + """ + if os.path.isfile(self.pyproject_toml): + with open(self.pyproject_toml) as f: + pp_toml = pytoml.load(f) + build_sys = pp_toml.get('build-system', {}) + return (build_sys.get('requires', ['setuptools', 'wheel']), True) + return (['setuptools', 'wheel'], False) + def run_egg_info(self): assert self.source_dir if self.name: @@ -418,7 +465,7 @@ class InstallRequirement(object): with indent_log(): script = SETUPTOOLS_SHIM % self.setup_py - base_cmd = [os.environ['PIP_PYTHON_PATH'], '-c', script] + base_cmd = [os.environ.get('PIP_PYTHON_PATH', sys.executable), '-c', script] if self.isolated: base_cmd += ["--no-user-cfg"] egg_info_cmd = base_cmd + ['egg_info'] @@ -431,11 +478,12 @@ class InstallRequirement(object): 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'] - call_subprocess( - egg_info_cmd + egg_base_option, - cwd=self.setup_py_dir, - show_stdout=False, - command_desc='python setup.py 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') if not self.req: if isinstance(parse_version(self.pkg_info()["Version"]), Version): @@ -506,7 +554,7 @@ class InstallRequirement(object): elif dir == 'test' or dir == 'tests': dirs.remove(dir) filenames.extend([os.path.join(root, dir) - for dir in dirs]) + for dir in dirs]) filenames = [f for f in filenames if f.endswith('.egg-info')] if not filenames: @@ -551,7 +599,7 @@ class InstallRequirement(object): logger.warning( 'Requested %s, but installing version %s', self, - self.installed_version, + version, ) else: logger.debug( @@ -590,7 +638,8 @@ class InstallRequirement(object): 'Unexpected version control type (in %s): %s' % (self.link, vc_type)) - def uninstall(self, auto_confirm=False): + def uninstall(self, auto_confirm=False, verbose=False, + use_user_site=False): """ Uninstall the distribution currently satisfying this requirement. @@ -603,171 +652,14 @@ class InstallRequirement(object): linked to global site-packages. """ - if not self.check_if_exists(): - raise UninstallationError( - "Cannot uninstall requirement %s, not installed" % (self.name,) - ) + if not self.check_if_exists(use_user_site): + logger.warning("Skipping %s as it is not installed.", self.name) + return dist = self.satisfied_by or self.conflicts_with - 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, - ) - self.nothing_to_uninstall = True - return - - if dist_path in get_stdlib(): - logger.info( - "Not uninstalling %s at %s, as it is in the standard library.", - dist.key, - dist_path, - ) - self.nothing_to_uninstall = True - return - - paths_to_remove = UninstallPathSet(dist) - develop_egg_link = egg_link_path(dist) - develop_egg_link_egg_info = '{0}.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: - warnings.warn( - "Uninstalling a distutils installed project ({0}) has been " - "deprecated and will be removed in a future version. This is " - "due to the fact that uninstalling a distutils project will " - "only partially uninstall the project.".format(self.name), - RemovedInPip10Warning, - ) - paths_to_remove.add(distutils_egg_info) - - 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 pip9.wheel.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, self.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 - if dist.has_metadata('entry_points.txt'): - if six.PY2: - options = {} - else: - options = {"delimiters": ('=', )} - config = configparser.SafeConfigParser(**options) - config.readfp( - FakeFile(dist.get_metadata_lines('entry_points.txt')) - ) - if config.has_section('console_scripts'): - for name, value in config.items('console_scripts'): - if dist_in_usersite(dist): - bin_dir = bin_user - else: - bin_dir = bin_py - paths_to_remove.add(os.path.join(bin_dir, name)) - if WINDOWS: - paths_to_remove.add( - os.path.join(bin_dir, name) + '.exe' - ) - paths_to_remove.add( - os.path.join(bin_dir, name) + '.exe.manifest' - ) - paths_to_remove.add( - os.path.join(bin_dir, name) + '-script.py' - ) - - paths_to_remove.remove(auto_confirm) - self.uninstalled = paths_to_remove - - def rollback_uninstall(self): - if self.uninstalled: - self.uninstalled.rollback() - else: - logger.error( - "Can't rollback %s, nothing uninstalled.", self.name, - ) - - def commit_uninstall(self): - if self.uninstalled: - self.uninstalled.commit() - elif not self.nothing_to_uninstall: - logger.error( - "Can't commit %s, nothing uninstalled.", self.name, - ) + uninstalled_pathset = UninstallPathSet.from_dist(dist) + uninstalled_pathset.remove(auto_confirm, verbose) + return uninstalled_pathset def archive(self, build_dir): assert self.source_dir @@ -837,17 +729,24 @@ class InstallRequirement(object): else: return True - def install(self, install_options, global_options=[], root=None, - prefix=None): + def install(self, install_options, global_options=None, root=None, + home=None, prefix=None, warn_script_location=True, + use_user_site=False, pycompile=True): + global_options = global_options if global_options is not None else [] if self.editable: self.install_editable( - install_options, global_options, prefix=prefix) + install_options, global_options, prefix=prefix, + ) return if self.is_wheel: - version = pip9.wheel.wheel_version(self.source_dir) - pip9.wheel.check_compatibility(version, self.name) + version = wheel.wheel_version(self.source_dir) + wheel.check_compatibility(version, self.name) - self.move_wheel_files(self.source_dir, root=root, prefix=prefix) + 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 @@ -856,35 +755,34 @@ class InstallRequirement(object): # 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 += self.options.get('global_options', []) - install_options += self.options.get('install_options', []) + global_options = list(global_options) + \ + self.options.get('global_options', []) + install_options = list(install_options) + \ + self.options.get('install_options', []) if self.isolated: - global_options = list(global_options) + ["--no-user-cfg"] + global_options = global_options + ["--no-user-cfg"] - temp_location = tempfile.mkdtemp('-record', 'pip-') - record_filename = os.path.join(temp_location, 'install-record.txt') - try: + 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) + 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(): - call_subprocess( - install_args + install_options, - cwd=self.setup_py_dir, - show_stdout=False, - spinner=spinner, - ) + 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 - if self.as_egg: - # there's no --always-unzip option we can pass to install - # command so we unable to save the installed-files.txt - return def prepend_root(path): if root is None or not os.path.isabs(path): @@ -914,16 +812,13 @@ class InstallRequirement(object): if os.path.isdir(filename): filename += os.path.sep new_lines.append( - os.path.relpath( - prepend_root(filename), egg_info_dir) + 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') - finally: - if os.path.exists(record_filename): - os.remove(record_filename) - rmtree(temp_location) def ensure_has_source_dir(self, parent_dir): """Ensure that a source_dir is set. @@ -939,22 +834,21 @@ class InstallRequirement(object): self.source_dir = self.build_location(parent_dir) return self.source_dir - def get_install_args(self, global_options, record_filename, root, prefix): - install_args = [os.environ['PIP_PYTHON_PATH'], "-u"] + def get_install_args(self, global_options, record_filename, root, prefix, + pycompile): + install_args = [os.environ.get('PIP_PYTHON_PATH', sys.executable), "-u"] install_args.append('-c') install_args.append(SETUPTOOLS_SHIM % self.setup_py) install_args += list(global_options) + \ ['install', '--record', record_filename] - - if not self.as_egg: - install_args += ['--single-version-externally-managed'] + 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 self.pycompile: + if pycompile: install_args += ["--compile"] else: install_args += ["--no-compile"] @@ -975,9 +869,8 @@ class InstallRequirement(object): logger.debug('Removing source in %s', self.source_dir) rmtree(self.source_dir) self.source_dir = None - if self._temp_build_dir and os.path.exists(self._temp_build_dir): - rmtree(self._temp_build_dir) - self._temp_build_dir = None + self._temp_build_dir.cleanup() + self.build_env.cleanup() def install_editable(self, install_options, global_options=(), prefix=None): @@ -987,27 +880,29 @@ class InstallRequirement(object): global_options = list(global_options) + ["--no-user-cfg"] if prefix: - prefix_param = ['--prefix={0}'.format(prefix)] + prefix_param = ['--prefix={}'.format(prefix)] install_options = list(install_options) + prefix_param with indent_log(): # FIXME: should we do --install-headers here too? - call_subprocess( - [ - os.environ['PIP_PYTHON_PATH'], - '-c', - SETUPTOOLS_SHIM % self.setup_py - ] + - list(global_options) + - ['develop', '--no-deps'] + - list(install_options), + with self.build_env: + call_subprocess( + [ + os.environ.get('PIP_PYTHON_PATH', 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) + cwd=self.setup_py_dir, + show_stdout=False, + ) self.install_succeeded = True - def check_if_exists(self): + def check_if_exists(self, use_user_site): """Find an installed distribution that satisfies or conflicts with this requirement, and set self.satisfied_by or self.conflicts_with appropriately. @@ -1034,7 +929,7 @@ class InstallRequirement(object): existing_dist = pkg_resources.get_distribution( self.req.name ) - if self.use_user_site: + if use_user_site: if dist_in_usersite(existing_dist): self.conflicts_with = existing_dist elif (running_under_virtualenv() and @@ -1052,27 +947,31 @@ class InstallRequirement(object): def is_wheel(self): return self.link and self.link.is_wheel - def move_wheel_files(self, wheeldir, root=None, prefix=None): + def move_wheel_files(self, wheeldir, root=None, home=None, prefix=None, + warn_script_location=True, use_user_site=False, + pycompile=True): move_wheel_files( self.name, self.req, wheeldir, - user=self.use_user_site, - home=self.target_dir, + user=use_user_site, + home=home, root=root, prefix=prefix, - pycompile=self.pycompile, + pycompile=pycompile, isolated=self.isolated, + warn_script_location=warn_script_location, ) def get_dist(self): """Return a pkg_resources.Distribution built from self.egg_info_path""" - egg_info = self.egg_info_path('').rstrip('/') + 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] return pkg_resources.Distribution( os.path.dirname(egg_info), project_name=dist_name, - metadata=metadata) + metadata=metadata, + ) @property def has_hash_options(self): @@ -1114,11 +1013,15 @@ def _strip_postfix(req): match = re.search(r'^(.*?)(?:-dev|-\d.*)$', req) if match: # Strip off -dev, -0.2, etc. + warnings.warn( + "#egg cleanup for editable urls will be dropped in the future", + RemovedInPip11Warning, + ) req = match.group(1) return req -def parse_editable(editable_req, default_vcs=None): +def parse_editable(editable_req): """Parses an editable requirement into: - a requirement name - an URL @@ -1129,18 +1032,12 @@ def parse_editable(editable_req, default_vcs=None): .[some_extra] """ - from pip9.index import Link + from notpip._internal.index import Link url = editable_req - extras = None # If a file path is specified with extras, strip off the extras. - m = re.match(r'^(.+)(\[[^\]]+\])$', url) - if m: - url_no_extras = m.group(1) - extras = m.group(2) - else: - url_no_extras = url + 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')): @@ -1168,19 +1065,11 @@ def parse_editable(editable_req, default_vcs=None): break if '+' not in url: - if default_vcs: - warnings.warn( - "--default-vcs has been deprecated and will be removed in " - "the future.", - RemovedInPip10Warning, - ) - url = default_vcs + '+' + url - else: - 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 - ) + 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() @@ -1193,11 +1082,34 @@ def parse_editable(editable_req, default_vcs=None): package_name = Link(url).egg_fragment if not package_name: raise InstallationError( - "Could not detect requirement name, please specify one with #egg=" - ) - if not package_name: - raise InstallationError( - '--editable=%s is not the right format; it must have ' - '#egg=Package' % editable_req + "Could not detect requirement name for '%s', please specify one " + "with #egg=your_package_name" % editable_req ) return _strip_postfix(package_name), url, None + + +def deduce_helpful_msg(req): + """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=1) + else: + msg += " File '%s' does not exist." % (req) + return msg diff --git a/pipenv/patched/notpip/_internal/req/req_set.py b/pipenv/patched/notpip/_internal/req/req_set.py new file mode 100644 index 00000000..d2c83b5e --- /dev/null +++ b/pipenv/patched/notpip/_internal/req/req_set.py @@ -0,0 +1,165 @@ +from __future__ import absolute_import + +import logging +from collections import OrderedDict + +from notpip._internal.exceptions import InstallationError +from notpip._internal.utils.logging import indent_log +from notpip._internal.wheel import Wheel + +logger = logging.getLogger(__name__) + + +class RequirementSet(object): + + def __init__(self, require_hashes=False, ignore_compatibility=True): + """Create a RequirementSet. + + :param wheel_cache: The pip wheel cache, for passing to + InstallRequirement. + """ + + self.requirements = OrderedDict() + self.require_hashes = require_hashes + + # Mapping of alias: real_name + self.requirement_aliases = {} + self.unnamed_requirements = [] + self.successfully_downloaded = [] + self.reqs_to_cleanup = [] + self.ignore_compatibility = ignore_compatibility + + 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, parent_req_name=None, + extras_requested=None): + """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 not install_req.match_markers(extras_requested): + logger.info("Ignoring %s: markers '%s' don't match your " + "environment", install_req.name, + install_req.markers) + return [], None + + # This check has to come after we filter requirements with the + # environment markers. + if install_req.link and install_req.link.is_wheel: + wheel = Wheel(install_req.link.filename) + if not wheel.supported() and not self.ignore_compatibility: + 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" + ) + + if not name: + # url or path requirement w/o an egg fragment + self.unnamed_requirements.append(install_req) + return [install_req], None + else: + try: + existing_req = self.get_requirement(name) + except KeyError: + existing_req = None + if (parent_req_name is None and existing_req and not + existing_req.constraint and + existing_req.extras == install_req.extras and not + existing_req.req.specifier == install_req.req.specifier): + raise InstallationError( + 'Double requirement given: %s (already in %s, name=%r)' + % (install_req, existing_req, name)) + if not existing_req: + # Add requirement + self.requirements[name] = install_req + # FIXME: what about other normalizations? E.g., _ vs. -? + if name.lower() != name: + self.requirement_aliases[name.lower()] = name + result = [install_req] + else: + # Assume there's no need to scan, and that we've already + # encountered this for scanning. + result = [] + if not install_req.constraint and existing_req.constraint: + if (install_req.link and not (existing_req.link and + install_req.link.path == existing_req.link.path)): + 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).union( + set(install_req.extras)))) + logger.debug("Setting %s extras to: %s", + existing_req, existing_req.extras) + # And now we need to scan this. + result = [existing_req] + # Canonicalise to the already-added object for the backref + # check below. + install_req = existing_req + + # We return install_req here to allow for the caller to add it to + # the dependency information for the parent package. + return result, install_req + + def has_requirement(self, project_name): + 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): + return list(req for req in self.requirements.values() if not + req.constraint) or self.unnamed_requirements + + def get_requirement(self, project_name): + 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): + """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/pipenv/patched/notpip/_internal/req/req_uninstall.py b/pipenv/patched/notpip/_internal/req/req_uninstall.py new file mode 100644 index 00000000..4d3b6743 --- /dev/null +++ b/pipenv/patched/notpip/_internal/req/req_uninstall.py @@ -0,0 +1,455 @@ +from __future__ import absolute_import + +import csv +import functools +import logging +import os +import sys +import sysconfig + +from notpip._vendor import pkg_resources + +from notpip._internal.compat import WINDOWS, cache_from_source, uses_pycache +from notpip._internal.exceptions import UninstallationError +from notpip._internal.locations import bin_py, bin_user +from notpip._internal.utils.logging import indent_log +from notpip._internal.utils.misc import ( + FakeFile, ask, dist_in_usersite, dist_is_local, egg_link_path, is_local, + normalize_path, renames, +) +from notpip._internal.utils.temp_dir import 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-.pyc + + Yield paths to all the files in RECORD. For each .py file in RECORD, add + the .pyc in the same directory. + + UninstallPathSet.add() takes care of the __pycache__ .pyc. + """ + 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 + + +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_add = any( + path.startswith(shortpath.rstrip("*")) and + path[len(shortpath.rstrip("*").rstrip(sep))] == sep + for shortpath in short_paths + ) + if not should_add: + short_paths.add(path) + return short_paths + + +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) + + 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.normcase(os.path.join(dirpath, fname)) + if os.path.isfile(file_) and file_ not in 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 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.save_dir = TempDirectory(kind="uninstall") + self._moved_paths = [] + + 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 _stash(self, path): + return os.path.join( + self.save_dir.path, os.path.splitdrive(path)[1].lstrip(os.path.sep) + ) + + 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): + self.save_dir.create() + + for path in sorted(compact(self.paths)): + new_path = self._stash(path) + logger.debug('Removing file or directory %s', path) + self._moved_paths.append(path) + renames(path, new_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) + + return ask('Proceed (y/n)? ', ('y', 'n')) == 'y' + + def rollback(self): + """Rollback the changes previously made by remove().""" + if self.save_dir.path is None: + 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) + for path in self._moved_paths: + tmp_path = self._stash(path) + logger.debug('Replacing %s', path) + renames(tmp_path, path) + for pth in self.pth.values(): + pth.rollback() + + def commit(self): + """Remove temporary save dir: rollback will no longer be possible.""" + self.save_dir.cleanup() + self._moved_paths = [] + + @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/pipenv/patched/notpip/_internal/resolve.py b/pipenv/patched/notpip/_internal/resolve.py new file mode 100644 index 00000000..fcc79524 --- /dev/null +++ b/pipenv/patched/notpip/_internal/resolve.py @@ -0,0 +1,381 @@ +"""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 notpip._internal.exceptions import ( + BestVersionAlreadyInstalled, DistributionNotFound, HashError, HashErrors, + UnsupportedPythonVersion, +) + +from notpip._internal.req.req_install import InstallRequirement +from notpip._internal.utils.logging import indent_log +from notpip._internal.utils.misc import dist_in_usersite, ensure_dir +from notpip._internal.utils.packaging import check_dist_requires_python + +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, session, finder, wheel_cache, use_user_site, + ignore_dependencies, ignore_installed, ignore_requires_python, + force_reinstall, isolated, upgrade_strategy): + 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 + + self.require_hashes = None # This is set in resolve + + 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.ignore_compatibility = ignore_requires_python + self.use_user_site = use_user_site + + self._discovered_dependencies = defaultdict(list) + + def resolve(self, requirement_set): + """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 = [] + 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): + 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): + """ + 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): + """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 'not upgraded as not directly required' + 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): + """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, req_to_install, ignore_requires_python=False): + """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 ignore_requires_python or self.ignore_requires_python: + self.ignore_compatibility = True + + 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(self.finder) + try: + check_dist_requires_python(dist) + except UnsupportedPythonVersion as err: + if self.ignore_compatibility: + logger.warning(err.args[0]) + else: + raise + + # A huge hack, by Kenneth Reitz. + try: + self.requires_python = check_dist_requires_python(dist, absorb=False) + except TypeError: + self.requires_python = None + + more_reqs = [] + + def add_req(subreq, extras_requested): + sub_install_req = InstallRequirement.from_req( + str(subreq), + req_to_install, + isolated=self.isolated, + wheel_cache=self.wheel_cache, + ) + 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): + available_requested = sorted( + set(dist.extras) & set(req_to_install.extras) + ) + # 'unnamed' requirements will get added here + req_to_install.is_direct = True + requirement_set.add_requirement( + req_to_install, parent_req_name=None, + extras_requested=available_requested, + ) + + 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) + + # Hack for deep-resolving extras. + for available in available_requested: + if hasattr(dist, '_DistInfoDistribution__dep_map'): + for req in dist._DistInfoDistribution__dep_map[available]: + req = InstallRequirement.from_req( + str(req), + req_to_install, + isolated=self.isolated, + wheel_cache=self.wheel_cache, + ) + + more_reqs.append(req) + + 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): + """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() + + 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/pipenv/patched/notpip/status_codes.py b/pipenv/patched/notpip/_internal/status_codes.py similarity index 100% rename from pipenv/patched/notpip/status_codes.py rename to pipenv/patched/notpip/_internal/status_codes.py diff --git a/pipenv/patched/notpip/_internal/utils/__init__.py b/pipenv/patched/notpip/_internal/utils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pipenv/patched/notpip/utils/appdirs.py b/pipenv/patched/notpip/_internal/utils/appdirs.py similarity index 94% rename from pipenv/patched/notpip/utils/appdirs.py rename to pipenv/patched/notpip/_internal/utils/appdirs.py index 026a9450..f84ada95 100644 --- a/pipenv/patched/notpip/utils/appdirs.py +++ b/pipenv/patched/notpip/_internal/utils/appdirs.py @@ -7,8 +7,9 @@ from __future__ import absolute_import import os import sys -from pip9.compat import WINDOWS, expanduser -from pip9._vendor.six import PY2, text_type +from notpip._vendor.six import PY2, text_type + +from notpip._internal.compat import WINDOWS, expanduser def user_cache_dir(appname): @@ -60,7 +61,7 @@ def user_cache_dir(appname): def user_data_dir(appname, roaming=False): - """ + r""" Return full path to the user-specific data dir for this application. "appname" is the name of application. @@ -74,6 +75,7 @@ def user_data_dir(appname, roaming=False): 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\\ ... @@ -93,6 +95,13 @@ def user_data_dir(appname, roaming=False): 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( @@ -137,7 +146,7 @@ def user_config_dir(appname, roaming=True): # for the discussion regarding site_config_dirs locations # see def site_config_dirs(appname): - """Return a list of potential user-shared config dirs for this application. + r"""Return a list of potential user-shared config dirs for this application. "appname" is the name of application. @@ -222,6 +231,7 @@ def _get_win_folder_with_ctypes(csidl_name): return buf.value + if WINDOWS: try: import ctypes diff --git a/pipenv/patched/notpip/utils/deprecation.py b/pipenv/patched/notpip/_internal/utils/deprecation.py similarity index 80% rename from pipenv/patched/notpip/utils/deprecation.py rename to pipenv/patched/notpip/_internal/utils/deprecation.py index afe12b00..66ee504c 100644 --- a/pipenv/patched/notpip/utils/deprecation.py +++ b/pipenv/patched/notpip/_internal/utils/deprecation.py @@ -6,6 +6,11 @@ from __future__ import absolute_import import logging import warnings +from notpip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any + class PipDeprecationWarning(Warning): pass @@ -15,22 +20,18 @@ class Pending(object): pass -class RemovedInPip10Warning(PipDeprecationWarning): +class RemovedInPip11Warning(PipDeprecationWarning): pass -class RemovedInPip11Warning(PipDeprecationWarning, Pending): - pass - - -class Python26DeprecationWarning(PipDeprecationWarning): +class RemovedInPip12Warning(PipDeprecationWarning, Pending): pass # Warnings <-> Logging Integration -_warnings_showwarning = None +_warnings_showwarning = None # type: Any def _showwarning(message, category, filename, lineno, file=None, line=None): @@ -42,8 +43,8 @@ def _showwarning(message, category, filename, lineno, file=None, line=None): else: if issubclass(category, PipDeprecationWarning): # We use a specially named logger which will handle all of the - # deprecation messages for pip9. - logger = logging.getLogger("pip9.deprecations") + # deprecation messages for pip. + logger = logging.getLogger("pip._internal.deprecations") # This is purposely using the % formatter here instead of letting # the logging module handle the interpolation. This is because we @@ -53,7 +54,7 @@ def _showwarning(message, category, filename, lineno, file=None, line=None): # PipDeprecationWarnings that are Pending still have at least 2 # versions to go until they are removed so they can just be # warnings. Otherwise, they will be removed in the very next - # version of pip9. We want these to be more obvious so we use the + # version of pip. We want these to be more obvious so we use the # ERROR logging level. if issubclass(category, Pending): logger.warning(log_message) diff --git a/pipenv/patched/notpip/utils/encoding.py b/pipenv/patched/notpip/_internal/utils/encoding.py similarity index 83% rename from pipenv/patched/notpip/utils/encoding.py rename to pipenv/patched/notpip/_internal/utils/encoding.py index 24831686..56f60361 100644 --- a/pipenv/patched/notpip/utils/encoding.py +++ b/pipenv/patched/notpip/_internal/utils/encoding.py @@ -1,7 +1,7 @@ import codecs import locale import re - +import sys BOMS = [ (codecs.BOM_UTF8, 'utf8'), @@ -13,7 +13,7 @@ BOMS = [ (codecs.BOM_UTF32_LE, 'utf32-le'), ] -ENCODING_RE = re.compile(b'coding[:=]\s*([-\w.]+)') +ENCODING_RE = re.compile(br'coding[:=]\s*([-\w.]+)') def auto_decode(data): @@ -28,4 +28,6 @@ def auto_decode(data): 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)) + return data.decode( + locale.getpreferredencoding(False) or sys.getdefaultencoding(), + ) diff --git a/pipenv/patched/notpip/utils/filesystem.py b/pipenv/patched/notpip/_internal/utils/filesystem.py similarity index 94% rename from pipenv/patched/notpip/utils/filesystem.py rename to pipenv/patched/notpip/_internal/utils/filesystem.py index e8bb76b1..0eee26a7 100644 --- a/pipenv/patched/notpip/utils/filesystem.py +++ b/pipenv/patched/notpip/_internal/utils/filesystem.py @@ -1,7 +1,7 @@ import os import os.path -from pip9.compat import get_path_uid +from notpip._internal.compat import get_path_uid def check_path_owner(path): diff --git a/pipenv/patched/notpip/utils/glibc.py b/pipenv/patched/notpip/_internal/utils/glibc.py similarity index 93% rename from pipenv/patched/notpip/utils/glibc.py rename to pipenv/patched/notpip/_internal/utils/glibc.py index 7847885c..ebcfc5be 100644 --- a/pipenv/patched/notpip/utils/glibc.py +++ b/pipenv/patched/notpip/_internal/utils/glibc.py @@ -1,8 +1,7 @@ from __future__ import absolute_import -import re import ctypes -import platform +import re import warnings @@ -73,9 +72,13 @@ def have_compatible_glibc(required_major, minimum_minor): # misleading. Solution: instead of using platform, use our code that actually # works. def libc_ver(): + """Try to determine the glibc version + + Returns a tuple of strings (lib, version) which default to empty strings + in case the lookup fails. + """ glibc_version = glibc_version_string() if glibc_version is None: - # For non-glibc platforms, fall back on platform.libc_ver - return platform.libc_ver() + return ("", "") else: return ("glibc", glibc_version) diff --git a/pipenv/patched/notpip/utils/hashes.py b/pipenv/patched/notpip/_internal/utils/hashes.py similarity index 92% rename from pipenv/patched/notpip/utils/hashes.py rename to pipenv/patched/notpip/_internal/utils/hashes.py index f9f13f5f..1e8fd889 100644 --- a/pipenv/patched/notpip/utils/hashes.py +++ b/pipenv/patched/notpip/_internal/utils/hashes.py @@ -2,10 +2,12 @@ from __future__ import absolute_import import hashlib -from pip9.exceptions import HashMismatch, HashMissing, InstallationError -from pip9.utils import read_chunks -from pip9._vendor.six import iteritems, iterkeys, itervalues +from notpip._vendor.six import iteritems, iterkeys, itervalues +from notpip._internal.exceptions import ( + HashMismatch, HashMissing, InstallationError, +) +from notpip._internal.utils.misc import read_chunks # The recommended hash algo of the moment. Change this whenever the state of # the art changes; it won't hurt backward compatibility. diff --git a/pipenv/patched/notpip/utils/logging.py b/pipenv/patched/notpip/_internal/utils/logging.py similarity index 88% rename from pipenv/patched/notpip/utils/logging.py rename to pipenv/patched/notpip/_internal/utils/logging.py index 82e7751f..3b40c83f 100644 --- a/pipenv/patched/notpip/utils/logging.py +++ b/pipenv/patched/notpip/_internal/utils/logging.py @@ -5,16 +5,17 @@ import logging import logging.handlers import os +from notpip._internal.compat import WINDOWS +from notpip._internal.utils.misc import ensure_dir + try: import threading except ImportError: - import dummy_threading as threading + import dummy_threading as threading # type: ignore -from pip9.compat import WINDOWS -from pip9.utils import ensure_dir try: - from pip9._vendor import colorama + from notpip._vendor import colorama # Lots of different errors can come from this, including SystemError and # ImportError. except Exception: @@ -75,15 +76,16 @@ class ColorizedStreamHandler(logging.StreamHandler): else: COLORS = [] - def __init__(self, stream=None): + 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 should_color(self): - # Don't colorize things if we do not have colorama - if not colorama: + # 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 = ( diff --git a/pipenv/patched/notpip/utils/__init__.py b/pipenv/patched/notpip/_internal/utils/misc.py similarity index 93% rename from pipenv/patched/notpip/utils/__init__.py rename to pipenv/patched/notpip/_internal/utils/misc.py index 7f6b06ff..b77907a1 100644 --- a/pipenv/patched/notpip/utils/__init__.py +++ b/pipenv/patched/notpip/_internal/utils/misc.py @@ -1,6 +1,5 @@ from __future__ import absolute_import -from collections import deque import contextlib import errno import io @@ -8,26 +7,30 @@ import locale # we have a submodule named 'logging' which would shadow this if we used the # regular name: import logging as std_logging -import re import os import posixpath +import re import shutil import stat import subprocess import sys import tarfile import zipfile +from collections import deque -from pip9.exceptions import InstallationError -from pip9.compat import console_to_str, expanduser, stdlib_pkgs -from pip9.locations import ( - site_packages, user_site, running_under_virtualenv, virtualenv_no_global, +from notpip._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 notpip._vendor.retrying import retry # type: ignore +from notpip._vendor.six import PY2 +from notpip._vendor.six.moves import input + +from notpip._internal.compat import console_to_str, expanduser, stdlib_pkgs +from notpip._internal.exceptions import InstallationError +from notpip._internal.locations import ( + running_under_virtualenv, site_packages, user_site, virtualenv_no_global, write_delete_marker_file, ) -from pip9._vendor import pkg_resources -from pip9._vendor.six.moves import input -from pip9._vendor.six import PY2 -from pip9._vendor.retrying import retry if PY2: from io import BytesIO as StringIO @@ -40,7 +43,7 @@ __all__ = ['rmtree', 'display_path', 'backup_dir', 'is_svn_page', 'file_contents', 'split_leading_dir', 'has_leading_dir', 'normalize_path', - 'renames', 'get_terminal_size', 'get_prog', + 'renames', 'get_prog', 'unzip_file', 'untar_file', 'unpack_file', 'call_subprocess', 'captured_stdout', 'ensure_dir', 'ARCHIVE_EXTENSIONS', 'SUPPORTED_EXTENSIONS', @@ -88,8 +91,11 @@ def ensure_dir(path): def get_prog(): try: - if os.path.basename(sys.argv[0]) in ('__main__.py', '-c'): - return "%s -m pip" % os.environ['PIP_PYTHON_PATH'] + prog = os.path.basename(sys.argv[0]) + if prog in ('__main__.py', '-c'): + return "%s -m pip" % os.environ.get('PIP_PYTHON_PATH', sys.executable) + else: + return prog except (AttributeError, TypeError, IndexError): pass return 'pip' @@ -308,7 +314,7 @@ def dist_in_usersite(dist): def dist_in_site_packages(dist): """ Return True if given Distribution is installed in - distutils.sysconfig.get_python_lib(). + sysconfig.get_python_lib(). """ return normalize_path( dist_location(dist) @@ -338,7 +344,7 @@ def get_installed_distributions(local_only=True, ``skip`` argument is an iterable of lower-case project names to ignore; defaults to stdlib_pkgs - If ``editables`` is False, don't report editables. + If ``include_editables`` is False, don't report editables. If ``editables_only`` is True , only report editables. @@ -432,36 +438,6 @@ def dist_location(dist): return dist.location -def get_terminal_size(): - """Returns a tuple (x, y) representing the width(x) and the height(x) - in characters of the terminal window.""" - def ioctl_GWINSZ(fd): - try: - import fcntl - import termios - import struct - cr = struct.unpack( - 'hh', - fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234') - ) - except: - 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: - pass - if not cr: - cr = (os.environ.get('LINES', 25), os.environ.get('COLUMNS', 80)) - return int(cr[1]), int(cr[0]) - - def current_umask(): """Get the current umask which involves having to set it temporarily.""" mask = os.umask(0) @@ -606,7 +582,7 @@ def unpack_file(filename, location, content_type, link): elif (content_type and content_type.startswith('text/html') and is_svn_page(file_contents(filename))): # We don't really care about this - from pip9.vcs.subversion import Subversion + from notpip._internal.vcs.subversion import Subversion Subversion('svn+' + link.url).unpack(location) else: # FIXME: handle? @@ -624,7 +600,14 @@ def unpack_file(filename, location, content_type, link): def call_subprocess(cmd, show_stdout=True, cwd=None, on_returncode='raise', command_desc=None, - extra_environ=None, spinner=None): + extra_environ=None, unset_environ=None, spinner=None): + """ + Args: + unset_environ: an iterable of environment variable names to unset + prior to calling subprocess.Popen(). + """ + 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. @@ -661,17 +644,21 @@ def call_subprocess(cmd, show_stdout=True, cwd=None, 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=None, stdout=stdout, - cwd=cwd, env=env) + 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: - all_output = [] while True: line = console_to_str(proc.stdout.readline()) if not line: @@ -685,7 +672,11 @@ def call_subprocess(cmd, show_stdout=True, cwd=None, # Update the spinner if spinner is not None: spinner.spin() - proc.wait() + try: + proc.wait() + finally: + if proc.stdout: + proc.stdout.close() if spinner is not None: if proc.returncode: spinner.finish("error") @@ -850,3 +841,11 @@ def get_installed_version(dist_name, lookup_dirs=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) diff --git a/pipenv/patched/notpip/utils/outdated.py b/pipenv/patched/notpip/_internal/utils/outdated.py similarity index 76% rename from pipenv/patched/notpip/utils/outdated.py rename to pipenv/patched/notpip/_internal/utils/outdated.py index 0f3eeee3..c0f401f2 100644 --- a/pipenv/patched/notpip/utils/outdated.py +++ b/pipenv/patched/notpip/_internal/utils/outdated.py @@ -6,15 +6,14 @@ import logging import os.path import sys -from pip9._vendor import lockfile -from pip9._vendor.packaging import version as packaging_version - -from pip9.compat import total_seconds, WINDOWS -from pip9.models import PyPI -from pip9.locations import USER_CACHE_DIR, running_under_virtualenv -from pip9.utils import ensure_dir, get_installed_version -from pip9.utils.filesystem import check_path_owner +from notpip._vendor import lockfile +from notpip._vendor.packaging import version as packaging_version +from notpip._internal.compat import WINDOWS +from notpip._internal.index import PackageFinder +from notpip._internal.locations import USER_CACHE_DIR, running_under_virtualenv +from notpip._internal.utils.filesystem import check_path_owner +from notpip._internal.utils.misc import ensure_dir, get_installed_version SELFCHECK_DATE_FMT = "%Y-%m-%dT%H:%M:%SZ" @@ -92,15 +91,15 @@ def load_selfcheck_statefile(): return GlobalSelfCheckState() -def pip_version_check(session): - """Check for an update for pip9. +def pip_version_check(session, options): + """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 installed_version is None: + if not installed_version: return pip_version = packaging_version.parse(installed_version) @@ -116,23 +115,26 @@ def pip_version_check(session): state.state["last_check"], SELFCHECK_DATE_FMT ) - if total_seconds(current_time - last_check) < 7 * 24 * 60 * 60: + 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: - resp = session.get( - PyPI.pip_json_url, - headers={"Accept": "application/json"}, + # 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, + process_dependency_links=options.process_dependency_links, + 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 ) - resp.raise_for_status() - pypi_version = [ - v for v in sorted( - list(resp.json()["releases"]), - key=packaging_version.parse, - ) - if not packaging_version.parse(v).is_prerelease - ][-1] # save that we've performed a check state.save(pypi_version, current_time) @@ -143,7 +145,7 @@ def pip_version_check(session): if (pip_version < remote_version and pip_version.base_version != remote_version.base_version): # Advise "python -m pip" on Windows to avoid issues - # with overwriting pip9.exe. + # with overwriting pip.exe. if WINDOWS: pip_cmd = "python -m pip" else: @@ -154,7 +156,6 @@ def pip_version_check(session): "'%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", diff --git a/pipenv/patched/notpip/utils/packaging.py b/pipenv/patched/notpip/_internal/utils/packaging.py similarity index 78% rename from pipenv/patched/notpip/utils/packaging.py rename to pipenv/patched/notpip/_internal/utils/packaging.py index 2f399e5b..a8d0e674 100644 --- a/pipenv/patched/notpip/utils/packaging.py +++ b/pipenv/patched/notpip/_internal/utils/packaging.py @@ -1,19 +1,18 @@ from __future__ import absolute_import -from email.parser import FeedParser - import logging -import sys import os +import sys +from email.parser import FeedParser # type: ignore -from pip9._vendor.packaging import specifiers -from pip9._vendor.packaging import version -from pip9._vendor import pkg_resources +from notpip._vendor import pkg_resources +from notpip._vendor.packaging import specifiers, version -from pip9 import exceptions +from notpip._internal import exceptions logger = logging.getLogger(__name__) + def check_requires_python(requires_python): """ Check if the python version in use match the `requires_python` specifier. @@ -28,6 +27,7 @@ def check_requires_python(requires_python): # The package provides no information return True requires_python_specifier = specifiers.SpecifierSet(requires_python) + # We only use major.minor.micro python_version = version.parse('{0}.{1}.{2}'.format(*sys.version_info[:3])) return python_version in requires_python_specifier @@ -49,19 +49,26 @@ def check_dist_requires_python(dist, absorb=True): requires_python = pkg_info_dict.get('Requires-Python') if not absorb: return 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, - # '{0}.{1}.{2}'.format(*sys.version_info[:3]) - # ) + # '.'.join(map(str, sys.version_info[:3])),) # ) return except specifiers.InvalidSpecifier as e: logger.warning( - "Package %s has an invalid Requires-Python entry %s - %s" % ( - dist.project_name, requires_python, e)) + "Package %s has an invalid Requires-Python entry %s - %s", + dist.project_name, requires_python, e, + ) return + + +def get_installer(dist): + if dist.has_metadata('INSTALLER'): + for line in dist.get_metadata_lines('INSTALLER'): + if line.strip(): + return line.strip() + return '' diff --git a/pipenv/patched/notpip/utils/setuptools_build.py b/pipenv/patched/notpip/_internal/utils/setuptools_build.py similarity index 100% rename from pipenv/patched/notpip/utils/setuptools_build.py rename to pipenv/patched/notpip/_internal/utils/setuptools_build.py diff --git a/pipenv/patched/notpip/_internal/utils/temp_dir.py b/pipenv/patched/notpip/_internal/utils/temp_dir.py new file mode 100644 index 00000000..a425a81c --- /dev/null +++ b/pipenv/patched/notpip/_internal/utils/temp_dir.py @@ -0,0 +1,82 @@ +from __future__ import absolute_import + +import logging +import os.path +import tempfile + +from notpip._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 it's 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 diff --git a/pipenv/patched/notpip/_internal/utils/typing.py b/pipenv/patched/notpip/_internal/utils/typing.py new file mode 100644 index 00000000..fc5186c6 --- /dev/null +++ b/pipenv/patched/notpip/_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 notpip.utils.typing import MYPY_CHECK_RUNNING + + if MYPY_CHECK_RUNNING: + from typing import ... + +Ref: https://github.com/python/mypy/issues/3216 +""" + +MYPY_CHECK_RUNNING = False diff --git a/pipenv/patched/notpip/utils/ui.py b/pipenv/patched/notpip/_internal/utils/ui.py similarity index 79% rename from pipenv/patched/notpip/utils/ui.py rename to pipenv/patched/notpip/_internal/utils/ui.py index 14cf605b..276dcea3 100644 --- a/pipenv/patched/notpip/utils/ui.py +++ b/pipenv/patched/notpip/_internal/utils/ui.py @@ -1,24 +1,30 @@ -from __future__ import absolute_import -from __future__ import division +from __future__ import absolute_import, division -import itertools -import sys -from signal import signal, SIGINT, default_int_handler -import time import contextlib +import itertools import logging +import sys +import time +from signal import SIGINT, default_int_handler, signal -from pip9.compat import WINDOWS -from pip9.utils import format_size -from pip9.utils.logging import get_indentation -from pip9._vendor import six -from pip9._vendor.progress.bar import Bar, IncrementalBar -from pip9._vendor.progress.helpers import (WritelnMixin, - HIDE_CURSOR, SHOW_CURSOR) -from pip9._vendor.progress.spinner import Spinner +from notpip._vendor import six +from notpip._vendor.progress.bar import ( + Bar, ChargingBar, FillingCirclesBar, FillingSquaresBar, IncrementalBar, + ShadyBar, +) +from notpip._vendor.progress.helpers import HIDE_CURSOR, SHOW_CURSOR, WritelnMixin +from notpip._vendor.progress.spinner import Spinner + +from notpip._internal.compat import WINDOWS +from notpip._internal.utils.logging import get_indentation +from notpip._internal.utils.misc import format_size +from notpip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any try: - from pip9._vendor import colorama + from notpip._vendor import colorama # Lots of different errors can come from this, including SystemError and # ImportError. except Exception: @@ -54,7 +60,7 @@ def _select_progress_class(preferred, fallback): return preferred -_BaseBar = _select_progress_class(IncrementalBar, Bar) +_BaseBar = _select_progress_class(IncrementalBar, Bar) # type: Any class InterruptibleMixin(object): @@ -112,6 +118,20 @@ class InterruptibleMixin(object): 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): @@ -171,13 +191,54 @@ class WindowsMixin(object): self.file.flush = lambda: self.file.wrapped.flush() -class DownloadProgressBar(WindowsMixin, InterruptibleMixin, - DownloadProgressMixin, _BaseBar): +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): # type: ignore + 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): @@ -205,6 +266,22 @@ class DownloadProgressSpinner(WindowsMixin, InterruptibleMixin, 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 # diff --git a/pipenv/patched/notpip/vcs/__init__.py b/pipenv/patched/notpip/_internal/vcs/__init__.py similarity index 76% rename from pipenv/patched/notpip/vcs/__init__.py rename to pipenv/patched/notpip/_internal/vcs/__init__.py index 5d0ba7a9..07de36d9 100644 --- a/pipenv/patched/notpip/vcs/__init__.py +++ b/pipenv/patched/notpip/_internal/vcs/__init__.py @@ -1,18 +1,24 @@ """Handles all VCS (version control) support""" from __future__ import absolute_import +import copy import errno import logging import os import shutil import sys -from pip9._vendor.six.moves.urllib import parse as urllib_parse +from notpip._vendor.six.moves.urllib import parse as urllib_parse -from pip9.exceptions import BadCommand -from pip9.utils import (display_path, backup_dir, call_subprocess, - rmtree, ask_path_exists) +from notpip._internal.exceptions import BadCommand +from notpip._internal.utils.misc import ( + display_path, backup_dir, call_subprocess, rmtree, ask_path_exists, +) +from notpip._internal.utils.typing import MYPY_CHECK_RUNNING +if MYPY_CHECK_RUNNING: + from typing import Dict, Optional, Tuple + from notpip._internal.basecommand import Command __all__ = ['vcs', 'get_src_requirement'] @@ -20,8 +26,69 @@ __all__ = ['vcs', 'get_src_requirement'] logger = logging.getLogger(__name__) +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): + """ + 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 ''.format(self.vcs.name, self.rev) + + @property + def arg_rev(self): + if self.rev is None: + return self.vcs.default_arg_rev + + return self.rev + + def to_args(self): + """ + Return the VCS-specific command arguments. + """ + args = [] + 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): + if not self.rev: + return '' + + return ' (to revision {})'.format(self.rev) + + def make_new(self, rev): + """ + 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 = {} + _registry = {} # type: Dict[str, Command] schemes = ['ssh', 'git', 'hg', 'bzr', 'sftp', 'svn'] def __init__(self): @@ -98,12 +165,34 @@ class VersionControl(object): name = '' dirname = '' # List of supported schemes for this Version Control - schemes = () + 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): + """ + 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) + def _is_local_repository(self, repo): """ posix absolute paths start with os.path.sep, @@ -175,31 +264,44 @@ class VersionControl(object): 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, rev_options): """ Update an already-existing repo to the given ``rev_options``. + + Args: + rev_options: a RevOptions object. """ raise NotImplementedError - def check_version(self, dest, rev_options): + def is_commit_id_equal(self, dest, name): """ - Return True if the version is identical to what exists and - doesn't need to be updated. + Return whether the id of the current commit equals the given name. + + Args: + dest: the repository directory. + name: a string name. """ raise NotImplementedError - def check_destination(self, dest, url, rev_options, rev_display): + def check_destination(self, dest, url, rev_options): """ Prepare a location to receive a checkout/clone. Return True if the location is ready for (and requires) a checkout/clone, False otherwise. + + Args: + rev_options: a RevOptions object. """ checkout = True prompt = False + rev_display = rev_options.to_display() if os.path.exists(dest): checkout = False if os.path.exists(os.path.join(dest, self.dirname)): @@ -211,7 +313,7 @@ class VersionControl(object): display_path(dest), url, ) - if not self.check_version(dest, rev_options): + if not self.is_commit_id_equal(dest, rev_options.rev): logger.info( 'Updating %s %s%s', display_path(dest), @@ -303,8 +405,7 @@ class VersionControl(object): def get_revision(self, location): """ - Return the current revision of the files at location - Used in get_info + Return the current commit id of the files at the given location. """ raise NotImplementedError @@ -322,12 +423,16 @@ class VersionControl(object): return call_subprocess(cmd, show_stdout, cwd, on_returncode, command_desc, extra_environ, - spinner) + unset_environ=self.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' % self.name) + raise BadCommand( + 'Cannot find command %r - do you have ' + '%r installed and in your ' + 'PATH?' % (self.name, self.name)) else: raise # re-raise exception if a different error occurred diff --git a/pipenv/patched/notpip/vcs/bazaar.py b/pipenv/patched/notpip/_internal/vcs/bazaar.py similarity index 67% rename from pipenv/patched/notpip/vcs/bazaar.py rename to pipenv/patched/notpip/_internal/vcs/bazaar.py index b75ad52f..a78ac8b9 100644 --- a/pipenv/patched/notpip/vcs/bazaar.py +++ b/pipenv/patched/notpip/_internal/vcs/bazaar.py @@ -2,18 +2,13 @@ from __future__ import absolute_import import logging import os -import tempfile -# TODO: Get this into six.moves.urllib.parse -try: - from urllib import parse as urllib_parse -except ImportError: - import urlparse as urllib_parse - -from pip9.utils import rmtree, display_path -from pip9.vcs import vcs, VersionControl -from pip9.download import path_to_url +from notpip._vendor.six.moves.urllib import parse as urllib_parse +from notpip._internal.download import path_to_url +from notpip._internal.utils.misc import display_path, rmtree +from notpip._internal.utils.temp_dir import TempDirectory +from notpip._internal.vcs import VersionControl, vcs logger = logging.getLogger(__name__) @@ -29,49 +24,50 @@ class Bazaar(VersionControl): def __init__(self, url=None, *args, **kwargs): super(Bazaar, self).__init__(url, *args, **kwargs) - # Python >= 2.7.4, 3.3 doesn't have uses_fragment or non_hierarchical + # 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']) - urllib_parse.non_hierarchical.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 """ - temp_dir = tempfile.mkdtemp('-export', 'pip-') - self.unpack(temp_dir) + # Remove the location to make sure Bazaar can export it correctly if os.path.exists(location): - # Remove the location to make sure Bazaar can export it correctly rmtree(location) - try: - self.run_command(['export', location], cwd=temp_dir, - show_stdout=False) - finally: - rmtree(temp_dir) + + 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 switch(self, dest, url, rev_options): self.run_command(['switch', url], cwd=dest) def update(self, dest, rev_options): - self.run_command(['pull', '-q'] + rev_options, cwd=dest) + cmd_args = ['pull', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) def obtain(self, dest): url, rev = self.get_url_rev() - if rev: - rev_options = ['-r', rev] - rev_display = ' (to revision %s)' % rev - else: - rev_options = [] - rev_display = '' - if self.check_destination(dest, url, rev_options, rev_display): + rev_options = self.make_rev_options(rev) + if self.check_destination(dest, url, rev_options): + rev_display = rev_options.to_display() logger.info( 'Checking out %s%s to %s', url, rev_display, display_path(dest), ) - self.run_command(['branch', '-q'] + rev_options + [url, dest]) + cmd_args = ['branch', '-q'] + rev_options.to_args() + [url, dest] + self.run_command(cmd_args) def get_url_rev(self): # hotfix the URL scheme after removing bzr+ from bzr+ssh:// readd it @@ -95,7 +91,8 @@ class Bazaar(VersionControl): def get_revision(self, location): revision = self.run_command( - ['revno'], show_stdout=False, cwd=location) + ['revno'], show_stdout=False, cwd=location, + ) return revision.splitlines()[-1] def get_src_requirement(self, dist, location): @@ -108,7 +105,7 @@ class Bazaar(VersionControl): current_rev = self.get_revision(location) return '%s@%s#egg=%s' % (repo, current_rev, egg_project_name) - def check_version(self, dest, rev_options): + def is_commit_id_equal(self, dest, name): """Always assume the versions don't match""" return False diff --git a/pipenv/patched/notpip/vcs/git.py b/pipenv/patched/notpip/_internal/vcs/git.py similarity index 61% rename from pipenv/patched/notpip/vcs/git.py rename to pipenv/patched/notpip/_internal/vcs/git.py index 69a449ca..581db323 100644 --- a/pipenv/patched/notpip/vcs/git.py +++ b/pipenv/patched/notpip/_internal/vcs/git.py @@ -1,18 +1,18 @@ from __future__ import absolute_import import logging -import tempfile import os.path +import re -from pip9.compat import samefile -from pip9.exceptions import BadCommand -from pip9._vendor.six.moves.urllib import parse as urllib_parse -from pip9._vendor.six.moves.urllib import request as urllib_request -from pip9._vendor.packaging.version import parse as parse_version - -from pip9.utils import display_path, rmtree -from pip9.vcs import vcs, VersionControl +from notpip._vendor.packaging.version import parse as parse_version +from notpip._vendor.six.moves.urllib import parse as urllib_parse +from notpip._vendor.six.moves.urllib import request as urllib_request +from notpip._internal.compat import samefile +from notpip._internal.exceptions import BadCommand +from notpip._internal.utils.misc import display_path +from notpip._internal.utils.temp_dir import TempDirectory +from notpip._internal.vcs import VersionControl, vcs urlsplit = urllib_parse.urlsplit urlunsplit = urllib_parse.urlunsplit @@ -21,6 +21,13 @@ 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' @@ -28,6 +35,10 @@ class Git(VersionControl): 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): @@ -50,11 +61,14 @@ class Git(VersionControl): 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):] + version = version[len(VERSION_PFX):].split()[0] else: version = '' # get first 3 positions of the git version becasue @@ -65,49 +79,86 @@ class Git(VersionControl): def export(self, location): """Export the Git repository at the url to the destination location""" - temp_dir = tempfile.mkdtemp('-export', 'pip-') - self.unpack(temp_dir) - try: - if not location.endswith('/'): - location = 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) - finally: - rmtree(temp_dir) - - def check_rev_options(self, rev, dest, rev_options): - """Check the revision options before checkout to compensate that tags - and branches may need origin/ as a prefix. - Returns the SHA1 of the branch or tag if found. - """ - revisions = self.get_short_refs(dest) - - origin_rev = 'origin/%s' % rev - if origin_rev in revisions: - # remote branch - return [revisions[origin_rev]] - elif rev in revisions: - # a local tag or branch name - return [revisions[rev]] - else: - logger.warning( - "Could not find a tag or branch '%s', assuming commit.", rev, + show_stdout=False, cwd=temp_dir.path ) - return rev_options - def check_version(self, dest, rev_options): + def get_revision_sha(self, dest, rev): """ - Compare the current sha to the ref. ref may be a branch or tag name, - but current rev will always point to a sha. This means that a branch - or tag will never compare as True. So this ultimately only matches - against exact shas. + Return a commit hash for the given revision if it names a remote + branch or tag. Otherwise, return None. + + Args: + dest: the repository directory. + rev: the revision name. """ - return self.get_revision(dest).startswith(rev_options[0]) + # 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) + + return refs.get(branch_ref) or refs.get(tag_ref) + + def check_rev_options(self, dest, rev_options): + """Check the revision options before checkout. + + Returns a new RevOptions object for the SHA1 of the branch or tag + if found. + + Args: + rev_options: a RevOptions object. + """ + rev = rev_options.arg_rev + sha = self.get_revision_sha(dest, rev) + + if sha is not None: + return rev_options.make_new(sha) + + # 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, + ) + 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 switch(self, dest, url, rev_options): self.run_command(['config', 'remote.origin.url', url], cwd=dest) - self.run_command(['checkout', '-q'] + rev_options, cwd=dest) + cmd_args = ['checkout', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) self.update_submodules(dest) @@ -119,44 +170,47 @@ class Git(VersionControl): else: self.run_command(['fetch', '-q'], cwd=dest) # Then reset to wanted revision (maybe even origin/master) - if rev_options: - rev_options = self.check_rev_options( - rev_options[0], dest, rev_options, - ) - self.run_command(['reset', '--hard', '-q'] + rev_options, cwd=dest) + rev_options = self.check_rev_options(dest, rev_options) + cmd_args = ['reset', '--hard', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) #: update submodules self.update_submodules(dest) def obtain(self, dest): url, rev = self.get_url_rev() - if rev: - rev_options = [rev] - rev_display = ' (to %s)' % rev - else: - rev_options = ['origin/master'] - rev_display = '' - if self.check_destination(dest, url, rev_options, rev_display): + rev_options = self.make_rev_options(rev) + if self.check_destination(dest, url, rev_options): + rev_display = rev_options.to_display() logger.info( 'Cloning %s%s to %s', url, rev_display, display_path(dest), ) self.run_command(['clone', '-q', url, dest]) if rev: - rev_options = self.check_rev_options(rev, dest, rev_options) - # Only do a checkout if rev_options differs from HEAD - if not self.check_version(dest, rev_options): - self.run_command( - ['checkout', '-q'] + rev_options, - cwd=dest, - ) + rev_options = self.check_rev_options(dest, rev_options) + # 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): + rev = rev_options.rev + # Only fetch the revision if it's a ref + if rev.startswith('refs/'): + self.run_command( + ['fetch', '-q', url] + rev_options.to_args(), + cwd=dest, + ) + # Change the revision to the SHA of the ref we fetched + rev = 'FETCH_HEAD' + self.run_command(['checkout', '-q', rev], cwd=dest) + #: repo may contain submodules self.update_submodules(dest) def get_url(self, location): """Return URL of the first remote encountered.""" remotes = self.run_command( - ['config', '--get-regexp', 'remote\..*\.url'], - show_stdout=False, cwd=location) + ['config', '--get-regexp', r'remote\..*\.url'], + show_stdout=False, cwd=location, + ) remotes = remotes.splitlines() found_remote = remotes[0] for remote in remotes: @@ -168,53 +222,10 @@ class Git(VersionControl): def get_revision(self, location): current_rev = self.run_command( - ['rev-parse', 'HEAD'], show_stdout=False, cwd=location) + ['rev-parse', 'HEAD'], show_stdout=False, cwd=location, + ) return current_rev.strip() - def get_full_refs(self, location): - """Yields tuples of (commit, ref) for branches and tags""" - output = self.run_command(['show-ref'], - show_stdout=False, cwd=location) - for line in output.strip().splitlines(): - commit, ref = line.split(' ', 1) - yield commit.strip(), ref.strip() - - def is_ref_remote(self, ref): - return ref.startswith('refs/remotes/') - - def is_ref_branch(self, ref): - return ref.startswith('refs/heads/') - - def is_ref_tag(self, ref): - return ref.startswith('refs/tags/') - - def is_ref_commit(self, ref): - """A ref is a commit sha if it is not anything else""" - return not any(( - self.is_ref_remote(ref), - self.is_ref_branch(ref), - self.is_ref_tag(ref), - )) - - # Should deprecate `get_refs` since it's ambiguous - def get_refs(self, location): - return self.get_short_refs(location) - - def get_short_refs(self, location): - """Return map of named refs (branches or tags) to commit hashes.""" - rv = {} - for commit, ref in self.get_full_refs(location): - ref_name = None - if self.is_ref_remote(ref): - ref_name = ref[len('refs/remotes/'):] - elif self.is_ref_branch(ref): - ref_name = ref[len('refs/heads/'):] - elif self.is_ref_tag(ref): - ref_name = ref[len('refs/tags/'):] - if ref_name is not None: - rv[ref_name] = commit - return rv - def _get_subdirectory(self, location): """Return the relative path of setup.py to the git repo root.""" # find the repo root diff --git a/pipenv/patched/notpip/vcs/mercurial.py b/pipenv/patched/notpip/_internal/vcs/mercurial.py similarity index 72% rename from pipenv/patched/notpip/vcs/mercurial.py rename to pipenv/patched/notpip/_internal/vcs/mercurial.py index 115e815b..58289894 100644 --- a/pipenv/patched/notpip/vcs/mercurial.py +++ b/pipenv/patched/notpip/_internal/vcs/mercurial.py @@ -2,13 +2,13 @@ from __future__ import absolute_import import logging import os -import tempfile -from pip9.utils import display_path, rmtree -from pip9.vcs import vcs, VersionControl -from pip9.download import path_to_url -from pip9._vendor.six.moves import configparser +from notpip._vendor.six.moves import configparser +from notpip._internal.download import path_to_url +from notpip._internal.utils.misc import display_path +from notpip._internal.utils.temp_dir import TempDirectory +from notpip._internal.vcs import VersionControl, vcs logger = logging.getLogger(__name__) @@ -19,15 +19,17 @@ class Mercurial(VersionControl): 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""" - temp_dir = tempfile.mkdtemp('-export', 'pip-') - self.unpack(temp_dir) - try: + with TempDirectory(kind="export") as temp_dir: + self.unpack(temp_dir.path) + self.run_command( - ['archive', location], show_stdout=False, cwd=temp_dir) - finally: - rmtree(temp_dir) + ['archive', location], show_stdout=False, cwd=temp_dir.path + ) def switch(self, dest, url, rev_options): repo_config = os.path.join(dest, self.dirname, 'hgrc') @@ -42,21 +44,19 @@ class Mercurial(VersionControl): 'Could not switch Mercurial repository to %s: %s', url, exc, ) else: - self.run_command(['update', '-q'] + rev_options, cwd=dest) + cmd_args = ['update', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) def update(self, dest, rev_options): self.run_command(['pull', '-q'], cwd=dest) - self.run_command(['update', '-q'] + rev_options, cwd=dest) + cmd_args = ['update', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) def obtain(self, dest): url, rev = self.get_url_rev() - if rev: - rev_options = [rev] - rev_display = ' (to revision %s)' % rev - else: - rev_options = [] - rev_display = '' - if self.check_destination(dest, url, rev_options, rev_display): + rev_options = self.make_rev_options(rev) + if self.check_destination(dest, url, rev_options): + rev_display = rev_options.to_display() logger.info( 'Cloning hg %s%s to %s', url, @@ -64,7 +64,8 @@ class Mercurial(VersionControl): display_path(dest), ) self.run_command(['clone', '--noupdate', '-q', url, dest]) - self.run_command(['update', '-q'] + rev_options, cwd=dest) + cmd_args = ['update', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) def get_url(self, location): url = self.run_command( @@ -96,8 +97,9 @@ class Mercurial(VersionControl): current_rev_hash = self.get_revision_hash(location) return '%s@%s#egg=%s' % (repo, current_rev_hash, egg_project_name) - def check_version(self, dest, rev_options): + def is_commit_id_equal(self, dest, name): """Always assume the versions don't match""" return False + vcs.register(Mercurial) diff --git a/pipenv/patched/notpip/vcs/subversion.py b/pipenv/patched/notpip/_internal/vcs/subversion.py similarity index 83% rename from pipenv/patched/notpip/vcs/subversion.py rename to pipenv/patched/notpip/_internal/vcs/subversion.py index 97220b30..d7caa653 100644 --- a/pipenv/patched/notpip/vcs/subversion.py +++ b/pipenv/patched/notpip/_internal/vcs/subversion.py @@ -4,15 +4,15 @@ import logging import os import re -from pip9._vendor.six.moves.urllib import parse as urllib_parse +from notpip._vendor.six.moves.urllib import parse as urllib_parse -from pip9.index import Link -from pip9.utils import rmtree, display_path -from pip9.utils.logging import indent_log -from pip9.vcs import vcs, VersionControl +from notpip._internal.index import Link +from notpip._internal.utils.logging import indent_log +from notpip._internal.utils.misc import display_path, rmtree +from notpip._internal.vcs import VersionControl, vcs _svn_xml_url_re = re.compile('url="([^"]+)"') -_svn_rev_re = re.compile('committed-rev="(\d+)"') +_svn_rev_re = re.compile(r'committed-rev="(\d+)"') _svn_url_re = re.compile(r'URL: (.+)') _svn_revision_re = re.compile(r'Revision: (.+)') _svn_info_xml_rev_re = re.compile(r'\s*revision="(\d+)"') @@ -28,6 +28,9 @@ class Subversion(VersionControl): repo_name = 'checkout' schemes = ('svn', 'svn+ssh', 'svn+http', 'svn+https', 'svn+svn') + def get_base_rev_args(self, rev): + return ['-r', rev] + def get_info(self, location): """Returns (url, revision), where both are strings""" assert not location.rstrip('/').endswith(self.dirname), \ @@ -59,7 +62,7 @@ class Subversion(VersionControl): def export(self, location): """Export the svn repository at the url to the destination location""" url, rev = self.get_url_rev() - rev_options = get_rev_options(url, rev) + rev_options = get_rev_options(self, url, rev) url = self.remove_auth_from_url(url) logger.info('Exporting svn repository %s to %s', url, location) with indent_log(): @@ -67,32 +70,31 @@ class Subversion(VersionControl): # Subversion doesn't like to check out over an existing # directory --force fixes this, but was only added in svn 1.5 rmtree(location) - self.run_command( - ['export'] + rev_options + [url, location], - show_stdout=False) + cmd_args = ['export'] + rev_options.to_args() + [url, location] + self.run_command(cmd_args, show_stdout=False) def switch(self, dest, url, rev_options): - self.run_command(['switch'] + rev_options + [url, dest]) + cmd_args = ['switch'] + rev_options.to_args() + [url, dest] + self.run_command(cmd_args) def update(self, dest, rev_options): - self.run_command(['update'] + rev_options + [dest]) + cmd_args = ['update'] + rev_options.to_args() + [dest] + self.run_command(cmd_args) def obtain(self, dest): url, rev = self.get_url_rev() - rev_options = get_rev_options(url, rev) + rev_options = get_rev_options(self, url, rev) url = self.remove_auth_from_url(url) - if rev: - rev_display = ' (to revision %s)' % rev - else: - rev_display = '' - if self.check_destination(dest, url, rev_options, rev_display): + if self.check_destination(dest, url, rev_options): + rev_display = rev_options.to_display() logger.info( 'Checking out %s%s to %s', url, rev_display, display_path(dest), ) - self.run_command(['checkout', '-q'] + rev_options + [url, dest]) + cmd_args = ['checkout', '-q'] + rev_options.to_args() + [url, dest] + self.run_command(cmd_args) def get_location(self, dist, dependency_links): for url in dependency_links: @@ -128,8 +130,8 @@ class Subversion(VersionControl): dirurl, localrev = self._get_svn_url_rev(base) if base == location: - base_url = dirurl + '/' # save the root url - elif not dirurl or not dirurl.startswith(base_url): + 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) @@ -163,7 +165,7 @@ class Subversion(VersionControl): return self._get_svn_url_rev(location)[0] def _get_svn_url_rev(self, location): - from pip9.exceptions import InstallationError + from notpip._internal.exceptions import InstallationError entries_path = os.path.join(location, self.dirname, 'entries') if os.path.exists(entries_path): @@ -215,7 +217,7 @@ class Subversion(VersionControl): rev = self.get_revision(location) return 'svn+%s@%s#egg=%s' % (repo, rev, egg_project_name) - def check_version(self, dest, rev_options): + def is_commit_id_equal(self, dest, name): """Always assume the versions don't match""" return False @@ -238,12 +240,10 @@ class Subversion(VersionControl): return surl -def get_rev_options(url, rev): - if rev: - rev_options = ['-r', rev] - else: - rev_options = [] - +def get_rev_options(vcs, url, rev): + """ + Return a RevOptions object. + """ r = urllib_parse.urlsplit(url) if hasattr(r, 'username'): # >= Python-2.5 @@ -259,11 +259,13 @@ def get_rev_options(url, rev): else: username, password = None, None + extra_args = [] if username: - rev_options += ['--username', username] + extra_args += ['--username', username] if password: - rev_options += ['--password', password] - return rev_options + extra_args += ['--password', password] + + return vcs.make_rev_options(rev, extra_args=extra_args) vcs.register(Subversion) diff --git a/pipenv/patched/notpip/wheel.py b/pipenv/patched/notpip/_internal/wheel.py similarity index 74% rename from pipenv/patched/notpip/wheel.py rename to pipenv/patched/notpip/_internal/wheel.py index 0c97be24..03364a59 100644 --- a/pipenv/patched/notpip/wheel.py +++ b/pipenv/patched/notpip/_internal/wheel.py @@ -3,44 +3,46 @@ Support for installing and building the "wheel" binary package format. """ from __future__ import absolute_import +import collections import compileall +import copy import csv -import errno -import functools import hashlib import logging -import os import os.path import re import shutil import stat import sys -import tempfile import warnings - from base64 import urlsafe_b64encode from email.parser import Parser -from pip9._vendor.six import StringIO +from notpip._vendor import pkg_resources +from notpip._vendor.distlib.scripts import ScriptMaker +from notpip._vendor.packaging.utils import canonicalize_name +from notpip._vendor.six import StringIO -import pip9 -from pip9.compat import expanduser -from pip9.download import path_to_url, unpack_url -from pip9.exceptions import ( - InstallationError, InvalidWheelFilename, UnsupportedWheel) -from pip9.locations import distutils_scheme, PIP_DELETE_MARKER_FILENAME -from notpip import pep425tags -from pip9.utils import ( - call_subprocess, ensure_dir, captured_stdout, rmtree, read_chunks, +from notpip._internal import pep425tags +from notpip._internal.build_env import BuildEnvironment +from notpip._internal.download import path_to_url, unpack_url +from notpip._internal.exceptions import ( + InstallationError, InvalidWheelFilename, UnsupportedWheel, ) -from pip9.utils.ui import open_spinner -from pip9.utils.logging import indent_log -from pip9.utils.setuptools_build import SETUPTOOLS_SHIM -from pip9._vendor.distlib.scripts import ScriptMaker -from pip9._vendor import pkg_resources -from pip9._vendor.packaging.utils import canonicalize_name -from pip9._vendor.six.moves import configparser +from notpip._internal.locations import ( + PIP_DELETE_MARKER_FILENAME, distutils_scheme, +) +from notpip._internal.utils.logging import indent_log +from notpip._internal.utils.misc import ( + call_subprocess, captured_stdout, ensure_dir, read_chunks, +) +from notpip._internal.utils.setuptools_build import SETUPTOOLS_SHIM +from notpip._internal.utils.temp_dir import TempDirectory +from notpip._internal.utils.typing import MYPY_CHECK_RUNNING +from notpip._internal.utils.ui import open_spinner +if MYPY_CHECK_RUNNING: + from typing import Dict, List, Optional wheel_ext = '.whl' @@ -50,104 +52,6 @@ VERSION_COMPATIBLE = (1, 0) logger = logging.getLogger(__name__) -class WheelCache(object): - """A cache of wheels for future installs.""" - - def __init__(self, cache_dir, format_control): - """Create a wheel cache. - - :param cache_dir: The root of the cache. - :param format_control: A pip9.index.FormatControl object to limit - binaries being read from the cache. - """ - self._cache_dir = expanduser(cache_dir) if cache_dir else None - self._format_control = format_control - - def cached_wheel(self, link, package_name): - return cached_wheel( - self._cache_dir, link, self._format_control, package_name) - - -def _cache_for_link(cache_dir, link): - """ - Return a directory to store cached wheels in 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 cache_dir: The cache_dir being used by pip9. - :param link: The link of the sdist for which this will cache wheels. - """ - - # 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:]] - - # Inside of the base location for cached wheels, expand our parts and join - # them all together. - return os.path.join(cache_dir, "wheels", *parts) - - -def cached_wheel(cache_dir, link, format_control, package_name): - if not cache_dir: - return link - if not link: - return link - if link.is_wheel: - return link - if not link.is_artifact: - return link - if not package_name: - return link - canonical_name = canonicalize_name(package_name) - formats = pip9.index.fmt_ctl_formats(format_control, canonical_name) - if "binary" not in formats: - return link - root = _cache_for_link(cache_dir, link) - try: - wheel_names = os.listdir(root) - except OSError as e: - if e.errno in (errno.ENOENT, errno.ENOTDIR): - return link - raise - candidates = [] - for wheel_name in wheel_names: - 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 - candidates.sort() - path = os.path.join(root, candidates[0][1]) - return pip9.index.Link(path_to_url(path)) - - def rehash(path, algo='sha256', blocksize=1 << 20): """Return (hash, length) for path using hashlib.new(algo)""" h = hashlib.new(algo) @@ -181,7 +85,7 @@ def fix_script(path): firstline = script.readline() if not firstline.startswith(b'#!python'): return False - exename = os.environ['PIP_PYTHON_PATH'].encode(sys.getfilesystemencoding()) + exename = os.environ.get('PIP_PYTHON_PATH', sys.executable).encode(sys.getfilesystemencoding()) firstline = b'#!' + exename + os.linesep.encode("ascii") rest = script.read() with open(path, 'wb') as script: @@ -189,7 +93,8 @@ def fix_script(path): script.write(rest) return True -dist_info_re = re.compile(r"""^(?P(?P.+?)(-(?P\d.+?))?) + +dist_info_re = re.compile(r"""^(?P(?P.+?)(-(?P.+?))?) \.dist-info$""", re.VERBOSE) @@ -224,21 +129,85 @@ def get_entrypoints(filename): data.write("\n") data.seek(0) - cp = configparser.RawConfigParser() - cp.optionxform = lambda option: option - cp.readfp(data) + # 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', {}) - console = {} - gui = {} - if cp.has_section('console_scripts'): - console = dict(cp.items('console_scripts')) - if cp.has_section('gui_scripts'): - gui = dict(cp.items('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: (List[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) for i in os.environ["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 move_wheel_files(name, req, wheeldir, user=False, home=None, root=None, - pycompile=True, scheme=None, isolated=False, prefix=None): + pycompile=True, scheme=None, isolated=False, prefix=None, + warn_script_location=True): """Install a wheel""" if not scheme: @@ -385,7 +354,7 @@ def move_wheel_files(name, req, wheeldir, user=False, home=None, root=None, # 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 = set(('', )) + maker.variants = {''} # This is required because otherwise distlib creates scripts that are not # executable. @@ -411,7 +380,7 @@ def move_wheel_files(name, req, wheeldir, user=False, home=None, root=None, } maker._get_script_text = _get_script_text - maker.script_template = """# -*- coding: utf-8 -*- + maker.script_template = r"""# -*- coding: utf-8 -*- import re import sys @@ -488,9 +457,16 @@ if __name__ == '__main__': # Generate the console and GUI entry points specified in the wheel if len(console) > 0: - generated.extend( - maker.make_multiple(['%s = %s' % kv for kv in console.items()]) + 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.warn(msg) + if len(gui) > 0: generated.extend( maker.make_multiple( @@ -527,40 +503,6 @@ if __name__ == '__main__': shutil.move(temp_record, record) -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 - - -# TODO: this goes somewhere besides the wheel module -@_unique -def uninstallation_paths(dist): - """ - Yield all the uninstallation paths for dist based on RECORD-without-.pyc - - Yield paths to all the files in RECORD. For each .py file in RECORD, add - the .pyc in the same directory. - - UninstallPathSet.add() takes care of the __pycache__ .pyc. - """ - from pip9.utils import FakeFile # circular import - 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 - - def wheel_version(source_dir): """ Return the Wheel-Version of an extracted wheel, if possible. @@ -615,8 +557,8 @@ class Wheel(object): # TODO: maybe move the install code into this class wheel_file_re = re.compile( - r"""^(?P(?P.+?)-(?P\d.*?)) - ((-(?P\d.*?))?-(?P.+?)-(?P.+?)-(?P.+?) + r"""^(?P(?P.+?)-(?P.*?)) + ((-(?P\d[^-]*?))?-(?P.+?)-(?P.+?)-(?P.+?) \.whl|\.dist-info)$""", re.VERBOSE ) @@ -635,15 +577,16 @@ class Wheel(object): # 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 = set( + 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): """ @@ -653,41 +596,51 @@ class Wheel(object): None is the wheel is not supported. """ if tags is None: # for mock - tags = pep425tags.supported_tags + 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): """Is this wheel supported on this system?""" if tags is None: # for mock - tags = pep425tags.supported_tags + tags = pep425tags.get_supported() return bool(set(tags).intersection(self.file_tags)) class WheelBuilder(object): """Build wheels from a RequirementSet.""" - def __init__(self, requirement_set, finder, build_options=None, - global_options=None): - self.requirement_set = requirement_set + def __init__(self, finder, preparer, wheel_cache, + build_options=None, global_options=None, no_clean=False): self.finder = finder - self._cache_root = requirement_set._wheel_cache._cache_dir - self._wheel_dir = requirement_set.wheel_download_dir + 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. """ - tempd = tempfile.mkdtemp('pip-wheel-') - try: - if self.__build_one(req, tempd, python_tag=python_tag): + # 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 self.__build_one(req, temp_dir.path, python_tag=python_tag): try: - wheel_name = os.listdir(tempd)[0] + wheel_name = os.listdir(temp_dir.path)[0] wheel_path = os.path.join(output_dir, wheel_name) - shutil.move(os.path.join(tempd, wheel_name), wheel_path) + shutil.move( + os.path.join(temp_dir.path, wheel_name), wheel_path + ) logger.info('Stored in directory: %s', output_dir) return wheel_path except: @@ -695,12 +648,14 @@ class WheelBuilder(object): # Ignore return, we can't do anything else useful. self._clean_one(req) return None - finally: - rmtree(tempd) 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 [ - (PIP_PYTHON_PATH or sys.executable), "-u", '-c', + os.environ.get('PIP_PYTHON_PATH', sys.executable), '-u', '-c', SETUPTOOLS_SHIM % req.setup_py ] + list(self.global_options) @@ -737,49 +692,53 @@ class WheelBuilder(object): logger.error('Failed cleaning build dir for %s', req.name) return False - def build(self, autobuilding=False): + def build(self, requirements, session, autobuilding=False): """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. """ - assert self._wheel_dir or (autobuilding and self._cache_root) - # unpack sdists and constructs req set - self.requirement_set.prepare_files(self.finder) + from notpip._internal import index - reqset = self.requirement_set.requirements.values() + building_is_possible = self._wheel_dir or ( + autobuilding and self.wheel_cache.cache_dir + ) + assert building_is_possible buildset = [] - for req in reqset: + for req in requirements: if req.constraint: continue if req.is_wheel: if not autobuilding: logger.info( - 'Skipping %s, due to already being wheel.', req.name) + 'Skipping %s, due to already being wheel.', req.name, + ) elif autobuilding and req.editable: pass - elif autobuilding and req.link and not req.link.is_artifact: - pass elif autobuilding and not req.source_dir: pass + elif autobuilding and req.link and not req.link.is_artifact: + # VCS checkout. Build wheel just for this run. + buildset.append((req, True)) else: + ephem_cache = False if autobuilding: link = req.link base, ext = link.splitext() - if pip9.index.egg_info_matches(base, None, link) is None: - # Doesn't look like a package - don't autobuild a wheel - # because we'll have no way to lookup the result sanely - continue - if "binary" not in pip9.index.fmt_ctl_formats( + if index.egg_info_matches(base, None, link) is None: + # E.g. local directory. Build wheel just for this run. + ephem_cache = True + if "binary" not in index.fmt_ctl_formats( self.finder.format_control, canonicalize_name(req.name)): logger.info( "Skipping bdist_wheel for %s, due to binaries " - "being disabled for it.", req.name) + "being disabled for it.", req.name, + ) continue - buildset.append(req) + buildset.append((req, ephem_cache)) if not buildset: return True @@ -787,15 +746,19 @@ class WheelBuilder(object): # Build the wheels. logger.info( 'Building wheels for collected packages: %s', - ', '.join([req.name for req in buildset]), + ', '.join([req.name for (req, _) in buildset]), ) + _cache = self.wheel_cache # shorter name with indent_log(): build_success, build_failure = [], [] - for req in buildset: + for req, ephem in buildset: python_tag = None if autobuilding: python_tag = pep425tags.implementation_tag - output_dir = _cache_for_link(self._cache_root, req.link) + 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: @@ -826,15 +789,16 @@ class WheelBuilder(object): # set the build directory again - name is known from # the work prepare_files did. req.source_dir = req.build_location( - self.requirement_set.build_dir) + self.preparer.build_dir + ) # Update the link for this. - req.link = pip9.index.Link( - path_to_url(wheel_file)) + req.link = index.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=self.requirement_set.session) + session=session, + ) else: build_failure.append(req) diff --git a/pipenv/patched/notpip/_vendor/__init__.py b/pipenv/patched/notpip/_vendor/__init__.py index c5ccaf05..41975818 100644 --- a/pipenv/patched/notpip/_vendor/__init__.py +++ b/pipenv/patched/notpip/_vendor/__init__.py @@ -1,8 +1,8 @@ """ -pip9._vendor is for vendoring dependencies of pip to prevent needing pip to +pip._vendor is for vendoring dependencies of pip to prevent needing pip to depend on something external. -Files inside of pip9._vendor should be considered immutable and should only be +Files inside of pip._vendor should be considered immutable and should only be updated to versions from upstream. """ from __future__ import absolute_import @@ -13,7 +13,7 @@ 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 pip9. +# 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 @@ -36,7 +36,7 @@ def vendored(modulename): __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 pip9._vendor.whatever`` + # got to this point it means that ``import notpip._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* @@ -70,11 +70,13 @@ if DEBUNDLED: vendored("six") vendored("six.moves") vendored("six.moves.urllib") + vendored("six.moves.urllib.parse") vendored("packaging") vendored("packaging.version") vendored("packaging.specifiers") vendored("pkg_resources") vendored("progress") + vendored("pytoml") vendored("retrying") vendored("requests") vendored("requests.packages") diff --git a/pipenv/patched/notpip/_vendor/appdirs.py b/pipenv/patched/notpip/_vendor/appdirs.py index 4b5c38bb..2bd39110 100644 --- a/pipenv/patched/notpip/_vendor/appdirs.py +++ b/pipenv/patched/notpip/_vendor/appdirs.py @@ -10,10 +10,10 @@ See 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 -# - macOS: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/index.html +# - 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, 0) +__version_info__ = (1, 4, 3) __version__ = '.'.join(map(str, __version_info__)) @@ -30,7 +30,7 @@ if sys.platform.startswith('java'): os_name = platform.java_ver()[3][0] if os_name.startswith('Windows'): # "Windows XP", "Windows 7", etc. system = 'win32' - elif os_name.startswith('Mac'): # "macOS", etc. + 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 @@ -64,7 +64,7 @@ def user_data_dir(appname=None, appauthor=None, version=None, roaming=False): for a discussion of issues. Typical user data directories are: - macOS: ~/Library/Application Support/ + Mac OS X: ~/Library/Application Support/ 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\\ @@ -98,7 +98,7 @@ def user_data_dir(appname=None, appauthor=None, version=None, roaming=False): def site_data_dir(appname=None, appauthor=None, version=None, multipath=False): - """Return full path to the user-shared data dir for this application. + 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. @@ -117,8 +117,8 @@ def site_data_dir(appname=None, appauthor=None, version=None, multipath=False): returned, or '/usr/local/share/', if XDG_DATA_DIRS is not set - Typical user data directories are: - macOS: /Library/Application Support/ + Typical site data directories are: + Mac OS X: /Library/Application Support/ Unix: /usr/local/share/ or /usr/share/ Win XP: C:\Documents and Settings\All Users\Application Data\\ Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) @@ -184,13 +184,13 @@ def user_config_dir(appname=None, appauthor=None, version=None, roaming=False): for a discussion of issues. - Typical user data directories are: - macOS: same as user_data_dir + Typical user config directories are: + Mac OS X: same as user_data_dir Unix: ~/.config/ # 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 deafult "~/.config/". + That means, by default "~/.config/". """ if system in ["win32", "darwin"]: path = user_data_dir(appname, appauthor, None, roaming) @@ -204,7 +204,7 @@ def user_config_dir(appname=None, appauthor=None, version=None, roaming=False): def site_config_dir(appname=None, appauthor=None, version=None, multipath=False): - """Return full path to the user-shared data dir for this application. + 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. @@ -222,8 +222,8 @@ def site_config_dir(appname=None, appauthor=None, version=None, multipath=False) returned. By default, the first item from XDG_CONFIG_DIRS is returned, or '/etc/xdg/', if XDG_CONFIG_DIRS is not set - Typical user data directories are: - macOS: same as site_data_dir + Typical site config directories are: + Mac OS X: same as site_data_dir Unix: /etc/xdg/ or $XDG_CONFIG_DIRS[i]/ for each value in $XDG_CONFIG_DIRS Win *: same as site_data_dir @@ -273,7 +273,7 @@ def user_cache_dir(appname=None, appauthor=None, version=None, opinion=True): discussion below. Typical user cache directories are: - macOS: ~/Library/Caches/ + Mac OS X: ~/Library/Caches/ Unix: ~/.cache/ (XDG default) Win XP: C:\Documents and Settings\\Local Settings\Application Data\\\Cache Vista: C:\Users\\AppData\Local\\\Cache @@ -311,6 +311,48 @@ def user_cache_dir(appname=None, appauthor=None, version=None, opinion=True): 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 ".". + 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 + + for a discussion of issues. + + Typical user state directories are: + Mac OS X: same as user_data_dir + Unix: ~/.local/state/ # or in $XDG_STATE_HOME, if defined + Win *: same as user_data_dir + + For Unix, we follow this Debian proposal + to extend the XDG spec and support $XDG_STATE_HOME. + + That means, by default "~/.local/state/". + """ + 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. @@ -329,8 +371,8 @@ def user_log_dir(appname=None, appauthor=None, version=None, opinion=True): "Logs" to the base app data dir for Windows, and "log" to the base cache dir for Unix. See discussion below. - Typical user cache directories are: - macOS: ~/Library/Logs/ + Typical user log directories are: + Mac OS X: ~/Library/Logs/ Unix: ~/.cache//log # or under $XDG_CACHE_HOME if defined Win XP: C:\Documents and Settings\\Local Settings\Application Data\\\Logs Vista: C:\Users\\AppData\Local\\\Logs @@ -364,8 +406,8 @@ def user_log_dir(appname=None, appauthor=None, version=None, opinion=True): class AppDirs(object): """Convenience wrapper for getting application dirs.""" - def __init__(self, appname, appauthor=None, version=None, roaming=False, - multipath=False): + def __init__(self, appname=None, appauthor=None, version=None, + roaming=False, multipath=False): self.appname = appname self.appauthor = appauthor self.version = version @@ -397,6 +439,11 @@ class AppDirs(object): 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, @@ -410,7 +457,10 @@ def _get_win_folder_from_registry(csidl_name): registry for this guarantees us the correct answer for all CSIDL_* names. """ - import _winreg + if PY3: + import winreg as _winreg + else: + import _winreg shell_folder_name = { "CSIDL_APPDATA": "AppData", @@ -500,25 +550,21 @@ def _get_win_folder_with_jna(csidl_name): if has_high_char: buf = array.zeros('c', buf_size) kernel = win32.Kernel32.INSTANCE - if kernal.GetShortPathName(dir, buf, buf_size): + if kernel.GetShortPathName(dir, buf, buf_size): dir = jna.Native.toString(buf.tostring()).rstrip("\0") return dir if system == "win32": try: - import win32com.shell - _get_win_folder = _get_win_folder_with_pywin32 + from ctypes import windll + _get_win_folder = _get_win_folder_with_ctypes except ImportError: try: - from ctypes import windll - _get_win_folder = _get_win_folder_with_ctypes + import com.sun.jna + _get_win_folder = _get_win_folder_with_jna 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 + _get_win_folder = _get_win_folder_from_registry #---- self test code @@ -527,9 +573,15 @@ if __name__ == "__main__": appname = "MyApp" appauthor = "MyCompany" - props = ("user_data_dir", "site_data_dir", - "user_config_dir", "site_config_dir", - "user_cache_dir", "user_log_dir") + 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") diff --git a/pipenv/patched/notpip/_vendor/cachecontrol/__init__.py b/pipenv/patched/notpip/_vendor/cachecontrol/__init__.py index ec9da2e3..f386d492 100644 --- a/pipenv/patched/notpip/_vendor/cachecontrol/__init__.py +++ b/pipenv/patched/notpip/_vendor/cachecontrol/__init__.py @@ -4,7 +4,7 @@ Make it easy to import from cachecontrol without long namespaces. """ __author__ = 'Eric Larson' __email__ = 'eric@ionrock.org' -__version__ = '0.11.7' +__version__ = '0.12.4' from .wrapper import CacheControl from .adapter import CacheControlAdapter diff --git a/pipenv/patched/notpip/_vendor/cachecontrol/_cmd.py b/pipenv/patched/notpip/_vendor/cachecontrol/_cmd.py index c338f4c3..6158c60e 100644 --- a/pipenv/patched/notpip/_vendor/cachecontrol/_cmd.py +++ b/pipenv/patched/notpip/_vendor/cachecontrol/_cmd.py @@ -1,10 +1,10 @@ import logging -from pip9._vendor import requests +from notpip._vendor import requests -from pip9._vendor.cachecontrol.adapter import CacheControlAdapter -from pip9._vendor.cachecontrol.cache import DictCache -from pip9._vendor.cachecontrol.controller import logger +from notpip._vendor.cachecontrol.adapter import CacheControlAdapter +from notpip._vendor.cachecontrol.cache import DictCache +from notpip._vendor.cachecontrol.controller import logger from argparse import ArgumentParser diff --git a/pipenv/patched/notpip/_vendor/cachecontrol/adapter.py b/pipenv/patched/notpip/_vendor/cachecontrol/adapter.py index b5525f08..03ce13a8 100644 --- a/pipenv/patched/notpip/_vendor/cachecontrol/adapter.py +++ b/pipenv/patched/notpip/_vendor/cachecontrol/adapter.py @@ -1,7 +1,8 @@ import types import functools +import zlib -from pip9._vendor.requests.adapters import HTTPAdapter +from notpip._vendor.requests.adapters import HTTPAdapter from .controller import CacheController from .cache import DictCache @@ -16,10 +17,12 @@ class CacheControlAdapter(HTTPAdapter): 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( @@ -28,13 +31,17 @@ class CacheControlAdapter(HTTPAdapter): serializer=serializer, ) - def send(self, request, **kw): + 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. """ - if request.method == 'GET': - cached_response = self.controller.cached_request(request) + 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) @@ -48,14 +55,16 @@ class CacheControlAdapter(HTTPAdapter): return resp - def build_response(self, request, response, from_cache=False): + 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 """ - if not from_cache and request.method == 'GET': + 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: diff --git a/pipenv/patched/notpip/_vendor/cachecontrol/caches/__init__.py b/pipenv/patched/notpip/_vendor/cachecontrol/caches/__init__.py index f9e66a1f..0e1658fa 100644 --- a/pipenv/patched/notpip/_vendor/cachecontrol/caches/__init__.py +++ b/pipenv/patched/notpip/_vendor/cachecontrol/caches/__init__.py @@ -1,18 +1,2 @@ -from textwrap import dedent - -try: - from .file_cache import FileCache -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 - ''') - print(notice) - - -try: - import redis - from .redis_cache import RedisCache -except ImportError: - pass +from .file_cache import FileCache # noqa +from .redis_cache import RedisCache # noqa diff --git a/pipenv/patched/notpip/_vendor/cachecontrol/caches/file_cache.py b/pipenv/patched/notpip/_vendor/cachecontrol/caches/file_cache.py index 443887c9..77fb92e5 100644 --- a/pipenv/patched/notpip/_vendor/cachecontrol/caches/file_cache.py +++ b/pipenv/patched/notpip/_vendor/cachecontrol/caches/file_cache.py @@ -1,12 +1,16 @@ import hashlib import os - -from pip9._vendor.lockfile import LockFile -from pip9._vendor.lockfile.mkdirlockfile import MkdirLockFile +from textwrap import dedent from ..cache import BaseCache from ..controller import CacheController +try: + FileNotFoundError +except NameError: + # py2.X + FileNotFoundError = OSError + def _secure_open_write(filename, fmode): # We only want to write to this file, so open it in write only mode @@ -55,11 +59,22 @@ class FileCache(BaseCache): if use_dir_lock is not None and lock_class is not None: raise ValueError("Cannot use use_dir_lock and lock_class together") - if use_dir_lock: - lock_class = MkdirLockFile + try: + from notpip._vendor.lockfile import LockFile + from notpip._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 - if lock_class is None: - lock_class = LockFile + elif lock_class is None: + lock_class = LockFile self.directory = directory self.forever = forever @@ -67,7 +82,6 @@ class FileCache(BaseCache): self.dirmode = dirmode self.lock_class = lock_class - @staticmethod def encode(x): return hashlib.sha224(x.encode()).hexdigest() @@ -104,7 +118,10 @@ class FileCache(BaseCache): def delete(self, key): name = self._fn(key) if not self.forever: - os.remove(name) + try: + os.remove(name) + except FileNotFoundError: + pass def url_to_file_path(url, filecache): diff --git a/pipenv/patched/notpip/_vendor/cachecontrol/caches/redis_cache.py b/pipenv/patched/notpip/_vendor/cachecontrol/caches/redis_cache.py index 9f5d55fd..94300cf1 100644 --- a/pipenv/patched/notpip/_vendor/cachecontrol/caches/redis_cache.py +++ b/pipenv/patched/notpip/_vendor/cachecontrol/caches/redis_cache.py @@ -1,19 +1,20 @@ from __future__ import division from datetime import datetime +from notpip._vendor.cachecontrol.cache import BaseCache def total_seconds(td): """Python 2.6 compatability""" if hasattr(td, 'total_seconds'): - return td.total_seconds() + return int(td.total_seconds()) ms = td.microseconds secs = (td.seconds + td.days * 24 * 3600) - return (ms + secs * 10**6) / 10**6 + return int((ms + secs * 10**6) / 10**6) -class RedisCache(object): +class RedisCache(BaseCache): def __init__(self, conn): self.conn = conn @@ -25,7 +26,7 @@ class RedisCache(object): if not expires: self.conn.set(key, value) else: - expires = expires - datetime.now() + expires = expires - datetime.utcnow() self.conn.setex(key, total_seconds(expires), value) def delete(self, key): @@ -38,4 +39,5 @@ class RedisCache(object): self.conn.delete(key) def close(self): - self.conn.disconnect() + """Redis uses connection pooling, no need to close the connection.""" + pass diff --git a/pipenv/patched/notpip/_vendor/cachecontrol/compat.py b/pipenv/patched/notpip/_vendor/cachecontrol/compat.py index 02f86d25..cea3d3be 100644 --- a/pipenv/patched/notpip/_vendor/cachecontrol/compat.py +++ b/pipenv/patched/notpip/_vendor/cachecontrol/compat.py @@ -10,11 +10,20 @@ except ImportError: import pickle -from pip9._vendor.urllib3.response import HTTPResponse -from pip9._vendor.urllib3.util import is_fp_closed +# Handle the case where the requests module has been patched to not have +# urllib3 bundled as part of its source. +try: + from notpip._vendor.requests.packages.urllib3.response import HTTPResponse +except ImportError: + from notpip._vendor.urllib3.response import HTTPResponse + +try: + from notpip._vendor.requests.packages.urllib3.util import is_fp_closed +except ImportError: + from notpip._vendor.urllib3.util import is_fp_closed # Replicate some six behaviour try: - text_type = (unicode,) + text_type = unicode except NameError: - text_type = (str,) + text_type = str diff --git a/pipenv/patched/notpip/_vendor/cachecontrol/controller.py b/pipenv/patched/notpip/_vendor/cachecontrol/controller.py index 137436a3..1d705ccd 100644 --- a/pipenv/patched/notpip/_vendor/cachecontrol/controller.py +++ b/pipenv/patched/notpip/_vendor/cachecontrol/controller.py @@ -7,7 +7,7 @@ import calendar import time from email.utils import parsedate_tz -from pip9._vendor.requests.structures import CaseInsensitiveDict +from notpip._vendor.requests.structures import CaseInsensitiveDict from .cache import DictCache from .serialize import Serializer @@ -30,10 +30,12 @@ def parse_uri(uri): class CacheController(object): """An interface to see if request should cached or not. """ - def __init__(self, cache=None, cache_etags=True, serializer=None): + 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): @@ -60,27 +62,51 @@ class CacheController(object): return cls._urlnorm(uri) def parse_cache_control(self, headers): - """ - Parse the cache control headers returning a dictionary with values - for the different directives. - """ + 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 = {} - cc_header = 'cache-control' - if 'Cache-Control' in headers: - cc_header = 'Cache-Control' + for cc_directive in cc_headers.split(','): + 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__) - if cc_header in headers: - parts = headers[cc_header].split(',') - parts_with_args = [ - tuple([x.strip().lower() for x in part.split("=", 1)]) - for part in parts if -1 != part.find("=") - ] - parts_wo_args = [ - (name.strip().lower(), 1) - for name in parts if -1 == name.find("=") - ] - retval = dict(parts_with_args + parts_wo_args) return retval def cached_request(self, request): @@ -154,8 +180,8 @@ class CacheController(object): freshness_lifetime = 0 # Check the max-age pragma in the cache control header - if 'max-age' in resp_cc and resp_cc['max-age'].isdigit(): - freshness_lifetime = int(resp_cc['max-age']) + if 'max-age' in resp_cc: + freshness_lifetime = resp_cc['max-age'] logger.debug('Freshness lifetime from max-age: %i', freshness_lifetime) @@ -171,18 +197,12 @@ class CacheController(object): # Determine if we are setting freshness limit in the # request. Note, this overrides what was in the response. if 'max-age' in cc: - try: - freshness_lifetime = int(cc['max-age']) - logger.debug('Freshness lifetime from request max-age: %i', - freshness_lifetime) - except ValueError: - freshness_lifetime = 0 + freshness_lifetime = cc['max-age'] + logger.debug('Freshness lifetime from request max-age: %i', + freshness_lifetime) if 'min-fresh' in cc: - try: - min_fresh = int(cc['min-fresh']) - except ValueError: - min_fresh = 0 + 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', @@ -220,7 +240,8 @@ class CacheController(object): return new_headers - def cache_response(self, request, response, body=None): + def cache_response(self, request, response, body=None, + status_codes=None): """ Algorithm for caching requests. @@ -228,7 +249,7 @@ class CacheController(object): """ # From httplib2: Don't cache 206's since we aren't going to # handle byte range requests - cacheable_status_codes = [200, 203, 300, 301] + 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', @@ -257,10 +278,10 @@ class CacheController(object): # Delete it from the cache if we happen to have it stored there no_store = False - if cc.get('no-store'): + if 'no-store' in cc: no_store = True logger.debug('Response header has "no-store"') - if cc_req.get('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): @@ -289,13 +310,12 @@ class CacheController(object): # the cache. elif 'date' in response_headers: # cache when there is a max-age > 0 - if cc and cc.get('max-age'): - if cc['max-age'].isdigit() and int(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 '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. diff --git a/pipenv/patched/notpip/_vendor/cachecontrol/heuristics.py b/pipenv/patched/notpip/_vendor/cachecontrol/heuristics.py index 94715a4e..f182ff02 100644 --- a/pipenv/patched/notpip/_vendor/cachecontrol/heuristics.py +++ b/pipenv/patched/notpip/_vendor/cachecontrol/heuristics.py @@ -9,7 +9,7 @@ TIME_FMT = "%a, %d %b %Y %H:%M:%S GMT" def expire_after(delta, date=None): - date = date or datetime.now() + date = date or datetime.utcnow() return date + delta diff --git a/pipenv/patched/notpip/_vendor/cachecontrol/serialize.py b/pipenv/patched/notpip/_vendor/cachecontrol/serialize.py index 41f4d9aa..884fb70e 100644 --- a/pipenv/patched/notpip/_vendor/cachecontrol/serialize.py +++ b/pipenv/patched/notpip/_vendor/cachecontrol/serialize.py @@ -3,25 +3,12 @@ import io import json import zlib -from pip9._vendor.requests.structures import CaseInsensitiveDict +from notpip._vendor import msgpack +from notpip._vendor.requests.structures import CaseInsensitiveDict from .compat import HTTPResponse, pickle, text_type -def _b64_encode_bytes(b): - return base64.b64encode(b).decode("ascii") - - -def _b64_encode_str(s): - return _b64_encode_bytes(s.encode("utf8")) - - -def _b64_encode(s): - if isinstance(s, text_type): - return _b64_encode_str(s) - return _b64_encode_bytes(s) - - def _b64_decode_bytes(b): return base64.b64decode(b.encode("ascii")) @@ -50,43 +37,40 @@ class Serializer(object): # `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 = { - "response": { - "body": _b64_encode_bytes(body), - "headers": dict( - (_b64_encode(k), _b64_encode(v)) + u"response": { + u"body": body, + u"headers": dict( + (text_type(k), text_type(v)) for k, v in response.headers.items() ), - "status": response.status, - "version": response.version, - "reason": _b64_encode_str(response.reason), - "strict": response.strict, - "decode_content": response.decode_content, + 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["vary"] = {} - if "vary" in response_headers: - varied_headers = response_headers['vary'].split(',') + data[u"vary"] = {} + if u"vary" in response_headers: + varied_headers = response_headers[u'vary'].split(',') for header in varied_headers: header = header.strip() - data["vary"][header] = request.headers.get(header, None) + 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 - # Encode our Vary headers to ensure they can be serialized as JSON - data["vary"] = dict( - (_b64_encode(k), _b64_encode(v) if v is not None else v) - for k, v in data["vary"].items() - ) - - return b",".join([ - b"cc=2", - zlib.compress( - json.dumps( - data, separators=(",", ":"), sort_keys=True, - ).encode("utf8"), - ), - ]) + 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 @@ -174,7 +158,7 @@ class Serializer(object): def _loads_v2(self, request, data): try: cached = json.loads(zlib.decompress(data).decode("utf8")) - except ValueError: + except (ValueError, zlib.error): return # We need to decode the items that we've base64 encoded @@ -194,3 +178,17 @@ class Serializer(object): ) 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/pipenv/patched/notpip/_vendor/cachecontrol/wrapper.py b/pipenv/patched/notpip/_vendor/cachecontrol/wrapper.py index ea421aa7..b50a6e27 100644 --- a/pipenv/patched/notpip/_vendor/cachecontrol/wrapper.py +++ b/pipenv/patched/notpip/_vendor/cachecontrol/wrapper.py @@ -6,14 +6,20 @@ def CacheControl(sess, cache=None, cache_etags=True, serializer=None, - heuristic=None): + heuristic=None, + controller_class=None, + adapter_class=None, + cacheable_methods=None): cache = cache or DictCache() - adapter = CacheControlAdapter( + 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) diff --git a/pipenv/patched/notpip/_vendor/chardet/cli/chardetect.py b/pipenv/patched/notpip/_vendor/chardet/cli/chardetect.py index f0a4cc5d..6f19789b 100644 --- a/pipenv/patched/notpip/_vendor/chardet/cli/chardetect.py +++ b/pipenv/patched/notpip/_vendor/chardet/cli/chardetect.py @@ -18,9 +18,9 @@ from __future__ import absolute_import, print_function, unicode_literals import argparse import sys -from chardet import __version__ -from chardet.compat import PY2 -from chardet.universaldetector import UniversalDetector +from notpip._vendor.chardet import __version__ +from notpip._vendor.chardet.compat import PY2 +from notpip._vendor.chardet.universaldetector import UniversalDetector def description_of(lines, name='stdin'): diff --git a/pipenv/patched/notpip/_vendor/colorama/__init__.py b/pipenv/patched/notpip/_vendor/colorama/__init__.py index 670e6b39..f4d9ce21 100644 --- a/pipenv/patched/notpip/_vendor/colorama/__init__.py +++ b/pipenv/patched/notpip/_vendor/colorama/__init__.py @@ -3,5 +3,5 @@ from .initialise import init, deinit, reinit, colorama_text from .ansi import Fore, Back, Style, Cursor from .ansitowin32 import AnsiToWin32 -__version__ = '0.3.7' +__version__ = '0.3.9' diff --git a/pipenv/patched/notpip/_vendor/colorama/ansitowin32.py b/pipenv/patched/notpip/_vendor/colorama/ansitowin32.py index b7ff6f21..1d6e6059 100644 --- a/pipenv/patched/notpip/_vendor/colorama/ansitowin32.py +++ b/pipenv/patched/notpip/_vendor/colorama/ansitowin32.py @@ -46,8 +46,8 @@ class AnsiToWin32(object): 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 + 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) diff --git a/pipenv/patched/notpip/_vendor/colorama/win32.py b/pipenv/patched/notpip/_vendor/colorama/win32.py index 3d1d2f2d..8262e350 100644 --- a/pipenv/patched/notpip/_vendor/colorama/win32.py +++ b/pipenv/patched/notpip/_vendor/colorama/win32.py @@ -83,9 +83,9 @@ else: ] _FillConsoleOutputAttribute.restype = wintypes.BOOL - _SetConsoleTitleW = windll.kernel32.SetConsoleTitleA + _SetConsoleTitleW = windll.kernel32.SetConsoleTitleW _SetConsoleTitleW.argtypes = [ - wintypes.LPCSTR + wintypes.LPCWSTR ] _SetConsoleTitleW.restype = wintypes.BOOL @@ -94,13 +94,15 @@ else: STDERR: _GetStdHandle(STDERR), } - def winapi_test(): - handle = handles[STDOUT] + 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 handles.values()) + def GetConsoleScreenBufferInfo(stream_id=STDOUT): handle = handles[stream_id] csbi = CONSOLE_SCREEN_BUFFER_INFO() diff --git a/pipenv/patched/notpip/_vendor/distlib/__init__.py b/pipenv/patched/notpip/_vendor/distlib/__init__.py index d186b0a3..d4aab453 100644 --- a/pipenv/patched/notpip/_vendor/distlib/__init__.py +++ b/pipenv/patched/notpip/_vendor/distlib/__init__.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2012-2016 Vinay Sajip. +# 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.4' +__version__ = '0.2.7' class DistlibException(Exception): pass diff --git a/pipenv/patched/notpip/_vendor/distlib/_backport/sysconfig.cfg b/pipenv/patched/notpip/_vendor/distlib/_backport/sysconfig.cfg index 1746bd01..c92cd481 100644 --- a/pipenv/patched/notpip/_vendor/distlib/_backport/sysconfig.cfg +++ b/pipenv/patched/notpip/_vendor/distlib/_backport/sysconfig.cfg @@ -1,84 +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} +[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/pipenv/patched/notpip/_vendor/distlib/_backport/sysconfig.py b/pipenv/patched/notpip/_vendor/distlib/_backport/sysconfig.py index ec28480a..1df3aba1 100644 --- a/pipenv/patched/notpip/_vendor/distlib/_backport/sysconfig.py +++ b/pipenv/patched/notpip/_vendor/distlib/_backport/sysconfig.py @@ -221,7 +221,7 @@ def _parse_makefile(filename, vars=None): """ # Regexes needed for parsing Makefile (and similar syntaxes, # like old-style Setup files). - _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)") + _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_]*)}") @@ -528,7 +528,7 @@ def get_config_vars(*args): major_version = int(kernel_version.split('.')[0]) if major_version < 8: - # On macOS before 10.4, check if -arch and -isysroot + # 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. @@ -537,7 +537,7 @@ def get_config_vars(*args): # patched up as well. 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): flags = _CONFIG_VARS[key] - flags = re.sub('-arch\s+\w+\s', ' ', flags) + flags = re.sub(r'-arch\s+\w+\s', ' ', flags) flags = re.sub('-isysroot [^ \t]*', ' ', flags) _CONFIG_VARS[key] = flags else: @@ -554,7 +554,7 @@ def get_config_vars(*args): 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): flags = _CONFIG_VARS[key] - flags = re.sub('-arch\s+\w+\s', ' ', flags) + flags = re.sub(r'-arch\s+\w+\s', ' ', flags) flags = flags + ' ' + arch _CONFIG_VARS[key] = flags @@ -569,7 +569,7 @@ def get_config_vars(*args): # when you install Xcode. # CFLAGS = _CONFIG_VARS.get('CFLAGS', '') - m = re.search('-isysroot\s+(\S+)', CFLAGS) + m = re.search(r'-isysroot\s+(\S+)', CFLAGS) if m is not None: sdk = m.group(1) if not os.path.exists(sdk): @@ -579,7 +579,7 @@ def get_config_vars(*args): 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): flags = _CONFIG_VARS[key] - flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags) + flags = re.sub(r'-isysroot\s+\S+(\s|$)', ' ', flags) _CONFIG_VARS[key] = flags if args: @@ -725,7 +725,7 @@ def get_platform(): machine = 'fat' cflags = get_config_vars().get('CFLAGS') - archs = re.findall('-arch\s+(\S+)', cflags) + archs = re.findall(r'-arch\s+(\S+)', cflags) archs = tuple(sorted(set(archs))) if len(archs) == 1: diff --git a/pipenv/patched/notpip/_vendor/distlib/compat.py b/pipenv/patched/notpip/_vendor/distlib/compat.py index 2b198dd5..ff328c8e 100644 --- a/pipenv/patched/notpip/_vendor/distlib/compat.py +++ b/pipenv/patched/notpip/_vendor/distlib/compat.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2013-2016 Vinay Sajip. +# Copyright (C) 2013-2017 Vinay Sajip. # Licensed to the Python Software Foundation under a contributor agreement. # See LICENSE.txt and CONTRIBUTORS.txt. # @@ -12,7 +12,7 @@ import sys try: import ssl -except ImportError: +except ImportError: # pragma: no cover ssl = None if sys.version_info[0] < 3: # pragma: no cover @@ -272,7 +272,7 @@ from zipfile import ZipFile as BaseZipFile if hasattr(BaseZipFile, '__enter__'): # pragma: no cover ZipFile = BaseZipFile -else: +else: # pragma: no cover from zipfile import ZipExtFile as BaseZipExtFile class ZipExtFile(BaseZipExtFile): @@ -329,7 +329,13 @@ try: fsencode = os.fsencode fsdecode = os.fsdecode except AttributeError: # pragma: no cover - _fsencoding = sys.getfilesystemencoding() + # 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: @@ -359,7 +365,7 @@ except ImportError: # pragma: no cover from codecs import BOM_UTF8, lookup import re - cookie_re = re.compile("coding[:=]\s*([-\w.]+)") + cookie_re = re.compile(r"coding[:=]\s*([-\w.]+)") def _get_normal_name(orig_enc): """Imitates get_normal_name in tokenizer.c.""" @@ -608,17 +614,20 @@ except ImportError: # pragma: no cover self.maps[0].clear() 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 + 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 diff --git a/pipenv/patched/notpip/_vendor/distlib/database.py b/pipenv/patched/notpip/_vendor/distlib/database.py index c3144264..a19905e2 100644 --- a/pipenv/patched/notpip/_vendor/distlib/database.py +++ b/pipenv/patched/notpip/_vendor/distlib/database.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2012-2016 The Python Software Foundation. +# Copyright (C) 2012-2017 The Python Software Foundation. # See LICENSE.txt and CONTRIBUTORS.txt. # """PEP 376 implementation.""" @@ -257,7 +257,7 @@ class DistributionPath(object): :type version: string """ matcher = None - if not version is None: + if version is not None: try: matcher = self._scheme.matcher('%s (%s)' % (name, version)) except ValueError: @@ -265,18 +265,23 @@ class DistributionPath(object): (name, version)) for dist in self.get_distributions(): - provided = dist.provides + # 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 + 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): """ @@ -529,9 +534,10 @@ class InstalledDistribution(BaseInstalledDistribution): hasher = 'sha256' def __init__(self, path, metadata=None, env=None): + self.modules = [] self.finder = finder = resources.finder_for_path(path) if finder is None: - import pdb; pdb.set_trace () + 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: @@ -553,11 +559,13 @@ class InstalledDistribution(BaseInstalledDistribution): if env and env._cache_enabled: env._cache.add(self) - try: - r = finder.find('REQUESTED') - except AttributeError: - import pdb; pdb.set_trace () + 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 '' % ( @@ -917,11 +925,14 @@ class EggInfoDistribution(BaseInstalledDistribution): pass return reqs + tl_path = tl_data = None if path.endswith('.egg'): if os.path.isdir(path): - meta_path = os.path.join(path, 'EGG-INFO', 'PKG-INFO') + 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(path, 'EGG-INFO', 'requires.txt') + 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 @@ -931,6 +942,7 @@ class EggInfoDistribution(BaseInstalledDistribution): 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 @@ -939,6 +951,7 @@ class EggInfoDistribution(BaseInstalledDistribution): 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, ' @@ -946,6 +959,16 @@ class EggInfoDistribution(BaseInstalledDistribution): 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): @@ -1025,20 +1048,21 @@ class EggInfoDistribution(BaseInstalledDistribution): :returns: iterator of paths """ record_path = os.path.join(self.path, 'installed-files.txt') - 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 + 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 diff --git a/pipenv/patched/notpip/_vendor/distlib/index.py b/pipenv/patched/notpip/_vendor/distlib/index.py index 25b96f99..7a87cdcf 100644 --- a/pipenv/patched/notpip/_vendor/distlib/index.py +++ b/pipenv/patched/notpip/_vendor/distlib/index.py @@ -49,7 +49,6 @@ class PackageIndex(object): self.ssl_verifier = None self.gpg = None self.gpg_home = None - self.rpc_proxy = None with open(os.devnull, 'w') as sink: # Use gpg by default rather than gpg2, as gpg2 insists on # prompting for passwords @@ -510,6 +509,8 @@ class PackageIndex(object): def search(self, terms, operator=None): if isinstance(terms, string_types): terms = {'name': terms} - if self.rpc_proxy is None: - self.rpc_proxy = ServerProxy(self.url, timeout=3.0) - return self.rpc_proxy.search(terms, operator or 'and') + rpc_proxy = ServerProxy(self.url, timeout=3.0) + try: + return rpc_proxy.search(terms, operator or 'and') + finally: + rpc_proxy('close')() diff --git a/pipenv/patched/notpip/_vendor/distlib/locators.py b/pipenv/patched/notpip/_vendor/distlib/locators.py index c25f629e..cb05b184 100644 --- a/pipenv/patched/notpip/_vendor/distlib/locators.py +++ b/pipenv/patched/notpip/_vendor/distlib/locators.py @@ -24,7 +24,7 @@ from .compat import (urljoin, urlparse, urlunparse, url2pathname, pathname2url, HTTPRedirectHandler as BaseRedirectHandler, text_type, Request, HTTPError, URLError) from .database import Distribution, DistributionPath, make_dist -from .metadata import Metadata +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) @@ -33,7 +33,7 @@ from .wheel import Wheel, is_compatible logger = logging.getLogger(__name__) -HASHER_HASH = re.compile('^(\w+)=([a-f0-9]+)') +HASHER_HASH = re.compile(r'^(\w+)=([a-f0-9]+)') CHARSET = re.compile(r';\s*charset\s*=\s*(.*)\s*$', re.I) HTML_CONTENT_TYPE = re.compile('text/html|application/x(ht)?ml') DEFAULT_INDEX = 'https://pypi.org/pypi' @@ -47,7 +47,10 @@ def get_all_distribution_names(url=None): if url is None: url = DEFAULT_INDEX client = ServerProxy(url, timeout=3.0) - return client.list_packages() + try: + return client.list_packages() + finally: + client('close')() class RedirectHandler(BaseRedirectHandler): """ @@ -66,7 +69,7 @@ class RedirectHandler(BaseRedirectHandler): if key in headers: newurl = headers[key] break - if newurl is None: + if newurl is None: # pragma: no cover return urlparts = urlparse(newurl) if urlparts.scheme == '': @@ -172,7 +175,7 @@ class Locator(object): This calls _get_project to do all the work, and just implements a caching layer on top. """ - if self._cache is None: + if self._cache is None: # pragma: no cover result = self._get_project(name) elif name in self._cache: result = self._cache[name] @@ -191,10 +194,11 @@ class Locator(object): basename = posixpath.basename(t.path) compatible = True is_wheel = basename.endswith('.whl') + is_downloadable = basename.endswith(self.downloadable_extensions) if is_wheel: compatible = is_compatible(Wheel(basename), self.wheel_tags) - return (t.scheme != 'https', 'pypi.org' in t.netloc, - is_wheel, compatible, basename) + return (t.scheme == 'https', 'pypi.org' in t.netloc, + is_downloadable, is_wheel, compatible, basename) def prefer_url(self, url1, url2): """ @@ -237,7 +241,7 @@ class Locator(object): result = None scheme, netloc, path, params, query, frag = urlparse(url) - if frag.lower().startswith('egg='): + if frag.lower().startswith('egg='): # pragma: no cover logger.debug('%s: version hint in fragment: %r', project_name, frag) m = HASHER_HASH.match(frag) @@ -246,7 +250,7 @@ class Locator(object): else: algo, digest = None, None origpath = path - if path and path[-1] == '/': + if path and path[-1] == '/': # pragma: no cover path = path[:-1] if path.endswith('.whl'): try: @@ -268,13 +272,15 @@ class Locator(object): } except Exception as e: # pragma: no cover logger.warning('invalid path for wheel: %s', path) - elif path.endswith(self.downloadable_extensions): + 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: + if not t: # pragma: no cover logger.debug('No match for project/version: %s', path) else: name, version, pyver = t @@ -287,7 +293,7 @@ class Locator(object): params, query, '')), #'packagetype': 'sdist', } - if pyver: + if pyver: # pragma: no cover result['python-version'] = pyver break if result and algo: @@ -348,7 +354,7 @@ class Locator(object): """ result = None r = parse_requirement(requirement) - if r is None: + 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) @@ -386,7 +392,7 @@ class Locator(object): d = {} sd = versions.get('digests', {}) for url in result.download_urls: - if url in sd: + if url in sd: # pragma: no cover d[url] = sd[url] result.digests = d self.matcher = None @@ -520,9 +526,9 @@ class Page(object): # declared with double quotes, single quotes or no quotes - which leads to # the length of the expression. _href = re.compile(""" -(rel\s*=\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\s\n]*))\s+)? -href\s*=\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\s\n]*)) -(\s+rel\s*=\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\s\n]*)))? +(rel\\s*=\\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\\s\n]*))\\s+)? +href\\s*=\\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\\s\n]*)) +(\\s+rel\\s*=\\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\\s\n]*)))? """, re.I | re.S | re.X) _base = re.compile(r"""]+)""", re.I | re.S) @@ -726,11 +732,14 @@ class SimpleScrapingLocator(Locator): continue for link, rel in page.links: if link not in self._seen: - 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) + 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: @@ -1236,7 +1245,7 @@ class DependencyFinder(object): ireqts = dist.run_requires | dist.meta_requires sreqts = dist.build_requires ereqts = set() - if dist in install_dists: + if meta_extras and dist in install_dists: for key in ('test', 'build', 'dev'): e = ':%s:' % key if e in meta_extras: diff --git a/pipenv/patched/notpip/_vendor/distlib/manifest.py b/pipenv/patched/notpip/_vendor/distlib/manifest.py index 9f033645..ca0fe442 100644 --- a/pipenv/patched/notpip/_vendor/distlib/manifest.py +++ b/pipenv/patched/notpip/_vendor/distlib/manifest.py @@ -24,7 +24,7 @@ __all__ = ['Manifest'] logger = logging.getLogger(__name__) # a \ followed by some spaces + EOL -_COLLAPSE_PATTERN = re.compile('\\\w*\n', re.M) +_COLLAPSE_PATTERN = re.compile('\\\\w*\n', re.M) _COMMENTED_LINE = re.compile('#.*?(?=\n)|\n(?=$)', re.M | re.S) # diff --git a/pipenv/patched/notpip/_vendor/distlib/markers.py b/pipenv/patched/notpip/_vendor/distlib/markers.py index afb19c62..ee1f3e23 100644 --- a/pipenv/patched/notpip/_vendor/distlib/markers.py +++ b/pipenv/patched/notpip/_vendor/distlib/markers.py @@ -1,182 +1,114 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2012-2013 Vinay Sajip. +# 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 345.""" +""" +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 ast import os import sys import platform +import re -from .compat import python_implementation, string_types -from .util import in_venv +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): """ - A limited evaluator for Python expressions. + This class is used to evaluate marker expessions. """ - operators = { - 'eq': lambda x, y: x == y, - 'gt': lambda x, y: x > y, - 'gte': lambda x, y: x >= y, + 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, - 'lt': lambda x, y: x < y, - 'lte': lambda x, y: x <= y, - 'not': lambda x: not x, - 'noteq': lambda x, y: x != y, - 'notin': lambda x, y: x not in y, + 'not in': lambda x, y: x not in y, } - allowed_values = { - 'sys_platform': sys.platform, - 'python_version': '%s.%s' % sys.version_info[:2], - # parsing sys.platform is not reliable, but there is no other - # way to get e.g. 2.7.2+, and the PEP is defined with sys.version - 'python_full_version': sys.version.split(' ', 1)[0], - 'os_name': os.name, - 'platform_in_venv': str(in_venv()), - 'platform_release': platform.release(), - 'platform_version': platform.version(), - 'platform_machine': platform.machine(), - 'platform_python_implementation': python_implementation(), - } - - def __init__(self, context=None): + def evaluate(self, expr, context): """ - Initialise an instance. - - :param context: If specified, names are looked up in this mapping. + Evaluate a marker expression returned by the :func:`parse_requirement` + function in the specified context. """ - self.context = context or {} - self.source = None - - def get_fragment(self, offset): - """ - Get the part of the source which is causing a problem. - """ - fragment_len = 10 - s = '%r' % (self.source[offset:offset + fragment_len]) - if offset + fragment_len < len(self.source): - s += '...' - return s - - def get_handler(self, node_type): - """ - Get a handler for the specified AST node type. - """ - return getattr(self, 'do_%s' % node_type, None) - - def evaluate(self, node, filename=None): - """ - Evaluate a source string or node, using ``filename`` when - displaying errors. - """ - if isinstance(node, string_types): - self.source = node - kwargs = {'mode': 'eval'} - if filename: - kwargs['filename'] = filename - try: - node = ast.parse(node, **kwargs) - except SyntaxError as e: - s = self.get_fragment(e.offset) - raise SyntaxError('syntax error %s' % s) - node_type = node.__class__.__name__.lower() - handler = self.get_handler(node_type) - if handler is None: - if self.source is None: - s = '(source not available)' + if isinstance(expr, string_types): + if expr[0] in '\'"': + result = expr[1:-1] else: - s = self.get_fragment(node.col_offset) - raise SyntaxError("don't know how to evaluate %r %s" % ( - node_type, s)) - return handler(node) - - def get_attr_key(self, node): - assert isinstance(node, ast.Attribute), 'attribute node expected' - return '%s.%s' % (node.value.id, node.attr) - - def do_attribute(self, node): - if not isinstance(node.value, ast.Name): - valid = False + if expr not in context: + raise SyntaxError('unknown variable: %s' % expr) + result = context[expr] else: - key = self.get_attr_key(node) - valid = key in self.context or key in self.allowed_values - if not valid: - raise SyntaxError('invalid expression: %s' % key) - if key in self.context: - result = self.context[key] - else: - result = self.allowed_values[key] + 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 do_boolop(self, node): - result = self.evaluate(node.values[0]) - is_or = node.op.__class__ is ast.Or - is_and = node.op.__class__ is ast.And - assert is_or or is_and - if (is_and and result) or (is_or and not result): - for n in node.values[1:]: - result = self.evaluate(n) - if (is_or and result) or (is_and and not result): - break - 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 - def do_compare(self, node): - def sanity_check(lhsnode, rhsnode): - valid = True - if isinstance(lhsnode, ast.Str) and isinstance(rhsnode, ast.Str): - valid = False - #elif (isinstance(lhsnode, ast.Attribute) - # and isinstance(rhsnode, ast.Attribute)): - # klhs = self.get_attr_key(lhsnode) - # krhs = self.get_attr_key(rhsnode) - # valid = klhs != krhs - if not valid: - s = self.get_fragment(node.col_offset) - raise SyntaxError('Invalid comparison: %s' % s) + if hasattr(sys, 'implementation'): + implementation_version = format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + else: + implementation_version = '0' + implementation_name = '' - lhsnode = node.left - lhs = self.evaluate(lhsnode) - result = True - for op, rhsnode in zip(node.ops, node.comparators): - sanity_check(lhsnode, rhsnode) - op = op.__class__.__name__.lower() - if op not in self.operators: - raise SyntaxError('unsupported operation: %r' % op) - rhs = self.evaluate(rhsnode) - result = self.operators[op](lhs, rhs) - if not result: - break - lhs = rhs - lhsnode = rhsnode - return result + 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 - def do_expression(self, node): - return self.evaluate(node.body) - - def do_name(self, node): - valid = False - if node.id in self.context: - valid = True - result = self.context[node.id] - elif node.id in self.allowed_values: - valid = True - result = self.allowed_values[node.id] - if not valid: - raise SyntaxError('invalid expression: %s' % node.id) - return result - - def do_str(self, node): - return node.s +DEFAULT_CONTEXT = default_context() +del default_context +evaluator = Evaluator() def interpret(marker, execution_context=None): """ @@ -187,4 +119,13 @@ def interpret(marker, execution_context=None): :param execution_context: The context used for name lookup. :type execution_context: mapping """ - return Evaluator(execution_context).evaluate(marker.strip()) + 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/pipenv/patched/notpip/_vendor/distlib/metadata.py b/pipenv/patched/notpip/_vendor/distlib/metadata.py index 75bfd68e..6d6470ff 100644 --- a/pipenv/patched/notpip/_vendor/distlib/metadata.py +++ b/pipenv/patched/notpip/_vendor/distlib/metadata.py @@ -50,7 +50,7 @@ PKG_INFO_ENCODING = 'utf-8' # to 1.2 once PEP 345 is supported everywhere PKG_INFO_PREFERRED_VERSION = '1.1' -_LINE_PREFIX_1_2 = re.compile('\n \|') +_LINE_PREFIX_1_2 = re.compile('\n \\|') _LINE_PREFIX_PRE_1_2 = re.compile('\n ') _241_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', 'Summary', 'Description', @@ -91,11 +91,16 @@ _426_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', _426_MARKERS = ('Private-Version', 'Provides-Extra', 'Obsoleted-By', 'Setup-Requires-Dist', 'Extension') +_566_FIELDS = _426_FIELDS + ('Description-Content-Type',) + +_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*("([^"]+)"|'([^']+)')''') @@ -107,6 +112,8 @@ def _version2fieldlist(version): 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) @@ -126,38 +133,51 @@ def _best_version(fields): continue keys.append(key) - possible_versions = ['1.0', '1.1', '1.2', '2.0'] + 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_0) > 1: - raise MetadataConflictError('You used incompatible 1.1/1.2/2.0 fields') + 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_0: + 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 @@ -165,6 +185,8 @@ def _best_version(fields): return '1.1' if is_1_2: return '1.2' + if is_2_1: + return '2.1' return '2.0' @@ -355,6 +377,7 @@ class LegacyMetadata(object): 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): @@ -634,7 +657,7 @@ class Metadata(object): instance which handles the key-value metadata format. """ - METADATA_VERSION_MATCHER = re.compile('^\d+(\.\d+)*$') + METADATA_VERSION_MATCHER = re.compile(r'^\d+(\.\d+)*$') NAME_MATCHER = re.compile('^[0-9A-Z]([0-9A-Z_.-]*[0-9A-Z])?$', re.I) diff --git a/pipenv/patched/notpip/_vendor/distlib/resources.py b/pipenv/patched/notpip/_vendor/distlib/resources.py index f07cde25..18840167 100644 --- a/pipenv/patched/notpip/_vendor/distlib/resources.py +++ b/pipenv/patched/notpip/_vendor/distlib/resources.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2013-2016 Vinay Sajip. +# Copyright (C) 2013-2017 Vinay Sajip. # Licensed to the Python Software Foundation under a contributor agreement. # See LICENSE.txt and CONTRIBUTORS.txt. # diff --git a/pipenv/patched/notpip/_vendor/distlib/scripts.py b/pipenv/patched/notpip/_vendor/distlib/scripts.py index 792fc2e1..0b7c3d0b 100644 --- a/pipenv/patched/notpip/_vendor/distlib/scripts.py +++ b/pipenv/patched/notpip/_vendor/distlib/scripts.py @@ -38,7 +38,7 @@ _DEFAULT_MANIFEST = ''' # check if Python is called on the first line with this expression FIRST_LINE_RE = re.compile(b'^#!.*pythonw?[0-9.]*([ \t].*)?$') -SCRIPT_TEMPLATE = '''# -*- coding: utf-8 -*- +SCRIPT_TEMPLATE = r'''# -*- coding: utf-8 -*- if __name__ == '__main__': import sys, re @@ -57,7 +57,7 @@ if __name__ == '__main__': 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) + sys.stderr.write('%%s\n' %% e) rc = 1 sys.exit(rc) ''' @@ -136,6 +136,37 @@ class ScriptMaker(object): 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: @@ -169,7 +200,7 @@ class ScriptMaker(object): 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 = b'#!' + executable + post_interp + b'\n' + 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 diff --git a/pipenv/patched/notpip/_vendor/distlib/t32.exe b/pipenv/patched/notpip/_vendor/distlib/t32.exe old mode 100644 new mode 100755 index 836211d848ec0ba46667d33cfade3348888062ae..a09d926872d84ae22a617dfe9ebb560d420b37de GIT binary patch delta 27840 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 O&Fjp&&X1Keh5kP{Zt+(D delta 24126 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 ZYETR6K_h4e?VuBMgWm2-Z>LUg{0~+?P|yGX delta 28004 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 1.2, < 2.0 [bar, baz]' -# -# The regex can seem a bit hairy, so we build it up out of smaller pieces -# which are manageable. +# Requirement parsing code as per PEP 508 # -COMMA = r'\s*,\s*' -COMMA_RE = re.compile(COMMA) +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\.{}()*+#:;,/?!~`@$%^&=|<>\[\]-]+)') -IDENT = r'(\w|[.-])+' -EXTRA_IDENT = r'(\*|:(\*|\w+):|' + IDENT + ')' -VERSPEC = IDENT + r'\*?' -RELOP = '([<>=!~]=)|[<>]' +def parse_marker(marker_string): + """ + Parse a marker string and return a dictionary containing a marker expression. -# -# The first relop is optional - if absent, will be taken as '~=' -# -BARE_CONSTRAINTS = ('(' + RELOP + r')?\s*(' + VERSPEC + ')(' + COMMA + '(' + - RELOP + r')\s*(' + VERSPEC + '))*') - -DIRECT_REF = '(from\s+(?P.*))' - -# -# Either the bare constraints or the bare constraints in parentheses -# -CONSTRAINTS = (r'\(\s*(?P' + BARE_CONSTRAINTS + '|' + DIRECT_REF + - r')\s*\)|(?P' + BARE_CONSTRAINTS + '\s*)') - -EXTRA_LIST = EXTRA_IDENT + '(' + COMMA + EXTRA_IDENT + ')*' -EXTRAS = r'\[\s*(?P' + EXTRA_LIST + r')?\s*\]' -REQUIREMENT = ('(?P' + IDENT + r')\s*(' + EXTRAS + r'\s*)?(\s*' + - CONSTRAINTS + ')?$') -REQUIREMENT_RE = re.compile(REQUIREMENT) - -# -# Used to scan through the constraints -# -RELOP_IDENT = '(?P' + RELOP + r')\s*(?P' + VERSPEC + ')' -RELOP_IDENT_RE = re.compile(RELOP_IDENT) - -def parse_requirement(s): - - def get_constraint(m): - d = m.groupdict() - return d['op'], d['vn'] - - result = None - m = REQUIREMENT_RE.match(s) - if m: - d = m.groupdict() - name = d['dn'] - cons = d['c1'] or d['c2'] - if not d['diref']: - url = None + 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: - # direct reference - cons = None - url = d['diref'].strip() - if not cons: - cons = None - constr = '' - rs = d['dn'] + 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: - if cons[0] not in '<>!=': - cons = '~=' + cons - iterator = RELOP_IDENT_RE.finditer(cons) - cons = [get_constraint(m) for m in iterator] - rs = '%s (%s)' % (name, ', '.join(['%s %s' % con for con in cons])) - if not d['ex']: + 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: - extras = COMMA_RE.split(d['ex']) - result = Container(name=name, constraints=cons, extras=extras, - requirement=rs, source=s, url=url) - return result + + 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(base, path): + def get_rel_path(root, path): # normalizes and returns a lstripped-/-separated path - base = base.replace(os.path.sep, '/') + root = root.replace(os.path.sep, '/') path = path.replace(os.path.sep, '/') - assert path.startswith(base) - return path[len(base):].lstrip('/') - + assert path.startswith(root) + return path[len(root):].lstrip('/') destinations = {} for base, suffix, dest in rules: @@ -161,7 +302,7 @@ def in_venv(): 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 macOS +# to the stub on OS X # if sys.platform == 'darwin' and ('__PYVENV_LAUNCHER__' # in os.environ): # result = os.environ['__PYVENV_LAUNCHER__'] @@ -1443,6 +1584,9 @@ def _csv_open(fn, mode, **kwargs): 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) @@ -1558,11 +1702,11 @@ class Configurator(BaseConfigurator): result = json.load(f) return result -# -# Mixin for running subprocesses and capturing their output -# class SubprocessMixin(object): + """ + Mixin for running subprocesses and capturing their output + """ def __init__(self, verbose=False, progress=None): self.verbose = verbose self.progress = progress diff --git a/pipenv/patched/notpip/_vendor/distlib/version.py b/pipenv/patched/notpip/_vendor/distlib/version.py index 48c17c0a..3eebe18e 100644 --- a/pipenv/patched/notpip/_vendor/distlib/version.py +++ b/pipenv/patched/notpip/_vendor/distlib/version.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2012-2016 The Python Software Foundation. +# Copyright (C) 2012-2017 The Python Software Foundation. # See LICENSE.txt and CONTRIBUTORS.txt. # """ @@ -12,6 +12,7 @@ import logging import re from .compat import string_types +from .util import parse_requirement __all__ = ['NormalizedVersion', 'NormalizedMatcher', 'LegacyVersion', 'LegacyMatcher', @@ -78,10 +79,6 @@ class Version(object): class Matcher(object): version_class = None - dist_re = re.compile(r"^(\w[\s\w'.-]*)(\((.*)\))?") - comp_re = re.compile(r'^(<=|>=|<|>|!=|={2,3}|~=)?\s*([^\s,]+)$') - num_re = re.compile(r'^\d+(\.\d+)*$') - # value is either a callable or the name of a method _operators = { '<': lambda v, c, p: v < c, @@ -95,26 +92,24 @@ class Matcher(object): '!=': 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() - m = self.dist_re.match(s) - if not m: + r = self.parse_requirement(s) + if not r: raise ValueError('Not valid: %r' % s) - groups = m.groups('') - self.name = groups[0].strip() + self.name = r.name self.key = self.name.lower() # for case-insensitive comparisons clist = [] - if groups[2]: - constraints = [c.strip() for c in groups[2].split(',')] - for c in constraints: - m = self.comp_re.match(c) - if not m: - raise ValueError('Invalid %r in %r' % (c, s)) - groups = m.groups() - op = groups[0] or '~=' - s = groups[1] + 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 ' @@ -122,9 +117,8 @@ class Matcher(object): # 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 - if not self.num_re.match(vn): - # Just to check that vn is a valid version - self.version_class(vn) + # 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 @@ -400,7 +394,7 @@ _REPLACEMENTS = ( _SUFFIX_REPLACEMENTS = ( (re.compile('^[:~._+-]+'), ''), # remove leading puncts - (re.compile('[,*")([\]]'), ''), # remove unwanted chars + (re.compile('[,*")([\\]]'), ''), # remove unwanted chars (re.compile('[~:+_ -]'), '.'), # replace illegal chars (re.compile('[.]{2,}'), '.'), # multiple runs of '.' (re.compile(r'\.$'), ''), # trailing '.' @@ -628,7 +622,7 @@ class LegacyMatcher(Matcher): _operators = dict(Matcher._operators) _operators['~='] = '_match_compatible' - numeric_re = re.compile('^(\d+(\.\d+)*)') + numeric_re = re.compile(r'^(\d+(\.\d+)*)') def _match_compatible(self, version, constraint, prefix): if version < constraint: diff --git a/pipenv/patched/notpip/_vendor/distlib/w32.exe b/pipenv/patched/notpip/_vendor/distlib/w32.exe old mode 100644 new mode 100755 index 85a90a5f51a9596679a7365eadd3352443b95782..732215a9d34ccb7b417d637a7646d9b843ecafa8 GIT binary patch delta 27021 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 N{Cn@ULd6eZ{|~Mk-)8^- delta 23145 zcmd_SdtB7j_BZ~SVZc!aK?FoVZldCSV6MysMg=4T8$|~xMJ=^yA|stKEp_w^l+#FQ z+sew08hWy_vSXR1#|AO+R$6(K@`gpab<8LYvCw(md(VJ%zTfZf_q?9h^WQ_Q*=w)8 z_I>TO*Is*nT(&cG*}BkG1`%Ct9OL{Xyz>3)Hu3FFn33_??Oze6H{ZVf6A#zj?%?5; z+v^bi9=-Z@8^Y_hklXKY`qm)-+F-bzhZ7%p$jZtTf`8@$K`0i53KuR-EbF8-3*tmk zxTuF9Yz67>0rLET2%`XAGDMWpeU(TMB!V#iBAF-}*mLXmf?!~LsUl&Md39QE*)ox^ zK`IEV>IETbby{Lv<~czyF^+H*2PS zrXUO)f)p=c7+@P2Ax?}K0jw3ka-SgcR#gHr}hg|}i_!(`9Z!bVA}iOi7pKm2|(o$dGg zUHjv0B7dyFsx9eId_k9Y6NE!7qo+h#rtsGmc9aA7am_V~on@wEicXZH_XaVi* zpq5@FCv-q;av-`}f^jKDYaCJ<7fI%aYQ+7+$=1-+%x%3mzlEjUpzmP}5qetb;X8i6 zr&ZzA-;8|8YhC#rxe+>0oYR9Og(W%*0(nqg8O=uy&UYZud$Y;94ec@0+qYToGivj5 z{S^=Rdd~4g?K+BtIr?7qZbkaW`PY0Q?t)g<%pXvcr=YcbIv*E{r_~=DgYj|=6l`Lf z$R=3KXtLQKTg(QrwWiG>^T$45U>xmX4pE`!Kwu_ZOQeD$dSexzT6=e!fGkPiQg}^# zrd%!U%deh+e6Yz96#L!P8BK_J3Z$hL%tTq4J3k}IAFK2dZ?{W`Hor}YNsyV8L<$*-^=QCViD zFY4L!#<=YnnI4rEY_>N4Niz~>(Hj`*MoC7@X*P7*JN!w06#82r)k;qVQsq4L48*M~c{#0+`SNnGMFqtDC}eyB zM%H6A)tiLf+rU(cdGrmaEtI+oIwC(2=3snNTqs#3W20t1P30Z?~n5pu2QWri_ zx|K(6-y+|IC&kNABwK}w)B5Xd$eMWKpP1b#VgM;!cX;x)tmhn7GfPZy&@{%k~X~4>G*R-G)3UAIE zEVNn~I~({AurumaMqSfM{i&T?k*$y(N8C)OwUehJ5~oPcK_gqrXh$epF!D0G8>4WP zW}xt+`Utjs9pdW^myOUnHkq{*+*HyB3eoRg(xUKsrb+eZQKP=m5kuF-2|}ZQAA#n@ zk)I;coYQ*?g1bP9)Cl?@PmM>a?+`TWoE*I)m6mj6vE8XHXf<0|h4e{qVU74ULK{U{ zO6hd$L9YE#?t+%af)1=tKgEbao3zk3k-vdy*{>oo=nWn}R)WRjkV13yrmf+zXmnhK zTTa)+lC?cE#NJr4x2LKP7KuN066O$68Ef5ⅅ=fOL|16jRy6oO-d~ZtUMt0zJY=* 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 bcSG)`+%382fAH^<#L1!`!|+cZKk>f+ixsqy diff --git a/pipenv/patched/notpip/_vendor/distlib/w64.exe b/pipenv/patched/notpip/_vendor/distlib/w64.exe old mode 100644 new mode 100755 index b3aea316f61163e2637a7c0b0a96cd3c664b54dc..c41bd0a011fd760ce20ba795d9e535e0d2c39876 GIT binary patch delta 30935 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ÐYKWd@lS~zoMC-wE9sGE@Cn?Fe+ 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 (3, 5): - raise subprocess.CalledProcessError(code, cmd, stdout, stderr) - elif sys.version_info[:2] >= (2, 7): - raise subprocess.CalledProcessError(code, cmd, stdout) - elif sys.version_info[:2] == (2, 6): - raise subprocess.CalledProcessError(code, cmd) + 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): @@ -950,7 +952,6 @@ class LinuxDistribution(object): """ props = {} for line in lines: - line = line.decode('utf-8') if isinstance(line, bytes) else line kv = line.strip('\n').split(':', 1) if len(kv) != 2: # Ignore lines without colon. @@ -959,7 +960,8 @@ class LinuxDistribution(object): props.update({k.replace(' ', '_').lower(): v.strip()}) return props - def _get_distro_release_info(self): + @cached_property + def _distro_release_info(self): """ Get the information items from the specified distro release file. @@ -981,11 +983,32 @@ class LinuxDistribution(object): distro_info['id'] = match.group(1) return distro_info else: - 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() + 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 @@ -1011,12 +1034,16 @@ class LinuxDistribution(object): Returns: A dictionary containing all information items. """ - if os.path.isfile(filepath): + 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()) - return {} + 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): @@ -1051,8 +1078,6 @@ _distro = LinuxDistribution() def main(): - import argparse - logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) logger.addHandler(logging.StreamHandler(sys.stdout)) @@ -1070,11 +1095,9 @@ def main(): else: logger.info('Name: %s', name(pretty=True)) distribution_version = version(pretty=True) - if distribution_version: - logger.info('Version: %s', distribution_version) + logger.info('Version: %s', distribution_version) distribution_codename = codename() - if distribution_codename: - logger.info('Codename: %s', distribution_codename) + logger.info('Codename: %s', distribution_codename) if __name__ == '__main__': diff --git a/pipenv/patched/notpip/_vendor/html5lib/__init__.py b/pipenv/patched/notpip/_vendor/html5lib/__init__.py index 7427eb12..99d9e89f 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/__init__.py +++ b/pipenv/patched/notpip/_vendor/html5lib/__init__.py @@ -1,14 +1,23 @@ """ -HTML parsing library based on the WHATWG "HTML5" -specification. The parser is designed to be compatible with existing -HTML found in the wild and implements well-defined error recovery that +HTML parsing library based on the `WHATWG HTML specification +`_. 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: +Example usage:: -import html5lib -f = open("my_document.html") -tree = html5lib.parse(f) + from notpip._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 @@ -22,4 +31,5 @@ __all__ = ["HTMLParser", "parse", "parseFragment", "getTreeBuilder", "getTreeWalker", "serialize"] # this has to be at the top level, see how setup.py parses this -__version__ = "1.0b10" +#: Distribution version number. +__version__ = "1.0.1" diff --git a/pipenv/patched/notpip/_vendor/html5lib/_ihatexml.py b/pipenv/patched/notpip/_vendor/html5lib/_ihatexml.py index d6d1d6fb..4c77717b 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/_ihatexml.py +++ b/pipenv/patched/notpip/_vendor/html5lib/_ihatexml.py @@ -180,7 +180,7 @@ nonXmlNameBMPRegexp = re.compile('[\x00-,/:-@\\[-\\^`\\{-\xb6\xb8-\xbf\xd7\xf7\u 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\-\'()+,./:=?;!*#@$_%]") +nonPubidCharRegexp = re.compile("[^\x20\x0D\x0Aa-zA-Z0-9\\-'()+,./:=?;!*#@$_%]") class InfosetFilter(object): diff --git a/pipenv/patched/notpip/_vendor/html5lib/_inputstream.py b/pipenv/patched/notpip/_vendor/html5lib/_inputstream.py index 249b0c5f..fcae4c04 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/_inputstream.py +++ b/pipenv/patched/notpip/_vendor/html5lib/_inputstream.py @@ -1,15 +1,15 @@ from __future__ import absolute_import, division, unicode_literals -from pip9._vendor.six import text_type, binary_type -from pip9._vendor.six.moves import http_client, urllib +from notpip._vendor.six import text_type, binary_type +from notpip._vendor.six.moves import http_client, urllib import codecs import re -from pip9._vendor import webencodings +from notpip._vendor import webencodings from .constants import EOF, spaceCharacters, asciiLetters, asciiUppercase -from .constants import ReparseException +from .constants import _ReparseException from . import _utils from io import StringIO @@ -48,7 +48,7 @@ non_bmp_invalid_codepoints = set([0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, 0xFFFFF, 0x10FFFE, 0x10FFFF]) -ascii_punctuation_re = re.compile("[\u0009-\u000D\u0020-\u002F\u003A-\u0040\u005B-\u0060\u007B-\u007E]") +ascii_punctuation_re = re.compile("[\u0009-\u000D\u0020-\u002F\u003A-\u0040\u005C\u005B-\u0060\u007B-\u007E]") # Cache for charsUntil() charsUntilRegEx = {} @@ -489,7 +489,7 @@ class HTMLBinaryInputStream(HTMLUnicodeInputStream): # Guess with chardet, if available if chardet: try: - from chardet.universaldetector import UniversalDetector + from notpip._vendor.chardet.universaldetector import UniversalDetector except ImportError: pass else: @@ -530,7 +530,7 @@ class HTMLBinaryInputStream(HTMLUnicodeInputStream): self.rawStream.seek(0) self.charEncoding = (newEncoding, "certain") self.reset() - raise ReparseException("Encoding changed from %s to %s" % (self.charEncoding[0], newEncoding)) + 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 diff --git a/pipenv/patched/notpip/_vendor/html5lib/_tokenizer.py b/pipenv/patched/notpip/_vendor/html5lib/_tokenizer.py index d472625c..f20c935a 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/_tokenizer.py +++ b/pipenv/patched/notpip/_vendor/html5lib/_tokenizer.py @@ -1,6 +1,6 @@ from __future__ import absolute_import, division, unicode_literals -from pip9._vendor.six import unichr as chr +from notpip._vendor.six import unichr as chr from collections import deque diff --git a/pipenv/patched/notpip/_vendor/html5lib/_trie/_base.py b/pipenv/patched/notpip/_vendor/html5lib/_trie/_base.py index 25eece46..a1158bbb 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/_trie/_base.py +++ b/pipenv/patched/notpip/_vendor/html5lib/_trie/_base.py @@ -13,8 +13,7 @@ class Trie(Mapping): if prefix is None: return set(keys) - # Python 2.6: no set comprehensions - return set([x for x in keys if x.startswith(prefix)]) + return {x for x in keys if x.startswith(prefix)} def has_keys_with_prefix(self, prefix): for key in self.keys(): diff --git a/pipenv/patched/notpip/_vendor/html5lib/_trie/datrie.py b/pipenv/patched/notpip/_vendor/html5lib/_trie/datrie.py index 2050ac4c..03083212 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/_trie/datrie.py +++ b/pipenv/patched/notpip/_vendor/html5lib/_trie/datrie.py @@ -1,7 +1,7 @@ from __future__ import absolute_import, division, unicode_literals from datrie import Trie as DATrie -from pip9._vendor.six import text_type +from notpip._vendor.six import text_type from ._base import Trie as ABCTrie diff --git a/pipenv/patched/notpip/_vendor/html5lib/_trie/py.py b/pipenv/patched/notpip/_vendor/html5lib/_trie/py.py index 226e903a..b5b1736f 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/_trie/py.py +++ b/pipenv/patched/notpip/_vendor/html5lib/_trie/py.py @@ -1,5 +1,5 @@ from __future__ import absolute_import, division, unicode_literals -from pip9._vendor.six import text_type +from notpip._vendor.six import text_type from bisect import bisect_left diff --git a/pipenv/patched/notpip/_vendor/html5lib/_utils.py b/pipenv/patched/notpip/_vendor/html5lib/_utils.py index 0610419c..7e1d61dd 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/_utils.py +++ b/pipenv/patched/notpip/_vendor/html5lib/_utils.py @@ -1,9 +1,8 @@ from __future__ import absolute_import, division, unicode_literals -import sys from types import ModuleType -from pip9._vendor.six import text_type +from notpip._vendor.six import text_type try: import xml.etree.cElementTree as default_etree @@ -13,11 +12,9 @@ except ImportError: __all__ = ["default_etree", "MethodDispatcher", "isSurrogatePair", "surrogatePairToCodepoint", "moduleFactoryFactory", - "supports_lone_surrogates", "PY27"] + "supports_lone_surrogates"] -PY27 = sys.version_info[0] == 2 and sys.version_info[1] >= 7 - # 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 diff --git a/pipenv/patched/notpip/_vendor/html5lib/constants.py b/pipenv/patched/notpip/_vendor/html5lib/constants.py index 9e7541d3..1ff80419 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/constants.py +++ b/pipenv/patched/notpip/_vendor/html5lib/constants.py @@ -423,7 +423,7 @@ specialElements = frozenset([ ]) htmlIntegrationPointElements = frozenset([ - (namespaces["mathml"], "annotaion-xml"), + (namespaces["mathml"], "annotation-xml"), (namespaces["svg"], "foreignObject"), (namespaces["svg"], "desc"), (namespaces["svg"], "title") @@ -588,7 +588,7 @@ rcdataElements = frozenset([ ]) booleanAttributes = { - "": frozenset(["irrelevant"]), + "": frozenset(["irrelevant", "itemscope"]), "style": frozenset(["scoped"]), "img": frozenset(["ismap"]), "audio": frozenset(["autoplay", "controls"]), @@ -606,6 +606,7 @@ booleanAttributes = { "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 @@ -2938,8 +2939,9 @@ 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): +class _ReparseException(Exception): pass diff --git a/pipenv/patched/notpip/_vendor/html5lib/filters/alphabeticalattributes.py b/pipenv/patched/notpip/_vendor/html5lib/filters/alphabeticalattributes.py index 4795baec..5ba926e3 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/filters/alphabeticalattributes.py +++ b/pipenv/patched/notpip/_vendor/html5lib/filters/alphabeticalattributes.py @@ -2,19 +2,28 @@ from __future__ import absolute_import, division, unicode_literals from . import base -try: - from collections import OrderedDict -except ImportError: - from ordereddict import OrderedDict +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=lambda x: x[0]): + key=_attr_key): attrs[name] = value token["data"] = attrs yield token diff --git a/pipenv/patched/notpip/_vendor/html5lib/filters/inject_meta_charset.py b/pipenv/patched/notpip/_vendor/html5lib/filters/inject_meta_charset.py index 2059ec86..aefb5c84 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/filters/inject_meta_charset.py +++ b/pipenv/patched/notpip/_vendor/html5lib/filters/inject_meta_charset.py @@ -4,7 +4,15 @@ from . import base class Filter(base.Filter): + """Injects ```` tag into head of document""" def __init__(self, source, encoding): + """Creates a Filter + + :arg source: the source token stream + + :arg encoding: the encoding to set + + """ base.Filter.__init__(self, source) self.encoding = encoding diff --git a/pipenv/patched/notpip/_vendor/html5lib/filters/lint.py b/pipenv/patched/notpip/_vendor/html5lib/filters/lint.py index 09a27025..67f8bd67 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/filters/lint.py +++ b/pipenv/patched/notpip/_vendor/html5lib/filters/lint.py @@ -1,6 +1,6 @@ from __future__ import absolute_import, division, unicode_literals -from pip9._vendor.six import text_type +from notpip._vendor.six import text_type from . import base from ..constants import namespaces, voidElements @@ -10,7 +10,19 @@ 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 diff --git a/pipenv/patched/notpip/_vendor/html5lib/filters/optionaltags.py b/pipenv/patched/notpip/_vendor/html5lib/filters/optionaltags.py index f6edb734..4a865012 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/filters/optionaltags.py +++ b/pipenv/patched/notpip/_vendor/html5lib/filters/optionaltags.py @@ -4,6 +4,7 @@ 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: diff --git a/pipenv/patched/notpip/_vendor/html5lib/filters/sanitizer.py b/pipenv/patched/notpip/_vendor/html5lib/filters/sanitizer.py index e70bfbac..11b5ca11 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/filters/sanitizer.py +++ b/pipenv/patched/notpip/_vendor/html5lib/filters/sanitizer.py @@ -3,7 +3,7 @@ from __future__ import absolute_import, division, unicode_literals import re from xml.sax.saxutils import escape, unescape -from pip9._vendor.six.moves import urllib_parse as urlparse +from notpip._vendor.six.moves import urllib_parse as urlparse from . import base from ..constants import namespaces, prefixes @@ -705,7 +705,7 @@ data_content_type = re.compile(r''' class Filter(base.Filter): - """ sanitization of XHTML+MathML+SVG and of inline style attributes.""" + """Sanitizes token stream of XHTML+MathML+SVG and of inline style attributes""" def __init__(self, source, allowed_elements=allowed_elements, @@ -718,6 +718,37 @@ class Filter(base.Filter): 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 @@ -737,11 +768,11 @@ class Filter(base.Filter): 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. + # 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> @@ -782,7 +813,7 @@ class Filter(base.Filter): # 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]+", '', + 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", "") @@ -807,7 +838,7 @@ class Filter(base.Filter): ' ', unescape(attrs[attr])) if (token["name"] in self.svg_allow_local_href and - (namespaces['xlink'], 'href') in attrs and re.search('^\s*[^#\s].*', + (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: @@ -837,16 +868,16 @@ class Filter(base.Filter): def sanitize_css(self, style): # disallow urls - style = re.compile('url\s*\(\s*[^\s)]+?\s*\)\s*').sub(' ', style) + style = re.compile(r'url\s*\(\s*[^\s)]+?\s*\)\s*').sub(' ', style) # gauntlet - if not re.match("""^([:,;#%.\sa-zA-Z0-9!]|\w-\w|'[\s\w]+'|"[\s\w]+"|\([\d,\s]+\))*$""", style): + if not re.match(r"""^([:,;#%.\sa-zA-Z0-9!]|\w-\w|'[\s\w]+'|"[\s\w]+"|\([\d,\s]+\))*$""", style): return '' - if not re.match("^\s*([-\w]+\s*:[^:;]*(;\s*|$))*$", style): + if not re.match(r"^\s*([-\w]+\s*:[^:;]*(;\s*|$))*$", style): return '' clean = [] - for prop, value in re.findall("([-\w]+)\s*:\s*([^:;]*)", style): + for prop, value in re.findall(r"([-\w]+)\s*:\s*([^:;]*)", style): if not value: continue if prop.lower() in self.allowed_css_properties: @@ -855,7 +886,7 @@ class Filter(base.Filter): 'padding']: for keyword in value.split(): if keyword not in self.allowed_css_keywords and \ - not re.match("^(#[0-9a-f]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|\d{0,2}\.?\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\))?)$", keyword): # noqa + 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 + ';') diff --git a/pipenv/patched/notpip/_vendor/html5lib/filters/whitespace.py b/pipenv/patched/notpip/_vendor/html5lib/filters/whitespace.py index 89210528..0d12584b 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/filters/whitespace.py +++ b/pipenv/patched/notpip/_vendor/html5lib/filters/whitespace.py @@ -10,7 +10,7 @@ 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): diff --git a/pipenv/patched/notpip/_vendor/html5lib/html5parser.py b/pipenv/patched/notpip/_vendor/html5lib/html5parser.py index dea0295e..3dae3829 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/html5parser.py +++ b/pipenv/patched/notpip/_vendor/html5lib/html5parser.py @@ -1,12 +1,8 @@ from __future__ import absolute_import, division, unicode_literals -from pip9._vendor.six import with_metaclass, viewkeys, PY3 +from notpip._vendor.six import with_metaclass, viewkeys import types - -try: - from collections import OrderedDict -except ImportError: - from pip9._vendor.ordereddict import OrderedDict +from collections import OrderedDict from . import _inputstream from . import _tokenizer @@ -24,18 +20,53 @@ from .constants import ( adjustForeignAttributes as adjustForeignAttributesMap, adjustMathMLAttributes, adjustSVGAttributes, E, - ReparseException + _ReparseException ) def parse(doc, treebuilder="etree", namespaceHTMLElements=True, **kwargs): - """Parse a string or file-like object into a tree""" + """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('

This is a doc

') + + + """ 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('this is a fragment') + + + """ tb = treebuilders.getTreeBuilder(treebuilder) p = HTMLParser(tb, namespaceHTMLElements=namespaceHTMLElements) return p.parseFragment(doc, container=container, **kwargs) @@ -54,16 +85,30 @@ def method_decorator_metaclass(function): class HTMLParser(object): - """HTML parser. Generates a tree structure from a stream of (possibly - malformed) HTML""" + """HTML parser + + Generates a tree structure from a stream of (possibly malformed) HTML. + + """ def __init__(self, tree=None, strict=False, namespaceHTMLElements=True, debug=False): """ - strict - raise an exception when a parse error is encountered + :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 - tree - a treebuilder class controlling the type of tree that will be - returned. Built in treebuilders can be accessed through - html5lib.treebuilders.getTreeBuilder(treeType) """ # Raise an exception on the first error encountered @@ -87,7 +132,7 @@ class HTMLParser(object): try: self.mainLoop() - except ReparseException: + except _ReparseException: self.reset() self.mainLoop() @@ -127,9 +172,8 @@ class HTMLParser(object): @property def documentEncoding(self): - """The name of the character encoding - that was used to decode the input stream, - or :obj:`None` if that is not determined yet. + """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'): @@ -223,14 +267,24 @@ class HTMLParser(object): def parse(self, stream, *args, **kwargs): """Parse a HTML document into a well-formed tree - stream - a filelike object or string containing the HTML to be parsed + :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) + 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('

This is a doc

') + - scripting - treat noscript elements as if javascript was turned on """ self._parse(stream, False, None, *args, **kwargs) return self.tree.getDocument() @@ -238,17 +292,27 @@ class HTMLParser(object): def parseFragment(self, stream, *args, **kwargs): """Parse a HTML fragment into a well-formed tree fragment - container - name of the element we're setting the innerHTML property - if set to None, default to 'div' + :arg container: name of the element we're setting the innerHTML + property if set to None, default to 'div' - stream - a filelike object or string containing the HTML to be parsed + :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) + 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('this is a fragment') + - scripting - treat noscript elements as if javascript was turned on """ self._parse(stream, True, *args, **kwargs) return self.tree.getFragment() @@ -262,8 +326,7 @@ class HTMLParser(object): raise ParseError(E[errorcode] % datavars) def normalizeToken(self, token): - """ HTML5 specific normalizations to the token stream """ - + # HTML5 specific normalizations to the token stream if token["type"] == tokenTypes["StartTag"]: raw = token["data"] token["data"] = OrderedDict(raw) @@ -331,9 +394,7 @@ class HTMLParser(object): self.phase = new_phase def parseRCDataRawtext(self, token, contentType): - """Generic RCDATA/RAWTEXT Parsing algorithm - contentType - RCDATA or RAWTEXT - """ + # Generic RCDATA/RAWTEXT Parsing algorithm assert contentType in ("RAWTEXT", "RCDATA") self.tree.insertElement(token) @@ -2711,10 +2772,7 @@ def getPhases(debug): def adjust_attributes(token, replacements): - if PY3 or _utils.PY27: - needs_adjustment = viewkeys(token['data']) & viewkeys(replacements) - else: - needs_adjustment = frozenset(token['data']) & frozenset(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()) diff --git a/pipenv/patched/notpip/_vendor/html5lib/serializer.py b/pipenv/patched/notpip/_vendor/html5lib/serializer.py index f7203e25..04f90857 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/serializer.py +++ b/pipenv/patched/notpip/_vendor/html5lib/serializer.py @@ -1,5 +1,5 @@ from __future__ import absolute_import, division, unicode_literals -from pip9._vendor.six import text_type +from notpip._vendor.six import text_type import re @@ -68,10 +68,33 @@ def htmlentityreplace_errors(exc): 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('

Hi!

') + >>> serialize(token_stream, omit_optional_tags=False) + '

Hi!

' + + """ # XXX: Should we cache this? walker = treewalkers.getTreeWalker(tree) s = HTMLSerializer(**serializer_opts) @@ -110,50 +133,83 @@ class HTMLSerializer(object): "strip_whitespace", "sanitize") def __init__(self, **kwargs): - """Initialize HTMLSerializer. + """Initialize HTMLSerializer - Keyword options (default given first unless specified) include: + :arg inject_meta_charset: Whether or not to inject the meta charset. - inject_meta_charset=True|False - Whether it insert a meta element to define the character set of the - document. - quote_attr_values="legacy"|"spec"|"always" - Whether to quote attribute values that don't require quoting - per legacy browser behaviour, when required by the standard, or always. - quote_char=u'"'|u"'" - Use given quote character for attribute quoting. Default is to - use double quote unless attribute value contains a double quote, - in which case single quotes are used instead. - escape_lt_in_attrs=False|True - Whether to escape < in attribute values. - escape_rcdata=False|True - Whether to escape characters that need to be escaped within normal - elements within rcdata elements such as style. - resolve_entities=True|False - Whether to resolve named character entities that appear in the - source tree. The XML predefined entities < > & " ' - are unaffected by this setting. - strip_whitespace=False|True - Whether to remove semantically meaningless whitespace. (This - compresses all whitespace to a single space except within pre.) - minimize_boolean_attributes=True|False - Shortens boolean attributes to give just the attribute value, - for example becomes . - use_trailing_solidus=False|True - Includes a close-tag slash at the end of the start tag of void - elements (empty elements whose end tag is forbidden). E.g.
. - space_before_trailing_solidus=True|False - Places a space immediately before the closing slash in a tag - using a trailing solidus. E.g.
. Requires use_trailing_solidus. - sanitize=False|True - Strip all unsafe or unknown constructs from output. - See `html5lib user documentation`_ - omit_optional_tags=True|False - Omit start/end tags that are optional. - alphabetical_attributes=False|True - Reorder attributes to be in alphabetical order. + 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:: + + + + becomes:: + + + + 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. ``
``. + + 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. + ``
``. 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``. - .. _html5lib user documentation: http://code.google.com/p/html5lib/wiki/UserDocumentation """ unexpected_args = frozenset(kwargs) - frozenset(self.options) if len(unexpected_args) > 0: @@ -317,6 +373,25 @@ class HTMLSerializer(object): 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('Hi!') + >>> walker = getTreeWalker('etree') + >>> serializer = HTMLSerializer(omit_optional_tags=False) + >>> serializer.render(walker(token_stream)) + 'Hi!' + + """ if encoding: return b"".join(list(self.serialize(treewalker, encoding))) else: diff --git a/pipenv/patched/notpip/_vendor/html5lib/treeadapters/__init__.py b/pipenv/patched/notpip/_vendor/html5lib/treeadapters/__init__.py index 4f978466..e5d7e88f 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/treeadapters/__init__.py +++ b/pipenv/patched/notpip/_vendor/html5lib/treeadapters/__init__.py @@ -1,3 +1,21 @@ +"""Tree adapters let you convert from one tree structure to another + +Example: + +.. code-block:: python + + from notpip._vendor import html5lib + from notpip._vendor.html5lib.treeadapters import genshi + + doc = 'Hi!' + 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 diff --git a/pipenv/patched/notpip/_vendor/html5lib/treeadapters/genshi.py b/pipenv/patched/notpip/_vendor/html5lib/treeadapters/genshi.py index 04e316df..61d5fb6a 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/treeadapters/genshi.py +++ b/pipenv/patched/notpip/_vendor/html5lib/treeadapters/genshi.py @@ -5,6 +5,13 @@ 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"] diff --git a/pipenv/patched/notpip/_vendor/html5lib/treeadapters/sax.py b/pipenv/patched/notpip/_vendor/html5lib/treeadapters/sax.py index ad47df95..f4ccea5a 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/treeadapters/sax.py +++ b/pipenv/patched/notpip/_vendor/html5lib/treeadapters/sax.py @@ -11,7 +11,13 @@ for prefix, localName, namespace in adjustForeignAttributes.values(): def to_sax(walker, handler): - """Call SAX-like content handler based on treewalker walker""" + """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) diff --git a/pipenv/patched/notpip/_vendor/html5lib/treebuilders/__init__.py b/pipenv/patched/notpip/_vendor/html5lib/treebuilders/__init__.py index e2328847..d44447ea 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/treebuilders/__init__.py +++ b/pipenv/patched/notpip/_vendor/html5lib/treebuilders/__init__.py @@ -1,29 +1,32 @@ -"""A collection of modules for building different kinds of tree from -HTML documents. +"""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. +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 +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 -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 @@ -34,23 +37,32 @@ treeBuilderCache = {} def getTreeBuilder(treeType, implementation=None, **kwargs): - """Get a TreeBuilder class for various types of tree with built-in support + """Get a TreeBuilder class for various types of trees with built-in support - treeType - the name of the tree type required (case-insensitive). Supported - values are: + :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. + * "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. - 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 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: diff --git a/pipenv/patched/notpip/_vendor/html5lib/treebuilders/base.py b/pipenv/patched/notpip/_vendor/html5lib/treebuilders/base.py index f0539cd4..2e2f7da6 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/treebuilders/base.py +++ b/pipenv/patched/notpip/_vendor/html5lib/treebuilders/base.py @@ -1,5 +1,5 @@ from __future__ import absolute_import, division, unicode_literals -from pip9._vendor.six import text_type +from notpip._vendor.six import text_type from ..constants import scopingElements, tableInsertModeElements, namespaces @@ -21,22 +21,25 @@ listElementsMap = { class Node(object): + """Represents an item in the tree""" def __init__(self, name): - """Node representing an item in the tree. - name - The tag name associated with the node - parent - The parent of the current node (or None for the document node) - value - The value of the current node (applies to text nodes and - comments - attributes - a dict holding name, value pairs for attributes of the node - childNodes - a list of child nodes of the current node. This must - include all elements but not necessarily other node types - _flags - A list of miscellaneous flags that can be set on the node + """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): @@ -53,23 +56,41 @@ class Node(object): 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""" + 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 @@ -77,6 +98,9 @@ class Node(object): """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: @@ -121,10 +145,12 @@ class ActiveFormattingElements(list): 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 + + * 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 @@ -144,6 +170,11 @@ class TreeBuilder(object): 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: @@ -367,11 +398,11 @@ class TreeBuilder(object): self.generateImpliedEndTags(exclude) def getDocument(self): - "Return the final tree" + """Return the final tree""" return self.document def getFragment(self): - "Return the final fragment" + """Return the final fragment""" # assert self.innerHTML fragment = self.fragmentClass() self.openElements[0].reparentChildren(fragment) @@ -379,5 +410,8 @@ class TreeBuilder(object): def testSerializer(self, node): """Serialize the subtree of node in the format required by unit tests - node - the node from which to start serializing""" + + :arg node: the node from which to start serializing + + """ raise NotImplementedError diff --git a/pipenv/patched/notpip/_vendor/html5lib/treebuilders/etree.py b/pipenv/patched/notpip/_vendor/html5lib/treebuilders/etree.py index ba5237b5..84859e10 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/treebuilders/etree.py +++ b/pipenv/patched/notpip/_vendor/html5lib/treebuilders/etree.py @@ -1,7 +1,7 @@ from __future__ import absolute_import, division, unicode_literals # pylint:disable=protected-access -from pip9._vendor.six import text_type +from notpip._vendor.six import text_type import re diff --git a/pipenv/patched/notpip/_vendor/html5lib/treebuilders/etree_lxml.py b/pipenv/patched/notpip/_vendor/html5lib/treebuilders/etree_lxml.py index 908820c0..ca12a99c 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/treebuilders/etree_lxml.py +++ b/pipenv/patched/notpip/_vendor/html5lib/treebuilders/etree_lxml.py @@ -309,7 +309,6 @@ class TreeBuilder(base.TreeBuilder): super(TreeBuilder, self).insertComment(data, parent) def insertRoot(self, token): - """Create the document root""" # 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 diff --git a/pipenv/patched/notpip/_vendor/html5lib/treewalkers/__init__.py b/pipenv/patched/notpip/_vendor/html5lib/treewalkers/__init__.py index 9e19a559..9bec2076 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/treewalkers/__init__.py +++ b/pipenv/patched/notpip/_vendor/html5lib/treewalkers/__init__.py @@ -13,7 +13,7 @@ from __future__ import absolute_import, division, unicode_literals from .. import constants from .._utils import default_etree -__all__ = ["getTreeWalker", "pprint", "dom", "etree", "genshi", "etree_lxml"] +__all__ = ["getTreeWalker", "pprint"] treeWalkerCache = {} @@ -21,20 +21,25 @@ treeWalkerCache = {} def getTreeWalker(treeType, implementation=None, **kwargs): """Get a TreeWalker class for various types of tree with built-in support - Args: - treeType (str): the name of the tree type required (case-insensitive). - Supported values are: + :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 + * "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 - Implementation: A module implementing the tree type e.g. - xml.etree.ElementTree or cElementTree (Currently applies to the - "etree" tree type only). """ treeType = treeType.lower() @@ -73,7 +78,13 @@ def concatenateCharacterTokens(tokens): def pprint(walker): - """Pretty printer for tree walkers""" + """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): diff --git a/pipenv/patched/notpip/_vendor/html5lib/treewalkers/base.py b/pipenv/patched/notpip/_vendor/html5lib/treewalkers/base.py index 36e1ba24..80c474c4 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/treewalkers/base.py +++ b/pipenv/patched/notpip/_vendor/html5lib/treewalkers/base.py @@ -18,16 +18,48 @@ 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} @@ -35,17 +67,61 @@ class TreeWalker(object): 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)] @@ -60,18 +136,44 @@ class TreeWalker(object): 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) diff --git a/pipenv/patched/notpip/_vendor/html5lib/treewalkers/etree.py b/pipenv/patched/notpip/_vendor/html5lib/treewalkers/etree.py index 197c8e81..dc891ee8 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/treewalkers/etree.py +++ b/pipenv/patched/notpip/_vendor/html5lib/treewalkers/etree.py @@ -1,16 +1,9 @@ from __future__ import absolute_import, division, unicode_literals -try: - from collections import OrderedDict -except ImportError: - try: - from ordereddict import OrderedDict - except ImportError: - OrderedDict = dict - +from collections import OrderedDict import re -from pip9._vendor.six import string_types +from notpip._vendor.six import string_types from . import base from .._utils import moduleFactoryFactory diff --git a/pipenv/patched/notpip/_vendor/html5lib/treewalkers/etree_lxml.py b/pipenv/patched/notpip/_vendor/html5lib/treewalkers/etree_lxml.py index 4de0dd0d..136c075a 100644 --- a/pipenv/patched/notpip/_vendor/html5lib/treewalkers/etree_lxml.py +++ b/pipenv/patched/notpip/_vendor/html5lib/treewalkers/etree_lxml.py @@ -1,5 +1,5 @@ from __future__ import absolute_import, division, unicode_literals -from pip9._vendor.six import text_type +from notpip._vendor.six import text_type from lxml import etree from ..treebuilders.etree import tag_regexp diff --git a/pipenv/patched/notpip/_vendor/ipaddress.py b/pipenv/patched/notpip/_vendor/ipaddress.py index 9cf71a74..8cfdd58a 100644 --- a/pipenv/patched/notpip/_vendor/ipaddress.py +++ b/pipenv/patched/notpip/_vendor/ipaddress.py @@ -14,7 +14,7 @@ from __future__ import unicode_literals import itertools import struct -__version__ = '1.0.17' +__version__ = '1.0.19' # Compatibility functions _compat_int_types = (int,) @@ -58,6 +58,8 @@ def _compat_to_bytes(intval, length, endianess): 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): @@ -547,8 +549,7 @@ class _IPAddressBase(_TotalOrderingMixin): 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?' - ) + ' a unicode object?') raise AddressValueError(msg % (address, address_len, expected_len, self._version)) @@ -1083,8 +1084,7 @@ class _BaseNetwork(_IPAddressBase): (self.prefixlen, prefixlen_diff)) return self.__class__(( int(self.network_address) & (int(self.netmask) << prefixlen_diff), - new_prefixlen - )) + new_prefixlen)) @property def is_multicast(self): @@ -1098,33 +1098,25 @@ class _BaseNetwork(_IPAddressBase): 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): - # always false if one is v4 and the other is v6. - if self._version != other._version: - return False - # dealing with another network. - if (hasattr(other, 'network_address') and - hasattr(other, 'broadcast_address')): - return (other.network_address <= self.network_address and - other.broadcast_address >= self.broadcast_address) - # dealing with another address - else: - raise TypeError('Unable to test subnet containment with element ' - 'of type %s' % type(other)) + """Return True if this network is a subnet of other.""" + return self._is_subnet_of(self, other) def supernet_of(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 (hasattr(other, 'network_address') and - hasattr(other, 'broadcast_address')): - return (other.network_address >= self.network_address and - other.broadcast_address <= self.broadcast_address) - # dealing with another address - else: - raise TypeError('Unable to test subnet containment with element ' - 'of type %s' % type(other)) + """Return True if this network is a supernet of other.""" + return self._is_subnet_of(other, self) @property def is_reserved(self): @@ -1535,7 +1527,8 @@ class IPv4Interface(IPv4Address): if address_less is NotImplemented: return NotImplemented try: - return self.network < other.network + 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. @@ -2227,7 +2220,8 @@ class IPv6Interface(IPv6Address): if address_less is NotImplemented: return NotImplemented try: - return self.network < other.network + 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. diff --git a/pipenv/patched/notpip/_vendor/msgpack/__init__.py b/pipenv/patched/notpip/_vendor/msgpack/__init__.py new file mode 100644 index 00000000..d33621ff --- /dev/null +++ b/pipenv/patched/notpip/_vendor/msgpack/__init__.py @@ -0,0 +1,66 @@ +# coding: utf-8 +from notpip._vendor.msgpack._version import version +from notpip._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 notpip._vendor.msgpack.fallback import Packer, unpackb, Unpacker +else: + try: + from notpip._vendor.msgpack._packer import Packer + from notpip._vendor.msgpack._unpacker import unpackb, Unpacker + except ImportError: + from notpip._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/pipenv/patched/notpip/_vendor/msgpack/_version.py b/pipenv/patched/notpip/_vendor/msgpack/_version.py new file mode 100644 index 00000000..d28f0deb --- /dev/null +++ b/pipenv/patched/notpip/_vendor/msgpack/_version.py @@ -0,0 +1 @@ +version = (0, 5, 6) diff --git a/pipenv/patched/notpip/_vendor/msgpack/exceptions.py b/pipenv/patched/notpip/_vendor/msgpack/exceptions.py new file mode 100644 index 00000000..97668814 --- /dev/null +++ b/pipenv/patched/notpip/_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/pipenv/patched/notpip/_vendor/msgpack/fallback.py b/pipenv/patched/notpip/_vendor/msgpack/fallback.py new file mode 100644 index 00000000..c5e4a80e --- /dev/null +++ b/pipenv/patched/notpip/_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 notpip._vendor.msgpack.exceptions import ( + BufferFull, + OutOfData, + UnpackValueError, + PackValueError, + PackOverflowError, + ExtraData) + +from notpip._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/pipenv/patched/notpip/_vendor/ordereddict.py b/pipenv/patched/notpip/_vendor/ordereddict.py deleted file mode 100644 index 7242b506..00000000 --- a/pipenv/patched/notpip/_vendor/ordereddict.py +++ /dev/null @@ -1,127 +0,0 @@ -# Copyright (c) 2009 Raymond Hettinger -# -# 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 UserDict import DictMixin - -class OrderedDict(dict, DictMixin): - - def __init__(self, *args, **kwds): - if len(args) > 1: - raise TypeError('expected at most 1 arguments, got %d' % len(args)) - try: - self.__end - except AttributeError: - self.clear() - self.update(*args, **kwds) - - def clear(self): - self.__end = end = [] - end += [None, end, end] # sentinel node for doubly linked list - self.__map = {} # key --> [key, prev, next] - dict.clear(self) - - def __setitem__(self, key, value): - if key not in self: - end = self.__end - curr = end[1] - curr[2] = end[1] = self.__map[key] = [key, curr, end] - dict.__setitem__(self, key, value) - - def __delitem__(self, key): - dict.__delitem__(self, key) - key, prev, next = self.__map.pop(key) - prev[2] = next - next[1] = prev - - def __iter__(self): - end = self.__end - curr = end[2] - while curr is not end: - yield curr[0] - curr = curr[2] - - def __reversed__(self): - end = self.__end - curr = end[1] - while curr is not end: - yield curr[0] - curr = curr[1] - - def popitem(self, last=True): - if not self: - raise KeyError('dictionary is empty') - if last: - key = reversed(self).next() - else: - key = iter(self).next() - value = self.pop(key) - return key, value - - def __reduce__(self): - items = [[k, self[k]] for k in self] - tmp = self.__map, self.__end - del self.__map, self.__end - inst_dict = vars(self).copy() - self.__map, self.__end = tmp - if inst_dict: - return (self.__class__, (items,), inst_dict) - return self.__class__, (items,) - - def keys(self): - return list(self) - - setdefault = DictMixin.setdefault - update = DictMixin.update - pop = DictMixin.pop - values = DictMixin.values - items = DictMixin.items - iterkeys = DictMixin.iterkeys - itervalues = DictMixin.itervalues - iteritems = DictMixin.iteritems - - def __repr__(self): - if not self: - return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, self.items()) - - def copy(self): - return self.__class__(self) - - @classmethod - def fromkeys(cls, iterable, value=None): - d = cls() - for key in iterable: - d[key] = value - return d - - def __eq__(self, other): - if isinstance(other, OrderedDict): - if len(self) != len(other): - return False - for p, q in zip(self.items(), other.items()): - if p != q: - return False - return True - return dict.__eq__(self, other) - - def __ne__(self, other): - return not self == other diff --git a/pipenv/patched/notpip/_vendor/packaging/__about__.py b/pipenv/patched/notpip/_vendor/packaging/__about__.py index 95d330ef..4255c5b5 100644 --- a/pipenv/patched/notpip/_vendor/packaging/__about__.py +++ b/pipenv/patched/notpip/_vendor/packaging/__about__.py @@ -12,7 +12,7 @@ __title__ = "packaging" __summary__ = "Core utilities for Python packages" __uri__ = "https://github.com/pypa/packaging" -__version__ = "16.8" +__version__ = "17.1" __author__ = "Donald Stufft and individual contributors" __email__ = "donald@stufft.io" diff --git a/pipenv/patched/notpip/_vendor/packaging/_structures.py b/pipenv/patched/notpip/_vendor/packaging/_structures.py index ccc27861..e9fc4a04 100644 --- a/pipenv/patched/notpip/_vendor/packaging/_structures.py +++ b/pipenv/patched/notpip/_vendor/packaging/_structures.py @@ -33,6 +33,7 @@ class Infinity(object): def __neg__(self): return NegativeInfinity + Infinity = Infinity() @@ -65,4 +66,5 @@ class NegativeInfinity(object): def __neg__(self): return Infinity + NegativeInfinity = NegativeInfinity() diff --git a/pipenv/patched/notpip/_vendor/packaging/markers.py b/pipenv/patched/notpip/_vendor/packaging/markers.py index d2381c06..a6c7f3e5 100644 --- a/pipenv/patched/notpip/_vendor/packaging/markers.py +++ b/pipenv/patched/notpip/_vendor/packaging/markers.py @@ -8,11 +8,9 @@ import os import platform import sys -from pip9._vendor.pyparsing import ( - ParseException, ParseResults, stringStart, stringEnd, -) -from pip9._vendor.pyparsing import ZeroOrMore, Group, Forward, QuotedString -from pip9._vendor.pyparsing import Literal as L # noqa +from notpip._vendor.pyparsing import ParseException, ParseResults, stringStart, stringEnd +from notpip._vendor.pyparsing import ZeroOrMore, Group, Forward, QuotedString +from notpip._vendor.pyparsing import Literal as L # noqa from ._compat import string_types from .specifiers import Specifier, InvalidSpecifier diff --git a/pipenv/patched/notpip/_vendor/packaging/requirements.py b/pipenv/patched/notpip/_vendor/packaging/requirements.py index 46381d4e..b65e9498 100644 --- a/pipenv/patched/notpip/_vendor/packaging/requirements.py +++ b/pipenv/patched/notpip/_vendor/packaging/requirements.py @@ -6,12 +6,10 @@ from __future__ import absolute_import, division, print_function import string import re -from pip9._vendor.pyparsing import ( - stringStart, stringEnd, originalTextFor, ParseException -) -from pip9._vendor.pyparsing import ZeroOrMore, Word, Optional, Regex, Combine -from pip9._vendor.pyparsing import Literal as L # noqa -from pip9._vendor.six.moves.urllib import parse as urlparse +from notpip._vendor.pyparsing import stringStart, stringEnd, originalTextFor, ParseException +from notpip._vendor.pyparsing import ZeroOrMore, Word, Optional, Regex, Combine +from notpip._vendor.pyparsing import Literal as L # noqa +from notpip._vendor.six.moves.urllib import parse as urlparse from .markers import MARKER_EXPR, Marker from .specifiers import LegacySpecifier, Specifier, SpecifierSet @@ -62,8 +60,8 @@ MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker") MARKER_EXPR.setParseAction( lambda s, l, t: Marker(s[t._original_start:t._original_end]) ) -MARKER_SEPERATOR = SEMICOLON -MARKER = MARKER_SEPERATOR + MARKER_EXPR +MARKER_SEPARATOR = SEMICOLON +MARKER = MARKER_SEPARATOR + MARKER_EXPR VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER) URL_AND_MARKER = URL + Optional(MARKER) @@ -72,6 +70,9 @@ 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): diff --git a/pipenv/patched/notpip/_vendor/packaging/specifiers.py b/pipenv/patched/notpip/_vendor/packaging/specifiers.py index 7f5a76cf..9b6353f0 100644 --- a/pipenv/patched/notpip/_vendor/packaging/specifiers.py +++ b/pipenv/patched/notpip/_vendor/packaging/specifiers.py @@ -198,7 +198,7 @@ class _IndividualSpecifier(BaseSpecifier): (prereleases or self.prereleases)): found_prereleases.append(version) # Either this is not a prerelease, or we should have been - # accepting prereleases from the begining. + # accepting prereleases from the beginning. else: yielded = True yield version diff --git a/pipenv/patched/notpip/_vendor/packaging/utils.py b/pipenv/patched/notpip/_vendor/packaging/utils.py index 942387ce..4b94a82f 100644 --- a/pipenv/patched/notpip/_vendor/packaging/utils.py +++ b/pipenv/patched/notpip/_vendor/packaging/utils.py @@ -5,6 +5,8 @@ from __future__ import absolute_import, division, print_function import re +from .version import InvalidVersion, Version + _canonicalize_regex = re.compile(r"[-_.]+") @@ -12,3 +14,50 @@ _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/pipenv/patched/notpip/_vendor/packaging/version.py b/pipenv/patched/notpip/_vendor/packaging/version.py index 83b5ee8c..6ed5cbbd 100644 --- a/pipenv/patched/notpip/_vendor/packaging/version.py +++ b/pipenv/patched/notpip/_vendor/packaging/version.py @@ -89,6 +89,26 @@ class LegacyVersion(_BaseVersion): 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 @@ -101,6 +121,10 @@ class LegacyVersion(_BaseVersion): 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, @@ -154,6 +178,7 @@ def _legacy_cmpkey(version): 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""" @@ -237,32 +262,57 @@ class Version(_BaseVersion): parts = [] # Epoch - if self._version.epoch != 0: - parts.append("{0}!".format(self._version.epoch)) + if self.epoch != 0: + parts.append("{0}!".format(self.epoch)) # Release segment - parts.append(".".join(str(x) for x in self._version.release)) + parts.append(".".join(str(x) for x in self.release)) # Pre-release - if self._version.pre is not None: - parts.append("".join(str(x) for x in self._version.pre)) + if self.pre is not None: + parts.append("".join(str(x) for x in self.pre)) # Post-release - if self._version.post is not None: - parts.append(".post{0}".format(self._version.post[1])) + if self.post is not None: + parts.append(".post{0}".format(self.post)) # Development release - if self._version.dev is not None: - parts.append(".dev{0}".format(self._version.dev[1])) + if self.dev is not None: + parts.append(".dev{0}".format(self.dev)) # Local version segment - if self._version.local is not None: - parts.append( - "+{0}".format(".".join(str(x) for x in self._version.local)) - ) + 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] @@ -272,27 +322,25 @@ class Version(_BaseVersion): parts = [] # Epoch - if self._version.epoch != 0: - parts.append("{0}!".format(self._version.epoch)) + if self.epoch != 0: + parts.append("{0}!".format(self.epoch)) # Release segment - parts.append(".".join(str(x) for x in self._version.release)) + parts.append(".".join(str(x) for x in self.release)) return "".join(parts) - @property - def local(self): - version_string = str(self) - if "+" in version_string: - return version_string.split("+", 1)[1] - @property def is_prerelease(self): - return bool(self._version.dev or self._version.pre) + return self.dev is not None or self.pre is not None @property def is_postrelease(self): - return bool(self._version.post) + return self.post is not None + + @property + def is_devrelease(self): + return self.dev is not None def _parse_letter_version(letter, number): @@ -326,7 +374,7 @@ def _parse_letter_version(letter, number): return letter, int(number) -_local_version_seperators = re.compile(r"[\._-]") +_local_version_separators = re.compile(r"[\._-]") def _parse_local_version(local): @@ -336,7 +384,7 @@ def _parse_local_version(local): if local is not None: return tuple( part.lower() if not part.isdigit() else int(part) - for part in _local_version_seperators.split(local) + for part in _local_version_separators.split(local) ) diff --git a/pipenv/patched/notpip/_vendor/pkg_resources/__init__.py b/pipenv/patched/notpip/_vendor/pkg_resources/__init__.py index 7b7da008..43fd4f8e 100644 --- a/pipenv/patched/notpip/_vendor/pkg_resources/__init__.py +++ b/pipenv/patched/notpip/_vendor/pkg_resources/__init__.py @@ -34,9 +34,11 @@ 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: @@ -45,8 +47,8 @@ except ImportError: # Python 3.2 compatibility import imp as _imp -from pip9._vendor import six -from pip9._vendor.six.moves import urllib, map, filter +from notpip._vendor import six +from notpip._vendor.six.moves import urllib, map, filter # capture these to bypass sandboxing from os import utime @@ -67,20 +69,42 @@ try: except ImportError: importlib_machinery = None -from pip9._vendor import appdirs -from pip9._vendor import packaging -__import__('pip9._vendor.packaging.version') -__import__('pip9._vendor.packaging.specifiers') -__import__('pip9._vendor.packaging.requirements') -__import__('pip9._vendor.packaging.markers') +from . import py31compat +from notpip._vendor import appdirs +from notpip._vendor import packaging +__import__('notpip._vendor.packaging.version') +__import__('notpip._vendor.packaging.specifiers') +__import__('notpip._vendor.packaging.requirements') +__import__('notpip._vendor.packaging.markers') + if (3, 0) < sys.version_info < (3, 3): raise RuntimeError("Python 3.3 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): @@ -90,118 +114,11 @@ class PEP440Warning(RuntimeWarning): """ -class _SetuptoolsVersionMixin(object): - def __hash__(self): - return super(_SetuptoolsVersionMixin, self).__hash__() - - def __lt__(self, other): - if isinstance(other, tuple): - return tuple(self) < other - else: - return super(_SetuptoolsVersionMixin, self).__lt__(other) - - def __le__(self, other): - if isinstance(other, tuple): - return tuple(self) <= other - else: - return super(_SetuptoolsVersionMixin, self).__le__(other) - - def __eq__(self, other): - if isinstance(other, tuple): - return tuple(self) == other - else: - return super(_SetuptoolsVersionMixin, self).__eq__(other) - - def __ge__(self, other): - if isinstance(other, tuple): - return tuple(self) >= other - else: - return super(_SetuptoolsVersionMixin, self).__ge__(other) - - def __gt__(self, other): - if isinstance(other, tuple): - return tuple(self) > other - else: - return super(_SetuptoolsVersionMixin, self).__gt__(other) - - def __ne__(self, other): - if isinstance(other, tuple): - return tuple(self) != other - else: - return super(_SetuptoolsVersionMixin, self).__ne__(other) - - def __getitem__(self, key): - return tuple(self)[key] - - def __iter__(self): - component_re = re.compile(r'(\d+ | [a-z]+ | \.| -)', re.VERBOSE) - replace = { - 'pre': 'c', - 'preview': 'c', - '-': 'final-', - 'rc': 'c', - 'dev': '@', - }.get - - def _parse_version_parts(s): - for part in component_re.split(s): - part = replace(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 old_parse_version(s): - parts = [] - for part in _parse_version_parts(s.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) - return tuple(parts) - - # Warn for use of this function - warnings.warn( - "You have iterated over the result of " - "pkg_resources.parse_version. This is a legacy behavior which is " - "inconsistent with the new version class introduced in setuptools " - "8.0. In most cases, conversion to a tuple is unnecessary. For " - "comparison of versions, sort the Version instances directly. If " - "you have another use case requiring the tuple, please file a " - "bug with the setuptools project describing that need.", - RuntimeWarning, - stacklevel=1, - ) - - for part in old_parse_version(str(self)): - yield part - - -class SetuptoolsVersion(_SetuptoolsVersionMixin, packaging.version.Version): - pass - - -class SetuptoolsLegacyVersion(_SetuptoolsVersionMixin, - packaging.version.LegacyVersion): - pass - - def parse_version(v): try: - return SetuptoolsVersion(v) + return packaging.version.Version(v) except packaging.version.InvalidVersion: - return SetuptoolsLegacyVersion(v) + return packaging.version.LegacyVersion(v) _state_vars = {} @@ -471,8 +388,10 @@ def get_build_platform(): try: version = _macosx_vers() machine = os.uname()[4].replace(" ", "_") - return "macosx-%d.%d-%s" % (int(version[0]), int(version[1]), - _macosx_arch(machine)) + 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 @@ -797,7 +716,8 @@ class WorkingSet(object): already-installed distribution; it should return a ``Distribution`` or ``None``. - Unless `replace_conflicting=True`, raises a VersionConflict exception if + 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 @@ -849,7 +769,10 @@ class WorkingSet(object): # distribution env = Environment([]) ws = WorkingSet([]) - dist = best[req.key] = env.best_match(req, ws, installer) + 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) @@ -873,8 +796,8 @@ class WorkingSet(object): # return list of distros to activate return to_activate - def find_plugins(self, plugin_env, full_env=None, installer=None, - fallback=True): + def find_plugins( + self, plugin_env, full_env=None, installer=None, fallback=True): """Find all activatable distributions in `plugin_env` Example usage:: @@ -1028,7 +951,8 @@ class _ReqExtras(dict): class Environment(object): """Searchable snapshot of distributions on a search path""" - def __init__(self, search_path=None, platform=get_supported_platform(), + def __init__( + self, search_path=None, platform=get_supported_platform(), python=PY_MAJOR): """Snapshot distributions available on a search path @@ -1058,9 +982,12 @@ class Environment(object): requirements specified when this environment was created, or False is returned. """ - return (self.python is None or dist.py_version is None - or dist.py_version == self.python) \ - and compatible_platforms(dist.platform, self.platform) + 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""" @@ -1101,7 +1028,8 @@ class Environment(object): dists.append(dist) dists.sort(key=operator.attrgetter('hashcmp'), reverse=True) - def best_match(self, req, working_set, installer=None): + 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 @@ -1114,7 +1042,12 @@ class Environment(object): calling the environment's ``obtain(req, installer)`` method will be returned. """ - dist = working_set.find(req) + 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]: @@ -1231,8 +1164,8 @@ class ResourceManager: 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: + The following error occurred while trying to extract file(s) + to the Python egg cache: {old_exc} @@ -1240,9 +1173,9 @@ class ResourceManager: {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. + 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 @@ -1267,7 +1200,7 @@ class ResourceManager: target_path = os.path.join(extract_path, archive_name + '-tmp', *names) try: _bypass_ensure_directory(target_path) - except: + except Exception: self.extraction_error() self._warn_unsafe_extraction_path(extract_path) @@ -1292,11 +1225,13 @@ class ResourceManager: 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 " + 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) + "PYTHON_EGG_CACHE environment variable)." % path + ) warnings.warn(msg, UserWarning) def postprocess(self, tempname, filename): @@ -1489,7 +1424,10 @@ class NullProvider: def run_script(self, script_name, namespace): script = 'scripts/' + script_name if not self.has_metadata(script): - raise ResolutionError("No script named %r" % script_name) + 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) @@ -1550,7 +1488,7 @@ class EggProvider(NullProvider): path = self.module_path old = None while path != old: - if _is_unpacked_egg(path): + 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 @@ -1580,8 +1518,11 @@ class DefaultProvider(EggProvider): @classmethod def _register(cls): - loader_cls = getattr(importlib_machinery, 'SourceFileLoader', - type(None)) + loader_cls = getattr( + importlib_machinery, + 'SourceFileLoader', + type(None), + ) register_loader_type(loader_cls, cls) @@ -1591,11 +1532,16 @@ DefaultProvider._register() class EmptyProvider(NullProvider): """Provider that returns nothing for all requests""" - _isdir = _has = lambda self, path: False - _get = lambda self, path: '' - _listdir = lambda self, path: [] module_path = None + _isdir = _has = lambda self, path: False + + def _get(self, path): + return '' + + def _listdir(self, path): + return [] + def __init__(self): pass @@ -1617,7 +1563,7 @@ class ZipManifests(dict): Use a platform-specific path separator (os.sep) for the path keys for compatibility with pypy on Windows. """ - with ContextualZipFile(path) as zfile: + with zipfile.ZipFile(path) as zfile: items = ( ( name.replace('/', os.sep), @@ -1650,26 +1596,6 @@ class MemoizedZipManifests(ZipManifests): return self[path].manifest -class ContextualZipFile(zipfile.ZipFile): - """ - Supplement ZipFile class to support context manager for Python 2.6 - """ - - def __enter__(self): - return self - - def __exit__(self, type, value, traceback): - self.close() - - def __new__(cls, *args, **kwargs): - """ - Construct a ZipFile or ContextualZipFile as appropriate - """ - if hasattr(zipfile.ZipFile, '__exit__'): - return zipfile.ZipFile(*args, **kwargs) - return super(ContextualZipFile, cls).__new__(cls) - - class ZipProvider(EggProvider): """Resource support for zips and eggs""" @@ -1683,6 +1609,9 @@ class ZipProvider(EggProvider): 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( @@ -1749,7 +1678,10 @@ class ZipProvider(EggProvider): if self._is_current(real_path, zip_path): return real_path - outf, tmpnam = _mkstemp(".$extract", dir=os.path.dirname(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)) @@ -1867,7 +1799,7 @@ class FileMetadata(EmptyProvider): return metadata def _warn_on_replacement(self, metadata): - # Python 2.6 and 3.2 compat for: replacement_char = '�' + # 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" @@ -1953,9 +1885,10 @@ def find_eggs_in_zip(importer, path_item, only=False): # don't yield nested distros return for subitem in metadata.resource_listdir('/'): - if _is_unpacked_egg(subitem): + if _is_egg_path(subitem): subpath = os.path.join(path_item, subitem) - for dist in find_eggs_in_zip(zipimport.zipimporter(subpath), subpath): + 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) @@ -1964,7 +1897,6 @@ def find_eggs_in_zip(importer, path_item, only=False): yield Distribution.from_location(path_item, subitem, submeta) - register_finder(zipimport.zipimporter, find_eggs_in_zip) @@ -2005,46 +1937,127 @@ def find_on_path(importer, path_item, only=False): """Yield distributions accessible on a sys.path directory""" path_item = _normalize_cached(path_item) - if os.path.isdir(path_item) and os.access(path_item, os.R_OK): - if _is_unpacked_egg(path_item): - yield Distribution.from_filename( - path_item, metadata=PathMetadata( - path_item, os.path.join(path_item, 'EGG-INFO') - ) + if _is_unpacked_egg(path_item): + yield Distribution.from_filename( + path_item, metadata=PathMetadata( + path_item, os.path.join(path_item, 'EGG-INFO') ) - else: - # scan for .egg and .egg-info in directory - path_item_entries = _by_version_descending(os.listdir(path_item)) - for entry in path_item_entries: - lower = entry.lower() - if lower.endswith('.egg-info') or lower.endswith('.dist-info'): - fullpath = os.path.join(path_item, entry) - if os.path.isdir(fullpath): - # egg-info directory, allow getting metadata - if len(os.listdir(fullpath)) == 0: - # Empty egg directory, skip. - continue - metadata = PathMetadata(path_item, fullpath) - else: - metadata = FileMetadata(fullpath) - yield Distribution.from_location( - path_item, entry, metadata, precedence=DEVELOP_DIST - ) - elif not only and _is_unpacked_egg(entry): - dists = find_distributions(os.path.join(path_item, entry)) - for dist in dists: - yield dist - elif not only and lower.endswith('.egg-link'): - with open(os.path.join(path_item, entry)) as entry_file: - entry_lines = entry_file.readlines() - for line in entry_lines: - if not line.strip(): - continue - path = os.path.join(path_item, line.rstrip()) - dists = find_distributions(path) - for item in dists: - yield item - break + ) + 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) @@ -2218,12 +2231,20 @@ def _normalize_cached(filename, _cache={}): 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 ( - path.lower().endswith('.egg') + _is_egg_path(path) and + os.path.isfile(os.path.join(path, 'EGG-INFO', 'PKG-INFO')) ) @@ -2273,7 +2294,7 @@ class EntryPoint(object): self.name = name self.module_name = module_name self.attrs = tuple(attrs) - self.extras = Requirement.parse(("x[%s]" % ','.join(extras))).extras + self.extras = tuple(extras) self.dist = dist def __str__(self): @@ -2410,7 +2431,8 @@ 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. """ - is_version_line = lambda line: line.lower().startswith('version:') + 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(':') @@ -2421,7 +2443,8 @@ class Distribution(object): """Wrap an actual or potential sys.path entry w/metadata""" PKG_INFO = 'PKG-INFO' - def __init__(self, location=None, metadata=None, project_name=None, + 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') @@ -2546,23 +2569,44 @@ class Distribution(object): @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: - dm = self.__dep_map = {None: []} - for name in 'requires.txt', 'depends.txt': - for extra, reqs in split_sections(self._get_metadata(name)): - if extra: - if ':' in extra: - extra, marker = extra.split(':', 1) - if invalid_marker(marker): - # XXX warn - reqs = [] - elif not evaluate_marker(marker): - reqs = [] - extra = safe_extra(extra) or None - dm.setdefault(extra, []).extend(parse_requirements(reqs)) - return dm + 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""" @@ -2697,7 +2741,8 @@ class Distribution(object): if replace: break else: - # don't modify path (even removing duplicates) if found and not replace + # 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 @@ -2794,7 +2839,10 @@ class EggInfoDistribution(Distribution): class DistInfoDistribution(Distribution): - """Wrap an actual or potential sys.path entry w/metadata, .dist-info style""" + """ + Wrap an actual or potential sys.path entry + w/metadata, .dist-info style. + """ PKG_INFO = 'METADATA' EQEQ = re.compile(r"([\(,])\s*(\d.*?)\s*([,\)])") @@ -2844,7 +2892,7 @@ _distributionImpl = { '.egg': Distribution, '.egg-info': EggInfoDistribution, '.dist-info': DistInfoDistribution, - } +} def issue_warning(*args, **kw): @@ -2880,7 +2928,10 @@ def parse_requirements(strs): # If there is a line continuation, drop it, and append the next line. if line.endswith('\\'): line = line[:-2].strip() - line += next(lines) + try: + line += next(lines) + except StopIteration: + return yield Requirement(line) @@ -2929,7 +2980,8 @@ class Requirement(packaging.requirements.Requirement): def __hash__(self): return self.__hash - def __repr__(self): return "Requirement.parse(%r)" % str(self) + def __repr__(self): + return "Requirement.parse(%r)" % str(self) @staticmethod def parse(s): @@ -2937,20 +2989,20 @@ class Requirement(packaging.requirements.Requirement): return req -def _get_mro(cls): - """Get an mro for a type or classic class""" - if not isinstance(cls, type): - - class cls(cls, object): - pass - - return cls.__mro__[1:] - return cls.__mro__ +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`""" - for t in _get_mro(getattr(ob, '__class__', type(ob))): + types = _always_object(inspect.getmro(getattr(ob, '__class__', type(ob)))) + for t in types: if t in registry: return registry[t] @@ -2958,8 +3010,7 @@ def _find_adapter(registry, ob): 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) + py31compat.makedirs(dirname, exist_ok=True) def _bypass_ensure_directory(path): @@ -3064,7 +3115,10 @@ def _initialize_master_working_set(): dist.activate(replace=False) for dist in working_set ) - add_activation_listener(lambda dist: dist.activate(replace=True), existing=False) + add_activation_listener( + lambda dist: dist.activate(replace=True), + existing=False, + ) working_set.entries = [] # match order list(map(working_set.add_entry, sys.path)) diff --git a/pipenv/patched/notpip/_vendor/pkg_resources/py31compat.py b/pipenv/patched/notpip/_vendor/pkg_resources/py31compat.py new file mode 100644 index 00000000..331a51bb --- /dev/null +++ b/pipenv/patched/notpip/_vendor/pkg_resources/py31compat.py @@ -0,0 +1,22 @@ +import os +import errno +import sys + + +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 = ( + sys.version_info < (3, 2, 5) or + (3, 3) <= sys.version_info < (3, 3, 6) or + (3, 4) <= sys.version_info < (3, 4, 1) +) +makedirs = _makedirs_31 if needs_makedirs else os.makedirs diff --git a/pipenv/patched/notpip/_vendor/progress/__init__.py b/pipenv/patched/notpip/_vendor/progress/__init__.py index 5107bc0a..09dfc1eb 100644 --- a/pipenv/patched/notpip/_vendor/progress/__init__.py +++ b/pipenv/patched/notpip/_vendor/progress/__init__.py @@ -21,18 +21,19 @@ from sys import stderr from time import time -__version__ = '1.2' +__version__ = '1.3' class Infinite(object): file = stderr - sma_window = 10 + 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._dt = deque(maxlen=self.sma_window) + self._xput = deque(maxlen=self.sma_window) for key, val in kwargs.items(): setattr(self, key, val) @@ -41,10 +42,6 @@ class Infinite(object): return None return getattr(self, key, None) - @property - def avg(self): - return sum(self._dt) / len(self._dt) if self._dt else 0 - @property def elapsed(self): return int(time() - self.start_ts) @@ -53,6 +50,11 @@ class Infinite(object): 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 @@ -63,20 +65,20 @@ class Infinite(object): pass def next(self, n=1): - if n > 0: - now = time() - dt = (now - self._ts) / n - self._dt.append(dt) - self._ts = now - + 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): - for x in it: - yield x - self.next() - self.finish() + try: + for x in it: + yield x + self.next() + finally: + self.finish() class Progress(Infinite): @@ -117,7 +119,9 @@ class Progress(Infinite): except TypeError: pass - for x in it: - yield x - self.next() - self.finish() + try: + for x in it: + yield x + self.next() + finally: + self.finish() diff --git a/pipenv/patched/notpip/_vendor/progress/bar.py b/pipenv/patched/notpip/_vendor/progress/bar.py index 8ce14610..5ee968f0 100644 --- a/pipenv/patched/notpip/_vendor/progress/bar.py +++ b/pipenv/patched/notpip/_vendor/progress/bar.py @@ -14,6 +14,7 @@ # 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 Progress from .helpers import WritelnMixin @@ -45,39 +46,43 @@ class ChargingBar(Bar): suffix = '%(percent)d%%' bar_prefix = ' ' bar_suffix = ' ' - empty_fill = u'∙' - fill = u'█' + empty_fill = '∙' + fill = '█' class FillingSquaresBar(ChargingBar): - empty_fill = u'▢' - fill = u'▣' + empty_fill = '▢' + fill = '▣' class FillingCirclesBar(ChargingBar): - empty_fill = u'◯' - fill = u'◉' + empty_fill = '◯' + fill = '◉' class IncrementalBar(Bar): - phases = (u' ', u'▏', u'▎', u'▍', u'▌', u'▋', u'▊', u'▉', u'█') + phases = (' ', '▏', '▎', '▍', '▌', '▋', '▊', '▉', '█') def update(self): nphases = len(self.phases) - expanded_length = int(nphases * self.width * self.progress) - filled_length = int(self.width * self.progress) - empty_length = self.width - filled_length - phase = expanded_length - (filled_length * nphases) + 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] * filled_length + bar = self.phases[-1] * nfull current = self.phases[phase] if phase > 0 else '' - empty = self.empty_fill * max(0, empty_length - len(current)) + 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 = (u' ', u'░', u'▒', u'▓', u'█') + phases = (' ', '░', '▒', '▓', '█') diff --git a/pipenv/patched/notpip/_vendor/progress/counter.py b/pipenv/patched/notpip/_vendor/progress/counter.py index caaddc68..6b45a1ec 100644 --- a/pipenv/patched/notpip/_vendor/progress/counter.py +++ b/pipenv/patched/notpip/_vendor/progress/counter.py @@ -14,6 +14,7 @@ # 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 @@ -34,7 +35,7 @@ class Countdown(WriteMixin, Progress): class Stack(WriteMixin, Progress): - phases = (u' ', u'▁', u'▂', u'▃', u'▄', u'▅', u'▆', u'▇', u'█') + phases = (' ', '▁', '▂', '▃', '▄', '▅', '▆', '▇', '█') hide_cursor = True def update(self): @@ -44,4 +45,4 @@ class Stack(WriteMixin, Progress): class Pie(Stack): - phases = (u'○', u'◔', u'◑', u'◕', u'●') + phases = ('○', '◔', '◑', '◕', '●') diff --git a/pipenv/patched/notpip/_vendor/progress/spinner.py b/pipenv/patched/notpip/_vendor/progress/spinner.py index 969bfbb5..464c7b27 100644 --- a/pipenv/patched/notpip/_vendor/progress/spinner.py +++ b/pipenv/patched/notpip/_vendor/progress/spinner.py @@ -14,6 +14,7 @@ # 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 @@ -29,12 +30,15 @@ class Spinner(WriteMixin, Infinite): class PieSpinner(Spinner): - phases = [u'◷', u'◶', u'◵', u'◴'] + phases = ['◷', '◶', '◵', '◴'] class MoonSpinner(Spinner): - phases = [u'◑', u'◒', u'◐', u'◓'] + phases = ['◑', '◒', '◐', '◓'] class LineSpinner(Spinner): - phases = [u'⎺', u'⎻', u'⎼', u'⎽', u'⎼', u'⎻'] + phases = ['⎺', '⎻', '⎼', '⎽', '⎼', '⎻'] + +class PixelSpinner(Spinner): + phases = ['⣾','⣷', '⣯', '⣟', '⡿', '⢿', '⣻', '⣽'] diff --git a/pipenv/patched/notpip/_vendor/pyparsing.py b/pipenv/patched/notpip/_vendor/pyparsing.py index cb46d411..ac8a3f2f 100644 --- a/pipenv/patched/notpip/_vendor/pyparsing.py +++ b/pipenv/patched/notpip/_vendor/pyparsing.py @@ -36,7 +36,7 @@ C{", !"}), built up using L{Word}, L{Literal}, and L{And} (L{'+'} operator gives L{And} expressions, strings are auto-converted to L{Literal} expressions):: - from pyparsing import Word, alphas + from notpip._vendor.pyparsing import Word, alphas # define grammar of a greeting greet = Word(alphas) + "," + Word(alphas) + "!" @@ -60,8 +60,8 @@ The pyparsing module handles some of the problems that are typically vexing when - embedded comments """ -__version__ = "2.1.10" -__versionTime__ = "07 Oct 2016 01:31 UTC" +__version__ = "2.2.0" +__versionTime__ = "06 Mar 2017 02:06 UTC" __author__ = "Paul McGuire " import string @@ -144,7 +144,7 @@ else: except UnicodeEncodeError: # Else encode it ret = unicode(obj).encode(sys.getdefaultencoding(), 'xmlcharrefreplace') - xmlcharref = Regex('&#\d+;') + xmlcharref = Regex(r'&#\d+;') xmlcharref.setParseAction(lambda t: '\\u' + hex(int(t[0][2:-1]))[2:]) return xmlcharref.transformString(ret) @@ -809,7 +809,7 @@ class ParseResults(object): 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. @@ -1226,7 +1226,7 @@ class ParserElement(object): def setParseAction( self, *fns, **kwargs ): """ - Define action to perform when successfully matching parse element definition. + Define one or more actions to perform when successfully matching parse element definition. Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)}, C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where: - s = the original string being parsed (see note below) @@ -1264,7 +1264,7 @@ class ParserElement(object): def addParseAction( self, *fns, **kwargs ): """ - Add parse action to expression's list of parse actions. See L{I{setParseAction}}. + Add one or more parse actions to expression's list of parse actions. See L{I{setParseAction}}. See examples in L{I{copy}}. """ @@ -1443,10 +1443,14 @@ class ParserElement(object): 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): @@ -1460,15 +1464,22 @@ class ParserElement(object): def set(self, key, value): cache[key] = value - if len(cache) > size: - cache.popitem(False) + 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): @@ -1483,7 +1494,7 @@ class ParserElement(object): def set(self, key, value): cache[key] = value - if len(cache) > size: + while len(key_fifo) > size: cache.pop(key_fifo.popleft(), None) key_fifo.append(key) @@ -1491,9 +1502,13 @@ class ParserElement(object): 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 @@ -1557,7 +1572,7 @@ class ParserElement(object): after importing pyparsing. Example:: - import pyparsing + from notpip._vendor import pyparsing pyparsing.ParserElement.enablePackrat() """ if not ParserElement._packratEnabled: @@ -1743,8 +1758,12 @@ class ParserElement(object): 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'] + [['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 ) ]) @@ -1819,7 +1838,7 @@ class ParserElement(object): warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), SyntaxWarning, stacklevel=2) return None - return And( [ self, And._ErrorStop(), other ] ) + return self + And._ErrorStop() + other def __rsub__(self, other ): """ @@ -2722,7 +2741,7 @@ class Word(Token): class Regex(Token): - """ + r""" Token for matching strings that match a given regular expression. Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module. If the given regex contains named groups (defined using C{(?P...)}), these will be preserved as @@ -2911,7 +2930,7 @@ class QuotedString(Token): # replace escaped characters if self.escChar: - ret = re.sub(self.escCharReplacePattern,"\g<1>",ret) + ret = re.sub(self.escCharReplacePattern, r"\g<1>", ret) # replace escaped quotes if self.escQuote: @@ -5020,7 +5039,9 @@ def infixNotation( baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')') ): constants C{opAssoc.RIGHT} and C{opAssoc.LEFT}. - parseAction is the parse action to be associated with expressions matching this operator expression (the - parse action tuple member may be omitted) + parse action tuple member may be omitted); if the parse action + is passed a tuple or list of functions, this is equivalent to + calling C{setParseAction(*fn)} (L{ParserElement.setParseAction}) - lpar - expression for matching left-parentheses (default=C{Suppress('(')}) - rpar - expression for matching right-parentheses (default=C{Suppress(')')}) @@ -5093,7 +5114,10 @@ def infixNotation( baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')') ): else: raise ValueError("operator must indicate right or left associativity") if pa: - matchExpr.setParseAction( pa ) + if isinstance(pa, (tuple, list)): + matchExpr.setParseAction(*pa) + else: + matchExpr.setParseAction(pa) thisExpr <<= ( matchExpr.setName(termName) | lastExpr ) lastExpr = thisExpr ret <<= lastExpr diff --git a/pipenv/patched/notpip/_vendor/pytoml/__init__.py b/pipenv/patched/notpip/_vendor/pytoml/__init__.py new file mode 100644 index 00000000..8dc73155 --- /dev/null +++ b/pipenv/patched/notpip/_vendor/pytoml/__init__.py @@ -0,0 +1,3 @@ +from .core import TomlError +from .parser import load, loads +from .writer import dump, dumps diff --git a/pipenv/patched/notpip/_vendor/pytoml/core.py b/pipenv/patched/notpip/_vendor/pytoml/core.py new file mode 100644 index 00000000..c182734e --- /dev/null +++ b/pipenv/patched/notpip/_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/pipenv/patched/notpip/_vendor/pytoml/parser.py b/pipenv/patched/notpip/_vendor/pytoml/parser.py new file mode 100644 index 00000000..7fc3d34d --- /dev/null +++ b/pipenv/patched/notpip/_vendor/pytoml/parser.py @@ -0,0 +1,374 @@ +import string, re, sys, datetime +from .core import TomlError + +if sys.version_info[0] == 2: + _chr = unichr +else: + _chr = chr + +def load(fin, translate=lambda t, x, v: v): + return loads(fin.read(), translate=translate, filename=getattr(fin, 'name', repr(fin))) + +def loads(s, filename='', translate=lambda t, x, v: v): + if isinstance(s, bytes): + s = s.decode('utf-8') + + s = s.replace('\r\n', '\n') + + root = {} + tables = {} + scope = root + + src = _Source(s, filename=filename) + ast = _p_toml(src) + + def error(msg): + raise TomlError(msg, pos[0], pos[1], filename) + + def process_value(v): + 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) for item in value] + elif kind == 'table': + value = dict([(k, process_value(value[k])) 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) + 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, {})) + + scope = {} + name = value[-1] + if name not in cur: + if is_table_array: + cur[name] = [(scope, {})] + else: + cur[name] = (scope, {}) + elif isinstance(cur[name], list): + if not is_table_array: + error('table_type_mismatch') + cur[name].append((scope, {})) + 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 = {} + 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('[bnrt"\'\\\\/f]') +_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): + res.append(_chr(int(s.last().group(1), 16))) + 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)*))?') +_datetime_re = re.compile(r'(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(\.\d+)?(?:Z|([+-]\d{2}):(\d{2}))') + +_basicstr_ml_re = re.compile(r'(?:(?:|"|"")[^"\\\000-\011\013-\037])*') +_litstr_re = re.compile(r"[^'\000-\037]*") +_litstr_ml_re = re.compile(r"(?:(?:|'|'')(?:[^'\000-\011\013-\037]))*") +def _p_value(s): + 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(_datetime_re): + m = s.last() + s0 = m.group(0) + 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 + dt = datetime.datetime(y, m, d, H, M, S, int(micro * 1000000), tz) + return 'datetime', s0, dt, 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)) + 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 = {} + if not s.consume('}'): + k = _p_key(s) + _p_ws(s) + s.expect('=') + _p_ws(s) + items[k] = _p_value(s) + _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) + _p_ws(s) + s.expect('}') + return 'table', None, items, pos + + s.fail() + +def _p_stmt(s): + 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) + return 'kv', (key, value), pos + +_stmtsep_re = re.compile(r'(?:[ \t]*(?:#[^\n]*)?\n)+[ \t]*') +def _p_toml(s): + stmts = [] + _p_ews(s) + with s: + stmts.append(_p_stmt(s)) + while True: + s.commit() + s.expect_re(_stmtsep_re) + stmts.append(_p_stmt(s)) + _p_ews(s) + s.expect_eof() + return stmts + +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/pipenv/patched/notpip/_vendor/pytoml/writer.py b/pipenv/patched/notpip/_vendor/pytoml/writer.py new file mode 100644 index 00000000..6eaf5d76 --- /dev/null +++ b/pipenv/patched/notpip/_vendor/pytoml/writer.py @@ -0,0 +1,127 @@ +from __future__ import unicode_literals +import io, datetime, math, sys + +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) + '"' + + +def _escape_id(s): + if any(not c.isalnum() and c not in '-_' for c in s): + return _escape_string(s) + return s + + +def _format_list(v): + return '[{0}]'.format(', '.join(_format_value(obj) for obj in v)) + +# Formula from: +# https://docs.python.org/2/library/datetime.html#datetime.timedelta.total_seconds +# Once support for py26 is dropped, this can be replaced by td.total_seconds() +def _total_seconds(td): + return ((td.microseconds + + (td.seconds + td.days * 24 * 3600) * 10**6) / 10.0**6) + +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): + offs = v.utcoffset() + offs = _total_seconds(offs) // 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 + elif isinstance(v, list): + return _format_list(v) + 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/pipenv/patched/notpip/_vendor/re-vendor.py b/pipenv/patched/notpip/_vendor/re-vendor.py deleted file mode 100644 index 5841a2ff..00000000 --- a/pipenv/patched/notpip/_vendor/re-vendor.py +++ /dev/null @@ -1,34 +0,0 @@ -import os -import sys -import pip9 -import glob -import shutil - -here = os.path.abspath(os.path.dirname(__file__)) - -def usage(): - print("Usage: re-vendor.py [clean|vendor]") - sys.exit(1) - -def clean(): - for fn in os.listdir(here): - dirname = os.path.join(here, fn) - if os.path.isdir(dirname): - shutil.rmtree(dirname) - # six is a single file, not a package - os.unlink(os.path.join(here, 'six.py')) - -def vendor(): - pip9.main(['install', '-t', here, '-r', 'vendor.txt']) - for dirname in glob.glob('*.egg-info'): - shutil.rmtree(dirname) - -if __name__ == '__main__': - if len(sys.argv) != 2: - usage() - if sys.argv[1] == 'clean': - clean() - elif sys.argv[1] == 'vendor': - vendor() - else: - usage() diff --git a/pipenv/patched/notpip/_vendor/requests/__init__.py b/pipenv/patched/notpip/_vendor/requests/__init__.py index 33667fdc..7af97bc8 100644 --- a/pipenv/patched/notpip/_vendor/requests/__init__.py +++ b/pipenv/patched/notpip/_vendor/requests/__init__.py @@ -40,8 +40,8 @@ is at . :license: Apache 2.0, see LICENSE for more details. """ -from pip9._vendor import urllib3 -from pip9._vendor import chardet +from notpip._vendor import urllib3 +from notpip._vendor import chardet import warnings from .exceptions import RequestsDependencyWarning @@ -80,14 +80,16 @@ except (AssertionError, ValueError): RequestsDependencyWarning) # Attempt to enable urllib3's SNI support, if possible -# try: -# from pip9._vendor.urllib3.contrib import pyopenssl -# pyopenssl.inject_into_urllib3() -# except ImportError: -# pass +from notpip._internal.compat import WINDOWS +if not WINDOWS: + try: + from notpip._vendor.urllib3.contrib import pyopenssl + pyopenssl.inject_into_urllib3() + except ImportError: + pass # urllib3's DependencyWarnings should be silenced. -from pip9._vendor.urllib3.exceptions import DependencyWarning +from notpip._vendor.urllib3.exceptions import DependencyWarning warnings.simplefilter('ignore', DependencyWarning) from .__version__ import __title__, __description__, __url__, __version__ diff --git a/pipenv/patched/notpip/_vendor/requests/adapters.py b/pipenv/patched/notpip/_vendor/requests/adapters.py index 4cdbf7e7..866be7e9 100644 --- a/pipenv/patched/notpip/_vendor/requests/adapters.py +++ b/pipenv/patched/notpip/_vendor/requests/adapters.py @@ -11,20 +11,20 @@ and maintain connections. import os.path import socket -from pip9._vendor.urllib3.poolmanager import PoolManager, proxy_from_url -from pip9._vendor.urllib3.response import HTTPResponse -from pip9._vendor.urllib3.util import Timeout as TimeoutSauce -from pip9._vendor.urllib3.util.retry import Retry -from pip9._vendor.urllib3.exceptions import ClosedPoolError -from pip9._vendor.urllib3.exceptions import ConnectTimeoutError -from pip9._vendor.urllib3.exceptions import HTTPError as _HTTPError -from pip9._vendor.urllib3.exceptions import MaxRetryError -from pip9._vendor.urllib3.exceptions import NewConnectionError -from pip9._vendor.urllib3.exceptions import ProxyError as _ProxyError -from pip9._vendor.urllib3.exceptions import ProtocolError -from pip9._vendor.urllib3.exceptions import ReadTimeoutError -from pip9._vendor.urllib3.exceptions import SSLError as _SSLError -from pip9._vendor.urllib3.exceptions import ResponseError +from notpip._vendor.urllib3.poolmanager import PoolManager, proxy_from_url +from notpip._vendor.urllib3.response import HTTPResponse +from notpip._vendor.urllib3.util import Timeout as TimeoutSauce +from notpip._vendor.urllib3.util.retry import Retry +from notpip._vendor.urllib3.exceptions import ClosedPoolError +from notpip._vendor.urllib3.exceptions import ConnectTimeoutError +from notpip._vendor.urllib3.exceptions import HTTPError as _HTTPError +from notpip._vendor.urllib3.exceptions import MaxRetryError +from notpip._vendor.urllib3.exceptions import NewConnectionError +from notpip._vendor.urllib3.exceptions import ProxyError as _ProxyError +from notpip._vendor.urllib3.exceptions import ProtocolError +from notpip._vendor.urllib3.exceptions import ReadTimeoutError +from notpip._vendor.urllib3.exceptions import SSLError as _SSLError +from notpip._vendor.urllib3.exceptions import ResponseError from .models import Response from .compat import urlparse, basestring @@ -38,7 +38,7 @@ from .exceptions import (ConnectionError, ConnectTimeout, ReadTimeout, SSLError, from .auth import _basic_auth_str try: - from pip9._vendor.urllib3.contrib.socks import SOCKSProxyManager + from notpip._vendor.urllib3.contrib.socks import SOCKSProxyManager except ImportError: def SOCKSProxyManager(*args, **kwargs): raise InvalidSchema("Missing dependencies for SOCKS support.") diff --git a/pipenv/patched/notpip/_vendor/requests/cacert.pem b/pipenv/patched/notpip/_vendor/requests/cacert.pem deleted file mode 100644 index 101ac98f..00000000 --- a/pipenv/patched/notpip/_vendor/requests/cacert.pem +++ /dev/null @@ -1,4433 +0,0 @@ - -# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA -# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA -# Label: "GlobalSign Root CA" -# Serial: 4835703278459707669005204 -# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a -# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c -# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99 ------BEGIN CERTIFICATE----- -MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG -A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv -b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw -MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i -YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT -aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ -jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp -xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp -1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG -snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ -U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 -9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E -BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B -AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz -yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE -38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP -AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad -DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME -HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 -# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 -# Label: "GlobalSign Root CA - R2" -# Serial: 4835703278459682885658125 -# MD5 Fingerprint: 94:14:77:7e:3e:5e:fd:8f:30:bd:41:b0:cf:e7:d0:30 -# SHA1 Fingerprint: 75:e0:ab:b6:13:85:12:27:1c:04:f8:5f:dd:de:38:e4:b7:24:2e:fe -# SHA256 Fingerprint: ca:42:dd:41:74:5f:d0:b8:1e:b9:02:36:2c:f9:d8:bf:71:9d:a1:bd:1b:1e:fc:94:6f:5b:4c:99:f4:2c:1b:9e ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 -MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL -v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 -eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq -tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd -C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa -zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB -mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH -V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n -bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG -3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs -J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO -291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS -ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd -AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 -TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== ------END CERTIFICATE----- - -# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only -# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only -# Label: "Verisign Class 3 Public Primary Certification Authority - G3" -# Serial: 206684696279472310254277870180966723415 -# MD5 Fingerprint: cd:68:b6:a7:c7:c4:ce:75:e0:1d:4f:57:44:61:92:09 -# SHA1 Fingerprint: 13:2d:0d:45:53:4b:69:97:cd:b2:d5:c3:39:e2:55:76:60:9b:5c:c6 -# SHA256 Fingerprint: eb:04:cf:5e:b1:f3:9a:fa:76:2f:2b:b1:20:f2:96:cb:a5:20:c1:b9:7d:b1:58:95:65:b8:1c:b9:a1:7b:72:44 ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b -N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t -KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu -kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm -CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ -Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu -imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te -2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe -DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC -/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p -F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt -TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== ------END CERTIFICATE----- - -# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited -# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited -# Label: "Entrust.net Premium 2048 Secure Server CA" -# Serial: 946069240 -# MD5 Fingerprint: ee:29:31:bc:32:7e:9a:e6:e8:b5:f7:51:b4:34:71:90 -# SHA1 Fingerprint: 50:30:06:09:1d:97:d4:f5:ae:39:f7:cb:e7:92:7d:7d:65:2d:34:31 -# SHA256 Fingerprint: 6d:c4:71:72:e0:1c:bc:b0:bf:62:58:0d:89:5f:e2:b8:ac:9a:d4:f8:73:80:1e:0c:10:b9:c8:37:d2:1e:b1:77 ------BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML -RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp -bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 -IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 -MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 -LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp -YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG -A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq -K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe -sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX -MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT -XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ -HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH -4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV -HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub -j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo -U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf -zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b -u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ -bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er -fF6adulZkMV8gzURZVE= ------END CERTIFICATE----- - -# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust -# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust -# Label: "Baltimore CyberTrust Root" -# Serial: 33554617 -# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4 -# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74 -# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ -RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD -VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX -DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y -ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy -VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr -mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr -IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK -mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu -XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy -dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye -jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 -BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 -DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 -9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx -jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 -Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz -ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS -R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp ------END CERTIFICATE----- - -# Issuer: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network -# Subject: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network -# Label: "AddTrust External Root" -# Serial: 1 -# MD5 Fingerprint: 1d:35:54:04:85:78:b0:3f:42:42:4d:bf:20:73:0a:3f -# SHA1 Fingerprint: 02:fa:f3:e2:91:43:54:68:60:78:57:69:4d:f5:e4:5b:68:85:18:68 -# SHA256 Fingerprint: 68:7f:a4:51:38:22:78:ff:f0:c8:b1:1f:8d:43:d5:76:67:1c:6e:b2:bc:ea:b4:13:fb:83:d9:65:d0:6d:2f:f2 ------BEGIN CERTIFICATE----- -MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs -IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 -MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux -FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h -bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v -dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt -H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 -uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX -mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX -a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN -E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 -WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD -VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 -Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU -cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx -IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN -AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH -YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 -6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC -Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX -c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a -mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= ------END CERTIFICATE----- - -# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. -# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. -# Label: "Entrust Root Certification Authority" -# Serial: 1164660820 -# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4 -# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9 -# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c ------BEGIN CERTIFICATE----- -MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC -VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 -Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW -KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl -cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw -NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw -NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy -ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV -BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo -Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 -4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 -KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI -rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi -94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB -sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi -gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo -kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE -vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA -A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t -O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua -AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP -9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ -eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m -0vdXcDazv/wor3ElhVsT/h5/WrQ8 ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Global CA O=GeoTrust Inc. -# Subject: CN=GeoTrust Global CA O=GeoTrust Inc. -# Label: "GeoTrust Global CA" -# Serial: 144470 -# MD5 Fingerprint: f7:75:ab:29:fb:51:4e:b7:77:5e:ff:05:3c:99:8e:f5 -# SHA1 Fingerprint: de:28:f4:a4:ff:e5:b9:2f:a3:c5:03:d1:a3:49:a7:f9:96:2a:82:12 -# SHA256 Fingerprint: ff:85:6a:2d:25:1d:cd:88:d3:66:56:f4:50:12:67:98:cf:ab:aa:de:40:79:9c:72:2d:e4:d2:b5:db:36:a7:3a ------BEGIN CERTIFICATE----- -MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT -MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i -YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG -EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg -R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 -9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq -fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv -iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU -1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ -bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW -MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA -ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l -uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn -Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS -tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF -PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un -hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV -5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Universal CA O=GeoTrust Inc. -# Subject: CN=GeoTrust Universal CA O=GeoTrust Inc. -# Label: "GeoTrust Universal CA" -# Serial: 1 -# MD5 Fingerprint: 92:65:58:8b:a2:1a:31:72:73:68:5c:b4:a5:7a:07:48 -# SHA1 Fingerprint: e6:21:f3:35:43:79:05:9a:4b:68:30:9d:8a:2f:74:22:15:87:ec:79 -# SHA256 Fingerprint: a0:45:9b:9f:63:b2:25:59:f5:fa:5d:4c:6d:b3:f9:f7:2f:f1:93:42:03:35:78:f0:73:bf:1d:1b:46:cb:b9:12 ------BEGIN CERTIFICATE----- -MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy -c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE -BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 -IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV -VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 -cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT -QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh -F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v -c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w -mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd -VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX -teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ -f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe -Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ -nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB -/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY -MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG -9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc -aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX -IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn -ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z -uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN -Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja -QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW -koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 -ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt -DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm -bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. -# Subject: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. -# Label: "GeoTrust Universal CA 2" -# Serial: 1 -# MD5 Fingerprint: 34:fc:b8:d0:36:db:9e:14:b3:c2:f2:db:8f:e4:94:c7 -# SHA1 Fingerprint: 37:9a:19:7b:41:85:45:35:0c:a6:03:69:f3:3c:2e:af:47:4f:20:79 -# SHA256 Fingerprint: a0:23:4f:3b:c8:52:7c:a5:62:8e:ec:81:ad:5d:69:89:5d:a5:68:0d:c9:1d:1c:b8:47:7f:33:f8:78:b9:5b:0b ------BEGIN CERTIFICATE----- -MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy -c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD -VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 -c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 -WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG -FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq -XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL -se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb -KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd -IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 -y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt -hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc -QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 -Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV -HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ -KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z -dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ -L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr -Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo -ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY -T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz -GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m -1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV -OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH -6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX -QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS ------END CERTIFICATE----- - -# Issuer: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association -# Subject: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association -# Label: "Visa eCommerce Root" -# Serial: 25952180776285836048024890241505565794 -# MD5 Fingerprint: fc:11:b8:d8:08:93:30:00:6d:23:f9:7e:eb:52:1e:02 -# SHA1 Fingerprint: 70:17:9b:86:8c:00:a4:fa:60:91:52:22:3f:9f:3e:32:bd:e0:05:62 -# SHA256 Fingerprint: 69:fa:c9:bd:55:fb:0a:c7:8d:53:bb:ee:5c:f1:d5:97:98:9f:d0:aa:ab:20:a2:51:51:bd:f1:73:3e:e7:d1:22 ------BEGIN CERTIFICATE----- -MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr -MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl -cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv -bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw -CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h -dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l -cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h -2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E -lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV -ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq -299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t -vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL -dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD -AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF -AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR -zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3 -LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd -7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw -++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt -398znM/jra6O1I7mT1GvFpLgXPYHDw== ------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----- -MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV -BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln -biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF -MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT -d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC -CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8 -76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+ -bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c -6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE -emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd -MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt -MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y -MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y -FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi -aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM -gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB -qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7 -lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn -8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov -L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6 -45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO -UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5 -O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC -bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv -GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a -77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC -hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3 -92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp -Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w -ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt -Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ ------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=T\xdcRKTRUST Elektronik Sertifika Hizmet Sa\u011flay\u0131c\u0131s\u0131 H5 O=T\xdcRKTRUST Bilgi \u0130leti\u015fim ve Bili\u015fim G\xfcvenli\u011fi Hizmetleri A.\u015e. -# Subject: CN=T\xdcRKTRUST Elektronik Sertifika Hizmet Sa\u011flay\u0131c\u0131s\u0131 H5 O=T\xdcRKTRUST Bilgi \u0130leti\u015fim ve Bili\u015fim G\xfcvenli\u011fi Hizmetleri A.\u015e. -# Label: "T\xdcRKTRUST Elektronik Sertifika Hizmet Sa\u011flay\u0131c\u0131s\u0131 H5" -# Serial: 156233699172481 -# MD5 Fingerprint: da:70:8e:f0:22:df:93:26:f6:5f:9f:d3:15:06:52:4e -# SHA1 Fingerprint: c4:18:f6:4d:46:d1:df:00:3d:27:30:13:72:43:a9:12:11:c6:75:fb -# SHA256 Fingerprint: 49:35:1b:90:34:44:c1:85:cc:dc:5c:69:3d:24:d8:55:5c:b2:08:d6:a8:14:13:07:69:9f:4a:f0:63:19:9d:78 ------BEGIN CERTIFICATE----- -MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UE -BhMCVFIxDzANBgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxn -aSDEsGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkg -QS7Fni4xQjBABgNVBAMMOVTDnFJLVFJVU1QgRWxla3Ryb25payBTZXJ0aWZpa2Eg -SGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSBINTAeFw0xMzA0MzAwODA3MDFaFw0yMzA0 -MjgwODA3MDFaMIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0wSwYD -VQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8 -dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBF -bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1MIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApCUZ4WWe60ghUEoI5RHwWrom -/4NZzkQqL/7hzmAD/I0Dpe3/a6i6zDQGn1k19uwsu537jVJp45wnEFPzpALFp/kR -Gml1bsMdi9GYjZOHp3GXDSHHmflS0yxjXVW86B8BSLlg/kJK9siArs1mep5Fimh3 -4khon6La8eHBEJ/rPCmBp+EyCNSgBbGM+42WAA4+Jd9ThiI7/PS98wl+d+yG6w8z -5UNP9FR1bSmZLmZaQ9/LXMrI5Tjxfjs1nQ/0xVqhzPMggCTTV+wVunUlm+hkS7M0 -hO8EuPbJbKoCPrZV4jI3X/xml1/N1p7HIL9Nxqw/dV8c7TKcfGkAaZHjIxhT6QID -AQABo0IwQDAdBgNVHQ4EFgQUVpkHHtOsDGlktAxQR95DLL4gwPswDgYDVR0PAQH/ -BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ5FdnsX -SDLyOIspve6WSk6BGLFRRyDN0GSxDsnZAdkJzsiZ3GglE9Rc8qPoBP5yCccLqh0l -VX6Wmle3usURehnmp349hQ71+S4pL+f5bFgWV1Al9j4uPqrtd3GqqpmWRgqujuwq -URawXs3qZwQcWDD1YIq9pr1N5Za0/EKJAWv2cMhQOQwt1WbZyNKzMrcbGW3LM/nf -peYVhDfwwvJllpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CF -Yv4HAqGEVka+lgqaE9chTLd8B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW -+qtB4Uu2NQvAmxU= ------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=Certplus Root CA G1 O=Certplus -# Subject: CN=Certplus Root CA G1 O=Certplus -# Label: "Certplus Root CA G1" -# Serial: 1491911565779898356709731176965615564637713 -# MD5 Fingerprint: 7f:09:9c:f7:d9:b9:5c:69:69:56:d5:37:3e:14:0d:42 -# SHA1 Fingerprint: 22:fd:d0:b7:fd:a2:4e:0d:ac:49:2c:a0:ac:a6:7b:6a:1f:e3:f7:66 -# SHA256 Fingerprint: 15:2a:40:2b:fc:df:2c:d5:48:05:4d:22:75:b3:9c:7f:ca:3e:c0:97:80:78:b0:f0:ea:76:e5:61:a6:c7:43:3e ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUA -MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy -dHBsdXMgUm9vdCBDQSBHMTAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBa -MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy -dHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB -ANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHNr49a -iZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt -6kuJPKNxQv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP -0FG7Yn2ksYyy/yARujVjBYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f -6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTvLRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDE -EW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2z4QTd28n6v+WZxcIbekN -1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc4nBvCGrc -h2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCT -mehd4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV -4EJQeIQEQWGw9CEjjy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPO -WftwenMGE9nTdDckQQoRb5fc5+R+ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1Ud -DwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSowcCbkahDFXxd -Bie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHYlwuBsTANBgkq -hkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh -66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7 -/SMNkPX0XtPGYX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BS -S7CTKtQ+FjPlnsZlFT5kOwQ/2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j -2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F6ALEUz65noe8zDUa3qHpimOHZR4R -Kttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilXCNQ314cnrUlZp5Gr -RHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWetUNy -6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEV -V/xuZDDCVRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5 -g4VCXA9DO2pJNdWY9BW/+mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl -++O/QmueD6i9a5jc2NvLi6Td11n0bt3+qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo= ------END CERTIFICATE----- - -# Issuer: CN=Certplus Root CA G2 O=Certplus -# Subject: CN=Certplus Root CA G2 O=Certplus -# Label: "Certplus Root CA G2" -# Serial: 1492087096131536844209563509228951875861589 -# MD5 Fingerprint: a7:ee:c4:78:2d:1b:ee:2d:b9:29:ce:d6:a7:96:32:31 -# SHA1 Fingerprint: 4f:65:8e:1f:e9:06:d8:28:02:e9:54:47:41:c9:54:25:5d:69:cc:1a -# SHA256 Fingerprint: 6c:c0:50:41:e6:44:5e:74:69:6c:4c:fb:c9:f8:0f:54:3b:7e:ab:bb:44:b4:ce:6f:78:7c:6a:99:71:c4:2f:17 ------BEGIN CERTIFICATE----- -MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4x -CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs -dXMgUm9vdCBDQSBHMjAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4x -CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs -dXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABM0PW1aC3/BFGtat -93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uNAm8x -Ik0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0P -AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwj -FNiPwyCrKGBZMB8GA1UdIwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqG -SM49BAMDA2gAMGUCMHD+sAvZ94OX7PNVHdTcswYO/jOYnYs5kGuUIe22113WTNch -p+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjlvPl5adytRSv3tjFzzAal -U5ORGpOucGpnutee5WEaXw== ------END CERTIFICATE----- - -# Issuer: CN=OpenTrust Root CA G1 O=OpenTrust -# Subject: CN=OpenTrust Root CA G1 O=OpenTrust -# Label: "OpenTrust Root CA G1" -# Serial: 1492036577811947013770400127034825178844775 -# MD5 Fingerprint: 76:00:cc:81:29:cd:55:5e:88:6a:7a:2e:f7:4d:39:da -# SHA1 Fingerprint: 79:91:e8:34:f7:e2:ee:dd:08:95:01:52:e9:55:2d:14:e9:58:d5:7e -# SHA256 Fingerprint: 56:c7:71:28:d9:8c:18:d9:1b:4c:fd:ff:bc:25:ee:91:03:d4:75:8e:a2:ab:ad:82:6a:90:f3:45:7d:46:0e:b4 ------BEGIN CERTIFICATE----- -MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUA -MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w -ZW5UcnVzdCBSb290IENBIEcxMB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAw -MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU -T3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7faYp6b -wiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX -/uMftk87ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR0 -77F9jAHiOH3BX2pfJLKOYheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGP -uY4zbGneWK2gDqdkVBFpRGZPTBKnjix9xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLx -p2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO9z0M+Yo0FMT7MzUj8czx -Kselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq3ywgsNw2 -TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+W -G+Oin6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPw -vFEVVJSmdz7QdFG9URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYY -EQRVzXR7z2FwefR7LFxckvzluFqrTJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUl0YhVyE1 -2jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/PxN3DlCPaTKbYw -DQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E -PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kf -gLMtMrpkZ2CvuVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbS -FXJfLkur1J1juONI5f6ELlgKn0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0 -V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLhX4SPgPL0DTatdrOjteFkdjpY3H1P -XlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80nR14SohWZ25g/4/I -i+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcmGS3t -TAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L91 -09S5zvE/bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/Ky -Pu1svf0OnWZzsD2097+o4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJ -AwSQiumPv+i2tCqjI40cHLI5kqiPAlxAOXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj -1oxx ------END CERTIFICATE----- - -# Issuer: CN=OpenTrust Root CA G2 O=OpenTrust -# Subject: CN=OpenTrust Root CA G2 O=OpenTrust -# Label: "OpenTrust Root CA G2" -# Serial: 1492012448042702096986875987676935573415441 -# MD5 Fingerprint: 57:24:b6:59:24:6b:ae:c8:fe:1c:0c:20:f2:c0:4e:eb -# SHA1 Fingerprint: 79:5f:88:60:c5:ab:7c:3d:92:e6:cb:f4:8d:e1:45:cd:11:ef:60:0b -# SHA256 Fingerprint: 27:99:58:29:fe:6a:75:15:c1:bf:e8:48:f9:c4:76:1d:b1:6c:22:59:29:25:7b:f4:0d:08:94:f2:9e:a8:ba:f2 ------BEGIN CERTIFICATE----- -MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUA -MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w -ZW5UcnVzdCBSb290IENBIEcyMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAw -MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU -T3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+Ntmh -/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78e -CbY2albz4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/6 -1UWY0jUJ9gNDlP7ZvyCVeYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fE -FY8ElggGQgT4hNYdvJGmQr5J1WqIP7wtUdGejeBSzFfdNTVY27SPJIjki9/ca1TS -gSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz3GIZ38i1MH/1PCZ1Eb3X -G7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj3CzMpSZy -YhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaH -vGOz9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4 -t/bQWVyJ98LVtZR00dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/ -gh7PU3+06yzbXfZqfUAkBXKJOAGTy3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUajn6QiL3 -5okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59M4PLuG53hq8w -DQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz -Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0 -nXGEL8pZ0keImUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qT -RmTFAHneIWv2V6CG1wZy7HBGS4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpT -wm+bREx50B1ws9efAvSyB7DH5fitIw6mVskpEndI2S9G/Tvw/HRwkqWOOAgfZDC2 -t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ6e18CL13zSdkzJTa -TkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97krgCf2 -o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU -3jg9CcCoSmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eA -iN1nE28daCSLT7d0geX0YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14f -WKGVyasvc0rQLW6aWQ9VGHgtPFGml4vmu7JwqkwR3v98KzfUetF3NI/n+UL3PIEM -S1IK ------END CERTIFICATE----- - -# Issuer: CN=OpenTrust Root CA G3 O=OpenTrust -# Subject: CN=OpenTrust Root CA G3 O=OpenTrust -# Label: "OpenTrust Root CA G3" -# Serial: 1492104908271485653071219941864171170455615 -# MD5 Fingerprint: 21:37:b4:17:16:92:7b:67:46:70:a9:96:d7:a8:13:24 -# SHA1 Fingerprint: 6e:26:64:f3:56:bf:34:55:bf:d1:93:3f:7c:01:de:d8:13:da:8a:a6 -# SHA256 Fingerprint: b7:c3:62:31:70:6e:81:07:8c:36:7c:b8:96:19:8f:1e:32:08:dd:92:69:49:dd:8f:57:09:a4:10:f7:5b:62:92 ------BEGIN CERTIFICATE----- -MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAx -CzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5U -cnVzdCBSb290IENBIEczMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFow -QDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwUT3Bl -blRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARK7liuTcpm -3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5Bta1d -oYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4G -A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5 -DMlv4VBN0BBY3JWIbTAfBgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAK -BggqhkjOPQQDAwNpADBmAjEAj6jcnboMBBf6Fek9LykBl7+BFjNAk2z8+e2AcG+q -j9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta3U1fJAuwACEl74+nBCZx -4nxp5V2a+EEfOzmTk51V6s2N8fvB ------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----- diff --git a/pipenv/patched/notpip/_vendor/requests/certs.py b/pipenv/patched/notpip/_vendor/requests/certs.py index 2439625d..f7a37f55 100644 --- a/pipenv/patched/notpip/_vendor/requests/certs.py +++ b/pipenv/patched/notpip/_vendor/requests/certs.py @@ -12,7 +12,7 @@ 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 pip9._vendor.certifi import where +from notpip._vendor.certifi import where if __name__ == '__main__': print(where()) diff --git a/pipenv/patched/notpip/_vendor/requests/compat.py b/pipenv/patched/notpip/_vendor/requests/compat.py index 7a9ba56d..eb9f88c2 100644 --- a/pipenv/patched/notpip/_vendor/requests/compat.py +++ b/pipenv/patched/notpip/_vendor/requests/compat.py @@ -8,7 +8,7 @@ This module handles import compatibility issues between Python 2 and Python 3. """ -from pip9._vendor import chardet +from notpip._vendor import chardet import sys @@ -25,9 +25,13 @@ 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: +# except (ImportError, SyntaxError): +# # simplejson does not support Python 3.2, it throws a SyntaxError +# # because of u'...' Unicode literals. import json # --------- @@ -44,7 +48,7 @@ if is_py2: from Cookie import Morsel from StringIO import StringIO - from pip9._vendor.urllib3.packages.ordered_dict import OrderedDict + from notpip._vendor.urllib3.packages.ordered_dict import OrderedDict builtin_str = str bytes = str diff --git a/pipenv/patched/notpip/_vendor/requests/exceptions.py b/pipenv/patched/notpip/_vendor/requests/exceptions.py index c116f8eb..eb3feea4 100644 --- a/pipenv/patched/notpip/_vendor/requests/exceptions.py +++ b/pipenv/patched/notpip/_vendor/requests/exceptions.py @@ -6,7 +6,7 @@ requests.exceptions This module contains the set of Requests' exceptions. """ -from pip9._vendor.urllib3.exceptions import HTTPError as BaseHTTPError +from notpip._vendor.urllib3.exceptions import HTTPError as BaseHTTPError class RequestException(IOError): diff --git a/pipenv/patched/notpip/_vendor/requests/help.py b/pipenv/patched/notpip/_vendor/requests/help.py index 96f656f5..61e03926 100644 --- a/pipenv/patched/notpip/_vendor/requests/help.py +++ b/pipenv/patched/notpip/_vendor/requests/help.py @@ -6,9 +6,9 @@ import platform import sys import ssl -from pip9._vendor import idna -from pip9._vendor import urllib3 -from pip9._vendor import chardet +from notpip._vendor import idna +from notpip._vendor import urllib3 +from notpip._vendor import chardet from . import __version__ as requests_version diff --git a/pipenv/patched/notpip/_vendor/requests/models.py b/pipenv/patched/notpip/_vendor/requests/models.py index a7efaa02..08a3c968 100644 --- a/pipenv/patched/notpip/_vendor/requests/models.py +++ b/pipenv/patched/notpip/_vendor/requests/models.py @@ -16,10 +16,10 @@ import sys # such as in Embedded Python. See https://github.com/requests/requests/issues/3578. import encodings.idna -from pip9._vendor.urllib3.fields import RequestField -from pip9._vendor.urllib3.filepost import encode_multipart_formdata -from pip9._vendor.urllib3.util import parse_url -from pip9._vendor.urllib3.exceptions import ( +from notpip._vendor.urllib3.fields import RequestField +from notpip._vendor.urllib3.filepost import encode_multipart_formdata +from notpip._vendor.urllib3.util import parse_url +from notpip._vendor.urllib3.exceptions import ( DecodeError, ReadTimeoutError, ProtocolError, LocationParseError) from io import UnsupportedOperation @@ -336,7 +336,7 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): @staticmethod def _get_idna_encoded_host(host): - import idna + from notpip._vendor import idna try: host = idna.encode(host, uts46=True).decode('utf-8') diff --git a/pipenv/patched/notpip/_vendor/requests/packages.py b/pipenv/patched/notpip/_vendor/requests/packages.py index 928d1bb9..258c89ed 100644 --- a/pipenv/patched/notpip/_vendor/requests/packages.py +++ b/pipenv/patched/notpip/_vendor/requests/packages.py @@ -4,13 +4,13 @@ import sys # I don't like it either. Just look the other way. :) for package in ('urllib3', 'idna', 'chardet'): - vendored_package = "pip9._vendor." + package + vendored_package = "notpip._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("pip9._vendor."):] - sys.modules['pip9._vendor.requests.packages.' + unprefixed_mod] = sys.modules[mod] + unprefixed_mod = mod[len("notpip._vendor."):] + sys.modules['notpip._vendor.requests.packages.' + unprefixed_mod] = sys.modules[mod] # Kinda cool, though, right? diff --git a/pipenv/patched/notpip/_vendor/retrying.py b/pipenv/patched/notpip/_vendor/retrying.py index dd3b7209..236b3953 100644 --- a/pipenv/patched/notpip/_vendor/retrying.py +++ b/pipenv/patched/notpip/_vendor/retrying.py @@ -13,7 +13,7 @@ ## limitations under the License. import random -from pip9._vendor import six +from notpip._vendor import six import sys import time import traceback diff --git a/pipenv/patched/notpip/_vendor/six.py b/pipenv/patched/notpip/_vendor/six.py index 190c0239..6bf4fd38 100644 --- a/pipenv/patched/notpip/_vendor/six.py +++ b/pipenv/patched/notpip/_vendor/six.py @@ -1,6 +1,4 @@ -"""Utilities for writing code that runs on Python 2 and 3""" - -# Copyright (c) 2010-2015 Benjamin Peterson +# Copyright (c) 2010-2017 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 @@ -20,6 +18,8 @@ # 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 @@ -29,7 +29,7 @@ import sys import types __author__ = "Benjamin Peterson " -__version__ = "1.10.0" +__version__ = "1.11.0" # Useful for very coarse version differentiation. @@ -241,6 +241,7 @@ _moved_attributes = [ 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"), @@ -262,10 +263,11 @@ _moved_attributes = [ 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("email_mime_base", "email.MIMEBase", "email.mime.base"), MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), @@ -337,10 +339,12 @@ _urllib_parse_moved_attributes = [ 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"), @@ -416,6 +420,8 @@ _urllib_request_moved_attributes = [ 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) @@ -679,11 +685,15 @@ 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 + 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): @@ -699,19 +709,28 @@ else: exec("""exec _code_ in _globs_, _locs_""") exec_("""def reraise(tp, value, tb=None): - raise tp, value, tb + try: + raise tp, value, tb + finally: + tb = None """) 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 + 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): - raise value from from_value + try: + raise value from from_value + finally: + value = None """) else: def raise_from(value, from_value): @@ -802,10 +821,14 @@ def with_metaclass(meta, *bases): # 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): + 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', (), {}) diff --git a/pipenv/patched/notpip/_vendor/urllib3/contrib/appengine.py b/pipenv/patched/notpip/_vendor/urllib3/contrib/appengine.py index 814b0222..fa7fb2ac 100644 --- a/pipenv/patched/notpip/_vendor/urllib3/contrib/appengine.py +++ b/pipenv/patched/notpip/_vendor/urllib3/contrib/appengine.py @@ -4,8 +4,8 @@ This module provides a pool manager that uses Google App Engine's Example usage:: - from urllib3 import PoolManager - from urllib3.contrib.appengine import AppEngineManager, is_appengine_sandbox + from notpip._vendor.urllib3 import PoolManager + from notpip._vendor.urllib3.contrib.appengine import AppEngineManager, is_appengine_sandbox if is_appengine_sandbox(): # AppEngineManager uses AppEngine's URLFetch API behind the scenes diff --git a/pipenv/patched/notpip/_vendor/urllib3/contrib/pyopenssl.py b/pipenv/patched/notpip/_vendor/urllib3/contrib/pyopenssl.py index f63b8401..ac24a808 100644 --- a/pipenv/patched/notpip/_vendor/urllib3/contrib/pyopenssl.py +++ b/pipenv/patched/notpip/_vendor/urllib3/contrib/pyopenssl.py @@ -164,7 +164,7 @@ def _dnsname_to_stdlib(name): that we can't just safely call `idna.encode`: it can explode for wildcard names. This avoids that problem. """ - import idna + from notpip._vendor import idna for prefix in [u'*.', u'.']: if name.startswith(prefix): diff --git a/pipenv/patched/notpip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py b/pipenv/patched/notpip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py index 1fd42f38..6f8703d6 100644 --- a/pipenv/patched/notpip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py +++ b/pipenv/patched/notpip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py @@ -12,7 +12,7 @@ import sys # backports.ssl_match_hostname to continue to be used all the way back to # python-2.4. try: - import ipaddress + from notpip._vendor import ipaddress except ImportError: ipaddress = None diff --git a/pipenv/patched/notpip/_vendor/urllib3/util/ssl_.py b/pipenv/patched/notpip/_vendor/urllib3/util/ssl_.py index 32fd9eda..670c888c 100644 --- a/pipenv/patched/notpip/_vendor/urllib3/util/ssl_.py +++ b/pipenv/patched/notpip/_vendor/urllib3/util/ssl_.py @@ -228,7 +228,7 @@ def create_urllib3_context(ssl_version=None, cert_reqs=None, If you wish to enable SSLv3, you can do:: - from urllib3.util import ssl_ + from notpip._vendor.urllib3.util import ssl_ context = ssl_.create_urllib3_context() context.options &= ~ssl_.OP_NO_SSLv3 diff --git a/pipenv/patched/notpip/_vendor/webencodings/__init__.py b/pipenv/patched/notpip/_vendor/webencodings/__init__.py index 03d5d357..d21d697c 100644 --- a/pipenv/patched/notpip/_vendor/webencodings/__init__.py +++ b/pipenv/patched/notpip/_vendor/webencodings/__init__.py @@ -1,4 +1,4 @@ -# coding: utf8 +# coding: utf-8 """ webencodings @@ -19,7 +19,7 @@ import codecs from .labels import LABELS -VERSION = '0.5' +VERSION = '0.5.1' # Some names in Encoding are not valid Python aliases. Remap these. diff --git a/pipenv/patched/notpip/_vendor/webencodings/tests.py b/pipenv/patched/notpip/_vendor/webencodings/tests.py index b8c5653e..e12c10d0 100644 --- a/pipenv/patched/notpip/_vendor/webencodings/tests.py +++ b/pipenv/patched/notpip/_vendor/webencodings/tests.py @@ -1,4 +1,4 @@ -# coding: utf8 +# coding: utf-8 """ webencodings.tests diff --git a/pipenv/patched/notpip/_vendor/webencodings/x_user_defined.py b/pipenv/patched/notpip/_vendor/webencodings/x_user_defined.py index f0daa11a..d16e3260 100644 --- a/pipenv/patched/notpip/_vendor/webencodings/x_user_defined.py +++ b/pipenv/patched/notpip/_vendor/webencodings/x_user_defined.py @@ -1,4 +1,4 @@ -# coding: utf8 +# coding: utf-8 """ webencodings.x_user_defined diff --git a/pipenv/patched/notpip/commands/check.py b/pipenv/patched/notpip/commands/check.py deleted file mode 100644 index 751878a9..00000000 --- a/pipenv/patched/notpip/commands/check.py +++ /dev/null @@ -1,39 +0,0 @@ -import logging - -from pip9.basecommand import Command -from pip9.operations.check import check_requirements -from pip9.utils import get_installed_distributions - - -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): - dists = get_installed_distributions(local_only=False, skip=()) - missing_reqs_dict, incompatible_reqs_dict = check_requirements(dists) - - for dist in dists: - key = '%s==%s' % (dist.project_name, dist.version) - - for requirement in missing_reqs_dict.get(key, []): - logger.info( - "%s %s requires %s, which is not installed.", - dist.project_name, dist.version, requirement.project_name) - - for requirement, actual in incompatible_reqs_dict.get(key, []): - logger.info( - "%s %s has requirement %s, but you have %s %s.", - dist.project_name, dist.version, requirement, - actual.project_name, actual.version) - - if missing_reqs_dict or incompatible_reqs_dict: - return 1 - else: - logger.info("No broken requirements found.") diff --git a/pipenv/patched/notpip/commands/install.py b/pipenv/patched/notpip/commands/install.py deleted file mode 100644 index f1bd7952..00000000 --- a/pipenv/patched/notpip/commands/install.py +++ /dev/null @@ -1,437 +0,0 @@ -from __future__ import absolute_import - -import logging -import operator -import os -import tempfile -import shutil -import warnings -try: - import wheel -except ImportError: - wheel = None - -from pip9.req import RequirementSet -from pip9.basecommand import RequirementCommand -from pip9.locations import virtualenv_no_global, distutils_scheme -from pip9.exceptions import ( - InstallationError, CommandError, PreviousBuildDirError, -) -from pip9 import cmdoptions -from pip9.utils import ensure_dir, get_installed_version -from pip9.utils.build import BuildDirectory -from pip9.utils.deprecation import RemovedInPip10Warning -from pip9.utils.filesystem import check_path_owner -from pip9.wheel import WheelCache, 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.constraints()) - cmd_opts.add_option(cmdoptions.editable()) - cmd_opts.add_option(cmdoptions.requirements()) - cmd_opts.add_option(cmdoptions.build_dir()) - - 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( - '-d', '--download', '--download-dir', '--download-directory', - dest='download_dir', - metavar='dir', - default=None, - help=("Download packages into instead of installing them, " - "regardless of what's already installed."), - ) - - 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='eager', - choices=['only-if-needed', 'eager'], - help='Determines how dependency upgrading should be handled. ' - '"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='When upgrading, 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_deps()) - - cmd_opts.add_option(cmdoptions.install_options()) - cmd_opts.add_option(cmdoptions.global_options()) - - 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( - '--egg', - dest='as_egg', - action='store_true', - help="Install packages as eggs, not 'flat', like pip normally " - "does. This option is not about installing *from* eggs. " - "(WARNING: Because this option overrides pip's normal install" - " logic, requirements files may not behave as expected.)") - - 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( - "--compile", - action="store_true", - dest="compile", - default=True, - help="Compile py files to pyc", - ) - - cmd_opts.add_option( - "--no-compile", - action="store_false", - dest="compile", - help="Do not compile py files to pyc", - ) - - cmd_opts.add_option(cmdoptions.use_wheel()) - cmd_opts.add_option(cmdoptions.no_use_wheel()) - cmd_opts.add_option(cmdoptions.no_binary()) - cmd_opts.add_option(cmdoptions.only_binary()) - cmd_opts.add_option(cmdoptions.pre()) - 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.resolve_wheel_no_use_binary(options) - cmdoptions.check_install_build_global(options) - - if options.as_egg: - warnings.warn( - "--egg has been deprecated and will be removed in the future. " - "This flag is mutually exclusive with large parts of pip, and " - "actually using it invalidates pip's ability to manage the " - "installation process.", - RemovedInPip10Warning, - ) - - if options.allow_external: - warnings.warn( - "--allow-external has been deprecated and will be removed in " - "the future. Due to changes in the repository protocol, it no " - "longer has any effect.", - RemovedInPip10Warning, - ) - - if options.allow_all_external: - warnings.warn( - "--allow-all-external has been deprecated and will be removed " - "in the future. Due to changes in the repository protocol, it " - "no longer has any effect.", - RemovedInPip10Warning, - ) - - if options.allow_unverified: - warnings.warn( - "--allow-unverified has been deprecated and will be removed " - "in the future. Due to changes in the repository protocol, it " - "no longer has any effect.", - RemovedInPip10Warning, - ) - - if options.download_dir: - warnings.warn( - "pip install --download has been deprecated and will be " - "removed in the future. Pip now has a download command that " - "should be used instead.", - RemovedInPip10Warning, - ) - options.ignore_installed = True - - if options.build_dir: - options.build_dir = os.path.abspath(options.build_dir) - - 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=') - - temp_target_dir = None - if options.target_dir: - options.ignore_installed = True - temp_target_dir = tempfile.mkdtemp() - 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." - ) - install_options.append('--home=' + temp_target_dir) - - global_options = options.global_options or [] - - 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) - 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 BuildDirectory(options.build_dir, - delete=build_delete) as build_dir: - requirement_set = RequirementSet( - build_dir=build_dir, - src_dir=options.src_dir, - download_dir=options.download_dir, - upgrade=options.upgrade, - upgrade_strategy=options.upgrade_strategy, - as_egg=options.as_egg, - ignore_installed=options.ignore_installed, - ignore_dependencies=options.ignore_dependencies, - ignore_requires_python=options.ignore_requires_python, - force_reinstall=options.force_reinstall, - use_user_site=options.use_user_site, - target_dir=temp_target_dir, - session=session, - pycompile=options.compile, - isolated=options.isolated_mode, - wheel_cache=wheel_cache, - require_hashes=options.require_hashes, - ) - - self.populate_requirement_set( - requirement_set, args, options, finder, session, self.name, - wheel_cache - ) - - if not requirement_set.has_requirements: - return - - try: - if (options.download_dir or not wheel or not - options.cache_dir): - # on -d don't do complex things like building - # wheels, and don't try to build wheels when wheel is - # not installed. - requirement_set.prepare_files(finder) - else: - # build wheels before install. - wb = WheelBuilder( - requirement_set, - finder, - build_options=[], - global_options=[], - ) - # Ignore the result: a failed wheel will be - # installed from the sdist/vcs whatever. - wb.build(autobuilding=True) - - if not options.download_dir: - requirement_set.install( - install_options, - global_options, - root=options.root_path, - prefix=options.prefix_path, - ) - - possible_lib_locations = get_lib_location_guesses( - user=options.use_user_site, - home=temp_target_dir, - root=options.root_path, - prefix=options.prefix_path, - isolated=options.isolated_mode, - ) - reqs = sorted( - requirement_set.successfully_installed, - key=operator.attrgetter('name')) - items = [] - for req in reqs: - item = req.name - try: - installed_version = get_installed_version( - req.name, possible_lib_locations - ) - if installed_version: - item += '-' + installed_version - except Exception: - pass - items.append(item) - installed = ' '.join(items) - if installed: - logger.info('Successfully installed %s', installed) - else: - downloaded = ' '.join([ - req.name - for req in requirement_set.successfully_downloaded - ]) - if downloaded: - logger.info( - 'Successfully downloaded %s', downloaded - ) - except PreviousBuildDirError: - options.no_clean = True - raise - finally: - # Clean up - if not options.no_clean: - requirement_set.cleanup_files() - - if options.target_dir: - ensure_dir(options.target_dir) - - # Checking both purelib and platlib directories for installed - # packages to be moved to target directory - lib_dir_list = [] - - purelib_dir = distutils_scheme('', home=temp_target_dir)['purelib'] - platlib_dir = distutils_scheme('', home=temp_target_dir)['platlib'] - - 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) - - for lib_dir in lib_dir_list: - for item in os.listdir(lib_dir): - target_item_dir = os.path.join(options.target_dir, item) - if os.path.exists(target_item_dir): - if not options.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 - ) - shutil.rmtree(temp_target_dir) - return requirement_set - - -def get_lib_location_guesses(*args, **kwargs): - scheme = distutils_scheme('', *args, **kwargs) - return [scheme['purelib'], scheme['platlib']] diff --git a/pipenv/patched/notpip/compat/__init__.py b/pipenv/patched/notpip/compat/__init__.py deleted file mode 100644 index e73caac5..00000000 --- a/pipenv/patched/notpip/compat/__init__.py +++ /dev/null @@ -1,169 +0,0 @@ -"""Stuff that differs in different Python versions and platform -distributions.""" -from __future__ import absolute_import, division - -import os -import sys -import locale - -from pip9._vendor.six import text_type - -try: - from logging.config import dictConfig as logging_dictConfig -except ImportError: - from pip9.compat.dictconfig import dictConfig as logging_dictConfig - -try: - from collections import OrderedDict -except ImportError: - from pip9._vendor.ordereddict import OrderedDict - -try: - import ipaddress -except ImportError: - try: - from pip9._vendor import ipaddress - except ImportError: - import ipaddr as ipaddress - ipaddress.ip_address = ipaddress.IPAddress - ipaddress.ip_network = ipaddress.IPNetwork - - -try: - import sysconfig - - def get_stdlib(): - paths = [ - sysconfig.get_path("stdlib"), - sysconfig.get_path("platstdlib"), - ] - return set(filter(bool, paths)) -except ImportError: - from distutils import sysconfig - - def get_stdlib(): - paths = [ - sysconfig.get_python_lib(standard_lib=True), - sysconfig.get_python_lib(standard_lib=True, plat_specific=True), - ] - return set(filter(bool, paths)) - - -__all__ = [ - "logging_dictConfig", "ipaddress", "uses_pycache", "console_to_str", - "native_str", "get_path_uid", "stdlib_pkgs", "WINDOWS", "samefile", - "OrderedDict", -] - - -if sys.version_info >= (3, 4): - uses_pycache = True - from importlib.util import cache_from_source -else: - import imp - uses_pycache = hasattr(imp, 'cache_from_source') - if uses_pycache: - cache_from_source = imp.cache_from_source - else: - cache_from_source = None - - -if sys.version_info >= (3,): - def console_to_str(s): - try: - return s.decode(sys.__stdout__.encoding) - except UnicodeDecodeError: - if sys.__stdout__.encoding == 'utf-8': - encoding = locale.getdefaultlocale()[1] - if encoding is not None and encoding.lower() != 'utf-8': - return s.decode(encoding) - return s.decode('utf_8') - - def native_str(s, replace=False): - if isinstance(s, bytes): - return s.decode('utf-8', 'replace' if replace else 'strict') - return s - -else: - def console_to_str(s): - return s - - def native_str(s, replace=False): - # Replace is ignored -- unicode to UTF-8 can't fail - if isinstance(s, text_type): - return s.encode('utf-8') - return s - - -def total_seconds(td): - if hasattr(td, "total_seconds"): - return td.total_seconds() - else: - val = td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6 - return val / 10 ** 6 - - -def get_path_uid(path): - """ - 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 - - -def expanduser(path): - """ - Expand ~ and ~user constructions. - - Includes a workaround for http://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') -if sys.version_info >= (2, 7): - stdlib_pkgs += ('argparse',) - - -# windows detection, covers cpython and ironpython -WINDOWS = (sys.platform.startswith("win") or - (sys.platform == 'cli' and os.name == 'nt')) - - -def samefile(file1, file2): - """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 diff --git a/pipenv/patched/notpip/compat/dictconfig.py b/pipenv/patched/notpip/compat/dictconfig.py deleted file mode 100644 index f69b53ec..00000000 --- a/pipenv/patched/notpip/compat/dictconfig.py +++ /dev/null @@ -1,565 +0,0 @@ -# This is a copy of the Python logging.config.dictconfig module, -# reproduced with permission. It is provided here for backwards -# compatibility for Python versions prior to 2.7. -# -# Copyright 2009-2010 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, 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 absolute_import - -import logging.handlers -import re -import sys -import types - -from pip9._vendor import six - -# flake8: noqa - -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 - -# -# This function is defined in logging only in recent versions of Python -# -try: - from logging import _checkLevel -except ImportError: - def _checkLevel(level): - if isinstance(level, int): - rv = level - elif str(level) == level: - if level not in logging._levelNames: - raise ValueError('Unknown level: %r' % level) - rv = logging._levelNames[level] - else: - raise TypeError('Level not an integer or a ' - 'valid string: %r' % level) - return rv - -# The ConvertingXXX classes are wrappers around standard Python containers, -# and they serve to convert any suitable values in the container. The -# conversion converts base dicts, lists and tuples to their wrapped -# equivalents, whereas strings which match a conversion format are converted -# appropriately. -# -# Each wrapper should have a configurator attribute holding the actual -# configurator to use for conversion. - - -class ConvertingDict(dict): - """A converting dictionary wrapper.""" - - def __getitem__(self, key): - value = dict.__getitem__(self, key) - result = self.configurator.convert(value) - # If the converted value is different, save for next time - if value is not result: - self[key] = result - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): - result.parent = self - result.key = key - return result - - def get(self, key, default=None): - value = dict.get(self, key, default) - result = self.configurator.convert(value) - # If the converted value is different, save for next time - if value is not result: - self[key] = result - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): - result.parent = self - result.key = key - return result - - def pop(self, key, default=None): - value = dict.pop(self, key, default) - result = self.configurator.convert(value) - if value is not result: - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): - result.parent = self - result.key = key - return result - - -class ConvertingList(list): - """A converting list wrapper.""" - def __getitem__(self, key): - value = list.__getitem__(self, key) - result = self.configurator.convert(value) - # If the converted value is different, save for next time - if value is not result: - self[key] = result - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): - result.parent = self - result.key = key - return result - - def pop(self, idx=-1): - value = list.pop(self, idx) - result = self.configurator.convert(value) - if value is not result: - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): - result.parent = self - return result - - -class ConvertingTuple(tuple): - """A converting tuple wrapper.""" - def __getitem__(self, key): - value = tuple.__getitem__(self, key) - result = self.configurator.convert(value) - if value is not result: - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): - result.parent = self - result.key = key - return result - - -class BaseConfigurator(object): - """ - The configurator base class which defines some useful defaults. - """ - - CONVERT_PATTERN = re.compile(r'^(?P[a-z]+)://(?P.*)$') - - WORD_PATTERN = re.compile(r'^\s*(\w+)\s*') - DOT_PATTERN = re.compile(r'^\.\s*(\w+)\s*') - INDEX_PATTERN = re.compile(r'^\[\s*(\w+)\s*\]\s*') - DIGIT_PATTERN = re.compile(r'^\d+$') - - value_converters = { - 'ext' : 'ext_convert', - 'cfg' : 'cfg_convert', - } - - # We might want to use a different one, e.g. importlib - importer = __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, six.string_types): # str for py3k - 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 hasattr(c, '__call__') and hasattr(types, 'ClassType') and type(c) != types.ClassType: - 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 - - -class DictConfigurator(BaseConfigurator): - """ - Configure logging using a dictionary-like object to describe the - configuration. - """ - - def configure(self): - """Do the configuration.""" - - config = self.config - if 'version' not in config: - raise ValueError("dictionary doesn't specify a version") - if config['version'] != 1: - raise ValueError("Unsupported version: %s" % config['version']) - incremental = config.pop('incremental', False) - EMPTY_DICT = {} - logging._acquireLock() - try: - if incremental: - handlers = config.get('handlers', EMPTY_DICT) - # incremental handler config only if handler name - # ties in to logging._handlers (Python 2.7) - if sys.version_info[:2] == (2, 7): - for name in handlers: - if name not in logging._handlers: - raise ValueError('No handler found with ' - 'name %r' % name) - else: - try: - handler = logging._handlers[name] - handler_config = handlers[name] - level = handler_config.get('level', None) - if level: - handler.setLevel(_checkLevel(level)) - except StandardError as e: - raise ValueError('Unable to configure handler ' - '%r: %s' % (name, e)) - loggers = config.get('loggers', EMPTY_DICT) - for name in loggers: - try: - self.configure_logger(name, loggers[name], True) - except StandardError as e: - raise ValueError('Unable to configure logger ' - '%r: %s' % (name, e)) - root = config.get('root', None) - if root: - try: - self.configure_root(root, True) - except StandardError as e: - raise ValueError('Unable to configure root ' - 'logger: %s' % e) - else: - disable_existing = config.pop('disable_existing_loggers', True) - - logging._handlers.clear() - del logging._handlerList[:] - - # Do formatters first - they don't refer to anything else - formatters = config.get('formatters', EMPTY_DICT) - for name in formatters: - try: - formatters[name] = self.configure_formatter( - formatters[name]) - except StandardError as e: - raise ValueError('Unable to configure ' - 'formatter %r: %s' % (name, e)) - # Next, do filters - they don't refer to anything else, either - filters = config.get('filters', EMPTY_DICT) - for name in filters: - try: - filters[name] = self.configure_filter(filters[name]) - except StandardError as e: - raise ValueError('Unable to configure ' - 'filter %r: %s' % (name, e)) - - # Next, do handlers - they refer to formatters and filters - # As handlers can refer to other handlers, sort the keys - # to allow a deterministic order of configuration - handlers = config.get('handlers', EMPTY_DICT) - for name in sorted(handlers): - try: - handler = self.configure_handler(handlers[name]) - handler.name = name - handlers[name] = handler - except StandardError as e: - raise ValueError('Unable to configure handler ' - '%r: %s' % (name, e)) - # Next, do loggers - they refer to handlers and filters - - # we don't want to lose the existing loggers, - # since other threads may have pointers to them. - # existing is set to contain all existing loggers, - # and as we go through the new configuration we - # remove any which are configured. At the end, - # what's left in existing is the set of loggers - # which were in the previous configuration but - # which are not in the new configuration. - root = logging.root - existing = list(root.manager.loggerDict) - # The list needs to be sorted so that we can - # avoid disabling child loggers of explicitly - # named loggers. With a sorted list it is easier - # to find the child loggers. - existing.sort() - # We'll keep the list of existing loggers - # which are children of named loggers here... - child_loggers = [] - # now set up the new ones... - loggers = config.get('loggers', EMPTY_DICT) - for name in loggers: - if name in existing: - i = existing.index(name) - prefixed = name + "." - pflen = len(prefixed) - num_existing = len(existing) - i = i + 1 # look at the entry after name - while (i < num_existing) and\ - (existing[i][:pflen] == prefixed): - child_loggers.append(existing[i]) - i = i + 1 - existing.remove(name) - try: - self.configure_logger(name, loggers[name]) - except StandardError as e: - raise ValueError('Unable to configure logger ' - '%r: %s' % (name, e)) - - # Disable any old loggers. There's no point deleting - # them as other threads may continue to hold references - # and by disabling them, you stop them doing any logging. - # However, don't disable children of named loggers, as that's - # probably not what was intended by the user. - for log in existing: - logger = root.manager.loggerDict[log] - if log in child_loggers: - logger.level = logging.NOTSET - logger.handlers = [] - logger.propagate = True - elif disable_existing: - logger.disabled = True - - # And finally, do the root logger - root = config.get('root', None) - if root: - try: - self.configure_root(root) - except StandardError as e: - raise ValueError('Unable to configure root ' - 'logger: %s' % e) - finally: - logging._releaseLock() - - def configure_formatter(self, config): - """Configure a formatter from a dictionary.""" - if '()' in config: - factory = config['()'] # for use in exception handler - try: - result = self.configure_custom(config) - except TypeError as te: - if "'format'" not in str(te): - raise - # Name of parameter changed from fmt to format. - # Retry with old name. - # This is so that code can be used with older Python versions - #(e.g. by Django) - config['fmt'] = config.pop('format') - config['()'] = factory - result = self.configure_custom(config) - else: - fmt = config.get('format', None) - dfmt = config.get('datefmt', None) - result = logging.Formatter(fmt, dfmt) - return result - - def configure_filter(self, config): - """Configure a filter from a dictionary.""" - if '()' in config: - result = self.configure_custom(config) - else: - name = config.get('name', '') - result = logging.Filter(name) - return result - - def add_filters(self, filterer, filters): - """Add filters to a filterer from a list of names.""" - for f in filters: - try: - filterer.addFilter(self.config['filters'][f]) - except StandardError as e: - raise ValueError('Unable to add filter %r: %s' % (f, e)) - - def configure_handler(self, config): - """Configure a handler from a dictionary.""" - formatter = config.pop('formatter', None) - if formatter: - try: - formatter = self.config['formatters'][formatter] - except StandardError as e: - raise ValueError('Unable to set formatter ' - '%r: %s' % (formatter, e)) - level = config.pop('level', None) - filters = config.pop('filters', None) - if '()' in config: - c = config.pop('()') - if not hasattr(c, '__call__') and hasattr(types, 'ClassType') and type(c) != types.ClassType: - c = self.resolve(c) - factory = c - else: - klass = self.resolve(config.pop('class')) - # Special case for handler which refers to another handler - if issubclass(klass, logging.handlers.MemoryHandler) and\ - 'target' in config: - try: - config['target'] = self.config['handlers'][config['target']] - except StandardError as e: - raise ValueError('Unable to set target handler ' - '%r: %s' % (config['target'], e)) - elif issubclass(klass, logging.handlers.SMTPHandler) and\ - 'mailhost' in config: - config['mailhost'] = self.as_tuple(config['mailhost']) - elif issubclass(klass, logging.handlers.SysLogHandler) and\ - 'address' in config: - config['address'] = self.as_tuple(config['address']) - factory = klass - kwargs = dict((k, config[k]) for k in config if valid_ident(k)) - try: - result = factory(**kwargs) - except TypeError as te: - if "'stream'" not in str(te): - raise - # The argument name changed from strm to stream - # Retry with old name. - # This is so that code can be used with older Python versions - #(e.g. by Django) - kwargs['strm'] = kwargs.pop('stream') - result = factory(**kwargs) - if formatter: - result.setFormatter(formatter) - if level is not None: - result.setLevel(_checkLevel(level)) - if filters: - self.add_filters(result, filters) - return result - - def add_handlers(self, logger, handlers): - """Add handlers to a logger from a list of names.""" - for h in handlers: - try: - logger.addHandler(self.config['handlers'][h]) - except StandardError as e: - raise ValueError('Unable to add handler %r: %s' % (h, e)) - - def common_logger_config(self, logger, config, incremental=False): - """ - Perform configuration which is common to root and non-root loggers. - """ - level = config.get('level', None) - if level is not None: - logger.setLevel(_checkLevel(level)) - if not incremental: - # Remove any existing handlers - for h in logger.handlers[:]: - logger.removeHandler(h) - handlers = config.get('handlers', None) - if handlers: - self.add_handlers(logger, handlers) - filters = config.get('filters', None) - if filters: - self.add_filters(logger, filters) - - def configure_logger(self, name, config, incremental=False): - """Configure a non-root logger from a dictionary.""" - logger = logging.getLogger(name) - self.common_logger_config(logger, config, incremental) - propagate = config.get('propagate', None) - if propagate is not None: - logger.propagate = propagate - - def configure_root(self, config, incremental=False): - """Configure a root logger from a dictionary.""" - root = logging.getLogger() - self.common_logger_config(root, config, incremental) - -dictConfigClass = DictConfigurator - - -def dictConfig(config): - """Configure logging using a dictionary.""" - dictConfigClass(config).configure() diff --git a/pipenv/patched/notpip/models/__init__.py b/pipenv/patched/notpip/models/__init__.py deleted file mode 100644 index 9e9d8ff7..00000000 --- a/pipenv/patched/notpip/models/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from pip9.models.index import Index, PyPI - - -__all__ = ["Index", "PyPI"] diff --git a/pipenv/patched/notpip/operations/check.py b/pipenv/patched/notpip/operations/check.py deleted file mode 100644 index 2cf67aae..00000000 --- a/pipenv/patched/notpip/operations/check.py +++ /dev/null @@ -1,49 +0,0 @@ - - -def check_requirements(installed_dists): - missing_reqs_dict = {} - incompatible_reqs_dict = {} - - for dist in installed_dists: - key = '%s==%s' % (dist.project_name, dist.version) - - missing_reqs = list(get_missing_reqs(dist, installed_dists)) - if missing_reqs: - missing_reqs_dict[key] = missing_reqs - - incompatible_reqs = list(get_incompatible_reqs( - dist, installed_dists)) - if incompatible_reqs: - incompatible_reqs_dict[key] = incompatible_reqs - - return (missing_reqs_dict, incompatible_reqs_dict) - - -def get_missing_reqs(dist, installed_dists): - """Return all of the requirements of `dist` that aren't present in - `installed_dists`. - - """ - installed_names = set(d.project_name.lower() for d in installed_dists) - missing_requirements = set() - - for requirement in dist.requires(): - if requirement.project_name.lower() not in installed_names: - missing_requirements.add(requirement) - yield requirement - - -def get_incompatible_reqs(dist, installed_dists): - """Return all of the requirements of `dist` that are present in - `installed_dists`, but have incompatible versions. - - """ - installed_dists_by_name = {} - for installed_dist in installed_dists: - installed_dists_by_name[installed_dist.project_name] = installed_dist - - for requirement in dist.requires(): - present_dist = installed_dists_by_name.get(requirement.project_name) - - if present_dist and present_dist not in requirement: - yield (requirement, present_dist) diff --git a/pipenv/patched/notpip/operations/freeze.py b/pipenv/patched/notpip/operations/freeze.py deleted file mode 100644 index 5e9c6ea9..00000000 --- a/pipenv/patched/notpip/operations/freeze.py +++ /dev/null @@ -1,132 +0,0 @@ -from __future__ import absolute_import - -import logging -import re - -import pip9 -from pip9.req import InstallRequirement -from pip9.req.req_file import COMMENT_RE -from pip9.utils import get_installed_distributions -from pip9._vendor import pkg_resources -from pip9._vendor.packaging.utils import canonicalize_name -from pip9._vendor.pkg_resources import RequirementParseError - - -logger = logging.getLogger(__name__) - - -def freeze( - requirement=None, - find_links=None, local_only=None, user_only=None, skip_regex=None, - default_vcs=None, - isolated=False, - wheel_cache=None, - skip=()): - find_links = find_links or [] - skip_match = None - - if skip_regex: - skip_match = re.compile(skip_regex).search - - dependency_links = [] - - for dist in pkg_resources.working_set: - if dist.has_metadata('dependency_links.txt'): - dependency_links.extend( - dist.get_metadata_lines('dependency_links.txt') - ) - for link in find_links: - if '#egg=' in link: - dependency_links.append(link) - for link in find_links: - yield '-f %s' % link - installations = {} - for dist in get_installed_distributions(local_only=local_only, - skip=(), - user_only=user_only): - try: - req = pip9.FrozenRequirement.from_dist( - dist, - dependency_links - ) - except RequirementParseError: - logger.warning( - "Could not parse requirement: %s", - dist.project_name - ) - 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() - 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 = InstallRequirement.from_editable( - line, - default_vcs=default_vcs, - isolated=isolated, - wheel_cache=wheel_cache, - ) - else: - line_req = InstallRequirement.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: - logger.warning( - "Requirement file [%s] contains %s, but that " - "package is not installed", - req_file_path, COMMENT_RE.sub('', line).strip(), - ) - else: - yield str(installations[line_req.name]).rstrip() - del installations[line_req.name] - - 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() diff --git a/pipenv/patched/notpip/req/__init__.py b/pipenv/patched/notpip/req/__init__.py deleted file mode 100644 index 00185a43..00000000 --- a/pipenv/patched/notpip/req/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -from __future__ import absolute_import - -from .req_install import InstallRequirement -from .req_set import RequirementSet, Requirements -from .req_file import parse_requirements - -__all__ = [ - "RequirementSet", "Requirements", "InstallRequirement", - "parse_requirements", -] diff --git a/pipenv/patched/notpip/req/req_set.py b/pipenv/patched/notpip/req/req_set.py deleted file mode 100644 index 75766bba..00000000 --- a/pipenv/patched/notpip/req/req_set.py +++ /dev/null @@ -1,838 +0,0 @@ -from __future__ import absolute_import - -from collections import defaultdict -from itertools import chain -import logging -import os - -from pip9._vendor import pkg_resources -from pip9._vendor import requests - -from pip9.compat import expanduser -from pip9.download import (is_file_url, is_dir_url, is_vcs_url, url_to_path, - unpack_url) -from pip9.exceptions import (InstallationError, BestVersionAlreadyInstalled, - DistributionNotFound, PreviousBuildDirError, - HashError, HashErrors, HashUnpinned, - DirectoryUrlHashUnsupported, VcsHashUnsupported, - UnsupportedPythonVersion) -from notpip.req.req_install import InstallRequirement -from pip9.utils import ( - display_path, dist_in_usersite, ensure_dir, normalize_path) -from pip9.utils.hashes import MissingHashes -from pip9.utils.logging import indent_log -from pip9.utils.packaging import check_dist_requires_python -from pip9.vcs import vcs -from pip9.wheel import Wheel - -logger = logging.getLogger(__name__) - - -class Requirements(object): - - def __init__(self): - self._keys = [] - self._dict = {} - - def keys(self): - return self._keys - - def values(self): - return [self._dict[key] for key in self._keys] - - def __contains__(self, item): - return item in self._keys - - def __setitem__(self, key, value): - if key not in self._keys: - self._keys.append(key) - self._dict[key] = value - - def __getitem__(self, key): - return self._dict[key] - - def __repr__(self): - values = ['%s: %s' % (repr(k), repr(self[k])) for k in self.keys()] - return 'Requirements({%s})' % ', '.join(values) - - -class DistAbstraction(object): - """Abstracts out the wheel vs non-wheel prepare_files 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_to_install): - self.req_to_install = req_to_install - - def dist(self, finder): - """Return a setuptools Dist object.""" - raise NotImplementedError(self.dist) - - def prep_for_dist(self): - """Ensure that we can get a Dist for this requirement.""" - raise NotImplementedError(self.dist) - - -def make_abstract_dist(req_to_install): - """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_to_install.editable: - return IsSDist(req_to_install) - elif req_to_install.link and req_to_install.link.is_wheel: - return IsWheel(req_to_install) - else: - return IsSDist(req_to_install) - - -class IsWheel(DistAbstraction): - - def dist(self, finder): - return list(pkg_resources.find_distributions( - self.req_to_install.source_dir))[0] - - def prep_for_dist(self): - # FIXME:https://github.com/pypa/pip/issues/1112 - pass - - -class IsSDist(DistAbstraction): - - def dist(self, finder): - dist = self.req_to_install.get_dist() - # FIXME: shouldn't be globally added: - if dist.has_metadata('dependency_links.txt'): - finder.add_dependency_links( - dist.get_metadata_lines('dependency_links.txt') - ) - if dist.has_metadata('requires.txt'): - dist.extra = finder.get_extras_links( - dist.get_metadata_lines('requires.txt') - ) - - return dist - - def prep_for_dist(self): - self.req_to_install.run_egg_info() - self.req_to_install.assert_source_matches_version() - - -class Installed(DistAbstraction): - - def dist(self, finder): - return self.req_to_install.satisfied_by - - def prep_for_dist(self): - pass - - -class RequirementSet(object): - - def __init__(self, build_dir, src_dir, download_dir, upgrade=False, - upgrade_strategy=None, ignore_installed=False, as_egg=False, - target_dir=None, ignore_dependencies=False, - force_reinstall=False, use_user_site=False, session=None, - pycompile=True, isolated=False, wheel_download_dir=None, - wheel_cache=None, require_hashes=False, - ignore_compatibility=True): - """Create a RequirementSet. - - :param wheel_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. - :param download_dir: Where still packed archives should be written to. - If None they are not saved, and are deleted immediately after - unpacking. - :param wheel_cache: The pip wheel cache, for passing to - InstallRequirement. - """ - if session is None: - raise TypeError( - "RequirementSet() missing 1 required keyword argument: " - "'session'" - ) - - self.build_dir = build_dir - self.src_dir = src_dir - # XXX: 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.download_dir = download_dir - self.upgrade = upgrade - self.upgrade_strategy = upgrade_strategy - self.ignore_installed = ignore_installed - self.force_reinstall = force_reinstall - self.requirements = Requirements() - # Mapping of alias: real_name - self.requirement_aliases = {} - self.unnamed_requirements = [] - self.ignore_dependencies = ignore_dependencies - self.ignore_compatibility = ignore_compatibility - self.successfully_downloaded = [] - self.successfully_installed = [] - self.reqs_to_cleanup = [] - self.as_egg = as_egg - self.use_user_site = use_user_site - self.target_dir = target_dir # set from --target option - self.session = session - self.pycompile = pycompile - self.isolated = isolated - if wheel_download_dir: - wheel_download_dir = normalize_path(wheel_download_dir) - self.wheel_download_dir = wheel_download_dir - self._wheel_cache = wheel_cache - self.require_hashes = require_hashes - # Maps from install_req -> dependencies_of_install_req - self._dependencies = defaultdict(list) - - 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, parent_req_name=None, - extras_requested=None): - """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 - environement 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 not install_req.match_markers(extras_requested): - logger.warning("Ignoring %s: markers '%s' don't match your " - "environment", install_req.name, - install_req.markers) - return [] - - # This check has to come after we filter requirements with the - # environment markers. - if install_req.link and install_req.link.is_wheel: - wheel = Wheel(install_req.link.filename) - if not wheel.supported() and not self.ignore_compatibility: - raise InstallationError( - "%s is not a supported wheel on this platform." % - wheel.filename - ) - - install_req.as_egg = self.as_egg - install_req.use_user_site = self.use_user_site - install_req.target_dir = self.target_dir - install_req.pycompile = self.pycompile - install_req.is_direct = (parent_req_name is None) - - if not name: - # url or path requirement w/o an egg fragment - self.unnamed_requirements.append(install_req) - return [install_req] - else: - try: - existing_req = self.get_requirement(name) - except KeyError: - existing_req = None - if (parent_req_name is None and existing_req and not - existing_req.constraint and - existing_req.extras == install_req.extras and not - existing_req.req.specifier == install_req.req.specifier): - raise InstallationError( - 'Double requirement given: %s (already in %s, name=%r)' - % (install_req, existing_req, name)) - if not existing_req: - # Add requirement - self.requirements[name] = install_req - # FIXME: what about other normalizations? E.g., _ vs. -? - if name.lower() != name: - self.requirement_aliases[name.lower()] = name - result = [install_req] - else: - # Assume there's no need to scan, and that we've already - # encountered this for scanning. - result = [] - if not install_req.constraint and existing_req.constraint: - if (install_req.link and not (existing_req.link and - install_req.link.path == existing_req.link.path)): - 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).union( - set(install_req.extras)))) - logger.debug("Setting %s extras to: %s", - existing_req, existing_req.extras) - # And now we need to scan this. - result = [existing_req] - # Canonicalise to the already-added object for the backref - # check below. - install_req = existing_req - if parent_req_name: - parent_req = self.get_requirement(parent_req_name) - self._dependencies[parent_req].append(install_req) - return result - - def has_requirement(self, project_name): - 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): - return list(req for req in self.requirements.values() if not - req.constraint) or self.unnamed_requirements - - @property - def is_download(self): - 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 get_requirement(self, project_name): - 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 uninstall(self, auto_confirm=False): - for req in self.requirements.values(): - if req.constraint: - continue - req.uninstall(auto_confirm=auto_confirm) - req.commit_uninstall() - - def prepare_files(self, finder): - """ - Prepare process. Create temp directories, download and/or unpack files. - """ - # make the wheelhouse - if self.wheel_download_dir: - ensure_dir(self.wheel_download_dir) - - # If any top-level requirement has a hash specified, enter - # hash-checking mode, which requires hashes from all. - root_reqs = self.unnamed_requirements + self.requirements.values() - require_hashes = (self.require_hashes or - any(req.has_hash_options for req in root_reqs)) - if require_hashes and self.as_egg: - raise InstallationError( - '--egg is not allowed with --require-hashes mode, since it ' - 'delegates dependency resolution to setuptools and could thus ' - 'result in installation of unhashed packages.') - - # 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 = [] - hash_errors = HashErrors() - for req in chain(root_reqs, discovered_reqs): - try: - discovered_reqs.extend(self._prepare_file( - finder, - req, - require_hashes=require_hashes, - ignore_dependencies=self.ignore_dependencies)) - except HashError as exc: - exc.req = req - hash_errors.append(exc) - - if hash_errors: - raise hash_errors - - def _is_upgrade_allowed(self, req): - return self.upgrade and ( - self.upgrade_strategy == "eager" or ( - self.upgrade_strategy == "only-if-needed" and req.is_direct - ) - ) - - def _check_skip_installed(self, req_to_install, finder): - """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. - """ - # Check whether to upgrade/reinstall this req or not. - req_to_install.check_if_exists() - if req_to_install.satisfied_by: - upgrade_allowed = self._is_upgrade_allowed(req_to_install) - - # Is the best version is installed. - best_installed = False - - if upgrade_allowed: - # For link based requirements we have to pull the - # tree down and inspect to assess the version #, so - # its handled way down. - if not (self.force_reinstall or req_to_install.link): - try: - finder.find_requirement( - req_to_install, upgrade_allowed) - except BestVersionAlreadyInstalled: - best_installed = True - 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 - - if not best_installed: - # don't uninstall conflict if user install and - # conflict is not user install - if not (self.use_user_site and not - dist_in_usersite(req_to_install.satisfied_by)): - req_to_install.conflicts_with = \ - req_to_install.satisfied_by - req_to_install.satisfied_by = None - - # Figure out a nice message to say why we're skipping this. - if best_installed: - skip_reason = 'already up-to-date' - elif self.upgrade_strategy == "only-if-needed": - skip_reason = 'not upgraded as not directly required' - else: - skip_reason = 'already satisfied' - - return skip_reason - else: - return None - - def _prepare_file(self, - finder, - req_to_install, - require_hashes=False, - ignore_dependencies=False, - ignore_requires_python=False): - """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 ignore_requires_python: - self.ignore_compatibility = True - - if req_to_install.constraint or req_to_install.prepared: - return [] - - req_to_install.prepared = True - - # ###################### # - # # print log messages # # - # ###################### # - if req_to_install.editable: - logger.info('Obtaining %s', req_to_install) - else: - # satisfied_by is only evaluated by calling _check_skip_installed, - # so it must be None here. - assert req_to_install.satisfied_by is None - if not self.ignore_installed: - skip_reason = self._check_skip_installed( - req_to_install, finder) - - if req_to_install.satisfied_by: - assert skip_reason is not None, ( - '_check_skip_installed returned None but ' - 'req_to_install.satisfied_by is set to %r' - % (req_to_install.satisfied_by,)) - logger.info( - 'Requirement %s: %s', skip_reason, - req_to_install) - else: - if (req_to_install.link and - req_to_install.link.scheme == 'file'): - path = url_to_path(req_to_install.link.url) - logger.info('Processing %s', display_path(path)) - else: - logger.info('Collecting %s', req_to_install) - - with indent_log(): - # ################################ # - # # vcs update or unpack archive # # - # ################################ # - if req_to_install.editable: - if require_hashes: - raise InstallationError( - 'The editable requirement %s cannot be installed when ' - 'requiring hashes, because there is no single file to ' - 'hash.' % req_to_install) - req_to_install.ensure_has_source_dir(self.src_dir) - req_to_install.update_editable(not self.is_download) - abstract_dist = make_abstract_dist(req_to_install) - abstract_dist.prep_for_dist() - if self.is_download: - req_to_install.archive(self.download_dir) - req_to_install.check_if_exists() - elif req_to_install.satisfied_by: - 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_to_install) - else: - # @@ 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_to_install.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_to_install.source_dir` - if os.path.exists( - os.path.join(req_to_install.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_to_install, req_to_install.source_dir) - ) - req_to_install.populate_link( - finder, - self._is_upgrade_allowed(req_to_install), - require_hashes - ) - # We can't hit this spot and have populate_link return None. - # req_to_install.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_to_install.link - link = req_to_install.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_to_install.original_link and - not req_to_install.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_to_install.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_to_install.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_to_install.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_to_install.link, req_to_install.source_dir, - download_dir, autodelete_unpacked, - session=self.session, hashes=hashes) - except requests.HTTPError as exc: - logger.critical( - 'Could not install requirement %s because ' - 'of error %s', - req_to_install, - exc, - ) - raise InstallationError( - 'Could not install requirement %s because ' - 'of HTTP error %s for URL %s' % - (req_to_install, exc, req_to_install.link) - ) - abstract_dist = make_abstract_dist(req_to_install) - abstract_dist.prep_for_dist() - if self.is_download: - # Make a .zip of the source_dir we already created. - if req_to_install.link.scheme in vcs.all_schemes: - req_to_install.archive(self.download_dir) - # req_to_install.req is only avail after unpack for URL - # pkgs repeat check_if_exists to uninstall-on-upgrade - # (#14) - if not self.ignore_installed: - req_to_install.check_if_exists() - if req_to_install.satisfied_by: - if self.upgrade or self.ignore_installed: - # don't uninstall conflict if user install and - # conflict is not user install - if not (self.use_user_site and not - dist_in_usersite( - req_to_install.satisfied_by)): - req_to_install.conflicts_with = \ - req_to_install.satisfied_by - req_to_install.satisfied_by = None - else: - logger.info( - 'Requirement already satisfied (use ' - '--upgrade to upgrade): %s', - req_to_install, - ) - - # ###################### # - # # parse dependencies # # - # ###################### # - dist = abstract_dist.dist(finder) - more_reqs = [] - - def add_req(subreq, extras_requested): - sub_install_req = InstallRequirement( - str(subreq), - req_to_install, - isolated=self.isolated, - wheel_cache=self._wheel_cache, - ) - - more_reqs.extend(self.add_requirement( - sub_install_req, req_to_install.name, - extras_requested=extras_requested)) - - try: - check_dist_requires_python(dist) - except (UnsupportedPythonVersion, TypeError) as e: - if self.ignore_compatibility: - logger.warning(e.args[0]) - else: - req_to_install.remove_temporary_source() - raise - - # A huge hack, by Kenneth Reitz. - try: - self.requires_python = check_dist_requires_python(dist, absorb=False) - except TypeError: - self.requires_python = None - - # We add req_to_install before its dependencies, so that we - # can refer to it when adding dependencies. - if not self.has_requirement(req_to_install.name): - available_requested = sorted( - set(dist.extras) & set(req_to_install.extras) - ) - # 'unnamed' requirements will get added here - self.add_requirement(req_to_install, None, extras_requested=available_requested) - - # self.add_requirement(req_to_install) - if not 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) - - - - - - # Hack for deep-resolving extras. - for available in available_requested: - if hasattr(dist, '_DistInfoDistribution__dep_map'): - for req in dist._DistInfoDistribution__dep_map[available]: - req = InstallRequirement( - str(req), - req_to_install, - isolated=self.isolated, - wheel_cache=self._wheel_cache, - ) - - more_reqs.append(req) - - # cleanup tmp src - self.reqs_to_cleanup.append(req_to_install) - - 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. - self.successfully_downloaded.append(req_to_install) - - return more_reqs - - def cleanup_files(self): - """Clean up files, remove builds.""" - logger.debug('Cleaning up...') - with indent_log(): - for req in self.reqs_to_cleanup: - req.remove_temporary_source() - - def _to_install(self): - """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() - - 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._dependencies[req]: - schedule(dep) - order.append(req) - for install_req in self.requirements.values(): - schedule(install_req) - return order - - def install(self, install_options, global_options=(), *args, **kwargs): - """ - Install everything in this set (after having downloaded and unpacked - the packages) - """ - to_install = self._to_install() - - 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(): - requirement.uninstall(auto_confirm=True) - try: - requirement.install( - install_options, - global_options, - *args, - **kwargs - ) - except: - # if install did not succeed, rollback previous uninstall - if (requirement.conflicts_with and not - requirement.install_succeeded): - requirement.rollback_uninstall() - raise - else: - if (requirement.conflicts_with and - requirement.install_succeeded): - requirement.commit_uninstall() - requirement.remove_temporary_source() - - self.successfully_installed = to_install diff --git a/pipenv/patched/notpip/req/req_uninstall.py b/pipenv/patched/notpip/req/req_uninstall.py deleted file mode 100644 index 34aa796f..00000000 --- a/pipenv/patched/notpip/req/req_uninstall.py +++ /dev/null @@ -1,195 +0,0 @@ -from __future__ import absolute_import - -import logging -import os -import tempfile - -from pip9.compat import uses_pycache, WINDOWS, cache_from_source -from pip9.exceptions import UninstallationError -from pip9.utils import rmtree, ask, is_local, renames, normalize_path -from pip9.utils.logging import indent_log - - -logger = logging.getLogger(__name__) - - -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.save_dir = None - self._moved_paths = [] - - 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 compact(self, 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.""" - short_paths = set() - for path in sorted(paths, key=len): - if not any([ - (path.startswith(shortpath) and - path[len(shortpath.rstrip(os.path.sep))] == os.path.sep) - for shortpath in short_paths]): - short_paths.add(path) - return short_paths - - def _stash(self, path): - return os.path.join( - self.save_dir, os.path.splitdrive(path)[1].lstrip(os.path.sep)) - - def remove(self, auto_confirm=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 - logger.info( - 'Uninstalling %s-%s:', - self.dist.project_name, self.dist.version - ) - - with indent_log(): - paths = sorted(self.compact(self.paths)) - - if auto_confirm: - response = 'y' - else: - for path in paths: - logger.info(path) - response = ask('Proceed (y/n)? ', ('y', 'n')) - if self._refuse: - logger.info('Not removing or modifying (outside of prefix):') - for path in self.compact(self._refuse): - logger.info(path) - if response == 'y': - self.save_dir = tempfile.mkdtemp(suffix='-uninstall', - prefix='pip-') - for path in paths: - new_path = self._stash(path) - logger.debug('Removing file or directory %s', path) - self._moved_paths.append(path) - renames(path, new_path) - for pth in self.pth.values(): - pth.remove() - logger.info( - 'Successfully uninstalled %s-%s', - self.dist.project_name, self.dist.version - ) - - def rollback(self): - """Rollback the changes previously made by remove().""" - if self.save_dir is None: - 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) - for path in self._moved_paths: - tmp_path = self._stash(path) - logger.debug('Replacing %s', path) - renames(tmp_path, path) - for pth in self.pth.values(): - pth.rollback() - - def commit(self): - """Remove temporary save dir: rollback will no longer be possible.""" - if self.save_dir is not None: - rmtree(self.save_dir) - self.save_dir = None - self._moved_paths = [] - - -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' - 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/pipenv/patched/notpip/utils/build.py b/pipenv/patched/notpip/utils/build.py deleted file mode 100644 index 8b11215f..00000000 --- a/pipenv/patched/notpip/utils/build.py +++ /dev/null @@ -1,42 +0,0 @@ -from __future__ import absolute_import - -import os.path -import tempfile - -from pip9.utils import rmtree - - -class BuildDirectory(object): - - def __init__(self, name=None, delete=None): - # If we were not given an explicit directory, and we were not given an - # explicit delete option, then we'll default to deleting. - if name is None and delete is None: - delete = True - - if name is None: - # 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. - name = os.path.realpath(tempfile.mkdtemp(prefix="pip-build-")) - # If we were not given an explicit directory, and we were not given - # an explicit delete option, then we'll default to deleting. - if delete is None: - delete = True - - self.name = name - self.delete = delete - - def __repr__(self): - return "<{} {!r}>".format(self.__class__.__name__, self.name) - - def __enter__(self): - return self.name - - def __exit__(self, exc, value, tb): - self.cleanup() - - def cleanup(self): - if self.delete: - rmtree(self.name) diff --git a/pipenv/patched/piptools/cache.py b/pipenv/patched/piptools/cache.py index 7595b964..afdecd23 100644 --- a/pipenv/patched/piptools/cache.py +++ b/pipenv/patched/piptools/cache.py @@ -6,7 +6,7 @@ import json import os import sys -from pip._vendor.packaging.requirements import Requirement +from notpip._vendor.packaging.requirements import Requirement from .exceptions import PipToolsError from .locations import CACHE_DIR diff --git a/pipenv/patched/piptools/locations.py b/pipenv/patched/piptools/locations.py index 0c43cb8c..4458f3cb 100644 --- a/pipenv/patched/piptools/locations.py +++ b/pipenv/patched/piptools/locations.py @@ -6,7 +6,7 @@ from .click import secho # from ._compat import user_cache_dir from pipenv.environments import PIPENV_CACHE_DIR -# The user_cache_dir helper comes straight from pip itself +# The user_cache_dir helper comes straight from notpip itself # CACHE_DIR = user_cache_dir(os.path.join('pip-tools')) CACHE_DIR = PIPENV_CACHE_DIR diff --git a/pipenv/patched/piptools/repositories/pypi.py b/pipenv/patched/piptools/repositories/pypi.py index 1c808f36..b9babc09 100644 --- a/pipenv/patched/piptools/repositories/pypi.py +++ b/pipenv/patched/piptools/repositories/pypi.py @@ -20,8 +20,8 @@ from .._compat import ( SafeFileCache, ) -from pip9._vendor.packaging.requirements import InvalidRequirement -from pip9._vendor.pyparsing import ParseException +from notpip._vendor.packaging.requirements import InvalidRequirement +from notpip._vendor.pyparsing import ParseException from ..cache import CACHE_DIR from pipenv.environments import PIPENV_CACHE_DIR @@ -32,15 +32,15 @@ from .base import BaseRepository try: - from pip._internal.operations.prepare import RequirementPreparer - from pip._internal.resolve import Resolver as PipResolver + from notpip._internal.operations.prepare import RequirementPreparer + from notpip._internal.resolve import Resolver as PipResolver except ImportError: pass try: - from pip._internal.cache import WheelCache + from notpip._internal.cache import WheelCache except ImportError: - from pip.wheel import WheelCache + from notpip.wheel import WheelCache class HashCache(SafeFileCache): diff --git a/pipenv/patched/piptools/resolver.py b/pipenv/patched/piptools/resolver.py index 6380e8f6..af82b0cc 100644 --- a/pipenv/patched/piptools/resolver.py +++ b/pipenv/patched/piptools/resolver.py @@ -302,7 +302,7 @@ class Resolver(object): dependency_strings = self.dependency_cache[ireq] log.debug(' {:25} requires {}'.format(format_requirement(ireq), ', '.join(sorted(dependency_strings, key=lambda s: s.lower())) or '-')) - from pip9._vendor.packaging.markers import InvalidMarker + from notpip._vendor.packaging.markers import InvalidMarker for dependency_string in dependency_strings: try: _dependency_string = dependency_string diff --git a/pipenv/patched/safety/cli.py b/pipenv/patched/safety/cli.py index 37ae3acb..d2140193 100644 --- a/pipenv/patched/safety/cli.py +++ b/pipenv/patched/safety/cli.py @@ -12,10 +12,10 @@ from safety.errors import DatabaseFetchError, DatabaseFileNotFoundError, Invalid try: # pip 9 - from pip import get_installed_distributions + from notpip import get_installed_distributions except ImportError: # pip 10 - from pip._internal.utils.misc import get_installed_distributions + from notpip._internal.utils.misc import get_installed_distributions @click.group() diff --git a/pipenv/vendor/pipdeptree.py b/pipenv/vendor/pipdeptree.py index f6042db4..6020a422 100644 --- a/pipenv/vendor/pipdeptree.py +++ b/pipenv/vendor/pipdeptree.py @@ -14,10 +14,10 @@ except ImportError: from ordereddict import OrderedDict try: - from pip9._internal import get_installed_distributions - from pip9._internal.operations.freeze import FrozenRequirement + from notpip._internal import get_installed_distributions + from notpip._internal.operations.freeze import FrozenRequirement except ImportError: - from pip9 import get_installed_distributions, FrozenRequirement + from notpip import get_installed_distributions, FrozenRequirement import pkg_resources # inline: diff --git a/pipenv/vendor/requirements/fragment.py b/pipenv/vendor/requirements/fragment.py index 6228cf0d..028e1871 100644 --- a/pipenv/vendor/requirements/fragment.py +++ b/pipenv/vendor/requirements/fragment.py @@ -1,6 +1,6 @@ import re -# Copied from pip9 +# Copied from notpip # https://github.com/pypa/pip/blob/281eb61b09d87765d7c2b92f6982b3fe76ccb0af/pip/index.py#L947 HASH_ALGORITHMS = set(['sha1', 'sha224', 'sha384', 'sha256', 'sha512', 'md5'])