Issue #21722: The distutils "upload" command now exits with a non-zero return code when uploading fails.

Patch by Martin Dengler.
This commit is contained in:
Antoine Pitrou 2014-06-18 23:07:46 -04:00
parent 845fd9aa44
commit 2e4d3b133a
4 changed files with 24 additions and 11 deletions

View file

@ -2,10 +2,6 @@
Implements the Distutils 'upload' subcommand (upload package to PyPI).""" Implements the Distutils 'upload' subcommand (upload package to PyPI)."""
from distutils.errors import *
from distutils.core import PyPIRCCommand
from distutils.spawn import spawn
from distutils import log
import sys import sys
import os, io import os, io
import socket import socket
@ -13,6 +9,10 @@ import platform
from base64 import standard_b64encode from base64 import standard_b64encode
from urllib.request import urlopen, Request, HTTPError from urllib.request import urlopen, Request, HTTPError
from urllib.parse import urlparse from urllib.parse import urlparse
from distutils.errors import DistutilsError, DistutilsOptionError
from distutils.core import PyPIRCCommand
from distutils.spawn import spawn
from distutils import log
# this keeps compatibility for 2.3 and 2.4 # this keeps compatibility for 2.3 and 2.4
if sys.version < "2.5": if sys.version < "2.5":
@ -184,7 +184,7 @@ class upload(PyPIRCCommand):
reason = result.msg reason = result.msg
except OSError as e: except OSError as e:
self.announce(str(e), log.ERROR) self.announce(str(e), log.ERROR)
return raise
except HTTPError as e: except HTTPError as e:
status = e.code status = e.code
reason = e.msg reason = e.msg
@ -193,8 +193,9 @@ class upload(PyPIRCCommand):
self.announce('Server response (%s): %s' % (status, reason), self.announce('Server response (%s): %s' % (status, reason),
log.INFO) log.INFO)
else: else:
self.announce('Upload failed (%s): %s' % (status, reason), msg = 'Upload failed (%s): %s' % (status, reason)
log.ERROR) self.announce(msg, log.ERROR)
raise DistutilsError(msg)
if self.show_response: if self.show_response:
text = self._read_pypi_response(result) text = self._read_pypi_response(result)
msg = '\n'.join(('-' * 75, text, '-' * 75)) msg = '\n'.join(('-' * 75, text, '-' * 75))

View file

@ -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.errors import DistutilsError
from distutils.log import INFO from distutils.log import INFO
from distutils.tests.test_config import PYPIRC, PyPIRCCommandTestCase from distutils.tests.test_config import PYPIRC, PyPIRCCommandTestCase
@ -41,13 +42,14 @@ username:me
class FakeOpen(object): class FakeOpen(object):
def __init__(self, url): def __init__(self, url, msg=None, code=None):
self.url = url self.url = url
if not isinstance(url, str): if not isinstance(url, str):
self.req = url self.req = url
else: else:
self.req = None self.req = None
self.msg = 'OK' self.msg = msg or 'OK'
self.code = code or 200
def getheader(self, name, default=None): def getheader(self, name, default=None):
return { return {
@ -58,7 +60,7 @@ class FakeOpen(object):
return b'xyzzy' return b'xyzzy'
def getcode(self): def getcode(self):
return 200 return self.code
class uploadTestCase(PyPIRCCommandTestCase): class uploadTestCase(PyPIRCCommandTestCase):
@ -68,13 +70,15 @@ class uploadTestCase(PyPIRCCommandTestCase):
self.old_open = upload_mod.urlopen self.old_open = upload_mod.urlopen
upload_mod.urlopen = self._urlopen upload_mod.urlopen = self._urlopen
self.last_open = None self.last_open = None
self.next_msg = None
self.next_code = None
def tearDown(self): def tearDown(self):
upload_mod.urlopen = self.old_open upload_mod.urlopen = self.old_open
super(uploadTestCase, self).tearDown() super(uploadTestCase, self).tearDown()
def _urlopen(self, url): def _urlopen(self, url):
self.last_open = FakeOpen(url) self.last_open = FakeOpen(url, msg=self.next_msg, code=self.next_code)
return self.last_open return self.last_open
def test_finalize_options(self): def test_finalize_options(self):
@ -135,6 +139,10 @@ class uploadTestCase(PyPIRCCommandTestCase):
results = self.get_logs(INFO) results = self.get_logs(INFO)
self.assertIn('xyzzy\n', results[-1]) self.assertIn('xyzzy\n', results[-1])
def test_upload_fails(self):
self.next_msg = "Not Found"
self.next_code = 404
self.assertRaises(DistutilsError, self.test_upload)
def test_suite(): def test_suite():
return unittest.makeSuite(uploadTestCase) return unittest.makeSuite(uploadTestCase)

View file

@ -308,6 +308,7 @@ Vincent Delft
Arnaud Delobelle Arnaud Delobelle
Konrad Delong Konrad Delong
Erik Demaine Erik Demaine
Martin Dengler
John Dennis John Dennis
L. Peter Deutsch L. Peter Deutsch
Roger Dev Roger Dev

View file

@ -27,6 +27,9 @@ Core and Builtins
Library Library
------- -------
- Issue #21722: The distutils "upload" command now exits with a non-zero
return code when uploading fails. Patch by Martin Dengler.
- Issue #21723: asyncio.Queue: support any type of number (ex: float) for the - Issue #21723: asyncio.Queue: support any type of number (ex: float) for the
maximum size. Patch written by Vajrasky Kok. maximum size. Patch written by Vajrasky Kok.