From 57f9da0bd7727c46eab866941fee46a3eaf8c8ea Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Fri, 21 Sep 2018 17:31:39 +0200 Subject: [PATCH] Do not load pip state if there is no 3rd party dependencies Safe import 3rd party dependency --- salt/modules/pip.py | 93 ++++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 43 deletions(-) diff --git a/salt/modules/pip.py b/salt/modules/pip.py index f7c101f6e4..742e0dd48a 100644 --- a/salt/modules/pip.py +++ b/salt/modules/pip.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- r""" Install Python packages with pip to either the system or a virtualenv @@ -77,9 +76,7 @@ of the 2015.5 branch: The issue is described here: https://github.com/saltstack/salt/issues/46163 """ -from __future__ import absolute_import, print_function, unicode_literals -# Import python libs import logging import os import re @@ -89,7 +86,6 @@ import tempfile import pkg_resources # pylint: disable=3rd-party-module-not-gated -# Import Salt libs import salt.utils.data import salt.utils.files import salt.utils.json @@ -101,6 +97,12 @@ import salt.utils.versions from salt.exceptions import CommandExecutionError, CommandNotFoundError from salt.ext import six +try: + import pkg_resources +except ImportError: + pkg_resources = None + + # This needs to be named logger so we don't shadow it in pip.install logger = logging.getLogger(__name__) # pylint: disable=C0103 @@ -118,7 +120,12 @@ def __virtual__(): entire filesystem. If it's not installed in a conventional location, the user is required to provide the location of pip each time it is used. """ - return "pip" + if pkg_resources is None: + ret = False, 'Package dependency "pkg_resource" is missing' + else: + ret = "pip" + + return ret def _pip_bin_env(cwd, bin_env): @@ -140,7 +147,7 @@ def _clear_context(bin_env=None): """ contextkey = "pip.version" if bin_env is not None: - contextkey = "{0}.{1}".format(contextkey, bin_env) + contextkey = "{}.{}".format(contextkey, bin_env) __context__.pop(contextkey, None) @@ -196,7 +203,7 @@ def _get_pip_bin(bin_env): bin_path, ) raise CommandNotFoundError( - "Could not find a pip binary in virtualenv {0}".format(bin_env) + "Could not find a pip binary in virtualenv {}".format(bin_env) ) # bin_env is the python or pip binary @@ -209,11 +216,11 @@ def _get_pip_bin(bin_env): return [os.path.normpath(bin_env)] raise CommandExecutionError( - "Could not find a pip binary within {0}".format(bin_env) + "Could not find a pip binary within {}".format(bin_env) ) else: raise CommandNotFoundError( - "Access denied to {0}, could not find a pip binary".format(bin_env) + "Access denied to {}, could not find a pip binary".format(bin_env) ) @@ -283,7 +290,7 @@ def _resolve_requirements_chain(requirements): chain = [] - if isinstance(requirements, six.string_types): + if isinstance(requirements, str): requirements = [requirements] for req_file in requirements: @@ -300,7 +307,7 @@ def _process_requirements(requirements, cmd, cwd, saltenv, user): cleanup_requirements = [] if requirements is not None: - if isinstance(requirements, six.string_types): + if isinstance(requirements, str): requirements = [r.strip() for r in requirements.split(",")] elif not isinstance(requirements, list): raise TypeError("requirements must be a string or list") @@ -314,7 +321,7 @@ def _process_requirements(requirements, cmd, cwd, saltenv, user): if not cached_requirements: ret = { "result": False, - "comment": "pip requirements file '{0}' not found".format( + "comment": "pip requirements file '{}' not found".format( requirement ), } @@ -412,15 +419,15 @@ def _format_env_vars(env_vars): ret = {} if env_vars: if isinstance(env_vars, dict): - for key, val in six.iteritems(env_vars): - if not isinstance(key, six.string_types): + for key, val in env_vars.items(): + if not isinstance(key, str): key = str(key) # future lint: disable=blacklisted-function - if not isinstance(val, six.string_types): + if not isinstance(val, str): val = str(val) # future lint: disable=blacklisted-function ret[key] = val else: raise CommandExecutionError( - "env_vars {0} is not a dictionary".format(env_vars) + "env_vars {} is not a dictionary".format(env_vars) ) return ret @@ -762,9 +769,9 @@ def install( if log: if os.path.isdir(log): - raise IOError("'{0}' is a directory. Use --log path_to_file".format(log)) + raise OSError("'{}' is a directory. Use --log path_to_file".format(log)) elif not os.access(log, os.W_OK): - raise IOError("'{0}' is not writeable".format(log)) + raise OSError("'{}' is not writeable".format(log)) cmd.extend(["--log", log]) @@ -790,12 +797,12 @@ def install( int(timeout) except ValueError: raise ValueError( - "'{0}' is not a valid timeout, must be an integer".format(timeout) + "'{}' is not a valid timeout, must be an integer".format(timeout) ) cmd.extend(["--timeout", timeout]) if find_links: - if isinstance(find_links, six.string_types): + if isinstance(find_links, str): find_links = [l.strip() for l in find_links.split(",")] for link in find_links: @@ -803,7 +810,7 @@ def install( salt.utils.url.validate(link, VALID_PROTOS) or os.path.exists(link) ): raise CommandExecutionError( - "'{0}' is not a valid URL or path".format(link) + "'{}' is not a valid URL or path".format(link) ) cmd.extend(["--find-links", link]) @@ -815,13 +822,13 @@ def install( if index_url: if not salt.utils.url.validate(index_url, VALID_PROTOS): - raise CommandExecutionError("'{0}' is not a valid URL".format(index_url)) + raise CommandExecutionError("'{}' is not a valid URL".format(index_url)) cmd.extend(["--index-url", index_url]) if extra_index_url: if not salt.utils.url.validate(extra_index_url, VALID_PROTOS): raise CommandExecutionError( - "'{0}' is not a valid URL".format(extra_index_url) + "'{}' is not a valid URL".format(extra_index_url) ) cmd.extend(["--extra-index-url", extra_index_url]) @@ -836,13 +843,13 @@ def install( " use index_url and/or extra_index_url instead" ) - if isinstance(mirrors, six.string_types): + if isinstance(mirrors, str): mirrors = [m.strip() for m in mirrors.split(",")] cmd.append("--use-mirrors") for mirror in mirrors: if not mirror.startswith("http://"): - raise CommandExecutionError("'{0}' is not a valid URL".format(mirror)) + raise CommandExecutionError("'{}' is not a valid URL".format(mirror)) cmd.extend(["--mirrors", mirror]) if disable_version_check: @@ -883,7 +890,7 @@ def install( if exists_action.lower() not in ("s", "i", "w", "b"): raise CommandExecutionError( "The exists_action pip option only supports the values " - "s, i, w, and b. '{0}' is not valid.".format(exists_action) + "s, i, w, and b. '{}' is not valid.".format(exists_action) ) cmd.extend(["--exists-action", exists_action]) @@ -911,14 +918,14 @@ def install( cmd.extend(["--cert", cert]) if global_options: - if isinstance(global_options, six.string_types): + if isinstance(global_options, str): global_options = [go.strip() for go in global_options.split(",")] for opt in global_options: cmd.extend(["--global-option", opt]) if install_options: - if isinstance(install_options, six.string_types): + if isinstance(install_options, str): install_options = [io.strip() for io in install_options.split(",")] for opt in install_options: @@ -929,7 +936,7 @@ def install( try: pkgs = [p.strip() for p in pkgs.split(",")] except AttributeError: - pkgs = [p.strip() for p in six.text_type(pkgs).split(",")] + pkgs = [p.strip() for p in str(pkgs).split(",")] pkgs = salt.utils.data.stringify(salt.utils.data.decode_list(pkgs)) # It's possible we replaced version-range commas with semicolons so @@ -945,7 +952,7 @@ def install( if editable: egg_match = re.compile(r"(?:#|#.*?&)egg=([^&]*)") - if isinstance(editable, six.string_types): + if isinstance(editable, str): editable = [e.strip() for e in editable.split(",")] for entry in editable: @@ -964,14 +971,14 @@ def install( cmd.append("--allow-all-external") if allow_external: - if isinstance(allow_external, six.string_types): + if isinstance(allow_external, str): allow_external = [p.strip() for p in allow_external.split(",")] for pkg in allow_external: cmd.extend(["--allow-external", pkg]) if allow_unverified: - if isinstance(allow_unverified, six.string_types): + if isinstance(allow_unverified, str): allow_unverified = [p.strip() for p in allow_unverified.split(",")] for pkg in allow_unverified: @@ -1106,8 +1113,8 @@ def uninstall( try: # TODO make this check if writeable os.path.exists(log) - except IOError: - raise IOError("'{0}' is not writeable".format(log)) + except OSError: + raise OSError("'{}' is not writeable".format(log)) cmd.extend(["--log", log]) @@ -1133,12 +1140,12 @@ def uninstall( int(timeout) except ValueError: raise ValueError( - "'{0}' is not a valid timeout, must be an integer".format(timeout) + "'{}' is not a valid timeout, must be an integer".format(timeout) ) cmd.extend(["--timeout", timeout]) if pkgs: - if isinstance(pkgs, six.string_types): + if isinstance(pkgs, str): pkgs = [p.strip() for p in pkgs.split(",")] if requirements: for requirement in requirements: @@ -1323,7 +1330,7 @@ def version(bin_env=None, cwd=None, user=None): cwd = _pip_bin_env(cwd, bin_env) contextkey = "pip.version" if bin_env is not None: - contextkey = "{0}.{1}".format(contextkey, bin_env) + contextkey = "{}.{}".format(contextkey, bin_env) if contextkey in __context__: return __context__[contextkey] @@ -1402,7 +1409,7 @@ def list_upgrades(bin_env=None, user=None, cwd=None): if match: name, version_ = match.groups() else: - logger.error("Can't parse line '{0}'".format(line)) + logger.error("Can't parse line '{}'".format(line)) continue packages[name] = version_ @@ -1414,7 +1421,7 @@ def list_upgrades(bin_env=None, user=None, cwd=None): raise CommandExecutionError("Invalid JSON", info=result) for pkg in pkgs: - packages[pkg["name"]] = "{0} [{1}]".format( + packages[pkg["name"]] = "{} [{}]".format( pkg["latest_version"], pkg["latest_filetype"] ) @@ -1602,17 +1609,17 @@ def list_all_versions( """ cwd = _pip_bin_env(cwd, bin_env) cmd = _get_pip_bin(bin_env) - cmd.extend(["install", "{0}==versions".format(pkg)]) + cmd.extend(["install", "{}==versions".format(pkg)]) if index_url: if not salt.utils.url.validate(index_url, VALID_PROTOS): - raise CommandExecutionError("'{0}' is not a valid URL".format(index_url)) + raise CommandExecutionError("'{}' is not a valid URL".format(index_url)) cmd.extend(["--index-url", index_url]) if extra_index_url: if not salt.utils.url.validate(extra_index_url, VALID_PROTOS): raise CommandExecutionError( - "'{0}' is not a valid URL".format(extra_index_url) + "'{}' is not a valid URL".format(extra_index_url) ) cmd.extend(["--extra-index-url", extra_index_url]) @@ -1632,7 +1639,7 @@ def list_all_versions( if not include_rc: filtered.append("rc") if filtered: - excludes = re.compile(r"^((?!{0}).)*$".format("|".join(filtered))) + excludes = re.compile(r"^((?!{}).)*$".format("|".join(filtered))) else: excludes = re.compile(r"") -- 2.29.2