diff -r 6c3d67ed3adb distutils2/command/__init__.py --- a/distutils2/command/__init__.py Sun Mar 13 15:52:26 2011 -0400 +++ b/distutils2/command/__init__.py Thu Jun 09 22:33:22 2011 -0400 @@ -56,3 +56,37 @@ return cls except KeyError: raise DistutilsModuleError("Invalid command %s" % name) + + +# grabbed from +# http://code.activestate.com/recipes/146306-http-client-to-post-using-multipartform-data/ +def encode_multipart(fields, files, boundary=None): + """ + fields is a sequence of (name, value) elements for regular form fields. + files is a sequence of (name, filename, value) elements for data to be uploaded as files + Return (content_type, body) ready for httplib.HTTP instance + """ + if boundary is None: + boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' + l = [] + for (key, values) in fields: + # handle multiple entries for the same name + if not isinstance(values, (tuple, list)): + values = [values] + for value in values: + l.extend([ + '--' + boundary, + 'Content-Disposition: form-data; name="%s"' % key, + '', + value]) + for (key, filename, value) in files: + l.extend([ + '--' + boundary, + 'Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename), + '', + value]) + l.append('--' + boundary + '--') + l.append('') + body = '\r\n'.join(l) + content_type = 'multipart/form-data; boundary=%s' % boundary + return content_type, body diff -r 6c3d67ed3adb distutils2/command/register.py --- a/distutils2/command/register.py Sun Mar 13 15:52:26 2011 -0400 +++ b/distutils2/command/register.py Thu Jun 09 22:33:22 2011 -0400 @@ -17,6 +17,7 @@ from distutils2.metadata import metadata_to_dict from distutils2.util import (read_pypirc, generate_pypirc, DEFAULT_REPOSITORY, DEFAULT_REALM, get_pypirc_path) +from distutils2.command import encode_multipart class register(Command): @@ -234,29 +235,11 @@ self.repository), logging.INFO) # Build up the MIME payload for the urllib2 POST data - boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' - sep_boundary = '\n--' + boundary - end_boundary = sep_boundary + '--' - body = StringIO.StringIO() - for key, value in data.iteritems(): - # handle multiple entries for the same name - if not isinstance(value, (tuple, list)): - value = [value] - - for value in value: - body.write(sep_boundary) - body.write('\nContent-Disposition: form-data; name="%s"'%key) - body.write("\n\n") - body.write(value) - if value and value[-1] == '\r': - body.write('\n') # write an extra newline (lurve Macs) - body.write(end_boundary) - body.write("\n") - body = body.getvalue() + content_type, body = encode_multipart(data.items(), []) # build the Request headers = { - 'Content-type': 'multipart/form-data; boundary=%s; charset=utf-8'%boundary, + 'Content-type': content_type, 'Content-length': str(len(body)) } req = urllib2.Request(self.repository, body, headers) diff -r 6c3d67ed3adb distutils2/command/upload.py --- a/distutils2/command/upload.py Sun Mar 13 15:52:26 2011 -0400 +++ b/distutils2/command/upload.py Thu Jun 09 22:33:22 2011 -0400 @@ -22,6 +22,7 @@ from distutils2.command.cmd import Command from distutils2.metadata import metadata_to_dict from distutils2.util import read_pypirc, DEFAULT_REPOSITORY, DEFAULT_REALM +from distutils2.command import encode_multipart class upload(Command): @@ -134,49 +135,19 @@ self.password) # Build up the MIME payload for the POST data - boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' - sep_boundary = '\n--' + boundary - end_boundary = sep_boundary + '--' - body = StringIO() - file_fields = ('content', 'gpg_signature') + files = [] + for key in ('content', 'gpg_signature'): + if key in data: + filename_, value = data.pop(key) + files.append((key, filename_, value)) - for key, values in data.iteritems(): - # handle multiple entries for the same name - if not isinstance(values, (tuple, list)): - values = [values] - - content_dispo = 'Content-Disposition: form-data; name="%s"' % key - - if key in file_fields: - filename_, content = values - filename_ = ';filename="%s"' % filename_ - body.write(sep_boundary) - body.write("\n") - body.write(content_dispo) - body.write(filename_) - body.write("\n\n") - body.write(content) - else: - for value in values: - body.write(sep_boundary) - body.write("\n") - body.write(content_dispo) - body.write("\n\n") - body.write(value) - if value and value[-1] == '\r': - # write an extra newline (lurve Macs) - body.write('\n') - - body.write(end_boundary) - body.write("\n") - body = body.getvalue() + content_type, body = encode_multipart(data.items(), files) self.announce("Submitting %s to %s" % (filename, self.repository), logging.INFO) # build the Request - headers = {'Content-type': - 'multipart/form-data; boundary=%s' % boundary, + headers = {'Content-type': content_type, 'Content-length': str(len(body)), 'Authorization': auth} diff -r 6c3d67ed3adb distutils2/command/upload_docs.py --- a/distutils2/command/upload_docs.py Sun Mar 13 15:52:26 2011 -0400 +++ b/distutils2/command/upload_docs.py Thu Jun 09 22:33:22 2011 -0400 @@ -15,6 +15,7 @@ from distutils2.command.cmd import Command from distutils2.errors import DistutilsFileError from distutils2.util import read_pypirc, DEFAULT_REPOSITORY, DEFAULT_REALM +from distutils2.command import encode_multipart def zip_dir(directory): """Compresses recursively contents of directory into a StringIO object""" @@ -29,35 +30,6 @@ zip_file.close() return destination -# grabbed from -# http://code.activestate.com/recipes/146306-http-client-to-post-using-multipartform-data/ -def encode_multipart(fields, files, boundary=None): - """ - fields is a sequence of (name, value) elements for regular form fields. - files is a sequence of (name, filename, value) elements for data to be uploaded as files - Return (content_type, body) ready for httplib.HTTP instance - """ - if boundary is None: - boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' - l = [] - for (key, value) in fields: - l.extend([ - '--' + boundary, - 'Content-Disposition: form-data; name="%s"' % key, - '', - value]) - for (key, filename, value) in files: - l.extend([ - '--' + boundary, - 'Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename), - '', - value]) - l.append('--' + boundary + '--') - l.append('') - body = '\r\n'.join(l) - content_type = 'multipart/form-data; boundary=%s' % boundary - return content_type, body - class upload_docs(Command): user_options = [ diff -r 6c3d67ed3adb distutils2/tests/test_command_register.py --- a/distutils2/tests/test_command_register.py Sun Mar 13 15:52:26 2011 -0400 +++ b/distutils2/tests/test_command_register.py Thu Jun 09 22:33:22 2011 -0400 @@ -170,7 +170,7 @@ self.assertTrue(self.conn.reqs, 1) req = self.conn.reqs[0] headers = dict(req.headers) - self.assertEqual(headers['Content-length'], '608') + self.assertEqual(headers['Content-length'], '628') self.assertTrue('tarek' in req.data) def test_password_reset(self): @@ -184,7 +184,7 @@ self.assertTrue(self.conn.reqs, 1) req = self.conn.reqs[0] headers = dict(req.headers) - self.assertEqual(headers['Content-length'], '290') + self.assertEqual(headers['Content-length'], '298') self.assertTrue('tarek' in req.data) @unittest.skipUnless(DOCUTILS_SUPPORT, 'needs docutils') diff -r 6c3d67ed3adb distutils2/tests/test_command_upload.py --- a/distutils2/tests/test_command_upload.py Sun Mar 13 15:52:26 2011 -0400 +++ b/distutils2/tests/test_command_upload.py Thu Jun 09 22:33:22 2011 -0400 @@ -109,7 +109,7 @@ self.assertIn('dédé', request_data) self.assertIn('xxx', request_data) self.assertEqual(int(headers['content-length']), len(request_data)) - self.assertTrue(int(headers['content-length']) < 2000) + self.assertEqual(int(headers['content-length']), 2041) self.assertTrue(headers['content-type'].startswith('multipart/form-data')) self.assertEqual(handler.command, 'POST') self.assertNotIn('\n', headers['authorization'])