Commit d47b6a2f authored by Antoine Pitrou's avatar Antoine Pitrou

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

Issue #21722: The distutils "upload" command now exits with a non-zero return code when uploading fails.
Patch by Martin Dengler.
parent 37ceab37
......@@ -2,10 +2,6 @@
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 os, io
import socket
......@@ -13,6 +9,10 @@ import platform
from base64 import standard_b64encode
from urllib.request import urlopen, Request, HTTPError
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
if sys.version < "2.5":
......@@ -184,7 +184,7 @@ class upload(PyPIRCCommand):
reason = result.msg
except OSError as e:
self.announce(str(e), log.ERROR)
return
raise
except HTTPError as e:
status = e.code
reason = e.msg
......@@ -193,8 +193,9 @@ class upload(PyPIRCCommand):
self.announce('Server response (%s): %s' % (status, reason),
log.INFO)
else:
self.announce('Upload failed (%s): %s' % (status, reason),
log.ERROR)
msg = 'Upload failed (%s): %s' % (status, reason)
self.announce(msg, log.ERROR)
raise DistutilsError(msg)
if self.show_response:
text = self._read_pypi_response(result)
msg = '\n'.join(('-' * 75, text, '-' * 75))
......
......@@ -6,6 +6,7 @@ from test.support import run_unittest
from distutils.command import upload as upload_mod
from distutils.command.upload import upload
from distutils.core import Distribution
from distutils.errors import DistutilsError
from distutils.log import INFO
from distutils.tests.test_config import PYPIRC, PyPIRCCommandTestCase
......@@ -41,13 +42,14 @@ username:me
class FakeOpen(object):
def __init__(self, url):
def __init__(self, url, msg=None, code=None):
self.url = url
if not isinstance(url, str):
self.req = url
else:
self.req = None
self.msg = 'OK'
self.msg = msg or 'OK'
self.code = code or 200
def getheader(self, name, default=None):
return {
......@@ -58,7 +60,7 @@ class FakeOpen(object):
return b'xyzzy'
def getcode(self):
return 200
return self.code
class uploadTestCase(PyPIRCCommandTestCase):
......@@ -68,13 +70,15 @@ class uploadTestCase(PyPIRCCommandTestCase):
self.old_open = upload_mod.urlopen
upload_mod.urlopen = self._urlopen
self.last_open = None
self.next_msg = None
self.next_code = None
def tearDown(self):
upload_mod.urlopen = self.old_open
super(uploadTestCase, self).tearDown()
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
def test_finalize_options(self):
......@@ -135,6 +139,10 @@ class uploadTestCase(PyPIRCCommandTestCase):
results = self.get_logs(INFO)
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():
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