Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1""" submit failure or test session information to a pastebin service. """ 

2import tempfile 

3 

4import pytest 

5 

6 

7def pytest_addoption(parser): 

8 group = parser.getgroup("terminal reporting") 

9 group._addoption( 

10 "--pastebin", 

11 metavar="mode", 

12 action="store", 

13 dest="pastebin", 

14 default=None, 

15 choices=["failed", "all"], 

16 help="send failed|all info to bpaste.net pastebin service.", 

17 ) 

18 

19 

20@pytest.hookimpl(trylast=True) 

21def pytest_configure(config): 

22 if config.option.pastebin == "all": 

23 tr = config.pluginmanager.getplugin("terminalreporter") 

24 # if no terminal reporter plugin is present, nothing we can do here; 

25 # this can happen when this function executes in a slave node 

26 # when using pytest-xdist, for example 

27 if tr is not None: 

28 # pastebin file will be utf-8 encoded binary file 

29 config._pastebinfile = tempfile.TemporaryFile("w+b") 

30 oldwrite = tr._tw.write 

31 

32 def tee_write(s, **kwargs): 

33 oldwrite(s, **kwargs) 

34 if isinstance(s, str): 

35 s = s.encode("utf-8") 

36 config._pastebinfile.write(s) 

37 

38 tr._tw.write = tee_write 

39 

40 

41def pytest_unconfigure(config): 

42 if hasattr(config, "_pastebinfile"): 

43 # get terminal contents and delete file 

44 config._pastebinfile.seek(0) 

45 sessionlog = config._pastebinfile.read() 

46 config._pastebinfile.close() 

47 del config._pastebinfile 

48 # undo our patching in the terminal reporter 

49 tr = config.pluginmanager.getplugin("terminalreporter") 

50 del tr._tw.__dict__["write"] 

51 # write summary 

52 tr.write_sep("=", "Sending information to Paste Service") 

53 pastebinurl = create_new_paste(sessionlog) 

54 tr.write_line("pastebin session-log: %s\n" % pastebinurl) 

55 

56 

57def create_new_paste(contents): 

58 """ 

59 Creates a new paste using bpaste.net service. 

60 

61 :contents: paste contents as utf-8 encoded bytes 

62 :returns: url to the pasted contents or error message 

63 """ 

64 import re 

65 from urllib.request import urlopen 

66 from urllib.parse import urlencode 

67 

68 params = {"code": contents, "lexer": "text", "expiry": "1week"} 

69 url = "https://bpaste.net" 

70 try: 

71 response = ( 

72 urlopen(url, data=urlencode(params).encode("ascii")).read().decode("utf-8") 

73 ) 

74 except OSError as exc_info: # urllib errors 

75 return "bad response: %s" % exc_info 

76 m = re.search(r'href="/raw/(\w+)"', response) 

77 if m: 

78 return "{}/show/{}".format(url, m.group(1)) 

79 else: 

80 return "bad response: invalid format ('" + response + "')" 

81 

82 

83def pytest_terminal_summary(terminalreporter): 

84 import _pytest.config 

85 

86 if terminalreporter.config.option.pastebin != "failed": 

87 return 

88 tr = terminalreporter 

89 if "failed" in tr.stats: 

90 terminalreporter.write_sep("=", "Sending information to Paste Service") 

91 for rep in terminalreporter.stats.get("failed"): 

92 try: 

93 msg = rep.longrepr.reprtraceback.reprentries[-1].reprfileloc 

94 except AttributeError: 

95 msg = tr._getfailureheadline(rep) 

96 tw = _pytest.config.create_terminal_writer( 

97 terminalreporter.config, stringio=True 

98 ) 

99 rep.toterminal(tw) 

100 s = tw.stringio.getvalue() 

101 assert len(s) 

102 pastebinurl = create_new_paste(s) 

103 tr.write_line("{} --> {}".format(msg, pastebinurl))