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""" version info, help messages, tracing configuration. """ 

2import os 

3import sys 

4from argparse import Action 

5 

6import py 

7 

8import pytest 

9from _pytest.config import PrintHelp 

10 

11 

12class HelpAction(Action): 

13 """This is an argparse Action that will raise an exception in 

14 order to skip the rest of the argument parsing when --help is passed. 

15 This prevents argparse from quitting due to missing required arguments 

16 when any are defined, for example by ``pytest_addoption``. 

17 This is similar to the way that the builtin argparse --help option is 

18 implemented by raising SystemExit. 

19 """ 

20 

21 def __init__(self, option_strings, dest=None, default=False, help=None): 

22 super().__init__( 

23 option_strings=option_strings, 

24 dest=dest, 

25 const=True, 

26 default=default, 

27 nargs=0, 

28 help=help, 

29 ) 

30 

31 def __call__(self, parser, namespace, values, option_string=None): 

32 setattr(namespace, self.dest, self.const) 

33 

34 # We should only skip the rest of the parsing after preparse is done 

35 if getattr(parser._parser, "after_preparse", False): 

36 raise PrintHelp 

37 

38 

39def pytest_addoption(parser): 

40 group = parser.getgroup("debugconfig") 

41 group.addoption( 

42 "--version", 

43 action="store_true", 

44 help="display pytest lib version and import information.", 

45 ) 

46 group._addoption( 

47 "-h", 

48 "--help", 

49 action=HelpAction, 

50 dest="help", 

51 help="show help message and configuration info", 

52 ) 

53 group._addoption( 

54 "-p", 

55 action="append", 

56 dest="plugins", 

57 default=[], 

58 metavar="name", 

59 help="early-load given plugin module name or entry point (multi-allowed). " 

60 "To avoid loading of plugins, use the `no:` prefix, e.g. " 

61 "`no:doctest`.", 

62 ) 

63 group.addoption( 

64 "--traceconfig", 

65 "--trace-config", 

66 action="store_true", 

67 default=False, 

68 help="trace considerations of conftest.py files.", 

69 ), 

70 group.addoption( 

71 "--debug", 

72 action="store_true", 

73 dest="debug", 

74 default=False, 

75 help="store internal tracing debug information in 'pytestdebug.log'.", 

76 ) 

77 group._addoption( 

78 "-o", 

79 "--override-ini", 

80 dest="override_ini", 

81 action="append", 

82 help='override ini option with "option=value" style, e.g. `-o xfail_strict=True -o cache_dir=cache`.', 

83 ) 

84 

85 

86@pytest.hookimpl(hookwrapper=True) 

87def pytest_cmdline_parse(): 

88 outcome = yield 

89 config = outcome.get_result() 

90 if config.option.debug: 

91 path = os.path.abspath("pytestdebug.log") 

92 debugfile = open(path, "w") 

93 debugfile.write( 

94 "versions pytest-%s, py-%s, " 

95 "python-%s\ncwd=%s\nargs=%s\n\n" 

96 % ( 

97 pytest.__version__, 

98 py.__version__, 

99 ".".join(map(str, sys.version_info)), 

100 os.getcwd(), 

101 config.invocation_params.args, 

102 ) 

103 ) 

104 config.trace.root.setwriter(debugfile.write) 

105 undo_tracing = config.pluginmanager.enable_tracing() 

106 sys.stderr.write("writing pytestdebug information to %s\n" % path) 

107 

108 def unset_tracing(): 

109 debugfile.close() 

110 sys.stderr.write("wrote pytestdebug information to %s\n" % debugfile.name) 

111 config.trace.root.setwriter(None) 

112 undo_tracing() 

113 

114 config.add_cleanup(unset_tracing) 

115 

116 

117def showversion(config): 

118 sys.stderr.write( 

119 "This is pytest version {}, imported from {}\n".format( 

120 pytest.__version__, pytest.__file__ 

121 ) 

122 ) 

123 plugininfo = getpluginversioninfo(config) 

124 if plugininfo: 

125 for line in plugininfo: 

126 sys.stderr.write(line + "\n") 

127 

128 

129def pytest_cmdline_main(config): 

130 if config.option.version: 

131 showversion(config) 

132 return 0 

133 elif config.option.help: 

134 config._do_configure() 

135 showhelp(config) 

136 config._ensure_unconfigure() 

137 return 0 

138 

139 

140def showhelp(config): 

141 import textwrap 

142 

143 reporter = config.pluginmanager.get_plugin("terminalreporter") 

144 tw = reporter._tw 

145 tw.write(config._parser.optparser.format_help()) 

146 tw.line() 

147 tw.line( 

148 "[pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg file found:" 

149 ) 

150 tw.line() 

151 

152 columns = tw.fullwidth # costly call 

153 indent_len = 24 # based on argparse's max_help_position=24 

154 indent = " " * indent_len 

155 for name in config._parser._ininames: 

156 help, type, default = config._parser._inidict[name] 

157 if type is None: 

158 type = "string" 

159 spec = "{} ({}):".format(name, type) 

160 tw.write(" %s" % spec) 

161 spec_len = len(spec) 

162 if spec_len > (indent_len - 3): 

163 # Display help starting at a new line. 

164 tw.line() 

165 helplines = textwrap.wrap( 

166 help, 

167 columns, 

168 initial_indent=indent, 

169 subsequent_indent=indent, 

170 break_on_hyphens=False, 

171 ) 

172 

173 for line in helplines: 

174 tw.line(line) 

175 else: 

176 # Display help starting after the spec, following lines indented. 

177 tw.write(" " * (indent_len - spec_len - 2)) 

178 wrapped = textwrap.wrap(help, columns - indent_len, break_on_hyphens=False) 

179 

180 tw.line(wrapped[0]) 

181 for line in wrapped[1:]: 

182 tw.line(indent + line) 

183 

184 tw.line() 

185 tw.line("environment variables:") 

186 vars = [ 

187 ("PYTEST_ADDOPTS", "extra command line options"), 

188 ("PYTEST_PLUGINS", "comma-separated plugins to load during startup"), 

189 ("PYTEST_DISABLE_PLUGIN_AUTOLOAD", "set to disable plugin auto-loading"), 

190 ("PYTEST_DEBUG", "set to enable debug tracing of pytest's internals"), 

191 ] 

192 for name, help in vars: 

193 tw.line(" {:<24} {}".format(name, help)) 

194 tw.line() 

195 tw.line() 

196 

197 tw.line("to see available markers type: pytest --markers") 

198 tw.line("to see available fixtures type: pytest --fixtures") 

199 tw.line( 

200 "(shown according to specified file_or_dir or current dir " 

201 "if not specified; fixtures with leading '_' are only shown " 

202 "with the '-v' option" 

203 ) 

204 

205 for warningreport in reporter.stats.get("warnings", []): 

206 tw.line("warning : " + warningreport.message, red=True) 

207 return 

208 

209 

210conftest_options = [("pytest_plugins", "list of plugin names to load")] 

211 

212 

213def getpluginversioninfo(config): 

214 lines = [] 

215 plugininfo = config.pluginmanager.list_plugin_distinfo() 

216 if plugininfo: 

217 lines.append("setuptools registered plugins:") 

218 for plugin, dist in plugininfo: 

219 loc = getattr(plugin, "__file__", repr(plugin)) 

220 content = "{}-{} at {}".format(dist.project_name, dist.version, loc) 

221 lines.append(" " + content) 

222 return lines 

223 

224 

225def pytest_report_header(config): 

226 lines = [] 

227 if config.option.debug or config.option.traceconfig: 

228 lines.append( 

229 "using: pytest-{} pylib-{}".format(pytest.__version__, py.__version__) 

230 ) 

231 

232 verinfo = getpluginversioninfo(config) 

233 if verinfo: 

234 lines.extend(verinfo) 

235 

236 if config.option.traceconfig: 

237 lines.append("active plugins:") 

238 items = config.pluginmanager.list_name_plugin() 

239 for name, plugin in items: 

240 if hasattr(plugin, "__file__"): 

241 r = plugin.__file__ 

242 else: 

243 r = repr(plugin) 

244 lines.append(" {:<20}: {}".format(name, r)) 

245 return lines