test_ok1/bin-for-dist/makepluginlist.py

297 lines
9.8 KiB
Python

import os, sys
WIDTH = 75
plugins = [
('advanced python testing',
'skipping mark pdb figleaf coverage '
'monkeypatch capture recwarn tmpdir',),
('other testing domains, misc',
'oejskit django xdist genscript'),
('reporting and failure logging',
'pastebin logxml xmlresult resultlog terminal',),
('other testing conventions',
'unittest nose doctest restdoc'),
('core debugging / help functionality',
'helpconfig hooklog')
#('internal plugins / core functionality',
# #'runner execnetcleanup # pytester',
# 'runner execnetcleanup' # pytester',
#)
]
externals = {
'oejskit': "run javascript tests in real life browsers",
'django': "for testing django applications",
'coverage': "for testing with Ned's coverage module ",
'xmlresult': "for generating xml reports "
"and CruiseControl integration",
}
def warn(*args):
msg = " ".join(map(str, args))
print >>sys.stderr, "WARN:", msg
class RestWriter:
_all_links = {}
def __init__(self, target):
self.target = py.path.local(target)
self.links = []
def _getmsg(self, args):
return " ".join(map(str, args))
def Print(self, *args, **kwargs):
msg = self._getmsg(args)
if 'indent' in kwargs:
indent = kwargs['indent'] * " "
lines = [(indent + x) for x in msg.split("\n")]
msg = "\n".join(lines)
self.out.write(msg)
if not msg or msg[-1] != "\n":
self.out.write("\n")
self.out.flush()
def sourcecode(self, source):
lines = str(source).split("\n")
self.Print(".. sourcecode:: python")
self.Print()
for line in lines:
self.Print(" ", line)
def _sep(self, separator, args):
msg = self._getmsg(args)
sep = len(msg) * separator
self.Print()
self.Print(msg)
self.Print(sep)
self.Print()
def h1(self, *args):
self._sep('=', args)
def h2(self, *args):
self._sep('-', args)
def h3(self, *args):
self._sep('+', args)
def li(self, *args):
msg = self._getmsg(args)
sep = "* %s" %(msg)
self.Print(sep)
def dt(self, term):
self.Print("``%s``" % term)
def dd(self, doc):
self.Print(doc, indent=4)
def para(self, *args):
msg = self._getmsg(args)
self.Print(msg)
def add_internal_link(self, name, path):
relpath = path.new(ext=".html").relto(self.target.dirpath())
self.links.append((name, relpath))
def write_links(self):
self.Print()
self.Print(".. include:: links.txt")
for link in self.links:
key = link[0]
if key in self._all_links:
assert self._all_links[key] == link[1], (key, link[1])
else:
self._all_links[key] = link[1]
def write_all_links(cls, linkpath):
p = linkpath.new(basename="links.txt")
p_writer = RestWriter(p)
p_writer.out = p_writer.target.open("w")
for name, value in cls._all_links.items():
p_writer.Print(".. _`%s`: %s" % (name, value))
p_writer.out.close()
del p_writer.out
write_all_links = classmethod(write_all_links)
def make(self, **kwargs):
self.out = self.target.open("w")
self.makerest(**kwargs)
self.write_links()
self.out.close()
print "wrote", self.target
del self.out
class PluginOverview(RestWriter):
def makerest(self, config):
plugindir = py._pydir.join('plugin')
for cat, specs in plugins:
pluginlist = specs.split()
self.h1(cat)
for name in pluginlist:
oneliner = externals.get(name, None)
docpath = self.target.dirpath(name).new(ext=".txt")
if oneliner is not None:
htmlpath = docpath.new(ext='.html')
self.para("%s_ (external) %s" %(name, oneliner))
self.add_internal_link(name, htmlpath)
else:
doc = PluginDoc(docpath)
doc.make(config=config, name=name)
self.add_internal_link(name, doc.target)
self.para("%s_ %s" %(name, doc.oneliner))
self.Print()
class HookSpec(RestWriter):
def makerest(self, config):
module = config.pluginmanager.hook._hookspecs
source = py.code.Source(module)
self.h1("hook specification sourcecode")
self.sourcecode(source)
class PluginDoc(RestWriter):
def makerest(self, config, name):
config.pluginmanager.import_plugin(name)
plugin = config.pluginmanager.getplugin(name)
assert plugin is not None, plugin
print plugin
doc = plugin.__doc__.strip()
i = doc.find("\n")
if i == -1:
oneliner = doc
moduledoc = ""
else:
oneliner = doc[:i].strip()
moduledoc = doc[i+1:].strip()
self.name = oneliner # plugin.__name__.split(".")[-1]
self.oneliner = oneliner
self.moduledoc = moduledoc
#self.h1("%s plugin" % self.name) # : %s" %(self.name, self.oneliner))
self.h1(oneliner)
#self.Print(self.oneliner)
self.Print()
self.Print(".. contents::")
self.Print(" :local:")
self.Print()
self.Print(moduledoc)
self.emit_funcargs(plugin)
self.emit_options(plugin)
self.emit_source(plugin, config.hg_changeset)
#self.sourcelink = (purename,
# "http://bitbucket.org/hpk42/py-trunk/src/tip/py/test/plugin/" +
# purename + ".py")
#
def emit_source(self, plugin, hg_changeset):
basename = py.path.local(plugin.__file__).basename
if basename.endswith("pyc"):
basename = basename[:-1]
#self.para("`%s`_ source code" % basename)
#self.links.append((basename,
# "http://bitbucket.org/hpk42/py-trunk/src/tip/py/test/plugin/" +
# basename))
self.h1("Start improving this plugin in 30 seconds")
self.para(py.code.Source("""
1. Download `%s`_ plugin source code
2. put it somewhere as ``%s`` into your import path
3. a subsequent ``py.test`` run will use your local version
Checkout customize_, other plugins_ or `get in contact`_.
""" % (basename, basename)))
# your work appreciated if you offer back your version. In this case
# it probably makes sense if you `checkout the py.test
# development version`_ and apply your changes to the plugin
# version in there.
#self.links.append((basename,
# "http://bitbucket.org/hpk42/py-trunk/raw/%s/"
# "py/test/plugin/%s" %(hg_changeset, basename)))
self.links.append((basename,
"http://bitbucket.org/hpk42/py-trunk/raw/%s/"
"py/plugin/%s" %(pyversion, basename)))
self.links.append(('customize', '../customize.html'))
self.links.append(('plugins', 'index.html'))
self.links.append(('get in contact', '../../contact.html'))
self.links.append(('checkout the py.test development version',
'../../install.html#checkout'))
if 0: # this breaks the page layout and makes large doc files
#self.h2("plugin source code")
self.Print()
self.para("For your convenience here is also an inlined version "
"of ``%s``:" %basename)
#self(or copy-paste from below)
self.Print()
self.sourcecode(py.code.Source(plugin))
def emit_funcargs(self, plugin):
funcargfuncs = []
prefix = "pytest_funcarg__"
for name in vars(plugin):
if name.startswith(prefix):
funcargfuncs.append(getattr(plugin, name))
if not funcargfuncs:
return
for func in funcargfuncs:
argname = func.__name__[len(prefix):]
self.Print()
self.Print(".. _`%s funcarg`:" % argname)
self.Print()
self.h2("the %r test function argument" % argname)
if func.__doc__:
doclines = func.__doc__.split("\n")
source = py.code.Source("\n".join(doclines[1:]))
source.lines.insert(0, doclines[0])
self.para(str(source))
else:
self.para("XXX missing docstring")
warn("missing docstring", func)
def emit_options(self, plugin):
from py._test.parseopt import Parser
options = []
parser = Parser(processopt=options.append)
if hasattr(plugin, 'pytest_addoption'):
plugin.pytest_addoption(parser)
if not options:
return
self.h2("command line options")
self.Print()
formatter = py.std.optparse.IndentedHelpFormatter()
for opt in options:
switches = formatter.format_option_strings(opt)
self.Print("``%s``" % switches)
self.Print(opt.help, indent=4)
if __name__ == "__main__":
if os.path.exists("py"):
sys.path.insert(0, os.getcwd())
import py
_config = py.test.config
_config.parse([])
_config.pluginmanager.do_configure(_config)
pydir = py.path.local(py.__file__).dirpath()
pyversion = py.version
cmd = "hg tip --template '{node}'"
old = pydir.dirpath().chdir()
_config.hg_changeset = py.process.cmdexec(cmd).strip()
testdir = pydir.dirpath("doc", 'test')
ov = PluginOverview(testdir.join("plugin", "index.txt"))
ov.make(config=_config)
ov = HookSpec(testdir.join("plugin", "hookspec.txt"))
ov.make(config=_config)
RestWriter.write_all_links(testdir.join("plugin", "links.txt"))