Added tests.builddocs, which builds HTML documentation by introspecting the model unit tests
git-svn-id: http://code.djangoproject.com/svn/django/trunk@348 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
47ce61533a
commit
5002b44f28
|
@ -0,0 +1,65 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
"""
|
||||||
|
This module builds HTML documentation for models by introspecting the model
|
||||||
|
unit tests.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.core import meta, template
|
||||||
|
import runtests
|
||||||
|
import inspect, os, re, sys
|
||||||
|
|
||||||
|
MODEL_DOC_TEMPLATE = """
|
||||||
|
<div class="document" id="model-{{ model_name }}">
|
||||||
|
|
||||||
|
<h1 class="title">{{ title }}</h1>
|
||||||
|
{{ blurb }}
|
||||||
|
|
||||||
|
<h2>Model source code</h2>
|
||||||
|
<pre>{{ model_source }}</pre>
|
||||||
|
|
||||||
|
<h2>Sample API usage</h2>
|
||||||
|
<pre>{{ api_usage }}</pre>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
|
||||||
|
def make_docs_from_model_tests(output_dir):
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
# Manually set INSTALLED_APPS to point to the test app.
|
||||||
|
settings.INSTALLED_APPS = (runtests.APP_NAME,)
|
||||||
|
|
||||||
|
for model_name in runtests.get_test_models():
|
||||||
|
mod = meta.get_app(model_name)
|
||||||
|
|
||||||
|
# Clean up the title and blurb.
|
||||||
|
title, blurb = mod.__doc__.strip().split('\n', 1)
|
||||||
|
blurb = '<p>%s</p>' % blurb.strip().replace('\n\n', '</p><p>')
|
||||||
|
api_usage = mod.API_TESTS
|
||||||
|
|
||||||
|
# Get the source code of the model, without the docstring or the
|
||||||
|
# API_TESTS variable.
|
||||||
|
model_source = inspect.getsource(mod)
|
||||||
|
model_source = model_source.replace(mod.__doc__, '')
|
||||||
|
model_source = model_source.replace(mod.API_TESTS, '')
|
||||||
|
model_source = model_source.replace('""""""\n', '\n')
|
||||||
|
model_source = model_source.replace('API_TESTS = ', '')
|
||||||
|
model_source = model_source.strip()
|
||||||
|
|
||||||
|
# Run this through the template system.
|
||||||
|
t = template.Template(MODEL_DOC_TEMPLATE)
|
||||||
|
c = template.Context(locals())
|
||||||
|
html = t.render(c)
|
||||||
|
|
||||||
|
file_name = os.path.join(output_dir, 'model_' + model_name + '.html')
|
||||||
|
try:
|
||||||
|
fp = open(file_name, 'w')
|
||||||
|
except IOError:
|
||||||
|
sys.stderr.write("Couldn't write to %s.\n" % file_name)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
fp.write(html)
|
||||||
|
fp.close()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
make_docs_from_model_tests(sys.argv[1])
|
|
@ -17,6 +17,11 @@ def log_error(model_name, title, description):
|
||||||
'description': description,
|
'description': description,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
MODEL_DIR = os.path.join(os.path.dirname(__file__), APP_NAME, 'models')
|
||||||
|
|
||||||
|
def get_test_models():
|
||||||
|
return [f[:-3] for f in os.listdir(MODEL_DIR) if f.endswith('.py') and not f.startswith('__init__')]
|
||||||
|
|
||||||
class DjangoDoctestRunner(doctest.DocTestRunner):
|
class DjangoDoctestRunner(doctest.DocTestRunner):
|
||||||
def __init__(self, verbosity_level, *args, **kwargs):
|
def __init__(self, verbosity_level, *args, **kwargs):
|
||||||
self.verbosity_level = verbosity_level
|
self.verbosity_level = verbosity_level
|
||||||
|
@ -51,13 +56,15 @@ class TestRunner:
|
||||||
# Manually set INSTALLED_APPS to point to the test app.
|
# Manually set INSTALLED_APPS to point to the test app.
|
||||||
settings.INSTALLED_APPS = (APP_NAME,)
|
settings.INSTALLED_APPS = (APP_NAME,)
|
||||||
|
|
||||||
# If we're using SQLite, it's more convient to test against an in-memory database
|
# If we're using SQLite, it's more convenient to test against an
|
||||||
|
# in-memory database.
|
||||||
if settings.DATABASE_ENGINE == "sqlite3":
|
if settings.DATABASE_ENGINE == "sqlite3":
|
||||||
global TEST_DATABASE_NAME
|
global TEST_DATABASE_NAME
|
||||||
TEST_DATABASE_NAME = ":memory:"
|
TEST_DATABASE_NAME = ":memory:"
|
||||||
else:
|
else:
|
||||||
# Create the test database and connect to it. We need autocommit() because
|
# Create the test database and connect to it. We need autocommit()
|
||||||
# PostgreSQL doesn't allow CREATE DATABASE statements within transactions.
|
# because PostgreSQL doesn't allow CREATE DATABASE statements
|
||||||
|
# within transactions.
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
try:
|
try:
|
||||||
db.connection.autocommit()
|
db.connection.autocommit()
|
||||||
|
@ -83,10 +90,8 @@ class TestRunner:
|
||||||
self.output(1, "Initializing test database")
|
self.output(1, "Initializing test database")
|
||||||
management.init()
|
management.init()
|
||||||
|
|
||||||
# Run the tests for each model within APP_NAME/models.
|
# Run the tests for each test model.
|
||||||
model_dir = os.path.join(os.path.dirname(__file__), APP_NAME, 'models')
|
for model_name in get_test_models():
|
||||||
test_models = [f[:-3] for f in os.listdir(model_dir) if f.endswith('.py') and not f.startswith('__init__')]
|
|
||||||
for model_name in test_models:
|
|
||||||
self.output(1, "%s model: Importing" % model_name)
|
self.output(1, "%s model: Importing" % model_name)
|
||||||
try:
|
try:
|
||||||
mod = meta.get_app(model_name)
|
mod = meta.get_app(model_name)
|
||||||
|
@ -106,7 +111,7 @@ class TestRunner:
|
||||||
self.output(1, "%s model: Running tests" % model_name)
|
self.output(1, "%s model: Running tests" % model_name)
|
||||||
runner.run(dtest, clear_globs=True, out=sys.stdout.write)
|
runner.run(dtest, clear_globs=True, out=sys.stdout.write)
|
||||||
|
|
||||||
# Unless we're using SQLite, remove the test database, to clean up after
|
# Unless we're using SQLite, remove the test database to clean up after
|
||||||
# ourselves. Connect to the previous database (not the test database)
|
# ourselves. Connect to the previous database (not the test database)
|
||||||
# to do so, because it's not allowed to delete a database while being
|
# to do so, because it's not allowed to delete a database while being
|
||||||
# connected to it.
|
# connected to it.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
"""
|
"""
|
||||||
7. The lookup API
|
7. The lookup API
|
||||||
|
|
||||||
|
This demonstrates features of the database API.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.core import meta
|
from django.core import meta
|
||||||
|
|
Loading…
Reference in New Issue