diff --git a/Lib/distutils/command/upload.py b/Lib/distutils/command/upload.py --- a/Lib/distutils/command/upload.py +++ b/Lib/distutils/command/upload.py @@ -144,28 +144,23 @@ class upload(PyPIRCCommand): # Build up the MIME payload for the POST data boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' sep_boundary = b'\n--' + boundary.encode('ascii') end_boundary = sep_boundary + b'--' body = io.BytesIO() for key, value in data.items(): title = '\nContent-Disposition: form-data; name="%s"' % key # handle multiple entries for the same name - if type(value) != type([]): + if not isinstance(value, (list, tuple)): value = [value] for value in value: - if type(value) is tuple: - title += '; filename="%s"' % value[0] - value = value[1] - else: - value = str(value).encode('utf-8') body.write(sep_boundary) body.write(title.encode('utf-8')) body.write(b"\n\n") - body.write(value) + body.write(str(value).encode('utf-8')) if value and value[-1:] == b'\r': body.write(b'\n') # write an extra newline (lurve Macs) body.write(end_boundary) body.write(b"\n") body = body.getvalue() self.announce("Submitting %s to %s" % (filename, self.repository), log.INFO) diff --git a/Lib/distutils/tests/test_dist.py b/Lib/distutils/tests/test_dist.py --- a/Lib/distutils/tests/test_dist.py +++ b/Lib/distutils/tests/test_dist.py @@ -329,21 +329,30 @@ class MetadataTestCase(support.TempdirMa def test_obsoletes_illegal(self): self.assertRaises(ValueError, Distribution, {"name": "package", "version": "1.0", "obsoletes": ["my.pkg (splat)"]}) def test_classifier(self): - attrs = {'name': 'Boa', 'version': '3.0', - 'classifiers': ['Programming Language :: Python :: 3']} - dist = Distribution(attrs) - meta = self.format_metadata(dist) - self.assertIn('Metadata-Version: 1.1', meta) + classifiers = ('Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 3') + attrs_tuple = {'name': 'BoaTuple', 'version': '3.0', + 'classifiers': classifiers} + attrs_list = {'name': 'BoaList', 'version': '3.0', + 'classifiers': list(classifiers)} + for attrs in attrs_tuple, attrs_list: + dist = Distribution(attrs) + meta = self.format_metadata(dist) + self.assertIn('Metadata-Version: 1.1', meta) + self.assertIn('Programming Language :: Python', meta) + self.assertIn('Programming Language :: Python :: 2', meta) + self.assertIn('Programming Language :: Python :: 3', meta) def test_download_url(self): attrs = {'name': 'Boa', 'version': '3.0', 'download_url': 'http://example.org/boa'} dist = Distribution(attrs) meta = self.format_metadata(dist) self.assertIn('Metadata-Version: 1.1', meta) diff --git a/Lib/distutils/tests/test_upload.py b/Lib/distutils/tests/test_upload.py --- a/Lib/distutils/tests/test_upload.py +++ b/Lib/distutils/tests/test_upload.py @@ -108,21 +108,63 @@ class uploadTestCase(PyPIRCCommandTestCa # 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 ? headers = dict(self.last_open.req.headers) - self.assertEqual(headers['Content-length'], '2087') - content_type = headers['Content-type'] - self.assertTrue(content_type.startswith('multipart/form-data')) + self.assertEqual(headers['Content-length'], str(len(self.last_open.req.data))) + self.assertTrue(headers['Content-type'].startswith('multipart/form-data')) self.assertEqual(self.last_open.req.get_method(), 'POST') - expected_url = 'https://pypi.python.org/pypi' - self.assertEqual(self.last_open.req.get_full_url(), expected_url) - self.assertTrue(b'xxx' in self.last_open.req.data) + self.assertEqual(self.last_open.req.get_full_url(), + 'https://pypi.python.org/pypi') + self.assertIn(b'xxx' in self.last_open.req.data) + + def test_upload_classifiers(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) + + _classifiers = ('Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 3') + tests = ( + ('footuplepkg', _classifiers), + ('foolistpkg', list(_classifiers)), + ) + for pkg_name, classifiers in tests: + pkg_dir, dist = self.create_dist(pkg_name=pkg_name, + dist_files=dist_files, + classifiers=classifiers) + cmd = upload(dist) + cmd.ensure_finalized() + cmd.run() + + # what did we send ? + headers = dict(self.last_open.req.headers) + expected_classifiers = (b'Content-Disposition: form-data; name="classifiers"\n\n' + b'Programming Language :: Python\n' + b'----------------GHSKFJDLGDS7543FJKLFHRE75642756743254\n' + b'Content-Disposition: form-data; name="classifiers"\n\n' + b'Programming Language :: Python :: 2\n' + b'----------------GHSKFJDLGDS7543FJKLFHRE75642756743254\n' + b'Content-Disposition: form-data; name="classifiers"\n\n' + b'Programming Language :: Python :: 3\n') + + self.assertIn(expected_classifiers, self.last_open.req.data) + self.assertEqual(headers['Content-length'], str(len(self.last_open.req.data))) + self.assertTrue(headers['Content-type'].startswith('multipart/form-data')) + self.assertEqual(self.last_open.req.get_method(), 'POST') + self.assertEqual(self.last_open.req.get_full_url(), + 'https://pypi.python.org/pypi') + self.assertIn(b'xxx', self.last_open.req.data) + def test_suite(): return unittest.makeSuite(uploadTestCase) if __name__ == "__main__": run_unittest(test_suite())