-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
initial commit, got console stuff working but its still a long way to
first actual release
- Loading branch information
0 parents
commit 5664573
Showing
7 changed files
with
232 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
`Sphinx`_ is one freaking great tool to write documentation. Not just python | ||
documentation, all kinds of documentation. And there is a big reason why to | ||
write documentation in `Sphinx`_. You can write code which will be nicely | ||
formated for you with all the shines. | ||
|
||
.. contents | ||
|
||
What happens if you want to test your documentation? | ||
---------------------------------------------------- | ||
|
||
Well not much. There is a build-in plugin `sphinx.ext.docstest`_ which enables | ||
you to do some testing, but is limited to only python. And how to test all that | ||
console commands? Using python? I am pythonista, but testing console commands | ||
with ptyhon os.system or similar sounds wrong and anybody doing this will burn | ||
in hell anyway. | ||
|
||
So here is where `sphinx.testing` comes in. It will use all those `.. | ||
code-block:: ` and `.. sourcecode::` blocks you have laying around in your | ||
documentation and run them for you, optionaly if you want it ofcourse. For now | ||
we only support python and console type of blocks, but its easy to extend and | ||
provide general test runner for any language that is actually supported by `.. | ||
code-block:`, which is basicaly what `Pygments`_ support (`list of lexers`_). | ||
|
||
|
||
TODO: write how to use it | ||
|
||
Credits | ||
======= | ||
|
||
* `Rok Garbas`_, author | ||
|
||
* `Manuel`_, for inspiration and all the documentation i borrowed and implement it to be more tightly integrated with sphinx. | ||
* `plone.testing`_, for pusing me to do this. once you taste the sweetness of layers you want to use them anywhere | ||
* `mrsd`_, to be first package to use this SphinxTestSuite | ||
|
||
Todo | ||
==== | ||
|
||
* support for python and "python cosole" aka doctests | ||
|
||
|
||
Changelog | ||
========= | ||
|
||
0.1 - 2010-09-01 | ||
---------------- | ||
|
||
* support for shell console code-block testing | ||
* initial release | ||
|
||
|
||
.. _`Sphinx`: http://sphinx.pocoo.org | ||
.. _`sphinx.ext.doctest`: http://sphinx.pocoo.org/ext/doctest.html | ||
.. _`Rok Garbas`: http://www.garbas.si | ||
.. _`plone.testing`: http://pypi.python.org/pypi/plone.testing | ||
.. _`mrsd`: http://pypi.python.org/pypi/mrsd | ||
.. _`Manuel`: http://pypi.python.org/pypi/manuel | ||
.. _`list of lexers`: http://pygments.org/docs/lexers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
from setuptools import setup, find_packages | ||
import os | ||
|
||
version = '0.1' | ||
|
||
setup(name='sphinx.testing', | ||
version=version, | ||
description="", | ||
long_description=open("README.txt").read(), | ||
# Get more strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers | ||
classifiers=[ | ||
"Programming Language :: Python", | ||
], | ||
keywords='', | ||
author='', | ||
author_email='', | ||
url='http://svn.plone.org/svn/collective/', | ||
license='GPL', | ||
packages=find_packages(exclude=['ez_setup']), | ||
namespace_packages=['sphinx'], | ||
include_package_data=True, | ||
zip_safe=False, | ||
install_requires=[ | ||
'setuptools', | ||
# -*- Extra requirements: -*- | ||
], | ||
extras_require={ | ||
'layer': [ | ||
'plone.testing', | ||
] | ||
}, | ||
entry_points=""" | ||
# -*- Entry points: -*- | ||
""", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages | ||
try: | ||
__import__('pkg_resources').declare_namespace(__name__) | ||
except ImportError: | ||
from pkgutil import extend_path | ||
__path__ = extend_path(__path__, __name__) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
import directive | ||
from suite import SphinxTestSuite |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
|
||
import subprocess | ||
import unittest2 as unittest | ||
|
||
|
||
class ConsoleTestCase(unittest.TestCase): | ||
|
||
def runTest(self): | ||
for command, expected_result in self.commands: | ||
p = subprocess.Popen(command.split(), | ||
stderr=subprocess.STDOUT, | ||
stdout=subprocess.PIPE, | ||
cwd=self.layer['buildout-directory']) | ||
result, _ = p.communicate() | ||
p.wait() | ||
result = result.rstrip('\n') | ||
self.assertEqual(expected_result, result) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import case | ||
import pygments.token | ||
import pygments.lexers | ||
import docutils.parsers.rst | ||
|
||
class CodeBlock(docutils.parsers.rst.Directive): | ||
|
||
has_content = True | ||
required_arguments = 1 | ||
optional_arguments = 1 | ||
final_argument_whitespace = True | ||
option_spec = dict( | ||
layer=docutils.parsers.rst.directives.unchanged) | ||
|
||
def run(self): | ||
self.assert_has_content() | ||
try: | ||
lexer = pygments.lexers.get_lexer_by_name(self.arguments[0]) | ||
except Exception, e: | ||
raise Exception('No appropriate lexer found for this ' | ||
'code-block: ' + self.arguments[0]) | ||
|
||
if self.arguments[0] == 'console': | ||
test = case.ConsoleTestCase() | ||
test.commands = [] | ||
test = self.prompt_parser(test, lexer) | ||
else: | ||
raise Exception('No testcase for code-block ' | ||
'found: ' + self.arguments[0]) | ||
return [docutils.nodes.raw(test, '')] | ||
|
||
def prompt_parser(self, test, lexer): | ||
command, expected_result = '', '' | ||
for item in lexer.get_tokens(u'\n'.join(self.content)): | ||
if item[0] == pygments.token.Token.Generic.Output: | ||
expected_result += item[1] | ||
elif item[0] not in [pygments.token.Token.Generic.Prompt, | ||
pygments.token.Token.Literal.String.Escape,]: | ||
command += item[1] | ||
if command and \ | ||
item[0] == pygments.token.Token.Generic.Prompt and \ | ||
item[1] in ['#', '$', '%']: # FIXME: should be generic | ||
test.commands.append((command.strip(), | ||
expected_result.rstrip('\n'))) | ||
command, expected_result = '', '' | ||
test.commands.append((command.strip(), | ||
expected_result.rstrip('\n'))) | ||
return test | ||
|
||
docutils.parsers.rst.directives.register_directive('code-block', CodeBlock) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import os | ||
import unittest2 as unittest | ||
import docutils.parsers.rst | ||
|
||
try: | ||
import plone.testing.layer as layer | ||
layer_support = True | ||
except: | ||
layer_support = False | ||
|
||
|
||
class SphinxTestSuite(unittest.TestSuite): | ||
|
||
def __init__(self, tests, layer=None): | ||
self.tests = [] | ||
self.parser = docutils.parsers.rst.Parser() | ||
self.addTests(tests, layer) | ||
|
||
def addTests(self, tests, default_layer): | ||
for test in tests: | ||
if isinstance(test, list) or isinstance(test, tuple): | ||
if len(test) == 2 and layer_support and \ | ||
isinstance(test[1], layer.Layer): | ||
self.addTest(test[0], test[1]) | ||
else: | ||
raise Exception('Test should come in pair with layer.') | ||
if default_layer is not None and layer_support and \ | ||
isinstance(default_layer, layer.Layer): | ||
self.addTest(test, default_layer) | ||
else: | ||
self.addTest(test) | ||
|
||
def addTest(self, test, layer=None): | ||
if not isinstance(test, basestring): | ||
raise Exception('Test should be path to existing file.') | ||
if not os.path.exists(test): | ||
raise Exception('File does not exists: ' + test) | ||
|
||
test_file = os.path.abspath(test) | ||
test_f = open(test_file) | ||
rst_input = test_f.read() | ||
test_f.close() | ||
|
||
settings = docutils.frontend.OptionParser( | ||
components=(self.parser,)).get_default_values() | ||
|
||
rst_document = docutils.utils.new_document(test_file, settings) | ||
try: | ||
self.parser.parse(rst_input, rst_document) | ||
except Exception, e: | ||
pass | ||
|
||
|
||
for test_block in rst_document.traverse(): | ||
test = test_block.rawsource | ||
if isinstance(test, unittest.TestCase): | ||
if layer is not None and \ | ||
not getattr(test, 'layer', False): | ||
test.layer = layer | ||
self.tests.append(test) | ||
|
||
def __iter__(self): | ||
for test in self.tests: | ||
yield test |