text: # -*- coding: utf-8 -*-
  '''
  Install Python packages with pip to either the system or a virtualenv
  '''
  
  # Import python libs
  import os
  import re
  import logging
  import shutil
  
  # Import salt libs
  import salt.utils
  from salt._compat import string_types
  from salt.exceptions import CommandExecutionError, CommandNotFoundError
  
  # It would be cool if we could use __virtual__() in this module, though, since
  # pip can be installed on a virtualenv anywhere on the filesystem, there's no
  # definite way to tell if pip is installed on not.
  
  logger = logging.getLogger(__name__)  # pylint: disable=C0103
  
  # Don't shadow built-in's.
  __func_alias__ = {
      'list_': 'list'
  }
  
  VALID_PROTOS = ['http', 'https', 'ftp', 'file']
  
  
  def _get_pip_bin(bin_env):
      '''
      Return the pip command to call, either from a virtualenv, an argument
      passed in, or from the global modules options
      '''
      if not bin_env:
          which_result = __salt__['cmd.which_bin'](['pip2', 'pip', 'pip-python'])
          if which_result is None:
              raise CommandNotFoundError('Could not find a `pip` binary')
          return which_result
  
      # try to get pip bin from env
      if os.path.isdir(bin_env):
          if salt.utils.is_windows():
              pip_bin = os.path.join(bin_env, 'Scripts', 'pip.exe')
          else:
              pip_bin = os.path.join(bin_env, 'bin', 'pip')
          if os.path.isfile(pip_bin):
              return pip_bin
          raise CommandNotFoundError('Could not find a `pip` binary')
  
      return bin_env
  
  
  def _get_cached_requirements(requirements, saltenv):
      '''Get the location of a cached requirements file; caching if necessary.'''
      cached_requirements = __salt__['cp.is_cached'](
          requirements, saltenv
      )
      if not cached_requirements:
          # It's not cached, let's cache it.
          cached_requirements = __salt__['cp.cache_file'](
              requirements, saltenv
          )
      # Check if the master version has changed.
      if __salt__['cp.hash_file'](requirements, saltenv) != \
              __salt__['cp.hash_file'](cached_requirements, saltenv):
          cached_requirements = __salt__['cp.cache_file'](
              requirements, saltenv
          )
  
      return cached_requirements
  
  
  def _get_env_activate(bin_env):
      if not bin_env:
          raise CommandNotFoundError('Could not find a `activate` binary')
  
      if os.path.isdir(bin_env):
          if salt.utils.is_windows():
              activate_bin = os.path.join(bin_env, 'Scripts', 'activate.bat')
          else:
              activate_bin = os.path.join(bin_env, 'bin', 'activate')
          if os.path.isfile(activate_bin):
              return activate_bin
      raise CommandNotFoundError('Could not find a `activate` binary')
  
  
  def install(pkgs=None,
              requirements=None,
              env=None,
              bin_env=None,
              use_wheel=False,
              log=None,
              proxy=None,
              timeout=None,
              editable=None,
              find_links=None,
              index_url=None,
              extra_index_url=None,
              no_index=False,
              mirrors=None,
              build=None,
              target=None,
              download=None,
              download_cache=None,
              source=None,
              upgrade=False,
              force_reinstall=False,
              ignore_installed=False,
              exists_action=None,
              no_deps=False,
              no_install=False,
              no_download=False,
              global_options=None,
              install_options=None,
              user=None,
              runas=None,
              no_chown=False,
              cwd=None,
              activate=False,
              pre_releases=False,
              __env__=None,
              saltenv='base'):
      '''
      Install packages with pip
  
      Install packages individually or from a pip requirements file. Install
      packages globally or to a virtualenv.
  
      pkgs
          comma separated list of packages to install
      requirements
          path to requirements
      bin_env
          path to pip bin or path to virtualenv. If doing a system install,
          and want to use a specific pip bin (pip-2.7, pip-2.6, etc..) just
          specify the pip bin you want.
          If installing into a virtualenv, just use the path to the virtualenv
          (/home/code/path/to/virtualenv/)
      env
          deprecated, use bin_env now
      use_wheel
          Prefer wheel archives (requires pip>=1.4)
      log
          Log file where a complete (maximum verbosity) record will be kept
      proxy
          Specify a proxy in the form
          user:passwd@proxy.server:port. Note that the
          user:password@ is optional and required only if you
          are behind an authenticated proxy.  If you provide
          user@proxy.server:port then you will be prompted for a
          password.
      timeout
          Set the socket timeout (default 15 seconds)
      editable
          install something editable (i.e.
          git+https://github.com/worldcompany/djangoembed.git#egg=djangoembed)
      find_links
          URL to look for packages at
      index_url
          Base URL of Python Package Index
      extra_index_url
          Extra URLs of package indexes to use in addition to ``index_url``
      no_index
          Ignore package index
      mirrors
          Specific mirror URL(s) to query (automatically adds --use-mirrors)
      build
          Unpack packages into ``build`` dir
      target
          Install packages into ``target`` dir
      download
          Download packages into ``download`` instead of installing them
      download_cache
          Cache downloaded packages in ``download_cache`` dir
      source
          Check out ``editable`` packages into ``source`` dir
      upgrade
          Upgrade all packages to the newest available version
      force_reinstall
          When upgrading, reinstall all packages even if they are already
          up-to-date.
      ignore_installed
          Ignore the installed packages (reinstalling instead)
      exists_action
          Default action when a path already exists: (s)witch, (i)gnore, (w)wipe,
          (b)ackup
      no_deps
          Ignore package dependencies
      no_install
          Download and unpack all packages, but don't actually install them
      no_download
          Don't download any packages, just install the ones
          already downloaded (completes an install run with
          --no-install)
      install_options
          Extra arguments to be supplied to the setup.py install
          command (use like --install-option="--install-
          scripts=/usr/local/bin").  Use multiple --install-
          option options to pass multiple options to setup.py
          install.  If you are using an option with a directory
          path, be sure to use absolute path.
      global_options
          Extra global options to be supplied to the setup.py call before the
          install command.
      user
          The user under which to run pip
  
      .. note::
          The ``runas`` argument is deprecated as of 0.16.2. ``user`` should be
          used instead.
  
      no_chown
          When user is given, do not attempt to copy and chown
          a requirements file
      cwd
          Current working directory to run pip from
      activate
          Activates the virtual environment, if given via bin_env,
          before running install.
      pre_releases
          Include pre-releases in the available versions
  
  
      CLI Example:
  
      .. code-block:: bash
  
          salt '*' pip.install <package name>,<package2 name>
          salt '*' pip.install requirements=/path/to/requirements.txt
          salt '*' pip.install <package name> bin_env=/path/to/virtualenv
          salt '*' pip.install <package name> bin_env=/path/to/pip_bin
  
      Complicated CLI example::
  
          salt '*' pip.install markdown,django editable=git+https://github.com/worldcompany/djangoembed.git#egg=djangoembed upgrade=True no_deps=True
  
      '''
      # Switching from using `pip_bin` and `env` to just `bin_env`
      # cause using an env and a pip bin that's not in the env could
      # be problematic.
      # Still using the `env` variable, for backwards compatibility's sake
      # but going fwd you should specify either a pip bin or an env with
      # the `bin_env` argument and we'll take care of the rest.
      if env and not bin_env:
          bin_env = env
  
      if isinstance(__env__, string_types):
          salt.utils.warn_until(
              'Boron',
              'Passing a salt environment should be done using \'saltenv\' '
              'not \'__env__\'. This functionality will be removed in Salt '
              'Boron.'
          )
          # Backwards compatibility
          saltenv = __env__
  
      if runas is not None:
          # The user is using a deprecated argument, warn!
          salt.utils.warn_until(
              'Hydrogen',
              'The \'runas\' argument to pip.install is deprecated, and will be '
              'removed in Salt {version}. Please use \'user\' instead.'
          )
  
      # "There can only be one"
      if runas is not None and user:
          raise CommandExecutionError(
              'The \'runas\' and \'user\' arguments are mutually exclusive. '
              'Please use \'user\' as \'runas\' is being deprecated.'
          )
  
      # Support deprecated 'runas' arg
      elif runas is not None and not user:
          user = str(runas)
  
      cmd = [_get_pip_bin(bin_env), 'install']
  
      if activate and bin_env:
          if not salt.utils.is_windows():
              cmd = ['.', _get_env_activate(bin_env), '&&'] + cmd
  
      cleanup_requirements = []
      if requirements is not None:
          if isinstance(requirements, string_types):
              requirements = [r.strip() for r in requirements.split(',')]
  
          for requirement in requirements:
              treq = None
              if requirement.startswith('salt://'):
                  cached_requirements = _get_cached_requirements(
                      requirement, saltenv
                  )
                  if not cached_requirements:
                      return {
                          'result': False,
                          'comment': (
                              'pip requirements file {0!r} not found'.format(
                                  requirement
                              )
                          )
                      }
                  requirement = cached_requirements
  
              if user and not no_chown:
                  # Need to make a temporary copy since the user will, most
                  # likely, not have the right permissions to read the file
                  treq = salt.utils.mkstemp()
                  shutil.copyfile(requirement, treq)
                  logger.debug(
                      'Changing ownership of requirements file {0!r} to '
                      'user {1!r}'.format(treq, user)
                  )
                  __salt__['file.chown'](treq, user, None)
                  cleanup_requirements.append(treq)
              cmd.append('--requirement={0!r}'.format(treq or requirement))
  
      if use_wheel:
          min_version = '1.4'
          cur_version = __salt__['pip.version'](bin_env)
          if not salt.utils.compare_versions(ver1=cur_version, oper='>=',
                                             ver2=min_version):
              log.error(
                  ('The --use-wheel option is only supported in pip {0} and '
                   'newer. The version of pip detected is {1}. This option '
                   'will be ignored.'.format(min_version, cur_version))
              )
          else:
              cmd.append('--use-wheel')
  
      if log:
          try:
              # TODO make this check if writeable
              os.path.exists(log)
          except IOError:
              raise IOError('{0!r} is not writeable'.format(log))
  
          cmd.append('--log={0}'.format(log))
  
      if proxy:
          cmd.append('--proxy={0!r}'.format(proxy))
  
      if timeout:
          try:
              int(timeout)
          except ValueError:
              raise ValueError(
                  '{0!r} is not a valid integer base 10.'.format(timeout)
              )
          cmd.append('--timeout={0}'.format(timeout))
  
      if find_links:
          if isinstance(find_links, string_types):
              find_links = [l.strip() for l in find_links.split(',')]
  
          for link in find_links:
              if not (salt.utils.valid_url(link, VALID_PROTOS) or os.path.exists(link)):
                  raise CommandExecutionError(
                      '{0!r} must be a valid URL or path'.format(link)
                  )
              cmd.append('--find-links={0}'.format(link))
  
      if no_index and (index_url or extra_index_url):
          raise CommandExecutionError(
              '\'no_index\' and (\'index_url\' or \'extra_index_url\') are '
              'mutually exclusive.'
          )
  
      if index_url:
          if not salt.utils.valid_url(index_url, VALID_PROTOS):
              raise CommandExecutionError(
                  '{0!r} must be a valid URL'.format(index_url)
              )
          cmd.append('--index-url={0!r}'.format(index_url))
  
      if extra_index_url:
          if not salt.utils.valid_url(extra_index_url, VALID_PROTOS):
              raise CommandExecutionError(
                  '{0!r} must be a valid URL'.format(extra_index_url)
              )
          cmd.append('--extra-index-url={0!r}'.format(extra_index_url))
  
      if no_index:
          cmd.append('--no-index')
  
      if mirrors:
          if isinstance(mirrors, string_types):
              mirrors = [m.strip() for m in mirrors.split(',')]
  
          cmd.append('--use-mirrors')
          for mirror in mirrors:
              if not mirror.startswith('http://'):
                  raise CommandExecutionError(
                      '{0!r} must be a valid URL'.format(mirror)
                  )
              cmd.append('--mirrors={0}'.format(mirror))
  
      if build:
          cmd.append('--build={0}'.format(build))
  
      if target:
          cmd.append('--target={0}'.format(target))
  
      if download:
          cmd.append('--download={0}'.format(download))
  
      if download_cache:
          cmd.append('--download-cache={0}'.format(download_cache))
  
      if source:
          cmd.append('--source={0}'.format(source))
  
      if upgrade:
          cmd.append('--upgrade')
  
      if force_reinstall:
          cmd.append('--force-reinstall')
  
      if ignore_installed:
          cmd.append('--ignore-installed')
  
      if exists_action:
          if exists_action.lower() not in ('s', 'i', 'w', 'b'):
              raise CommandExecutionError(
                  'The `exists_action`(`--exists-action`) pip option only '
                  'allows one of (s, i, w, b) to be passed. The {0!r} value '
                  'is not valid.'.format(exists_action)
              )
          cmd.append('--exists-action={0}'.format(exists_action))
  
      if no_deps:
          cmd.append('--no-deps')
  
      if no_install:
          cmd.append('--no-install')
  
      if no_download:
          cmd.append('--no-download')
  
      if pre_releases:
          # Check the locally installed pip version
          pip_version_cmd = '{0} --version'.format(_get_pip_bin(bin_env))
          output = __salt__['cmd.run_all'](pip_version_cmd).get('stdout', '')
          pip_version = output.split()[1]
  
          # From pip v1.4 the --pre flag is available
          if salt.utils.compare_versions(ver1=pip_version, oper='>=', ver2='1.4'):
              cmd.append('--pre')
  
      if global_options:
          if isinstance(global_options, string_types):
              global_options = [go.strip() for go in global_options.split(',')]
  
          for opt in global_options:
              cmd.append('--global-option={0!r}'.format(opt))
  
      if install_options:
          if isinstance(install_options, string_types):
              install_options = [io.strip() for io in install_options.split(',')]
  
          for opt in install_options:
              cmd.append('--install-option={0!r}'.format(opt))
  
      if pkgs:
          if isinstance(pkgs, string_types):
              pkgs = [p.strip() for p in pkgs.split(',')]
  
          # It's possible we replaced version-range commas with semicolons so
          # they would survive the previous line (in the pip.installed state).
          # Put the commas back in while making sure the names are contained in
          # quotes, this allows for proper version spec passing salt>=0.17.0
          cmd.extend(
              ['{0!r}'.format(p.replace(';', ',')) for p in pkgs]
          )
  
      if editable:
          egg_match = re.compile(r'(?:#|#.*?&)egg=([^&]*)')
          if isinstance(editable, string_types):
              editable = [e.strip() for e in editable.split(',')]
  
          for entry in editable:
              # Is the editable local?
              if not (entry == '.' or entry.startswith(('file://', '/'))):
                  match = egg_match.search(entry)
  
                  if not match or not match.group(1):
                      # Missing #egg=theEggName
                      raise CommandExecutionError(
                          'You must specify an egg for this editable'
                      )
              cmd.append('--editable={0}'.format(entry))
  
      try:
          cmd_kwargs = dict(runas=user, cwd=cwd, saltenv=saltenv)
          if bin_env and os.path.isdir(bin_env):
              cmd_kwargs['env'] = {'VIRTUAL_ENV': bin_env}
          return __salt__['cmd.run_all'](' '.join(cmd), **cmd_kwargs)
      finally:
          for requirement in cleanup_requirements:
              try:
                  os.remove(requirement)
              except Exception:
                  pass
  
  
  def uninstall(pkgs=None,
                requirements=None,
                bin_env=None,
                log=None,
                proxy=None,
                timeout=None,
                user=None,
                runas=None,
                no_chown=False,
                cwd=None,
                __env__=None,
                saltenv='base'):
      '''
      Uninstall packages with pip
  
      Uninstall packages individually or from a pip requirements file. Uninstall
      packages globally or from a virtualenv.
  
      pkgs
          comma separated list of packages to install
      requirements
          path to requirements
      bin_env
          path to pip bin or path to virtualenv. If doing an uninstall from
          the system python and want to use a specific pip bin (pip-2.7,
          pip-2.6, etc..) just specify the pip bin you want.
          If uninstalling from a virtualenv, just use the path to the virtualenv
          (/home/code/path/to/virtualenv/)
      log
          Log file where a complete (maximum verbosity) record will be kept
      proxy
          Specify a proxy in the form
          user:passwd@proxy.server:port. Note that the
          user:password@ is optional and required only if you
          are behind an authenticated proxy.  If you provide
          user@proxy.server:port then you will be prompted for a
          password.
      timeout
          Set the socket timeout (default 15 seconds)
      user
          The user under which to run pip
  
      .. note::
          The ``runas`` argument is deprecated as of 0.16.2. ``user`` should be
          used instead.
  
      no_chown
          When user is given, do not attempt to copy and chown
          a requirements file
      cwd
          Current working directory to run pip from
  
      CLI Example:
  
      .. code-block:: bash
  
          salt '*' pip.uninstall <package name>,<package2 name>
          salt '*' pip.uninstall requirements=/path/to/requirements.txt
          salt '*' pip.uninstall <package name> bin_env=/path/to/virtualenv
          salt '*' pip.uninstall <package name> bin_env=/path/to/pip_bin
  
      '''
      cmd = [_get_pip_bin(bin_env), 'uninstall', '-y']
  
      if isinstance(__env__, string_types):
          salt.utils.warn_until(
              'Boron',
              'Passing a salt environment should be done using \'saltenv\' '
              'not \'__env__\'. This functionality will be removed in Salt '
              'Boron.'
          )
          # Backwards compatibility
          saltenv = __env__
  
      if runas is not None:
          # The user is using a deprecated argument, warn!
          salt.utils.warn_until(
              'Hydrogen',
              'The \'runas\' argument to pip.install is deprecated, and will be '
              'removed in Salt {version}. Please use \'user\' instead.'
          )
  
      # "There can only be one"
      if runas is not None and user:
          raise CommandExecutionError(
              'The \'runas\' and \'user\' arguments are mutually exclusive. '
              'Please use \'user\' as \'runas\' is being deprecated.'
          )
  
      # Support deprecated 'runas' arg
      elif runas is not None and not user:
          user = str(runas)
  
      cleanup_requirements = []
      if requirements is not None:
          if isinstance(requirements, string_types):
              requirements = [r.strip() for r in requirements.split(',')]
  
          for requirement in requirements:
              treq = None
              if requirement.startswith('salt://'):
                  cached_requirements = _get_cached_requirements(
                      requirement, saltenv
                  )
                  if not cached_requirements:
                      return {
                          'result': False,
                          'comment': (
                              'pip requirements file {0!r} not found'.format(
                                  requirement
                              )
                          )
                      }
                  requirement = cached_requirements
  
              if user and not no_chown:
                  # Need to make a temporary copy since the user will, most
                  # likely, not have the right permissions to read the file
                  treq = salt.utils.mkstemp()
                  shutil.copyfile(requirement, treq)
                  logger.debug(
                      'Changing ownership of requirements file {0!r} to '
                      'user {1!r}'.format(treq, user)
                  )
                  __salt__['file.chown'](treq, user, None)
                  cleanup_requirements.append(treq)
              cmd.append('--requirement={0!r}'.format(treq or requirement))
  
      if log:
          try:
              # TODO make this check if writeable
              os.path.exists(log)
          except IOError:
              raise IOError('{0!r} is not writeable'.format(log))
  
          cmd.append('--log={0}'.format(log))
  
      if proxy:
          cmd.append('--proxy={0!r}'.format(proxy))
  
      if timeout:
          try:
              int(timeout)
          except ValueError:
              raise ValueError(
                  '{0!r} is not a valid integer base 10.'.format(timeout)
              )
          cmd.append('--timeout={0}'.format(timeout))
  
      if pkgs:
          if isinstance(pkgs, string_types):
              pkgs = [p.strip() for p in pkgs.split(',')]
          cmd.extend(pkgs)
  
      cmd_kwargs = dict(runas=user, cwd=cwd, saltenv=saltenv)
      if bin_env and os.path.isdir(bin_env):
          cmd_kwargs['env'] = {'VIRTUAL_ENV': bin_env}
  
      try:
          return __salt__['cmd.run_all'](' '.join(cmd), **cmd_kwargs)
      finally:
          for requirement in cleanup_requirements:
              try:
                  os.remove(requirement)
              except Exception:
                  pass
  
  
  def freeze(bin_env=None,
             user=None,
             runas=None,
             cwd=None):
      '''
      Return a list of installed packages either globally or in the specified
      virtualenv
  
      bin_env
          path to pip bin or path to virtualenv. If doing an uninstall from
          the system python and want to use a specific pip bin (pip-2.7,
          pip-2.6, etc..) just specify the pip bin you want.
          If uninstalling from a virtualenv, just use the path to the virtualenv
          (/home/code/path/to/virtualenv/)
      user
          The user under which to run pip
  
      .. note::
          The ``runas`` argument is deprecated as of 0.16.2. ``user`` should be
          used instead.
  
      cwd
          Current working directory to run pip from
  
      CLI Example:
  
      .. code-block:: bash
  
          salt '*' pip.freeze /home/code/path/to/virtualenv/
      '''
      if runas is not None:
          # The user is using a deprecated argument, warn!
          salt.utils.warn_until(
              'Hydrogen',
              'The \'runas\' argument to pip.install is deprecated, and will be '
              'removed in Salt {version}. Please use \'user\' instead.'
          )
  
      # "There can only be one"
      if runas is not None and user:
          raise CommandExecutionError(
              'The \'runas\' and \'user\' arguments are mutually exclusive. '
              'Please use \'user\' as \'runas\' is being deprecated.'
          )
  
      # Support deprecated 'runas' arg
      elif runas is not None and not user:
          user = str(runas)
  
      cmd = [_get_pip_bin(bin_env), 'freeze']
      cmd_kwargs = dict(runas=user, cwd=cwd)
      if bin_env and os.path.isdir(bin_env):
          cmd_kwargs['env'] = {'VIRTUAL_ENV': bin_env}
      result = __salt__['cmd.run_all'](' '.join(cmd), **cmd_kwargs)
  
      if result['retcode'] > 0:
          raise CommandExecutionError(result['stderr'])
  
      return result['stdout'].splitlines()
  
  
  def list_(prefix=None,
            bin_env=None,
            user=None,
            runas=None,
            cwd=None):
      '''
      Filter list of installed apps from ``freeze`` and check to see if
      ``prefix`` exists in the list of packages installed.
  
      CLI Example:
  
      .. code-block:: bash
  
          salt '*' pip.list salt
      '''
      packages = {}
  
      pip_bin = _get_pip_bin(bin_env)
      pip_version_cmd = [pip_bin, '--version']
      cmd = [pip_bin, 'freeze']
  
      if runas is not None:
          # The user is using a deprecated argument, warn!
          salt.utils.warn_until(
              'Hydrogen',
              'The \'runas\' argument to pip.install is deprecated, and will be '
              'removed in Salt {version}. Please use \'user\' instead.'
          )
  
      # "There can only be one"
      if runas is not None and user:
          raise CommandExecutionError(
              'The \'runas\' and \'user\' arguments are mutually exclusive. '
              'Please use \'user\' as \'runas\' is being deprecated.'
          )
  
      # Support deprecated 'runas' arg
      elif runas is not None and not user:
          user = str(runas)
  
      cmd_kwargs = dict(runas=user, cwd=cwd)
      if bin_env and os.path.isdir(bin_env):
          cmd_kwargs['env'] = {'VIRTUAL_ENV': bin_env}
  
      if not prefix or prefix in ('p', 'pi', 'pip'):
          pip_version_result = __salt__['cmd.run_all'](' '.join(pip_version_cmd),
                                                       **cmd_kwargs)
          if pip_version_result['retcode'] > 0:
              raise CommandExecutionError(pip_version_result['stderr'])
          packages['pip'] = pip_version_result['stdout'].split()[1]
  
      result = __salt__['cmd.run_all'](' '.join(cmd), **cmd_kwargs)
      if result['retcode'] > 0:
          raise CommandExecutionError(result['stderr'])
  
      for line in result['stdout'].splitlines():
          if line.startswith('-f') or line.startswith('#'):
              # ignore -f line as it contains --find-links directory
              # ignore comment lines
              continue
          elif line.startswith('-e'):
              line = line.split('-e ')[1]
              version_, name = line.split('#egg=')
          elif len(line.split('==')) >= 2:
              name = line.split('==')[0]
              version_ = line.split('==')[1]
          else:
              logger.error("Can't parse line '%s'", line)
              continue
  
          if prefix:
              if name.lower().startswith(prefix.lower()):
                  packages[name] = version_
          else:
              packages[name] = version_
      return packages
  
  
  def version(bin_env=None):
      '''
      .. versionadded:: 0.17.0
  
      Returns the version of pip. Use ``bin_env`` to specify the path to a
      virtualenv and get the version of pip in that virtualenv.
  
      If unable to detect the pip version, returns ``None``.
  
      CLI Example:
  
      .. code-block:: bash
  
          salt '*' pip.version
      '''
      output = __salt__['cmd.run']('{0} --version'.format(_get_pip_bin(bin_env)))
      try:
          return re.match(r'^pip (\S+)', output).group(1)
      except AttributeError:
          return None
  