2015-07-07 07:00:21 +00:00
|
|
|
"""Helpers to install PyPi packages."""
|
2015-09-05 08:50:35 +00:00
|
|
|
import logging
|
2015-09-17 06:12:38 +00:00
|
|
|
import os
|
2015-09-05 08:50:35 +00:00
|
|
|
import pkg_resources
|
2015-07-07 07:00:21 +00:00
|
|
|
import subprocess
|
2015-07-16 01:37:24 +00:00
|
|
|
import sys
|
2015-09-05 08:50:35 +00:00
|
|
|
import threading
|
2015-09-09 02:49:27 +00:00
|
|
|
from urllib.parse import urlparse
|
2015-07-07 07:00:21 +00:00
|
|
|
|
2015-09-05 08:50:35 +00:00
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
INSTALL_LOCK = threading.Lock()
|
2015-07-07 07:00:21 +00:00
|
|
|
|
2015-09-05 08:50:35 +00:00
|
|
|
|
|
|
|
def install_package(package, upgrade=True, target=None):
|
2015-07-07 07:00:21 +00:00
|
|
|
"""Install a package on PyPi. Accepts pip compatible package strings.
|
|
|
|
Return boolean if install successfull."""
|
|
|
|
# Not using 'import pip; pip.main([])' because it breaks the logger
|
2015-09-05 08:50:35 +00:00
|
|
|
with INSTALL_LOCK:
|
|
|
|
if check_package_exists(package, target):
|
|
|
|
return True
|
|
|
|
|
|
|
|
_LOGGER.info('Attempting install of %s', package)
|
2015-09-17 06:12:38 +00:00
|
|
|
args = [sys.executable, '-m', 'pip', 'install', '--quiet', package]
|
|
|
|
if upgrade:
|
|
|
|
args.append('--upgrade')
|
|
|
|
if target:
|
|
|
|
args += ['--target', os.path.abspath(target)]
|
|
|
|
|
2015-09-05 08:50:35 +00:00
|
|
|
try:
|
|
|
|
return 0 == subprocess.call(args)
|
|
|
|
except subprocess.SubprocessError:
|
2015-11-15 10:05:13 +00:00
|
|
|
_LOGGER.exception('Unable to install pacakge %s', package)
|
2015-09-05 08:50:35 +00:00
|
|
|
return False
|
|
|
|
|
|
|
|
|
2015-11-09 06:55:22 +00:00
|
|
|
def check_package_exists(package, lib_dir):
|
|
|
|
"""Check if a package is installed globally or in lib_dir.
|
2015-09-05 08:50:35 +00:00
|
|
|
Returns True when the requirement is met.
|
|
|
|
Returns False when the package is not installed or doesn't meet req."""
|
2015-09-09 02:49:27 +00:00
|
|
|
try:
|
|
|
|
req = pkg_resources.Requirement.parse(package)
|
|
|
|
except ValueError:
|
|
|
|
# This is a zip file
|
|
|
|
req = pkg_resources.Requirement.parse(urlparse(package).fragment)
|
2015-09-05 08:50:35 +00:00
|
|
|
|
2015-11-09 06:55:22 +00:00
|
|
|
# Check packages from lib dir
|
|
|
|
if lib_dir is not None:
|
|
|
|
if any(dist in req for dist in
|
|
|
|
pkg_resources.find_distributions(lib_dir)):
|
|
|
|
return True
|
|
|
|
|
|
|
|
# Check packages from global + virtual environment
|
|
|
|
return any(dist in req for dist in pkg_resources.working_set)
|