Django

Code

root/django/branches/newforms-admin/django/contrib/admindocs/utils.py

Revision 6776, 3.6 kB (checked in by jkocherhans, 1 year ago)

newforms-admin: Merged trunk revision [6671].

  • Property svn:eol-style set to native
Line 
1 "Misc. utility functions/classes for admin documentation generator."
2
3 import re
4 from email.Parser import HeaderParser
5 from email.Errors import HeaderParseError
6 from django.utils.safestring import mark_safe
7 try:
8     import docutils.core
9     import docutils.nodes
10     import docutils.parsers.rst.roles
11 except ImportError:
12     docutils_is_available = False
13 else:
14     docutils_is_available = True
15
16 def trim_docstring(docstring):
17     """
18     Uniformly trims leading/trailing whitespace from docstrings.
19
20     Based on http://www.python.org/peps/pep-0257.html#handling-docstring-indentation
21     """
22     if not docstring or not docstring.strip():
23         return ''
24     # Convert tabs to spaces and split into lines
25     lines = docstring.expandtabs().splitlines()
26     indent = min([len(line) - len(line.lstrip()) for line in lines if line.lstrip()])
27     trimmed = [lines[0].lstrip()] + [line[indent:].rstrip() for line in lines[1:]]
28     return "\n".join(trimmed).strip()
29
30 def parse_docstring(docstring):
31     """
32     Parse out the parts of a docstring.  Returns (title, body, metadata).
33     """
34     docstring = trim_docstring(docstring)
35     parts = re.split(r'\n{2,}', docstring)
36     title = parts[0]
37     if len(parts) == 1:
38         body = ''
39         metadata = {}
40     else:
41         parser = HeaderParser()
42         try:
43             metadata = parser.parsestr(parts[-1])
44         except HeaderParseError:
45             metadata = {}
46             body = "\n\n".join(parts[1:])
47         else:
48             metadata = dict(metadata.items())
49             if metadata:
50                 body = "\n\n".join(parts[1:-1])
51             else:
52                 body = "\n\n".join(parts[1:])
53     return title, body, metadata
54
55 def parse_rst(text, default_reference_context, thing_being_parsed=None, link_base='../..'):
56     """
57     Convert the string from reST to an XHTML fragment.
58     """
59     overrides = {
60         'doctitle_xform' : True,
61         'inital_header_level' : 3,
62         "default_reference_context" : default_reference_context,
63         "link_base" : link_base,
64     }
65     if thing_being_parsed:
66         thing_being_parsed = "<%s>" % thing_being_parsed
67     parts = docutils.core.publish_parts(text, source_path=thing_being_parsed,
68                 destination_path=None, writer_name='html',
69                 settings_overrides=overrides)
70     return mark_safe(parts['fragment'])
71
72 #
73 # reST roles
74 #
75 ROLES = {
76     'model'    : '%s/models/%s/',
77     'view'     : '%s/views/%s/',
78     'template' : '%s/templates/%s/',
79     'filter'   : '%s/filters/#%s',
80     'tag'      : '%s/tags/#%s',
81 }
82
83 def create_reference_role(rolename, urlbase):
84     def _role(name, rawtext, text, lineno, inliner, options=None, content=None):
85         if options is None: options = {}
86         if content is None: content = []
87         node = docutils.nodes.reference(rawtext, text, refuri=(urlbase % (inliner.document.settings.link_base, text.lower())), **options)
88         return [node], []
89     docutils.parsers.rst.roles.register_canonical_role(rolename, _role)
90
91 def default_reference_role(name, rawtext, text, lineno, inliner, options=None, content=None):
92     if options is None: options = {}
93     if content is None: content = []
94     context = inliner.document.settings.default_reference_context
95     node = docutils.nodes.reference(rawtext, text, refuri=(ROLES[context] % (inliner.document.settings.link_base, text.lower())), **options)
96     return [node], []
97
98 if docutils_is_available:
99     docutils.parsers.rst.roles.register_canonical_role('cmsreference', default_reference_role)
100     docutils.parsers.rst.roles.DEFAULT_INTERPRETED_ROLE = 'cmsreference'
101
102     for name, urlbase in ROLES.items():
103         create_reference_role(name, urlbase)
Note: See TracBrowser for help on using the browser.