Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
niedbalski committed May 23, 2012
2 parents dac305d + e0db44e commit 126b1ba
Show file tree
Hide file tree
Showing 16 changed files with 174 additions and 100 deletions.
72 changes: 1 addition & 71 deletions pip/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import re
import difflib

from pip.backwardcompat import walk_packages, console_to_str
from pip.backwardcompat import walk_packages
from pip.basecommand import command_dict, load_command, load_all_commands, command_names
from pip.baseparser import parser
from pip.exceptions import InstallationError
Expand Down Expand Up @@ -196,76 +196,6 @@ def __str__(self):
req = '-e %s' % req
return '\n'.join(list(self.comments)+[str(req)])+'\n'

############################################################
## Requirement files


def call_subprocess(cmd, show_stdout=True,
filter_stdout=None, cwd=None,
raise_on_returncode=True,
command_level=logger.DEBUG, command_desc=None,
extra_environ=None):
if command_desc is None:
cmd_parts = []
for part in cmd:
if ' ' in part or '\n' in part or '"' in part or "'" in part:
part = '"%s"' % part.replace('"', '\\"')
cmd_parts.append(part)
command_desc = ' '.join(cmd_parts)
if show_stdout:
stdout = None
else:
stdout = subprocess.PIPE
logger.log(command_level, "Running command %s" % command_desc)
env = os.environ.copy()
if extra_environ:
env.update(extra_environ)
try:
proc = subprocess.Popen(
cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
cwd=cwd, env=env)
except Exception:
e = sys.exc_info()[1]
logger.fatal(
"Error %s while executing command %s" % (e, command_desc))
raise
all_output = []
if stdout is not None:
stdout = proc.stdout
while 1:
line = console_to_str(stdout.readline())
if not line:
break
line = line.rstrip()
all_output.append(line + '\n')
if filter_stdout:
level = filter_stdout(line)
if isinstance(level, tuple):
level, line = level
logger.log(level, line)
if not logger.stdout_level_matches(level):
logger.show_progress()
else:
logger.info(line)
else:
returned_stdout, returned_stderr = proc.communicate()
all_output = [returned_stdout or '']
proc.wait()
if proc.returncode:
if raise_on_returncode:
if all_output:
logger.notify('Complete output from command %s:' % command_desc)
logger.notify('\n'.join(all_output) + '\n----------------------------------------')
raise InstallationError(
"Command %s failed with error code %s in %s"
% (command_desc, proc.returncode, cwd))
else:
logger.warn(
"Command %s had error code %s in %s"
% (command_desc, proc.returncode, cwd))
if stdout is not None:
return ''.join(all_output)


if __name__ == '__main__':
exit = main()
Expand Down
70 changes: 69 additions & 1 deletion pip/baseparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,75 @@
from pip.locations import default_config_file, default_log_file


class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter):
class PipPrettyHelpFormatter(optparse.IndentedHelpFormatter):
"""A prettier/less verbose help formatter for optparse."""

def __init__(self, *args, **kw):
kw['max_help_position'] = 23
kw['indent_increment'] = 1

# do as argparse does
try:
kw['width'] = int(os.environ['COLUMNS']) - 2
except:
kw['width'] = 78

optparse.IndentedHelpFormatter.__init__(self, *args, **kw)

def format_option_strings(self, option):
return self._format_option_strings(option, ' <%s>', ', ')

def _format_option_strings(self, option, mvarfmt=' <%s>', optsep=', '):
"""
Return a comma-separated list of option strings and metavars.
:param option: tuple of (short opt, long opt), e.g: ('-f', '--format')
:param mvarfmt: metavar format string - evaluated as mvarfmt % metavar
:param optsep: separator
"""

opts = []

if option._short_opts: opts.append(option._short_opts[0])
if option._long_opts: opts.append(option._long_opts[0])
if len(opts) > 1: opts.insert(1, optsep)

if option.takes_value():
metavar = option.metavar or option.dest.lower()
opts.append(mvarfmt % metavar)

return ''.join(opts)

def format_heading(self, heading):
if heading == 'Options': return ''
return heading + ':\n'

def format_usage(self, usage):
# ensure there is only one newline between usage and the first heading
# if there is no description

msg = 'Usage: %s' % usage
if self.parser.description:
msg += '\n'

return msg

def format_description(self, description):
# leave full control over description to us
if description:
return description
else:
return ''

def format_epilog(self, epilog):
# leave full control over epilog to us
if epilog:
return epilog
else:
return ''


class UpdatingDefaultsHelpFormatter(PipPrettyHelpFormatter):
"""Custom help formatter for use in ConfigOptionParser that updates
the defaults before expanding them, allowing them to show up correctly
in the help listing"""
Expand Down
17 changes: 10 additions & 7 deletions pip/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
"""Exceptions used throughout package"""


class InstallationError(Exception):
class PipError(Exception):
"""Base pip exception"""


class InstallationError(PipError):
"""General exception during installation"""


class UninstallationError(Exception):
class UninstallationError(PipError):
"""General exception during uninstallation"""


class DistributionNotFound(InstallationError):
"""Raised when a distribution cannot be found to satisfy a requirement"""


class BestVersionAlreadyInstalled(Exception):
class BestVersionAlreadyInstalled(PipError):
"""Raised when the most up-to-date version of a package is already
installed.
"""
installed. """


class BadCommand(Exception):
class BadCommand(PipError):
"""Raised when virtualenv or a command is not found"""


class CommandError(Exception):
class CommandError(PipError):
"""Raised when there is an error in command-line arguments"""
11 changes: 7 additions & 4 deletions pip/locations.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@ def running_under_virtualenv():
build_prefix = os.path.join(sys.prefix, 'build')
src_prefix = os.path.join(sys.prefix, 'src')
else:
## FIXME: this isn't a very good default
build_prefix = os.path.join(os.getcwd(), 'build')
src_prefix = os.path.join(os.getcwd(), 'src')
try:
## FIXME: this isn't a very good default
build_prefix = os.path.join(os.getcwd(), 'build')
src_prefix = os.path.join(os.getcwd(), 'src')
except OSError:
# In case the current working directory has been renamed or deleted
sys.exit("The folder you are executing pip from can no longer be found.")

# under Mac OS X + virtualenv sys.prefix is not properly resolved
# it is something like /path/to/python/bin/..
Expand All @@ -36,7 +40,6 @@ def running_under_virtualenv():
# buildout uses 'bin' on Windows too?
if not os.path.exists(bin_py):
bin_py = os.path.join(sys.prefix, 'bin')
user_dir = os.environ.get('APPDATA', user_dir) # Use %APPDATA% for roaming
default_storage_dir = os.path.join(user_dir, 'pip')
default_config_file = os.path.join(default_storage_dir, 'pip.ini')
default_log_file = os.path.join(default_storage_dir, 'pip.log')
Expand Down
12 changes: 6 additions & 6 deletions pip/req.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from pip.util import is_installable_dir, is_local, dist_is_local
from pip.util import renames, normalize_path, egg_link_path
from pip.util import make_path_relative
from pip import call_subprocess
from pip.util import call_subprocess
from pip.backwardcompat import (any, copytree, urlparse, urllib,
ConfigParser, string_types, HTTPError,
FeedParser, get_python_version,
Expand Down Expand Up @@ -289,7 +289,10 @@ def egg_info_path(self, filename):
for dir in vcs.dirnames:
if dir in dirs:
dirs.remove(dir)
for dir in dirs:
# Iterate over a copy of ``dirs``, since mutating
# a list while iterating over it can cause trouble.
# (See https://github.com/pypa/pip/pull/462.)
for dir in list(dirs):
# Don't search in anything that looks like a virtualenv environment
if (os.path.exists(os.path.join(root, dir, 'bin', 'python'))
or os.path.exists(os.path.join(root, dir, 'Scripts', 'Python.exe'))):
Expand Down Expand Up @@ -770,10 +773,7 @@ def keys(self):
return self._keys

def values(self):
values_list = []
for key in self._keys:
values_list.append(self._dict[key])
return values_list
return [self._dict[key] for key in self._keys]

def __contains__(self, item):
return item in self._keys
Expand Down
71 changes: 68 additions & 3 deletions pip/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
import pkg_resources
import zipfile
import tarfile
import subprocess
from pip.exceptions import InstallationError, BadCommand
from pip.backwardcompat import WindowsError, string_types, raw_input
from pip.backwardcompat import WindowsError, string_types, raw_input, console_to_str
from pip.locations import site_packages, running_under_virtualenv
from pip.log import logger

Expand All @@ -21,7 +22,7 @@
'make_path_relative', 'normalize_path',
'renames', 'get_terminal_size',
'unzip_file', 'untar_file', 'create_download_cache_folder',
'cache_download', 'unpack_file']
'cache_download', 'unpack_file', 'call_subprocess']


def rmtree(dir, ignore_errors=False):
Expand Down Expand Up @@ -505,4 +506,68 @@ def unpack_file(filename, location, content_type, link):
raise InstallationError('Cannot determine archive format of %s' % location)



def call_subprocess(cmd, show_stdout=True,
filter_stdout=None, cwd=None,
raise_on_returncode=True,
command_level=logger.DEBUG, command_desc=None,
extra_environ=None):
if command_desc is None:
cmd_parts = []
for part in cmd:
if ' ' in part or '\n' in part or '"' in part or "'" in part:
part = '"%s"' % part.replace('"', '\\"')
cmd_parts.append(part)
command_desc = ' '.join(cmd_parts)
if show_stdout:
stdout = None
else:
stdout = subprocess.PIPE
logger.log(command_level, "Running command %s" % command_desc)
env = os.environ.copy()
if extra_environ:
env.update(extra_environ)
try:
proc = subprocess.Popen(
cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
cwd=cwd, env=env)
except Exception:
e = sys.exc_info()[1]
logger.fatal(
"Error %s while executing command %s" % (e, command_desc))
raise
all_output = []
if stdout is not None:
stdout = proc.stdout
while 1:
line = console_to_str(stdout.readline())
if not line:
break
line = line.rstrip()
all_output.append(line + '\n')
if filter_stdout:
level = filter_stdout(line)
if isinstance(level, tuple):
level, line = level
logger.log(level, line)
if not logger.stdout_level_matches(level):
logger.show_progress()
else:
logger.info(line)
else:
returned_stdout, returned_stderr = proc.communicate()
all_output = [returned_stdout or '']
proc.wait()
if proc.returncode:
if raise_on_returncode:
if all_output:
logger.notify('Complete output from command %s:' % command_desc)
logger.notify('\n'.join(all_output) + '\n----------------------------------------')
raise InstallationError(
"Command %s failed with error code %s in %s"
% (command_desc, proc.returncode, cwd))
else:
logger.warn(
"Command %s had error code %s in %s"
% (command_desc, proc.returncode, cwd))
if stdout is not None:
return ''.join(all_output)
3 changes: 1 addition & 2 deletions pip/vcs/bazaar.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import os
import tempfile
import re
from pip import call_subprocess
from pip.backwardcompat import urlparse
from pip.log import logger
from pip.util import rmtree, display_path
from pip.util import rmtree, display_path, call_subprocess
from pip.vcs import vcs, VersionControl
from pip.download import path_to_url2

Expand Down
2 changes: 1 addition & 1 deletion pip/vcs/git.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import tempfile
import re
from pip import call_subprocess
from pip.util import call_subprocess
from pip.util import display_path, rmtree
from pip.vcs import vcs, VersionControl
from pip.log import logger
Expand Down
2 changes: 1 addition & 1 deletion pip/vcs/mercurial.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import tempfile
import re
import sys
from pip import call_subprocess
from pip.util import call_subprocess
from pip.util import display_path, rmtree
from pip.log import logger
from pip.vcs import vcs, VersionControl
Expand Down
4 changes: 2 additions & 2 deletions pip/vcs/subversion.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import os
import re
from pip.backwardcompat import urlparse
from pip import call_subprocess, InstallationError
from pip import InstallationError
from pip.index import Link
from pip.util import rmtree, display_path
from pip.util import rmtree, display_path, call_subprocess
from pip.log import logger
from pip.vcs import vcs, VersionControl

Expand Down
1 change: 1 addition & 0 deletions tests/test_install_requirement.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from pip.req import InstallRequirement


def test_url_with_query():
"""InstallRequirement should strip the fragment, but not the query."""
url = 'http://foo.com/?p=bar.git;a=snapshot;h=v0.1;sf=tgz'
Expand Down
Loading

0 comments on commit 126b1ba

Please sign in to comment.