Commit 6797a9d0 authored by Jason R. Coombs's avatar Jason R. Coombs

Merge support for loading credentials from .pypirc (based on pull request #11). Fixes #27.

parents e9175087 915b99c8
......@@ -486,6 +486,15 @@ You can do this with both index page URLs and direct download URLs. As long
as any HTML pages read by easy_install use *relative* links to point to the
downloads, the same user ID and password will be used to do the downloading.
Using .pypirc Credentials
-------------------------
In additional to supplying credentials in the URL, ``easy_install`` will also
honor credentials if present in the .pypirc file. Teams maintaining a private
repository of packages may already have defined access credentials for
uploading packages according to the distutils documentation. ``easy_install``
will attempt to honor those if present. Refer to the distutils documentation
for Python 2.5 or later for details on the syntax.
Controlling Build Options
~~~~~~~~~~~~~~~~~~~~~~~~~
......
......@@ -17,7 +17,8 @@ from distutils.errors import DistutilsError
from setuptools.compat import (urllib2, httplib, StringIO, HTTPError,
urlparse, urlunparse, unquote, splituser,
url2pathname, name2codepoint,
unichr, urljoin, urlsplit, urlunsplit)
unichr, urljoin, urlsplit, urlunsplit,
ConfigParser)
from setuptools.compat import filterfalse
from fnmatch import translate
from setuptools.py24compat import hashlib
......@@ -920,6 +921,60 @@ def _encode_auth(auth):
# strip the trailing carriage return
return encoded.rstrip()
class Credential(object):
"""
A username/password pair. Use like a namedtuple.
"""
def __init__(self, username, password):
self.username = username
self.password = password
def __iter__(self):
yield self.username
yield self.password
def __str__(self):
return '%(username)s:%(password)s' % vars(self)
class PyPIConfig(ConfigParser.ConfigParser):
def __init__(self):
"""
Load from ~/.pypirc
"""
defaults = dict.fromkeys(['username', 'password', 'repository'], '')
super(PyPIConfig, self).__init__(defaults)
rc = os.path.join(os.path.expanduser('~'), '.pypirc')
if os.path.exists(rc):
self.read(rc)
@property
def creds_by_repository(self):
sections_with_repositories = [
section for section in self.sections()
if self.get(section, 'repository').strip()
]
return dict(map(self._get_repo_cred, sections_with_repositories))
def _get_repo_cred(self, section):
repo = self.get(section, 'repository').strip()
return repo, Credential(
self.get(section, 'username').strip(),
self.get(section, 'password').strip(),
)
def find_credential(self, url):
"""
If the URL indicated appears to be a repository defined in this
config, return the credential for that repository.
"""
for repository, cred in self.creds_by_repository.items():
if url.startswith(repository):
return cred
def open_with_auth(url, opener=urllib2.urlopen):
"""Open a urllib2 request, handling HTTP authentication"""
......@@ -935,6 +990,13 @@ def open_with_auth(url, opener=urllib2.urlopen):
else:
auth = None
if not auth:
cred = PyPIConfig().find_credential(url)
if cred:
auth = str(cred)
info = cred.username, url
log.info('Authenticating as %s for %s (from .pypirc)' % info)
if auth:
auth = "Basic " + _encode_auth(auth)
new_url = urlunparse((scheme,host,path,params,query,frag))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment