[py-svn] pytest commit b7651df53029: remove restdoc plugin which now lives as pytest-restdoc on bitbucket,
commits-noreply at bitbucket.org
commits-noreply at bitbucket.org
Sun Oct 31 19:04:34 CET 2010
# HG changeset patch -- Bitbucket.org
# Project pytest
# URL http://bitbucket.org/hpk42/pytest/overview
# User holger krekel <holger at merlinux.eu>
# Date 1288548262 -3600
# Node ID b7651df530291c647314b300add17a24b72ac350
# Parent 4400a75da1653fbf4a932f58e720e33543148858
remove restdoc plugin which now lives as pytest-restdoc on bitbucket,
and be easily included in a project now (like PyPy which still needs it)
--- a/testing/plugin/test_restdoc.py
+++ /dev/null
@@ -1,96 +0,0 @@
-import py
-from pytest.plugin.restdoc import deindent
-
-def test_deindent():
- assert deindent('foo') == 'foo'
- assert deindent('foo\n bar') == 'foo\n bar'
- assert deindent(' foo\n bar\n') == 'foo\nbar\n'
- assert deindent(' foo\n\n bar\n') == 'foo\n\nbar\n'
- assert deindent(' foo\n bar\n') == 'foo\n bar\n'
- assert deindent(' foo\n bar\n') == ' foo\nbar\n'
-
-class TestDoctest:
- def setup_class(cls):
- py.test.importorskip("docutils")
-
- def pytest_funcarg__testdir(self, request):
- testdir = request.getfuncargvalue("testdir")
- testdir.plugins.append("restdoc")
- assert request.module.__name__ == __name__
- testdir.makepyfile(confrest=
- "from pytest.plugin.restdoc import Project")
- # we scope our confrest file so that it doesn't
- # conflict with another global confrest.py
- testdir.makepyfile(__init__="")
- return testdir
-
- def test_doctest_extra_exec(self, testdir):
- xtxt = testdir.maketxtfile(x="""
- hello::
- .. >>> raise ValueError
- >>> None
- """)
- result = testdir.runpytest(xtxt)
- result.stdout.fnmatch_lines(['*1 fail*'])
-
- def test_doctest_basic(self, testdir):
- xtxt = testdir.maketxtfile(x="""
- ..
- >>> from os.path import abspath
-
- hello world
-
- >>> assert abspath
- >>> i=3
- >>> print (i)
- 3
-
- yes yes
-
- >>> i
- 3
-
- end
- """)
- result = testdir.runpytest(xtxt)
- result.stdout.fnmatch_lines([
- "*2 passed*"
- ])
-
- def test_doctest_eol(self, testdir):
- ytxt = testdir.maketxtfile(y=".. >>> 1 + 1\r\n 2\r\n\r\n")
- result = testdir.runpytest(ytxt)
- result.stdout.fnmatch_lines(["*2 passed*"])
-
- def test_doctest_indentation(self, testdir):
- footxt = testdir.maketxtfile(foo=
- '..\n >>> print ("foo\\n bar")\n foo\n bar\n')
- result = testdir.runpytest(footxt)
- result.stdout.fnmatch_lines(["*2 passed*"])
-
- def test_js_ignore(self, testdir):
- xtxt = testdir.maketxtfile(xtxt="""
- `blah`_
-
- .. _`blah`: javascript:some_function()
- """)
- result = testdir.runpytest(xtxt)
- result.stdout.fnmatch_lines(["*3 passed*"])
-
- def test_pytest_doctest_prepare_content(self, testdir):
- testdir.makeconftest("""
- def pytest_doctest_prepare_content(content):
- return content.replace("False", "True")
- """)
- xtxt = testdir.maketxtfile(x="""
- hello:
-
- >>> 2 == 2
- False
-
- """)
- result = testdir.runpytest(xtxt)
- outcomes = result.parseoutcomes()
- assert outcomes['passed'] >= 1
- assert 'failed' not in outcomes
- assert 'skipped' not in outcomes
--- a/pytest/plugin/restdoc.py
+++ /dev/null
@@ -1,429 +0,0 @@
-"""
-perform ReST syntax, local and remote reference tests on .rst/.txt files.
-"""
-import py
-import sys, os, re
-
-def pytest_addoption(parser):
- group = parser.getgroup("ReST", "ReST documentation check options")
- group.addoption('-R', '--urlcheck',
- action="store_true", dest="urlcheck", default=False,
- help="urlopen() remote links found in ReST text files.")
- group.addoption('--urltimeout', action="store", metavar="secs",
- type="int", dest="urlcheck_timeout", default=5,
- help="timeout in seconds for remote urlchecks")
- group.addoption('--forcegen',
- action="store_true", dest="forcegen", default=False,
- help="force generation of html files.")
-
-def pytest_collect_file(path, parent):
- if path.ext in (".txt", ".rst"):
- project = getproject(path)
- if project is not None:
- return ReSTFile(path, parent=parent, project=project)
-
-def getproject(path):
- for parent in path.parts(reverse=True):
- confrest = parent.join("confrest.py")
- if confrest.check():
- Project = confrest.pyimport().Project
- return Project(parent)
-
-class ReSTFile(py.test.collect.File):
- def __init__(self, fspath, parent, project):
- super(ReSTFile, self).__init__(fspath=fspath, parent=parent)
- self.project = project
-
- def collect(self):
- return [
- ReSTSyntaxTest("ReSTSyntax", parent=self, project=self.project),
- LinkCheckerMaker("checklinks", parent=self),
- DoctestText("doctest", parent=self),
- ]
-
-def deindent(s, sep='\n'):
- leastspaces = -1
- lines = s.split(sep)
- for line in lines:
- if not line.strip():
- continue
- spaces = len(line) - len(line.lstrip())
- if leastspaces == -1 or spaces < leastspaces:
- leastspaces = spaces
- if leastspaces == -1:
- return s
- for i, line in enumerate(lines):
- if not line.strip():
- lines[i] = ''
- else:
- lines[i] = line[leastspaces:]
- return sep.join(lines)
-
-class ReSTSyntaxTest(py.test.collect.Item):
- def __init__(self, name, parent, project):
- super(ReSTSyntaxTest, self).__init__(name=name, parent=parent)
- self.project = project
-
- def reportinfo(self):
- return self.fspath, None, "syntax check"
-
- def runtest(self):
- self.restcheck(py.path.svnwc(self.fspath))
-
- def restcheck(self, path):
- py.test.importorskip("docutils")
- self.register_linkrole()
- from docutils.utils import SystemMessage
- try:
- self._checkskip(path, self.project.get_htmloutputpath(path))
- self.project.process(path)
- except KeyboardInterrupt:
- raise
- except SystemMessage:
- # we assume docutils printed info on stdout
- py.test.fail("docutils processing failed, see captured stderr")
-
- def register_linkrole(self):
- #directive.register_linkrole('api', self.resolve_linkrole)
- #directive.register_linkrole('source', self.resolve_linkrole)
-#
-# # XXX fake sphinx' "toctree" and refs
-# directive.register_linkrole('ref', self.resolve_linkrole)
-
- from docutils.parsers.rst import directives
- def toctree_directive(name, arguments, options, content, lineno,
- content_offset, block_text, state, state_machine):
- return []
- toctree_directive.content = 1
- toctree_directive.options = {'maxdepth': int, 'glob': directives.flag,
- 'hidden': directives.flag}
- directives.register_directive('toctree', toctree_directive)
- self.register_pygments()
-
- def register_pygments(self):
- # taken from pygments-main/external/rst-directive.py
- from docutils.parsers.rst import directives
- try:
- from pygments.formatters import HtmlFormatter
- except ImportError:
- def pygments_directive(name, arguments, options, content, lineno,
- content_offset, block_text, state, state_machine):
- return []
- pygments_directive.options = {}
- else:
- # The default formatter
- DEFAULT = HtmlFormatter(noclasses=True)
- # Add name -> formatter pairs for every variant you want to use
- VARIANTS = {
- # 'linenos': HtmlFormatter(noclasses=INLINESTYLES, linenos=True),
- }
-
- from docutils import nodes
-
- from pygments import highlight
- from pygments.lexers import get_lexer_by_name, TextLexer
-
- def pygments_directive(name, arguments, options, content, lineno,
- content_offset, block_text, state, state_machine):
- try:
- lexer = get_lexer_by_name(arguments[0])
- except ValueError:
- # no lexer found - use the text one instead of an exception
- lexer = TextLexer()
- # take an arbitrary option if more than one is given
- formatter = options and VARIANTS[options.keys()[0]] or DEFAULT
- parsed = highlight('\n'.join(content), lexer, formatter)
- return [nodes.raw('', parsed, format='html')]
-
- pygments_directive.options = dict([(key, directives.flag) for key in VARIANTS])
-
- pygments_directive.arguments = (1, 0, 1)
- pygments_directive.content = 1
- directives.register_directive('sourcecode', pygments_directive)
-
- def resolve_linkrole(self, name, text, check=True):
- apigen_relpath = self.project.apigen_relpath
-
- if name == 'api':
- if text == 'py':
- return ('py', apigen_relpath + 'api/index.html')
- else:
- assert text.startswith('py.'), (
- 'api link "%s" does not point to the py package') % (text,)
- dotted_name = text
- if dotted_name.find('(') > -1:
- dotted_name = dotted_name[:text.find('(')]
- # remove pkg root
- path = dotted_name.split('.')[1:]
- dotted_name = '.'.join(path)
- obj = py
- if check:
- for chunk in path:
- try:
- obj = getattr(obj, chunk)
- except AttributeError:
- raise AssertionError(
- 'problem with linkrole :api:`%s`: can not resolve '
- 'dotted name %s' % (text, dotted_name,))
- return (text, apigen_relpath + 'api/%s.html' % (dotted_name,))
- elif name == 'source':
- assert text.startswith('py/'), ('source link "%s" does not point '
- 'to the py package') % (text,)
- relpath = '/'.join(text.split('/')[1:])
- if check:
- pkgroot = py._pydir
- abspath = pkgroot.join(relpath)
- assert pkgroot.join(relpath).check(), (
- 'problem with linkrole :source:`%s`: '
- 'path %s does not exist' % (text, relpath))
- if relpath.endswith('/') or not relpath:
- relpath += 'index.html'
- else:
- relpath += '.html'
- return (text, apigen_relpath + 'source/%s' % (relpath,))
- elif name == 'ref':
- return ("", "")
-
- def _checkskip(self, lpath, htmlpath=None):
- if not self.config.getvalue("forcegen"):
- lpath = py.path.local(lpath)
- if htmlpath is not None:
- htmlpath = py.path.local(htmlpath)
- if lpath.ext == '.txt':
- htmlpath = htmlpath or lpath.new(ext='.html')
- if htmlpath.check(file=1) and htmlpath.mtime() >= lpath.mtime():
- py.test.skip("html file is up to date, use --forcegen to regenerate")
- #return [] # no need to rebuild
-
-class DoctestText(py.test.collect.Item):
- def reportinfo(self):
- return self.fspath, None, "doctest"
-
- def runtest(self):
- content = self._normalize_linesep()
- newcontent = self.config.hook.pytest_doctest_prepare_content(content=content)
- if newcontent is not None:
- content = newcontent
- s = content
- l = []
- prefix = '.. >>> '
- mod = py.std.types.ModuleType(self.fspath.purebasename)
- skipchunk = False
- for line in deindent(s).split('\n'):
- stripped = line.strip()
- if skipchunk and line.startswith(skipchunk):
- py.builtin.print_("skipping", line)
- continue
- skipchunk = False
- if stripped.startswith(prefix):
- try:
- py.builtin.exec_(py.code.Source(
- stripped[len(prefix):]).compile(), mod.__dict__)
- except ValueError:
- e = sys.exc_info()[1]
- if e.args and e.args[0] == "skipchunk":
- skipchunk = " " * (len(line) - len(line.lstrip()))
- else:
- raise
- else:
- l.append(line)
- docstring = "\n".join(l)
- mod.__doc__ = docstring
- failed, tot = py.std.doctest.testmod(mod, verbose=1)
- if failed:
- py.test.fail("doctest %s: %s failed out of %s" %(
- self.fspath, failed, tot))
-
- def _normalize_linesep(self):
- # XXX quite nasty... but it works (fixes win32 issues)
- s = self.fspath.read()
- linesep = '\n'
- if '\r' in s:
- if '\n' not in s:
- linesep = '\r'
- else:
- linesep = '\r\n'
- s = s.replace(linesep, '\n')
- return s
-
-class LinkCheckerMaker(py.test.collect.Collector):
- def collect(self):
- return list(self.genlinkchecks())
-
- def genlinkchecks(self):
- path = self.fspath
- # generating functions + args as single tests
- timeout = self.config.getvalue("urlcheck_timeout")
- for lineno, line in enumerate(path.readlines()):
- line = line.strip()
- if line.startswith('.. _'):
- if line.startswith('.. _`'):
- delim = '`:'
- else:
- delim = ':'
- l = line.split(delim, 1)
- if len(l) != 2:
- continue
- tryfn = l[1].strip()
- name = "%s:%d" %(tryfn, lineno)
- if tryfn.startswith('http:') or tryfn.startswith('https'):
- if self.config.getvalue("urlcheck"):
- yield CheckLink(name, parent=self,
- args=(tryfn, path, lineno, timeout), checkfunc=urlcheck)
- elif tryfn.startswith('webcal:'):
- continue
- else:
- i = tryfn.find('#')
- if i != -1:
- checkfn = tryfn[:i]
- else:
- checkfn = tryfn
- if checkfn.strip() and (1 or checkfn.endswith('.html')):
- yield CheckLink(name, parent=self,
- args=(tryfn, path, lineno), checkfunc=localrefcheck)
-
-class CheckLink(py.test.collect.Item):
- def __init__(self, name, parent, args, checkfunc):
- super(CheckLink, self).__init__(name, parent)
- self.args = args
- self.checkfunc = checkfunc
-
- def runtest(self):
- return self.checkfunc(*self.args)
-
- def reportinfo(self, basedir=None):
- return (self.fspath, self.args[2], "checklink: %s" % self.args[0])
-
-def urlcheck(tryfn, path, lineno, TIMEOUT_URLOPEN):
- old = py.std.socket.getdefaulttimeout()
- py.std.socket.setdefaulttimeout(TIMEOUT_URLOPEN)
- try:
- try:
- py.builtin.print_("trying remote", tryfn)
- py.std.urllib2.urlopen(tryfn)
- finally:
- py.std.socket.setdefaulttimeout(old)
- except (py.std.urllib2.URLError, py.std.urllib2.HTTPError):
- e = sys.exc_info()[1]
- if getattr(e, 'code', None) in (401, 403): # authorization required, forbidden
- py.test.skip("%s: %s" %(tryfn, str(e)))
- else:
- py.test.fail("remote reference error %r in %s:%d\n%s" %(
- tryfn, path.basename, lineno+1, e))
-
-def localrefcheck(tryfn, path, lineno):
- # assume it should be a file
- i = tryfn.find('#')
- if tryfn.startswith('javascript:'):
- return # don't check JS refs
- if i != -1:
- anchor = tryfn[i+1:]
- tryfn = tryfn[:i]
- else:
- anchor = ''
- fn = path.dirpath(tryfn)
- ishtml = fn.ext == '.html'
- fn = ishtml and fn.new(ext='.txt') or fn
- py.builtin.print_("filename is", fn)
- if not fn.check(): # not ishtml or not fn.check():
- if not py.path.local(tryfn).check(): # the html could be there
- py.test.fail("reference error %r in %s:%d" %(
- tryfn, path.basename, lineno+1))
- if anchor:
- source = unicode(fn.read(), 'latin1')
- source = source.lower().replace('-', ' ') # aehem
-
- anchor = anchor.replace('-', ' ')
- match2 = ".. _`%s`:" % anchor
- match3 = ".. _%s:" % anchor
- candidates = (anchor, match2, match3)
- py.builtin.print_("candidates", repr(candidates))
- for line in source.split('\n'):
- line = line.strip()
- if line in candidates:
- break
- else:
- py.test.fail("anchor reference error %s#%s in %s:%d" %(
- tryfn, anchor, path.basename, lineno+1))
-
-if hasattr(sys.stdout, 'fileno') and os.isatty(sys.stdout.fileno()):
- def log(msg):
- print(msg)
-else:
- def log(msg):
- pass
-
-def convert_rest_html(source, source_path, stylesheet=None, encoding='latin1'):
- """ return html latin1-encoded document for the given input.
- source a ReST-string
- sourcepath where to look for includes (basically)
- stylesheet path (to be used if any)
- """
- from docutils.core import publish_string
- kwargs = {
- 'stylesheet' : stylesheet,
- 'stylesheet_path': None,
- 'traceback' : 1,
- 'embed_stylesheet': 0,
- 'output_encoding' : encoding,
- #'halt' : 0, # 'info',
- 'halt_level' : 2,
- }
- # docutils uses os.getcwd() :-(
- source_path = os.path.abspath(str(source_path))
- prevdir = os.getcwd()
- try:
- #os.chdir(os.path.dirname(source_path))
- return publish_string(source, source_path, writer_name='html',
- settings_overrides=kwargs)
- finally:
- os.chdir(prevdir)
-
-def process(txtpath, encoding='latin1'):
- """ process a textfile """
- log("processing %s" % txtpath)
- assert txtpath.check(ext='.txt')
- if isinstance(txtpath, py.path.svnwc):
- txtpath = txtpath.localpath
- htmlpath = txtpath.new(ext='.html')
- #svninfopath = txtpath.localpath.new(ext='.svninfo')
-
- style = txtpath.dirpath('style.css')
- if style.check():
- stylesheet = style.basename
- else:
- stylesheet = None
- content = unicode(txtpath.read(), encoding)
- doc = convert_rest_html(content, txtpath, stylesheet=stylesheet, encoding=encoding)
- htmlpath.open('wb').write(doc)
- #log("wrote %r" % htmlpath)
- #if txtpath.check(svnwc=1, versioned=1):
- # info = txtpath.info()
- # svninfopath.dump(info)
-
-if sys.version_info > (3, 0):
- def _uni(s): return s
-else:
- def _uni(s):
- return unicode(s)
-
-rex1 = re.compile(r'.*<body>(.*)</body>.*', re.MULTILINE | re.DOTALL)
-rex2 = re.compile(r'.*<div class="document">(.*)</div>.*', re.MULTILINE | re.DOTALL)
-
-def strip_html_header(string, encoding='utf8'):
- """ return the content of the body-tag """
- uni = unicode(string, encoding)
- for rex in rex1,rex2:
- match = rex.search(uni)
- if not match:
- break
- uni = match.group(1)
- return uni
-
-class Project: # used for confrest.py files
- def __init__(self, sourcepath):
- self.sourcepath = sourcepath
- def process(self, path):
- return process(path)
- def get_htmloutputpath(self, path):
- return path.new(ext='html')
More information about the pytest-commit
mailing list