Gracefully handle HTTP errors from pastebin
We find that the --pastebin option to pytest sometimes fails with "HTTP Error 400: Bad Request". We're still investigating the exact cause of these errors, but in the meantime, a failure to upload to the pastebin service should probably not crash pytest and cause a test failure in the continuous-integration. This patch catches exceptions like HTTPError that may be thrown while trying to communicate with the pastebin service, and reports them as a "bad response", without crashing with a backtrace or failing the entire test suite.
This commit is contained in:
parent
5bf9f9a711
commit
d47b9d04d4
1
AUTHORS
1
AUTHORS
|
@ -173,6 +173,7 @@ mbyt
|
||||||
Michael Aquilina
|
Michael Aquilina
|
||||||
Michael Birtwell
|
Michael Birtwell
|
||||||
Michael Droettboom
|
Michael Droettboom
|
||||||
|
Michael Goerz
|
||||||
Michael Seifert
|
Michael Seifert
|
||||||
Michal Wajszczuk
|
Michal Wajszczuk
|
||||||
Mihai Capotă
|
Mihai Capotă
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
New behavior of the ``--pastebin`` option: failures to connect to the pastebin server are reported, without failing the pytest run
|
|
@ -59,7 +59,7 @@ def create_new_paste(contents):
|
||||||
Creates a new paste using bpaste.net service.
|
Creates a new paste using bpaste.net service.
|
||||||
|
|
||||||
:contents: paste contents as utf-8 encoded bytes
|
:contents: paste contents as utf-8 encoded bytes
|
||||||
:returns: url to the pasted contents
|
:returns: url to the pasted contents or error message
|
||||||
"""
|
"""
|
||||||
import re
|
import re
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
@ -67,12 +67,17 @@ def create_new_paste(contents):
|
||||||
|
|
||||||
params = {"code": contents, "lexer": "python3", "expiry": "1week"}
|
params = {"code": contents, "lexer": "python3", "expiry": "1week"}
|
||||||
url = "https://bpaste.net"
|
url = "https://bpaste.net"
|
||||||
response = urlopen(url, data=urlencode(params).encode("ascii")).read()
|
try:
|
||||||
m = re.search(r'href="/raw/(\w+)"', response.decode("utf-8"))
|
response = (
|
||||||
|
urlopen(url, data=urlencode(params).encode("ascii")).read().decode("utf-8")
|
||||||
|
)
|
||||||
|
except OSError as exc_info: # urllib errors
|
||||||
|
return "bad response: %s" % exc_info
|
||||||
|
m = re.search(r'href="/raw/(\w+)"', response)
|
||||||
if m:
|
if m:
|
||||||
return "{}/show/{}".format(url, m.group(1))
|
return "{}/show/{}".format(url, m.group(1))
|
||||||
else:
|
else:
|
||||||
return "bad response: " + response.decode("utf-8")
|
return "bad response: invalid format ('" + response + "')"
|
||||||
|
|
||||||
|
|
||||||
def pytest_terminal_summary(terminalreporter):
|
def pytest_terminal_summary(terminalreporter):
|
||||||
|
|
|
@ -82,6 +82,47 @@ class TestPaste:
|
||||||
def pastebin(self, request):
|
def pastebin(self, request):
|
||||||
return request.config.pluginmanager.getplugin("pastebin")
|
return request.config.pluginmanager.getplugin("pastebin")
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mocked_urlopen_fail(self, monkeypatch):
|
||||||
|
"""
|
||||||
|
monkeypatch the actual urlopen call to emulate a HTTP Error 400
|
||||||
|
"""
|
||||||
|
calls = []
|
||||||
|
|
||||||
|
import urllib.error
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
def mocked(url, data):
|
||||||
|
calls.append((url, data))
|
||||||
|
raise urllib.error.HTTPError(url, 400, "Bad request", None, None)
|
||||||
|
|
||||||
|
monkeypatch.setattr(urllib.request, "urlopen", mocked)
|
||||||
|
return calls
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mocked_urlopen_invalid(self, monkeypatch):
|
||||||
|
"""
|
||||||
|
monkeypatch the actual urlopen calls done by the internal plugin
|
||||||
|
function that connects to bpaste service, but return a url in an
|
||||||
|
unexpected format
|
||||||
|
"""
|
||||||
|
calls = []
|
||||||
|
|
||||||
|
def mocked(url, data):
|
||||||
|
calls.append((url, data))
|
||||||
|
|
||||||
|
class DummyFile:
|
||||||
|
def read(self):
|
||||||
|
# part of html of a normal response
|
||||||
|
return b'View <a href="/invalid/3c0c6750bd">raw</a>.'
|
||||||
|
|
||||||
|
return DummyFile()
|
||||||
|
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
monkeypatch.setattr(urllib.request, "urlopen", mocked)
|
||||||
|
return calls
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def mocked_urlopen(self, monkeypatch):
|
def mocked_urlopen(self, monkeypatch):
|
||||||
"""
|
"""
|
||||||
|
@ -105,6 +146,19 @@ class TestPaste:
|
||||||
monkeypatch.setattr(urllib.request, "urlopen", mocked)
|
monkeypatch.setattr(urllib.request, "urlopen", mocked)
|
||||||
return calls
|
return calls
|
||||||
|
|
||||||
|
def test_pastebin_invalid_url(self, pastebin, mocked_urlopen_invalid):
|
||||||
|
result = pastebin.create_new_paste(b"full-paste-contents")
|
||||||
|
assert (
|
||||||
|
result
|
||||||
|
== "bad response: invalid format ('View <a href=\"/invalid/3c0c6750bd\">raw</a>.')"
|
||||||
|
)
|
||||||
|
assert len(mocked_urlopen_invalid) == 1
|
||||||
|
|
||||||
|
def test_pastebin_http_error(self, pastebin, mocked_urlopen_fail):
|
||||||
|
result = pastebin.create_new_paste(b"full-paste-contents")
|
||||||
|
assert result == "bad response: HTTP Error 400: Bad request"
|
||||||
|
assert len(mocked_urlopen_fail) == 1
|
||||||
|
|
||||||
def test_create_new_paste(self, pastebin, mocked_urlopen):
|
def test_create_new_paste(self, pastebin, mocked_urlopen):
|
||||||
result = pastebin.create_new_paste(b"full-paste-contents")
|
result = pastebin.create_new_paste(b"full-paste-contents")
|
||||||
assert result == "https://bpaste.net/show/3c0c6750bd"
|
assert result == "https://bpaste.net/show/3c0c6750bd"
|
||||||
|
@ -127,4 +181,4 @@ class TestPaste:
|
||||||
|
|
||||||
monkeypatch.setattr(urllib.request, "urlopen", response)
|
monkeypatch.setattr(urllib.request, "urlopen", response)
|
||||||
result = pastebin.create_new_paste(b"full-paste-contents")
|
result = pastebin.create_new_paste(b"full-paste-contents")
|
||||||
assert result == "bad response: something bad occurred"
|
assert result == "bad response: invalid format ('something bad occurred')"
|
||||||
|
|
Loading…
Reference in New Issue