diff options
Diffstat (limited to 'dev/deps.py')
-rw-r--r-- | dev/deps.py | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/dev/deps.py b/dev/deps.py new file mode 100644 index 0000000..36370f0 --- /dev/null +++ b/dev/deps.py @@ -0,0 +1,212 @@ +# coding: utf-8 +from __future__ import unicode_literals, division, absolute_import, print_function + +import imp +import os +import subprocess +import sys +import warnings +import shutil +import tempfile +import platform +import site + + +OTHER_PACKAGES = [ + 'https://github.com/wbond/oscrypto.git', + 'https://github.com/wbond/certbuilder.git', + 'https://github.com/wbond/certvalidator.git', + 'https://github.com/wbond/crlbuilder.git', + 'https://github.com/wbond/csrbuilder.git', + 'https://github.com/wbond/ocspbuilder.git', +] + + +def run(): + """ + Ensures a recent version of pip is installed, then uses that to install + required development dependencies. Uses git to checkout other modularcrypto + repos for more accurate coverage data. + """ + + package_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) + build_root = os.path.abspath(os.path.join(package_root, '..')) + try: + tmpdir = None + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + + major_minor = '%s.%s' % sys.version_info[0:2] + tmpdir = tempfile.mkdtemp() + _pip = _bootstrap_pip(tmpdir) + + print("Using pip to install dependencies") + _pip(['install', '-q', '--upgrade', '-r', os.path.join(package_root, 'requires', 'ci')]) + + if OTHER_PACKAGES: + print("Checking out modularcrypto packages for coverage") + for pkg_url in OTHER_PACKAGES: + pkg_name = os.path.basename(pkg_url).replace('.git', '') + pkg_dir = os.path.join(build_root, pkg_name) + if os.path.exists(pkg_dir): + print("%s is already present" % pkg_name) + continue + print("Cloning %s" % pkg_url) + _execute(['git', 'clone', pkg_url], build_root) + print() + + finally: + if tmpdir: + shutil.rmtree(tmpdir, ignore_errors=True) + + return True + +def _download(url, dest): + """ + Downloads a URL to a directory + + :param url: + The URL to download + + :param dest: + The path to the directory to save the file in + + :return: + The filesystem path to the saved file + """ + + filename = os.path.basename(url) + dest_path = os.path.join(dest, filename) + + if sys.platform == 'win32': + system_root = os.environ.get('SystemRoot') + powershell_exe = os.path.join('system32\\WindowsPowerShell\\v1.0\\powershell.exe') + code = "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12;" + code += " (New-Object Net.WebClient).DownloadFile('%s', '%s');" % (url, dest_path) + _execute([powershell_exe, '-Command', code], dest) + + else: + _execute(['curl', '--silent', '--show-error', '-O', url], dest) + + return dest_path + + +def _execute(params, cwd): + """ + Executes a subprocess + + :param params: + A list of the executable and arguments to pass to it + + :param cwd: + The working directory to execute the command in + + :return: + A 2-element tuple of (stdout, stderr) + """ + + proc = subprocess.Popen( + params, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + cwd=cwd + ) + stdout, stderr = proc.communicate() + code = proc.wait() + if code != 0: + e = OSError('subprocess exit code was non-zero') + e.stdout = stdout + e.stderr = stderr + raise e + return (stdout, stderr) + + +def _get_pip_main(download_dir): + """ + Executes get-pip.py in the current Python interpreter + + :param download_dir: + The directory that contains get-pip.py + """ + + module_info = imp.find_module('get-pip', [download_dir]) + get_pip_module = imp.load_module('_cideps.get-pip', *module_info) + + orig_sys_exit = sys.exit + orig_sys_argv = sys.argv + sys.exit = lambda c: None + sys.argv = ['get-pip.py', '--user', '-q'] + + get_pip_module.main() + + sys.exit = orig_sys_exit + sys.argv = orig_sys_argv + + # Unload pip modules that came from the zip file + module_names = sorted(sys.modules.keys()) + end_token = os.sep + 'pip.zip' + mid_token = end_token + os.sep + 'pip' + for module_name in module_names: + try: + module_path = sys.modules[module_name].__file__ + if mid_token in module_path or module_path.endswith(end_token): + del sys.modules[module_name] + except AttributeError: + pass + + if sys.path[0].endswith('pip.zip'): + sys.path = sys.path[1:] + + if site.USER_SITE not in sys.path: + sys.path.append(site.USER_SITE) + + +def _bootstrap_pip(tmpdir): + """ + Bootstraps the current version of pip for use in the current Python + interpreter + + :param tmpdir: + A temporary directory to download get-pip.py and cacert.pem + + :return: + A function that invokes pip. Accepts one arguments, a list of parameters + to pass to pip. + """ + + try: + import pip + + print('Upgrading pip') + pip.main(['install', '-q', '--upgrade', 'pip']) + certs_path = None + + except ImportError: + print("Downloading cacert.pem from curl") + certs_path = _download('https://curl.haxx.se/ca/cacert.pem', tmpdir) + + print("Downloading get-pip.py") + if sys.version_info[0:2] == (3, 2): + path = _download('https://bootstrap.pypa.io/3.2/get-pip.py', tmpdir) + else: + path = _download('https://bootstrap.pypa.io/get-pip.py', tmpdir) + + print("Running get-pip.py") + _get_pip_main(tmpdir) + + import pip + + def _pip(args): + base_args = ['--disable-pip-version-check'] + if certs_path: + base_args += ['--cert', certs_path] + if sys.platform == 'darwin' and sys.version_info[0:2] in [(2, 6), (2, 7)]: + new_args = [] + for arg in args: + new_args.append(arg) + if arg == 'install': + new_args.append('--user') + args = new_args + pip.main(base_args + args) + + return _pip |