diff options
| author | Jacob Kaplan-Moss <jacob@jacobian.org> | 2008-08-23 22:25:40 +0000 |
|---|---|---|
| committer | Jacob Kaplan-Moss <jacob@jacobian.org> | 2008-08-23 22:25:40 +0000 |
| commit | 97cb07c3a10ff0e584a260a7ee1001614691eb1d (patch) | |
| tree | 204f4382c51e1c288dbf547875161731661733f5 /docs/_ext | |
| parent | b3688e81943d6d059d3f3c95095498a5aab84852 (diff) | |
Massive reorganization of the docs. See the new docs online at http://docs.djangoproject.com/.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@8506 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'docs/_ext')
| -rw-r--r-- | docs/_ext/applyxrefs.py | 88 | ||||
| -rw-r--r-- | docs/_ext/djangodocs.py | 146 | ||||
| -rw-r--r-- | docs/_ext/literals_to_xrefs.py | 171 |
3 files changed, 405 insertions, 0 deletions
diff --git a/docs/_ext/applyxrefs.py b/docs/_ext/applyxrefs.py new file mode 100644 index 0000000000..3809088c1f --- /dev/null +++ b/docs/_ext/applyxrefs.py @@ -0,0 +1,88 @@ +"""Adds xref targets to the top of files.""" + +import sys +import os + +testing = False + +DONT_TOUCH = ( + './index.txt', + ) + +def target_name(fn): + if fn.endswith('.txt'): + fn = fn[:-4] + return '_' + fn.lstrip('./').replace('/', '-') + +def process_file(fn, lines): + lines.insert(0, '\n') + lines.insert(0, '.. %s:\n' % target_name(fn)) + try: + f = open(fn, 'w') + except IOError: + print("Can't open %s for writing. Not touching it." % fn) + return + try: + f.writelines(lines) + except IOError: + print("Can't write to %s. Not touching it." % fn) + finally: + f.close() + +def has_target(fn): + try: + f = open(fn, 'r') + except IOError: + print("Can't open %s. Not touching it." % fn) + return (True, None) + readok = True + try: + lines = f.readlines() + except IOError: + print("Can't read %s. Not touching it." % fn) + readok = False + finally: + f.close() + if not readok: + return (True, None) + + #print fn, len(lines) + if len(lines) < 1: + print("Not touching empty file %s." % fn) + return (True, None) + if lines[0].startswith('.. _'): + return (True, None) + return (False, lines) + +def main(argv=None): + if argv is None: + argv = sys.argv + + if len(argv) == 1: + argv.extend('.') + + files = [] + for root in argv[1:]: + for (dirpath, dirnames, filenames) in os.walk(root): + files.extend([(dirpath, f) for f in filenames]) + files.sort() + files = [os.path.join(p, fn) for p, fn in files if fn.endswith('.txt')] + #print files + + for fn in files: + if fn in DONT_TOUCH: + print("Skipping blacklisted file %s." % fn) + continue + + target_found, lines = has_target(fn) + if not target_found: + if testing: + print '%s: %s' % (fn, lines[0]), + else: + print "Adding xref to %s" % fn + process_file(fn, lines) + else: + print "Skipping %s: already has a xref" % fn + +if __name__ == '__main__': + sys.exit(main())
\ No newline at end of file diff --git a/docs/_ext/djangodocs.py b/docs/_ext/djangodocs.py new file mode 100644 index 0000000000..2375be481d --- /dev/null +++ b/docs/_ext/djangodocs.py @@ -0,0 +1,146 @@ +""" +Sphinx plugins for Django documentation. +""" + +import docutils.nodes +import docutils.transforms +import sphinx +import sphinx.addnodes +import sphinx.builder +import sphinx.directives +import sphinx.environment +import sphinx.htmlwriter + +def setup(app): + app.add_crossref_type( + directivename = "setting", + rolename = "setting", + indextemplate = "pair: %s; setting", + ) + app.add_crossref_type( + directivename = "templatetag", + rolename = "ttag", + indextemplate = "pair: %s; template tag" + ) + app.add_crossref_type( + directivename = "templatefilter", + rolename = "tfilter", + indextemplate = "pair: %s; template filter" + ) + app.add_crossref_type( + directivename = "fieldlookup", + rolename = "lookup", + indextemplate = "pair: %s, field lookup type", + ) + app.add_description_unit( + directivename = "django-admin", + rolename = "djadmin", + indextemplate = "pair: %s; django-admin command", + parse_node = parse_django_admin_node, + ) + app.add_description_unit( + directivename = "django-admin-option", + rolename = "djadminopt", + indextemplate = "pair: %s; django-admin command-line option", + parse_node = lambda env, sig, signode: sphinx.directives.parse_option_desc(signode, sig), + ) + app.add_transform(SuppressBlockquotes) + + # Monkeypatch PickleHTMLBuilder so that it doesn't die in Sphinx 0.4.2 + if sphinx.__version__ == '0.4.2': + monkeypatch_pickle_builder() + +class SuppressBlockquotes(docutils.transforms.Transform): + """ + Remove the default blockquotes that encase indented list, tables, etc. + """ + default_priority = 300 + + suppress_blockquote_child_nodes = ( + docutils.nodes.bullet_list, + docutils.nodes.enumerated_list, + docutils.nodes.definition_list, + docutils.nodes.literal_block, + docutils.nodes.doctest_block, + docutils.nodes.line_block, + docutils.nodes.table + ) + + def apply(self): + for node in self.document.traverse(docutils.nodes.block_quote): + if len(node.children) == 1 and isinstance(node.children[0], self.suppress_blockquote_child_nodes): + node.replace_self(node.children[0]) + +class DjangoHTMLTranslator(sphinx.htmlwriter.SmartyPantsHTMLTranslator): + """ + Django-specific reST to HTML tweaks. + """ + + # Don't use border=1, which docutils does by default. + def visit_table(self, node): + self.body.append(self.starttag(node, 'table', CLASS='docutils')) + + # Give each section a unique ID -- nice for custom CSS hooks + # This is different on docutils 0.5 vs. 0.4... + + # The docutils 0.4 override. + if hasattr(sphinx.htmlwriter.SmartyPantsHTMLTranslator, 'start_tag_with_title'): + def start_tag_with_title(self, node, tagname, **atts): + node = { + 'classes': node.get('classes', []), + 'ids': ['s-%s' % i for i in node.get('ids', [])] + } + return self.starttag(node, tagname, **atts) + + # The docutils 0.5 override. + else: + def visit_section(self, node): + old_ids = node.get('ids', []) + node['ids'] = ['s-' + i for i in old_ids] + sphinx.htmlwriter.SmartyPantsHTMLTranslator.visit_section(self, node) + node['ids'] = old_ids + +def parse_django_admin_node(env, sig, signode): + command = sig.split(' ')[0] + env._django_curr_admin_command = command + title = "django-admin.py %s" % sig + signode += sphinx.addnodes.desc_name(title, title) + return sig + +def monkeypatch_pickle_builder(): + import shutil + from os import path + try: + import cPickle as pickle + except ImportError: + import pickle + from sphinx.util.console import bold + + def handle_finish(self): + # dump the global context + outfilename = path.join(self.outdir, 'globalcontext.pickle') + f = open(outfilename, 'wb') + try: + pickle.dump(self.globalcontext, f, 2) + finally: + f.close() + + self.info(bold('dumping search index...')) + self.indexer.prune(self.env.all_docs) + f = open(path.join(self.outdir, 'searchindex.pickle'), 'wb') + try: + self.indexer.dump(f, 'pickle') + finally: + f.close() + + # copy the environment file from the doctree dir to the output dir + # as needed by the web app + shutil.copyfile(path.join(self.doctreedir, sphinx.builder.ENV_PICKLE_FILENAME), + path.join(self.outdir, sphinx.builder.ENV_PICKLE_FILENAME)) + + # touch 'last build' file, used by the web application to determine + # when to reload its environment and clear the cache + open(path.join(self.outdir, sphinx.builder.LAST_BUILD_FILENAME), 'w').close() + + sphinx.builder.PickleHTMLBuilder.handle_finish = handle_finish + diff --git a/docs/_ext/literals_to_xrefs.py b/docs/_ext/literals_to_xrefs.py new file mode 100644 index 0000000000..569193c72d --- /dev/null +++ b/docs/_ext/literals_to_xrefs.py @@ -0,0 +1,171 @@ +""" +Runs through a reST file looking for old-style literals, and helps replace them +with new-style references. +""" + +import re +import sys +import shelve + +refre = re.compile(r'``([^`\s]+?)``') + +ROLES = ( + 'attr', + 'class', + "djadmin", + 'data', + 'exc', + 'file', + 'func', + 'lookup', + 'meth', + 'mod' , + "djadminopt", + "ref", + "setting", + "term", + "tfilter", + "ttag", + + # special + "skip" +) + +ALWAYS_SKIP = [ + "NULL", + "True", + "False", +] + +def fixliterals(fname): + data = open(fname).read() + + last = 0 + new = [] + storage = shelve.open("/tmp/literals_to_xref.shelve") + lastvalues = storage.get("lastvalues", {}) + + for m in refre.finditer(data): + + new.append(data[last:m.start()]) + last = m.end() + + line_start = data.rfind("\n", 0, m.start()) + line_end = data.find("\n", m.end()) + prev_start = data.rfind("\n", 0, line_start) + next_end = data.find("\n", line_end + 1) + + # Skip always-skip stuff + if m.group(1) in ALWAYS_SKIP: + new.append(m.group(0)) + continue + + # skip when the next line is a title + next_line = data[m.end():next_end].strip() + if next_line[0] in "!-/:-@[-`{-~" and all(c == next_line[0] for c in next_line): + new.append(m.group(0)) + continue + + sys.stdout.write("\n"+"-"*80+"\n") + sys.stdout.write(data[prev_start+1:m.start()]) + sys.stdout.write(colorize(m.group(0), fg="red")) + sys.stdout.write(data[m.end():next_end]) + sys.stdout.write("\n\n") + + replace_type = None + while replace_type is None: + replace_type = raw_input( + colorize("Replace role: ", fg="yellow") + ).strip().lower() + if replace_type and replace_type not in ROLES: + replace_type = None + + if replace_type == "": + new.append(m.group(0)) + continue + + if replace_type == "skip": + new.append(m.group(0)) + ALWAYS_SKIP.append(m.group(1)) + continue + + default = lastvalues.get(m.group(1), m.group(1)) + if default.endswith("()") and replace_type in ("class", "func", "meth"): + default = default[:-2] + replace_value = raw_input( + colorize("Text <target> [", fg="yellow") + default + colorize("]: ", fg="yellow") + ).strip() + if not replace_value: + replace_value = default + new.append(":%s:`%s`" % (replace_type, replace_value)) + lastvalues[m.group(1)] = replace_value + + new.append(data[last:]) + open(fname, "w").write("".join(new)) + + storage["lastvalues"] = lastvalues + storage.close() + +# +# The following is taken from django.utils.termcolors and is copied here to +# avoid the dependancy. +# + + +def colorize(text='', opts=(), **kwargs): + """ + Returns your text, enclosed in ANSI graphics codes. + + Depends on the keyword arguments 'fg' and 'bg', and the contents of + the opts tuple/list. + + Returns the RESET code if no parameters are given. + + Valid colors: + 'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white' + + Valid options: + 'bold' + 'underscore' + 'blink' + 'reverse' + 'conceal' + 'noreset' - string will not be auto-terminated with the RESET code + + Examples: + colorize('hello', fg='red', bg='blue', opts=('blink',)) + colorize() + colorize('goodbye', opts=('underscore',)) + print colorize('first line', fg='red', opts=('noreset',)) + print 'this should be red too' + print colorize('and so should this') + print 'this should not be red' + """ + color_names = ('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white') + foreground = dict([(color_names[x], '3%s' % x) for x in range(8)]) + background = dict([(color_names[x], '4%s' % x) for x in range(8)]) + + RESET = '0' + opt_dict = {'bold': '1', 'underscore': '4', 'blink': '5', 'reverse': '7', 'conceal': '8'} + + text = str(text) + code_list = [] + if text == '' and len(opts) == 1 and opts[0] == 'reset': + return '\x1b[%sm' % RESET + for k, v in kwargs.iteritems(): + if k == 'fg': + code_list.append(foreground[v]) + elif k == 'bg': + code_list.append(background[v]) + for o in opts: + if o in opt_dict: + code_list.append(opt_dict[o]) + if 'noreset' not in opts: + text = text + '\x1b[%sm' % RESET + return ('\x1b[%sm' % ';'.join(code_list)) + text + +if __name__ == '__main__': + try: + fixliterals(sys.argv[1]) + except (KeyboardInterrupt, SystemExit): + print
\ No newline at end of file |
