From 537dca477bf7ef9294b4a6466a1063c64ad2c17a Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 22 Oct 2014 21:52:40 -0200 Subject: [PATCH] Fixing --pastebin option by using a POST request instead of a XMLRPC call fixes #614 --HG-- branch : fix-pastebin --- CHANGELOG | 3 ++ _pytest/pastebin.py | 47 ++++++++++++++++++---------- testing/test_pastebin.py | 67 ++++++++++++++++++++++++++++------------ 3 files changed, 82 insertions(+), 35 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 009ece156..a92ecf4cc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,9 @@ - "python_classes" and "python_functions" options now support glob-patterns for test discovery, as discussed in issue600. Thanks Ldiary Translations. +- fix issue614: fixed pastebin support. + + 2.6.4.dev ---------- diff --git a/_pytest/pastebin.py b/_pytest/pastebin.py index 4151fbf0d..be4b464f8 100644 --- a/_pytest/pastebin.py +++ b/_pytest/pastebin.py @@ -3,10 +3,6 @@ import pytest import py, sys import tempfile -class url: - base = "http://bpaste.net" - xmlrpc = base + "/xmlrpc/" - show = base + "/show/" def pytest_addoption(parser): group = parser.getgroup("terminal reporting") @@ -28,22 +24,45 @@ def pytest_configure(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": @@ -51,9 +70,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 @@ -63,6 +79,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