helpconfig.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. """ version info, help messages, tracing configuration. """
  2. from __future__ import absolute_import, division, print_function
  3. import py
  4. import pytest
  5. from _pytest.config import PrintHelp
  6. import os
  7. import sys
  8. from argparse import Action
  9. class HelpAction(Action):
  10. """This is an argparse Action that will raise an exception in
  11. order to skip the rest of the argument parsing when --help is passed.
  12. This prevents argparse from quitting due to missing required arguments
  13. when any are defined, for example by ``pytest_addoption``.
  14. This is similar to the way that the builtin argparse --help option is
  15. implemented by raising SystemExit.
  16. """
  17. def __init__(self, option_strings, dest=None, default=False, help=None):
  18. super(HelpAction, self).__init__(
  19. option_strings=option_strings,
  20. dest=dest,
  21. const=True,
  22. default=default,
  23. nargs=0,
  24. help=help,
  25. )
  26. def __call__(self, parser, namespace, values, option_string=None):
  27. setattr(namespace, self.dest, self.const)
  28. # We should only skip the rest of the parsing after preparse is done
  29. if getattr(parser._parser, "after_preparse", False):
  30. raise PrintHelp
  31. def pytest_addoption(parser):
  32. group = parser.getgroup("debugconfig")
  33. group.addoption(
  34. "--version",
  35. action="store_true",
  36. help="display pytest lib version and import information.",
  37. )
  38. group._addoption(
  39. "-h",
  40. "--help",
  41. action=HelpAction,
  42. dest="help",
  43. help="show help message and configuration info",
  44. )
  45. group._addoption(
  46. "-p",
  47. action="append",
  48. dest="plugins",
  49. default=[],
  50. metavar="name",
  51. help="early-load given plugin (multi-allowed). "
  52. "To avoid loading of plugins, use the `no:` prefix, e.g. "
  53. "`no:doctest`.",
  54. )
  55. group.addoption(
  56. "--traceconfig",
  57. "--trace-config",
  58. action="store_true",
  59. default=False,
  60. help="trace considerations of conftest.py files.",
  61. ),
  62. group.addoption(
  63. "--debug",
  64. action="store_true",
  65. dest="debug",
  66. default=False,
  67. help="store internal tracing debug information in 'pytestdebug.log'.",
  68. )
  69. group._addoption(
  70. "-o",
  71. "--override-ini",
  72. dest="override_ini",
  73. action="append",
  74. help='override ini option with "option=value" style, e.g. `-o xfail_strict=True -o cache_dir=cache`.',
  75. )
  76. @pytest.hookimpl(hookwrapper=True)
  77. def pytest_cmdline_parse():
  78. outcome = yield
  79. config = outcome.get_result()
  80. if config.option.debug:
  81. path = os.path.abspath("pytestdebug.log")
  82. debugfile = open(path, "w")
  83. debugfile.write(
  84. "versions pytest-%s, py-%s, "
  85. "python-%s\ncwd=%s\nargs=%s\n\n"
  86. % (
  87. pytest.__version__,
  88. py.__version__,
  89. ".".join(map(str, sys.version_info)),
  90. os.getcwd(),
  91. config._origargs,
  92. )
  93. )
  94. config.trace.root.setwriter(debugfile.write)
  95. undo_tracing = config.pluginmanager.enable_tracing()
  96. sys.stderr.write("writing pytestdebug information to %s\n" % path)
  97. def unset_tracing():
  98. debugfile.close()
  99. sys.stderr.write("wrote pytestdebug information to %s\n" % debugfile.name)
  100. config.trace.root.setwriter(None)
  101. undo_tracing()
  102. config.add_cleanup(unset_tracing)
  103. def pytest_cmdline_main(config):
  104. if config.option.version:
  105. p = py.path.local(pytest.__file__)
  106. sys.stderr.write(
  107. "This is pytest version %s, imported from %s\n" % (pytest.__version__, p)
  108. )
  109. plugininfo = getpluginversioninfo(config)
  110. if plugininfo:
  111. for line in plugininfo:
  112. sys.stderr.write(line + "\n")
  113. return 0
  114. elif config.option.help:
  115. config._do_configure()
  116. showhelp(config)
  117. config._ensure_unconfigure()
  118. return 0
  119. def showhelp(config):
  120. reporter = config.pluginmanager.get_plugin("terminalreporter")
  121. tw = reporter._tw
  122. tw.write(config._parser.optparser.format_help())
  123. tw.line()
  124. tw.line()
  125. tw.line(
  126. "[pytest] ini-options in the first " "pytest.ini|tox.ini|setup.cfg file found:"
  127. )
  128. tw.line()
  129. for name in config._parser._ininames:
  130. help, type, default = config._parser._inidict[name]
  131. if type is None:
  132. type = "string"
  133. spec = "%s (%s)" % (name, type)
  134. line = " %-24s %s" % (spec, help)
  135. tw.line(line[: tw.fullwidth])
  136. tw.line()
  137. tw.line("environment variables:")
  138. vars = [
  139. ("PYTEST_ADDOPTS", "extra command line options"),
  140. ("PYTEST_PLUGINS", "comma-separated plugins to load during startup"),
  141. ("PYTEST_DEBUG", "set to enable debug tracing of pytest's internals"),
  142. ]
  143. for name, help in vars:
  144. tw.line(" %-24s %s" % (name, help))
  145. tw.line()
  146. tw.line()
  147. tw.line("to see available markers type: pytest --markers")
  148. tw.line("to see available fixtures type: pytest --fixtures")
  149. tw.line(
  150. "(shown according to specified file_or_dir or current dir "
  151. "if not specified; fixtures with leading '_' are only shown "
  152. "with the '-v' option"
  153. )
  154. for warningreport in reporter.stats.get("warnings", []):
  155. tw.line("warning : " + warningreport.message, red=True)
  156. return
  157. conftest_options = [("pytest_plugins", "list of plugin names to load")]
  158. def getpluginversioninfo(config):
  159. lines = []
  160. plugininfo = config.pluginmanager.list_plugin_distinfo()
  161. if plugininfo:
  162. lines.append("setuptools registered plugins:")
  163. for plugin, dist in plugininfo:
  164. loc = getattr(plugin, "__file__", repr(plugin))
  165. content = "%s-%s at %s" % (dist.project_name, dist.version, loc)
  166. lines.append(" " + content)
  167. return lines
  168. def pytest_report_header(config):
  169. lines = []
  170. if config.option.debug or config.option.traceconfig:
  171. lines.append("using: pytest-%s pylib-%s" % (pytest.__version__, py.__version__))
  172. verinfo = getpluginversioninfo(config)
  173. if verinfo:
  174. lines.extend(verinfo)
  175. if config.option.traceconfig:
  176. lines.append("active plugins:")
  177. items = config.pluginmanager.list_name_plugin()
  178. for name, plugin in items:
  179. if hasattr(plugin, "__file__"):
  180. r = plugin.__file__
  181. else:
  182. r = repr(plugin)
  183. lines.append(" %-20s: %s" % (name, r))
  184. return lines