Commit 8fdd3d8d authored by Tarek Ziadé's avatar Tarek Ziadé

Issue #6286: distutils upload command now uses urllib2

parent 130d9fa5
...@@ -5,7 +5,7 @@ import sys ...@@ -5,7 +5,7 @@ import sys
import os import os
import socket import socket
import platform import platform
import httplib from urllib2 import urlopen, Request, HTTPError
import base64 import base64
import urlparse import urlparse
import cStringIO as StringIO import cStringIO as StringIO
...@@ -62,6 +62,15 @@ class upload(PyPIRCCommand): ...@@ -62,6 +62,15 @@ class upload(PyPIRCCommand):
self.upload_file(command, pyversion, filename) self.upload_file(command, pyversion, filename)
def upload_file(self, command, pyversion, filename): def upload_file(self, command, pyversion, filename):
# Makes sure the repository URL is compliant
schema, netloc, url, params, query, fragments = \
urlparse.urlparse(self.repository)
if params or query or fragments:
raise AssertionError("Incompatible url %s" % self.repository)
if schema not in ('http', 'https'):
raise AssertionError("unsupported schema " + schema)
# Sign if requested # Sign if requested
if self.sign: if self.sign:
gpg_args = ["gpg", "--detach-sign", "-a", filename] gpg_args = ["gpg", "--detach-sign", "-a", filename]
...@@ -153,39 +162,30 @@ class upload(PyPIRCCommand): ...@@ -153,39 +162,30 @@ class upload(PyPIRCCommand):
self.announce("Submitting %s to %s" % (filename, self.repository), log.INFO) self.announce("Submitting %s to %s" % (filename, self.repository), log.INFO)
# build the Request # build the Request
# We can't use urllib2 since we need to send the Basic headers = {'Content-type':
# auth right with the first request 'multipart/form-data; boundary=%s' % boundary,
schema, netloc, url, params, query, fragments = \ 'Content-length': str(len(body)),
urlparse.urlparse(self.repository) 'Authorization': auth}
assert not params and not query and not fragments
if schema == 'http': request = Request(self.repository, data=body,
http = httplib.HTTPConnection(netloc) headers=headers)
elif schema == 'https': # send the data
http = httplib.HTTPSConnection(netloc)
else:
raise AssertionError, "unsupported schema "+schema
data = ''
loglevel = log.INFO
try: try:
http.connect() result = urlopen(request)
http.putrequest("POST", url) status = result.getcode()
http.putheader('Content-type', reason = result.msg
'multipart/form-data; boundary=%s'%boundary)
http.putheader('Content-length', str(len(body)))
http.putheader('Authorization', auth)
http.endheaders()
http.send(body)
except socket.error, e: except socket.error, e:
self.announce(str(e), log.ERROR) self.announce(str(e), log.ERROR)
return return
except HTTPError, e:
status = e.code
reason = e.msg
r = http.getresponse() if status == 200:
if r.status == 200: self.announce('Server response (%s): %s' % (status, reason),
self.announce('Server response (%s): %s' % (r.status, r.reason),
log.INFO) log.INFO)
else: else:
self.announce('Upload failed (%s): %s' % (r.status, r.reason), self.announce('Upload failed (%s): %s' % (status, reason),
log.ERROR) log.ERROR)
if self.show_response: if self.show_response:
self.announce('-'*75, r.read(), '-'*75) self.announce('-'*75, result.read(), '-'*75)
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
import sys import sys
import os import os
import unittest import unittest
import httplib
from distutils.command import upload as upload_mod
from distutils.command.upload import upload from distutils.command.upload import upload
from distutils.core import Distribution from distutils.core import Distribution
...@@ -19,48 +19,37 @@ index-servers = ...@@ -19,48 +19,37 @@ index-servers =
[server1] [server1]
username:me username:me
""" """
class Response(object):
def __init__(self, status=200, reason='OK'):
self.status = status
self.reason = reason
class FakeConnection(object): class FakeOpen(object):
def __init__(self): def __init__(self, url):
self.requests = [] self.url = url
self.headers = [] if not isinstance(url, str):
self.body = '' self.req = url
else:
self.req = None
self.msg = 'OK'
def __call__(self, netloc): def getcode(self):
return self return 200
def connect(self):
pass
endheaders = connect
def putrequest(self, method, url):
self.requests.append((method, url))
def putheader(self, name, value):
self.headers.append((name, value))
def send(self, body):
self.body = body
def getresponse(self):
return Response()
class uploadTestCase(PyPIRCCommandTestCase): class uploadTestCase(PyPIRCCommandTestCase):
def setUp(self): def setUp(self):
super(uploadTestCase, self).setUp() super(uploadTestCase, self).setUp()
self.old_class = httplib.HTTPConnection self.old_open = upload_mod.urlopen
self.conn = httplib.HTTPConnection = FakeConnection() upload_mod.urlopen = self._urlopen
self.last_open = None
def tearDown(self): def tearDown(self):
httplib.HTTPConnection = self.old_class upload_mod.urlopen = self.old_open
super(uploadTestCase, self).tearDown() super(uploadTestCase, self).tearDown()
def _urlopen(self, url):
self.last_open = FakeOpen(url)
return self.last_open
def test_finalize_options(self): def test_finalize_options(self):
# new format # new format
...@@ -105,12 +94,13 @@ class uploadTestCase(PyPIRCCommandTestCase): ...@@ -105,12 +94,13 @@ class uploadTestCase(PyPIRCCommandTestCase):
cmd.run() cmd.run()
# what did we send ? # what did we send ?
headers = dict(self.conn.headers) headers = dict(self.last_open.req.headers)
self.assertEquals(headers['Content-length'], '2086') self.assertEquals(headers['Content-length'], '2086')
self.assert_(headers['Content-type'].startswith('multipart/form-data')) self.assert_(headers['Content-type'].startswith('multipart/form-data'))
self.assertEquals(self.last_open.req.get_method(), 'POST')
self.assertEquals(self.conn.requests, [('POST', '/pypi')]) self.assertEquals(self.last_open.req.get_full_url(),
self.assert_('xxx' in self.conn.body) 'http://pypi.python.org/pypi')
self.assert_('xxx' in self.last_open.req.data)
def test_suite(): def test_suite():
return unittest.makeSuite(uploadTestCase) return unittest.makeSuite(uploadTestCase)
......
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