Initial release of pip-system-certs

This commit is contained in:
Andrew Leech
2018-03-21 15:09:14 +11:00
commit 4c86e44bdf
11 changed files with 271 additions and 0 deletions

53
.gitignore vendored Normal file
View File

@@ -0,0 +1,53 @@
*.py[cod]
# C extensions
*.so
# Packages
*.egg
*.egg-info
.eggs/
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
lib
lib64
man
include
.Python
MANIFEST
.venv
.idea
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
nosetests.xml
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# Editor save files.
.*.swp
# Sphinx documentation.
docs/_build
# Coverage.
htmlcov
.coverage
.tddium*

16
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,16 @@
stages:
- deploy
deploy:
tags:
- windows_python3_gitlab_runner
stage: deploy
script:
- python -m venv .venv
- .venv\Scripts\activate.ps1
- pip install -U twine setuptools
# We don't want to build wheel here as it doesn't support post-install script
- python setup.py sdist
- twine upload -u $PYPI_USER -p $PYPI_PASS dist/*
only:
- tags

24
LICENSE Normal file
View File

@@ -0,0 +1,24 @@
Copyright (c) 2017, Andrew Leech
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

1
MANIFEST.in Normal file
View File

@@ -0,0 +1 @@
include pip_system_certs.pth

18
README.rst Normal file
View File

@@ -0,0 +1,18 @@
================
pip-system-certs
================
This package patches pip at runtime to use certificates from the default system store (rather than the bundled certs ca).
This will allow pip to verify tls/ssl connections to servers who's cert is trusted by your system install.
Simply install with::
pip install pip_system_certs
and pip should trust your hosts if your host system does.
Acknowledgements
----------------
The method of patching at runtime is built from the autowrapt module: https://pypi.python.org/pypi/autowrapt

1
pip_system_certs.pth Normal file
View File

@@ -0,0 +1 @@
import os, sys; __import__('pip_system_certs.bootstrap') and sys.modules['pip_system_certs.bootstrap'].bootstrap()

View File

View File

@@ -0,0 +1,69 @@
import sys
import site
_registered = False
def _register_bootstrap_functions():
# This should in practice only ever be called once, but protect
# outselves just in case it is somehow called a second time.
global _registered
if _registered:
return
_registered = True
# Now discover and register post import hook
#
# It should be safe to import wrapt at this point as this code
# ill be executed after all module search path has been setup.
if sys.platform == 'win32':
# This will register the patches
from . import wrapt_pip
def _execsitecustomize_wrapper(wrapped):
def _execsitecustomize(*args, **kwargs):
try:
return wrapped(*args, **kwargs)
finally:
# Check whether 'usercustomize' support is actually disabled.
# In that case we do our work after 'sitecustomize' is loaded.
if not site.ENABLE_USER_SITE:
_register_bootstrap_functions()
return _execsitecustomize
def _execusercustomize_wrapper(wrapped):
def _execusercustomize(*args, **kwargs):
try:
return wrapped(*args, **kwargs)
finally:
_register_bootstrap_functions()
return _execusercustomize
def bootstrap():
# We want to do our real work as the very last thing in the 'site'
# module when it is being imported so that the module search path is
# initialised properly. What is the last thing executed depends on
# whether 'usercustomize' module support is enabled. Such support
# will not be enabled in Python virtual enviromments. We therefore
# wrap the functions for the loading of both the 'sitecustomize' and
# 'usercustomize' modules but detect when 'usercustomize' support is
# disabled and in that case do what we need to after 'sitecustomize'
# is loaded.
#
# In wrapping these functions though, we can't actually use wrapt
# to do so. This is because depending on how wrapt was installed it
# may technically be dependent on '.pth' evaluation for Python to
# know where to import it from. The addition of the directory which
# contains wrapt may not yet have been done. We thus use a simple
# function wrapper instead.
site.execsitecustomize = _execsitecustomize_wrapper(site.execsitecustomize)
site.execusercustomize = _execusercustomize_wrapper(site.execusercustomize)

View File

@@ -0,0 +1,34 @@
from __future__ import absolute_import
import wrapt
# pip master has most commands moved into _internal folder
@wrapt.when_imported('pip._internal.download')
def apply_patches(download):
override_ssl_handler(download)
@wrapt.when_imported('pip.download')
def apply_patches(download):
override_ssl_handler(download)
def override_ssl_handler(download):
class SslContextHttpAdapter(download.HTTPAdapter):
"""Transport adapter that allows us to use system-provided SSL
certificates."""
def init_poolmanager(self, *args, **kwargs):
import ssl
ssl_context = ssl.create_default_context()
ssl_context.load_default_certs()
kwargs['ssl_context'] = ssl_context
return super().init_poolmanager(*args, **kwargs)
def wrapper(wrapped, instance, args, kwargs):
retries = kwargs.get("retries", 0)
wrapped(*args, **kwargs)
secure_adapter = SslContextHttpAdapter(max_retries=retries)
instance.mount("https://", secure_adapter)
wrapt.wrap_function_wrapper(download.PipSession, '__init__', wrapper)

2
setup.cfg Normal file
View File

@@ -0,0 +1,2 @@
[bdist_wheel]
universal = 1

53
setup.py Normal file
View File

@@ -0,0 +1,53 @@
import os
import sys
import distutils.sysconfig
from setuptools import setup
from setuptools.command.install import install
from setuptools.command.develop import develop
with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as readme:
long_description = readme.read()
def check_pth(self):
pthfile = os.path.join(self.install_dir, "pip_system_certs.pth")
if not os.path.exists(pthfile):
sys.stderr.write("WARNING: pip_system_certs.pth not installed correctly, will try to correct.\n")
sys.stderr.write("Please report an issue at https://gitlab.com/alelec/pip-system-certs with your\n")
sys.stderr.write("python and pip versions included in the description\n")
import shutil
shutil.copyfile("pip_system_certs.pth", pthfile)
class InstallCheck(install):
def run(self):
install.run(self)
check_pth(self)
class DevelopCheck(develop):
def run(self):
develop.run(self)
check_pth(self)
site_packages = distutils.sysconfig.get_python_lib()
setup(
name='pip_system_certs',
use_scm_version=True,
setup_requires=['setuptools_scm'],
description='Live patches pip to use system certs by default',
long_description=long_description,
author='Andrew Leech',
author_email='andrew@alelec.net',
license='BSD',
url='https://gitlab.com/alelec/pip-system-certs',
packages=['pip_system_certs'],
data_files=[(site_packages, ['pip_system_certs.pth'])],
install_requires=['wrapt>=1.10.4', 'setuptools_scm'],
zip_safe=False,
cmdclass={"install": InstallCheck, "develop": DevelopCheck},
python_requires='>=2.7.9, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
)