From 60cdb875ed17f1e6ca0b189a4bc2cb12de5835f4 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 24 Oct 2014 15:24:44 +0200 Subject: [PATCH] backport pastebin fix --HG-- branch : pytest-2.6 --- CHANGELOG | 4 ++- _pytest/pastebin.py | 47 ++++++++++++++++++---------- testing/test_pastebin.py | 67 ++++++++++++++++++++++++++++------------ 3 files changed, 82 insertions(+), 36 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 221666d6e..9f56a0e84 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -2.6.4.dev +2.6.4 ---------- - Improve assertion failure reporting on iterables, by using ndiff and pprint. @@ -18,6 +18,8 @@ - fix issue620: add explanation in the --genscript target about what the binary blob means. Thanks Dinu Gherman. +- fix issue614: fixed pastebin support. + 2.6.3 ----------- diff --git a/_pytest/pastebin.py b/_pytest/pastebin.py index cc9d0b5f0..16bb1b63e 100644 --- a/_pytest/pastebin.py +++ b/_pytest/pastebin.py @@ -1,10 +1,6 @@ """ submit failure or test session information to a pastebin service. """ import py, sys -class url: - base = "http://bpaste.net" - xmlrpc = base + "/xmlrpc/" - show = base + "/show/" def pytest_addoption(parser): group = parser.getgroup("terminal reporting") @@ -27,22 +23,45 @@ def pytest_configure(__multicall__, config): def pytest_unconfigure(config): if hasattr(config, '_pastebinfile'): + # get terminal contents and delete file config._pastebinfile.seek(0) sessionlog = config._pastebinfile.read() config._pastebinfile.close() del config._pastebinfile - proxyid = getproxy().newPaste("python", sessionlog) - pastebinurl = "%s%s" % (url.show, proxyid) - sys.stderr.write("pastebin session-log: %s\n" % pastebinurl) + # undo our patching in the terminal reporter tr = config.pluginmanager.getplugin('terminalreporter') del tr._tw.__dict__['write'] + # write summary + tr.write_sep("=", "Sending information to Paste Service") + pastebinurl = create_new_paste(sessionlog) + tr.write_line("pastebin session-log: %s\n" % pastebinurl) -def getproxy(): +def create_new_paste(contents): + """ + Creates a new paste using bpaste.net service. + + :contents: paste contents + :returns: url to the pasted contents + """ + import re if sys.version_info < (3, 0): - from xmlrpclib import ServerProxy + from urllib import urlopen, urlencode else: - from xmlrpc.client import ServerProxy - return ServerProxy(url.xmlrpc).pastes + from urllib.request import urlopen + from urllib.parse import urlencode + + params = { + 'code': contents, + 'lexer': 'python3' if sys.version_info[0] == 3 else 'python', + 'expiry': '1week', + } + url = 'https://bpaste.net' + response = urlopen(url, data=urlencode(params)).read() + m = re.search(r'href="/raw/(\w+)"', response) + if m: + return '%s/show/%s' % (url, m.group(1)) + else: + return 'bad response: ' + response def pytest_terminal_summary(terminalreporter): if terminalreporter.config.option.pastebin != "failed": @@ -50,9 +69,6 @@ def pytest_terminal_summary(terminalreporter): tr = terminalreporter if 'failed' in tr.stats: terminalreporter.write_sep("=", "Sending information to Paste Service") - if tr.config.option.debug: - terminalreporter.write_line("xmlrpcurl: %s" %(url.xmlrpc,)) - serverproxy = getproxy() for rep in terminalreporter.stats.get('failed'): try: msg = rep.longrepr.reprtraceback.reprentries[-1].reprfileloc @@ -62,6 +78,5 @@ def pytest_terminal_summary(terminalreporter): rep.toterminal(tw) s = tw.stringio.getvalue() assert len(s) - proxyid = serverproxy.newPaste("python", s) - pastebinurl = "%s%s" % (url.show, proxyid) + pastebinurl = create_new_paste(s) tr.write_line("%s --> %s" %(msg, pastebinurl)) diff --git a/testing/test_pastebin.py b/testing/test_pastebin.py index c81bf88bf..1b5fb1dca 100644 --- a/testing/test_pastebin.py +++ b/testing/test_pastebin.py @@ -1,13 +1,13 @@ +import sys +import pytest class TestPasting: - def pytest_funcarg__pastebinlist(self, request): - mp = request.getfuncargvalue("monkeypatch") + + @pytest.fixture + def pastebinlist(self, monkeypatch, request): pastebinlist = [] - class MockProxy: - def newPaste(self, language, code): - pastebinlist.append((language, code)) plugin = request.config.pluginmanager.getplugin('pastebin') - mp.setattr(plugin, 'getproxy', MockProxy) + monkeypatch.setattr(plugin, 'create_new_paste', pastebinlist.append) return pastebinlist def test_failed(self, testdir, pastebinlist): @@ -22,8 +22,7 @@ class TestPasting: """) reprec = testdir.inline_run(testpath, "--paste=failed") assert len(pastebinlist) == 1 - assert pastebinlist[0][0] == "python" - s = pastebinlist[0][1] + s = pastebinlist[0] assert s.find("def test_fail") != -1 assert reprec.countoutcomes() == [1,1,1] @@ -37,22 +36,52 @@ class TestPasting: def test_skip(): pytest.skip("") """) - reprec = testdir.inline_run(testpath, "--pastebin=all") + reprec = testdir.inline_run(testpath, "--pastebin=all", '-v') assert reprec.countoutcomes() == [1,1,1] assert len(pastebinlist) == 1 - assert pastebinlist[0][0] == "python" - s = pastebinlist[0][1] - for x in 'test_fail test_skip skipped'.split(): - assert s.find(x), (s, x) + s = pastebinlist[0] + for x in 'test_fail test_skip test_pass'.split(): + assert x in s -class TestRPCClient: - def pytest_funcarg__pastebin(self, request): +class TestPaste: + + @pytest.fixture + def pastebin(self, request): return request.config.pluginmanager.getplugin('pastebin') - def test_getproxy(self, pastebin): - proxy = pastebin.getproxy() - assert proxy is not None - assert proxy.__class__.__module__.startswith('xmlrpc') + @pytest.fixture + def mocked_urlopen(self, monkeypatch): + """ + monkeypatch the actual urlopen calls done by the internal plugin + function that connects to bpaste service. + """ + calls = [] + def mocked(url, data): + calls.append((url, data)) + class DummyFile: + def read(self): + # part of html of a normal response + return 'View raw.' + return DummyFile() + + if sys.version_info < (3, 0): + import urllib + monkeypatch.setattr(urllib, 'urlopen', mocked) + else: + import urllib.request + monkeypatch.setattr(urllib.request, 'urlopen', mocked) + return calls + + def test_create_new_paste(self, pastebin, mocked_urlopen): + result = pastebin.create_new_paste('full-paste-contents') + assert result == 'https://bpaste.net/show/3c0c6750bd' + assert len(mocked_urlopen) == 1 + url, data = mocked_urlopen[0] + lexer = 'python3' if sys.version_info[0] == 3 else 'python' + assert url == 'https://bpaste.net' + assert 'lexer=%s' % lexer in data + assert 'code=full-paste-contents' in data + assert 'expiry=1week' in data