mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 08:47:57 +00:00
Fix pip installation issues.
This commit is to fix issue #325. There were three issues with the PIP installations. 1) If multiple instances of the same platform were found, pip could attempt to install the same dependency multiple times at once by being run simultaneously in different processes. This would cause pip failures due to race conditions. This has been fixed by using a thread lock to allow only one instance of PIP to run at a time. 2) PIP would not check the target if the dependency was already met. This would lead to PIP attempting to reinstall every dependency on every boot. This would eventually fail because the package was already installed, but it significantly increased boot time, especially on Raspberry Pis. 3) PIP would not upgrade packages that were already installed. Usually, when a version is specified to PIP, it will install the specified version if it is not already installed, even without the \-\-upgrade flag. This behavior did not work when using the \-\-target flag. When using the target flag, a new install is always attempted, but nothing will be overwritten unless the \-\-upgrade flag is also given. This caused new packages to not be installed when their dependencies were increased. This is fixed by defaulting towards using the \-\-upgrade flag.
This commit is contained in:
parent
97e19908be
commit
34c4bb585a
@ -1,19 +1,54 @@
|
||||
"""Helpers to install PyPi packages."""
|
||||
import os
|
||||
import logging
|
||||
import pkg_resources
|
||||
import subprocess
|
||||
import sys
|
||||
import threading
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
INSTALL_LOCK = threading.Lock()
|
||||
|
||||
|
||||
def install_package(package, upgrade=False, target=None):
|
||||
def install_package(package, upgrade=True, target=None):
|
||||
"""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
|
||||
args = [sys.executable, '-m', 'pip', 'install', '--quiet', package]
|
||||
|
||||
if upgrade:
|
||||
args.append('--upgrade')
|
||||
if target:
|
||||
args += ['--target', os.path.abspath(target)]
|
||||
target = os.path.abspath(target)
|
||||
args += ['--target', target]
|
||||
|
||||
with INSTALL_LOCK:
|
||||
if check_package_exists(package, target):
|
||||
return True
|
||||
|
||||
_LOGGER.info('Attempting install of %s', package)
|
||||
try:
|
||||
return 0 == subprocess.call(args)
|
||||
except subprocess.SubprocessError:
|
||||
return False
|
||||
|
||||
|
||||
def check_package_exists(package, target=None):
|
||||
"""Check if a package exists.
|
||||
Returns True when the requirement is met.
|
||||
Returns False when the package is not installed or doesn't meet req."""
|
||||
req = pkg_resources.Requirement.parse(package)
|
||||
|
||||
if target:
|
||||
work_set = pkg_resources.WorkingSet([target])
|
||||
search_fun = work_set.find
|
||||
|
||||
else:
|
||||
search_fun = pkg_resources.get_distribution
|
||||
|
||||
try:
|
||||
return 0 == subprocess.call(args)
|
||||
except subprocess.SubprocessError:
|
||||
result = search_fun(req)
|
||||
except (pkg_resources.DistributionNotFound, pkg_resources.VersionConflict):
|
||||
return False
|
||||
|
||||
return bool(result)
|
||||
|
Loading…
x
Reference in New Issue
Block a user