From: Tarek Ziadé Date: Sun, 20 Dec 2009 23:54:52 +0000 (+0000) Subject: Merged revisions 76952 via svnmerge from X-Git-Tag: v2.6.5rc1~250 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e220d6793970e2ee0d71c5faa9cb712a4fe15de4;p=python Merged revisions 76952 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r76952 | tarek.ziade | 2009-12-21 00:23:34 +0100 (Mon, 21 Dec 2009) | 1 line Fixed #7552: fixed distutils.command.upload failure on very long passwords ........ --- diff --git a/Lib/distutils/command/upload.py b/Lib/distutils/command/upload.py index 8805d41da0..9f1aae6aa4 100644 --- a/Lib/distutils/command/upload.py +++ b/Lib/distutils/command/upload.py @@ -11,7 +11,7 @@ import os import socket import platform import httplib -import base64 +from base64 import standard_b64encode import urlparse import cStringIO as StringIO from ConfigParser import ConfigParser @@ -115,7 +115,8 @@ class upload(PyPIRCCommand): open(filename+".asc").read()) # set up the authentication - auth = "Basic " + base64.encodestring(self.username + ":" + self.password).strip() + auth = "Basic " + standard_b64encode(self.username + ":" + + self.password) # Build up the MIME payload for the POST data boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' diff --git a/Lib/distutils/tests/support.py b/Lib/distutils/tests/support.py index d24a18ea0e..9d373e94e4 100644 --- a/Lib/distutils/tests/support.py +++ b/Lib/distutils/tests/support.py @@ -1,10 +1,10 @@ """Support code for distutils test cases.""" - +import os import shutil import tempfile from distutils import log - +from distutils.dist import Distribution class LoggingSilencer(object): @@ -55,6 +55,23 @@ class TempdirManager(object): finally: f.close() + def create_dist(self, pkg_name='foo', **kw): + """Will generate a test environment. + + This function creates: + - a Distribution instance using keywords + - a temporary directory with a package structure + + It returns the package directory and the distribution + instance. + """ + tmp_dir = self.mkdtemp() + pkg_dir = os.path.join(tmp_dir, pkg_name) + os.mkdir(pkg_dir) + dist = Distribution(attrs=kw) + + return pkg_dir, dist + class DummyCommand: """Class to store options for retrieval via set_undefined_options().""" diff --git a/Lib/distutils/tests/test_upload.py b/Lib/distutils/tests/test_upload.py index b05ab1f78b..322beb778c 100644 --- a/Lib/distutils/tests/test_upload.py +++ b/Lib/distutils/tests/test_upload.py @@ -2,6 +2,7 @@ import sys import os import unittest +import httplib from distutils.command.upload import upload from distutils.core import Distribution @@ -9,8 +10,66 @@ from distutils.core import Distribution from distutils.tests import support from distutils.tests.test_config import PYPIRC, PyPIRCCommandTestCase +PYPIRC_LONG_PASSWORD = """\ +[distutils] + +index-servers = + server1 + server2 + +[server1] +username:me +password:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +[server2] +username:meagain +password: secret +realm:acme +repository:http://another.pypi/ +""" + +class _Resp(object): + def __init__(self, status): + self.status = status + self.reason = 'OK' + +_CONNECTIONS = [] + +class _FakeHTTPConnection(object): + def __init__(self, netloc): + self.requests = [] + self.headers = {} + self.body = None + self.netloc = netloc + _CONNECTIONS.append(self) + + def connect(self): + pass + endheaders = connect + + def send(self, body): + self.body = body + + def putrequest(self, type_, data): + self.requests.append((type_, data)) + + def putheader(self, name, value): + self.headers[name] = value + + def getresponse(self): + return _Resp(200) + class uploadTestCase(PyPIRCCommandTestCase): + def setUp(self): + super(uploadTestCase, self).setUp() + self.old_klass = httplib.HTTPConnection + httplib.HTTPConnection = _FakeHTTPConnection + + def tearDown(self): + httplib.HTTPConnection = self.old_klass + super(uploadTestCase, self).tearDown() + def test_finalize_options(self): # new format @@ -27,6 +86,33 @@ class uploadTestCase(PyPIRCCommandTestCase): self.assertEquals(getattr(cmd, attr), waited) + def test_upload(self): + tmp = self.mkdtemp() + path = os.path.join(tmp, 'xxx') + self.write_file(path) + command, pyversion, filename = 'xxx', '2.6', path + dist_files = [(command, pyversion, filename)] + self.write_file(self.rc, PYPIRC_LONG_PASSWORD) + + # lets run it + pkg_dir, dist = self.create_dist(dist_files=dist_files) + cmd = upload(dist) + cmd.ensure_finalized() + cmd.run() + + # what did we send ? + res = _CONNECTIONS[-1] + + headers = res.headers + self.assertEquals(headers['Content-length'], '2086') + self.assertTrue(headers['Content-type'].startswith('multipart/form-data')) + + method, request = res.requests[-1] + self.assertEquals(method, 'POST') + self.assertEquals(res.netloc, 'pypi.python.org') + self.assertTrue('xxx' in res.body) + self.assertFalse('\n' in headers['Authorization']) + def test_suite(): return unittest.makeSuite(uploadTestCase) diff --git a/Misc/NEWS b/Misc/NEWS index 817429270f..6cbb39dfe5 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -35,6 +35,10 @@ Core and Builtins Library ------- +- Issue #7552: Removed line feed in the base64 Authorization header in + the Distutils upload command to avoid an error when PyPI reads it. + This occurs on long passwords. Initial patch by JP St. Pierre. + - Issue #7231: urllib2 cannot handle https with proxy requiring auth. Patch by Tatsuhiro Tsujikawa.