Commit 335a5128 authored by Antoine Pitrou's avatar Antoine Pitrou

Fix TypeError on "setup.py upload --show-response".

parent f20ea139
...@@ -5,7 +5,6 @@ Implements the Distutils 'register' command (register with the repository). ...@@ -5,7 +5,6 @@ Implements the Distutils 'register' command (register with the repository).
# created 2002/10/21, Richard Jones # created 2002/10/21, Richard Jones
import cgi
import os, string, getpass import os, string, getpass
import io import io
import urllib.parse, urllib.request import urllib.parse, urllib.request
...@@ -88,9 +87,7 @@ class register(PyPIRCCommand): ...@@ -88,9 +87,7 @@ class register(PyPIRCCommand):
''' '''
url = self.repository+'?:action=list_classifiers' url = self.repository+'?:action=list_classifiers'
response = urllib.request.urlopen(url) response = urllib.request.urlopen(url)
content_type = response.getheader('content-type', 'text/plain') log.info(self._read_pypi_response(response))
encoding = cgi.parse_header(content_type)[1].get('charset', 'ascii')
log.info(response.read().decode(encoding))
def verify_metadata(self): def verify_metadata(self):
''' Send the metadata to the package index server to be checked. ''' Send the metadata to the package index server to be checked.
......
...@@ -196,5 +196,6 @@ class upload(PyPIRCCommand): ...@@ -196,5 +196,6 @@ class upload(PyPIRCCommand):
self.announce('Upload failed (%s): %s' % (status, reason), self.announce('Upload failed (%s): %s' % (status, reason),
log.ERROR) log.ERROR)
if self.show_response: if self.show_response:
msg = '\n'.join(('-' * 75, result.read(), '-' * 75)) text = self._read_pypi_response(result)
msg = '\n'.join(('-' * 75, text, '-' * 75))
self.announce(msg, log.INFO) self.announce(msg, log.INFO)
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
Provides the PyPIRCCommand class, the base class for the command classes Provides the PyPIRCCommand class, the base class for the command classes
that uses .pypirc in the distutils.command package. that uses .pypirc in the distutils.command package.
""" """
import cgi
import os import os
from configparser import ConfigParser from configparser import ConfigParser
...@@ -101,6 +102,12 @@ class PyPIRCCommand(Command): ...@@ -101,6 +102,12 @@ class PyPIRCCommand(Command):
return {} return {}
def _read_pypi_response(self, response):
"""Read and decode a PyPI HTTP response."""
content_type = response.getheader('content-type', 'text/plain')
encoding = cgi.parse_header(content_type)[1].get('charset', 'ascii')
return response.read().decode(encoding)
def initialize_options(self): def initialize_options(self):
"""Initialize options.""" """Initialize options."""
self.repository = None self.repository = None
......
...@@ -6,6 +6,7 @@ from test.support import run_unittest ...@@ -6,6 +6,7 @@ from test.support import run_unittest
from distutils.command import upload as upload_mod 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
from distutils.log import INFO
from distutils.tests.test_config import PYPIRC, PyPIRCCommandTestCase from distutils.tests.test_config import PYPIRC, PyPIRCCommandTestCase
...@@ -48,6 +49,14 @@ class FakeOpen(object): ...@@ -48,6 +49,14 @@ class FakeOpen(object):
self.req = None self.req = None
self.msg = 'OK' self.msg = 'OK'
def getheader(self, name, default=None):
return {
'content-type': 'text/plain; charset=utf-8',
}.get(name.lower(), default)
def read(self):
return b'xyzzy'
def getcode(self): def getcode(self):
return 200 return 200
...@@ -108,10 +117,11 @@ class uploadTestCase(PyPIRCCommandTestCase): ...@@ -108,10 +117,11 @@ class uploadTestCase(PyPIRCCommandTestCase):
# lets run it # lets run it
pkg_dir, dist = self.create_dist(dist_files=dist_files) pkg_dir, dist = self.create_dist(dist_files=dist_files)
cmd = upload(dist) cmd = upload(dist)
cmd.show_response = 1
cmd.ensure_finalized() cmd.ensure_finalized()
cmd.run() cmd.run()
# what did we send ? # what did we send ?
headers = dict(self.last_open.req.headers) headers = dict(self.last_open.req.headers)
self.assertEqual(headers['Content-length'], '2087') self.assertEqual(headers['Content-length'], '2087')
self.assertTrue(headers['Content-type'].startswith('multipart/form-data')) self.assertTrue(headers['Content-type'].startswith('multipart/form-data'))
...@@ -120,6 +130,11 @@ class uploadTestCase(PyPIRCCommandTestCase): ...@@ -120,6 +130,11 @@ class uploadTestCase(PyPIRCCommandTestCase):
'https://pypi.python.org/pypi') 'https://pypi.python.org/pypi')
self.assertIn(b'xxx', self.last_open.req.data) self.assertIn(b'xxx', self.last_open.req.data)
# The PyPI response body was echoed
results = self.get_logs(INFO)
self.assertIn('xyzzy\n', results[-1])
def test_suite(): def test_suite():
return unittest.makeSuite(uploadTestCase) return unittest.makeSuite(uploadTestCase)
......
...@@ -29,6 +29,8 @@ Core and Builtins ...@@ -29,6 +29,8 @@ Core and Builtins
Library Library
------- -------
- Fix TypeError on "setup.py upload --show-response".
- Issue #12226: HTTPS is now used by default when connecting to PyPI. - Issue #12226: HTTPS is now used by default when connecting to PyPI.
- Issue #20045: Fix "setup.py register --list-classifiers". - Issue #20045: Fix "setup.py register --list-classifiers".
......
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