summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZach Smith <zd@zdsmith.com>2015-12-28 14:34:50 -0500
committerZach Smith <zd@zdsmith.com>2015-12-28 14:34:50 -0500
commit9210e408de9b5911f4524f18b7ee741a9ceea6ac (patch)
tree4e1a3ed87a30f1891365a7c6c26561dce2aa8bb7
parent725ecf8bc1022c3816dbea65ea62061cbaf6094d (diff)
parent8b5258d627a7f9269b7cf31341b4a5d953318f0f (diff)
downloadpycco-9210e408de9b5911f4524f18b7ee741a9ceea6ac.tar.gz
Merge branch 'sitemap'
-rw-r--r--pycco/compat.py6
-rw-r--r--pycco/generate_index.py77
-rw-r--r--pycco/main.py53
-rw-r--r--pycco_resources/__init__.py8
-rw-r--r--tests/test_pycco.py19
5 files changed, 137 insertions, 26 deletions
diff --git a/pycco/compat.py b/pycco/compat.py
index 6660531..68233a4 100644
--- a/pycco/compat.py
+++ b/pycco/compat.py
@@ -2,3 +2,9 @@ try:
pycco_unichr = unichr
except NameError:
pycco_unichr = chr
+
+def compat_items(d):
+ try:
+ return d.iteritems()
+ except AttributeError:
+ return d.items()
diff --git a/pycco/generate_index.py b/pycco/generate_index.py
new file mode 100644
index 0000000..2ddf301
--- /dev/null
+++ b/pycco/generate_index.py
@@ -0,0 +1,77 @@
+"""
+This is the module responsible for automatically generating an HTML index of
+all documentation files generated by Pycco.
+"""
+import re
+from os import path
+
+from pycco.compat import compat_items
+from pycco_resources import pycco_template
+
+
+__all__ = ('generate_index',)
+
+
+def build_tree(file_paths, outdir):
+ tree = {}
+ for file_path in file_paths:
+ entry = {
+ 'path': file_path,
+ 'relpath': path.relpath(file_path, outdir)
+ }
+ path_steps = entry['relpath'].split(path.sep)
+ add_file(entry, path_steps, tree)
+
+ return tree
+
+
+def add_file(entry, path_steps, tree):
+ """
+ :param entry: A dictionary containing a path to a documentation file, and a
+ relative path to the same file.
+ :param path_steps: A list of steps in a file path to look within.
+ """
+ node, subpath = path_steps[0], path_steps[1:]
+ if node not in tree:
+ tree[node] = {}
+
+ if subpath:
+ add_file(entry, subpath, tree[node])
+
+ else:
+ tree[node]['entry'] = entry
+
+
+def generate_tree_html(tree):
+ """
+ Given a tree representing HTML file paths, return an HTML table plotting
+ those paths.
+ """
+ items = []
+ for node, subtree in sorted(compat_items(tree)):
+ if 'entry' in subtree:
+ html = '<li><a href="{}">{}</a></li>'.format(subtree['entry']['relpath'], node)
+ else:
+ html = '<dl><dt>{}</dt><dd><ul>{}</ul></dd></dl>'.format(node, generate_tree_html(subtree))
+
+ items.append(html)
+
+ return ''.join(items)
+
+
+def generate_index(files, outdir):
+ """
+ Given a list of generated documentation files, generate HTML to display
+ index of all files.
+ """
+ tree = build_tree(files, outdir)
+ css_path = path.join(outdir, "pycco.css")
+
+ rendered = pycco_template({
+ "title": 'Index',
+ "stylesheet": css_path,
+ "sections": {'docs_html': generate_tree_html(tree)},
+ "source": '',
+ })
+
+ return re.sub(r"__DOUBLE_OPEN_STACHE__", "{{", rendered).encode("utf-8")
diff --git a/pycco/main.py b/pycco/main.py
index aaca009..e95ad73 100644
--- a/pycco/main.py
+++ b/pycco/main.py
@@ -1,6 +1,9 @@
#!/usr/bin/env python
from __future__ import print_function
+# This module contains all of our static resources.
+from pycco_resources import pycco_template, css as pycco_css
+
"""
"**Pycco**" is a Python port of [Docco](http://jashkenas.github.com/docco/):
the original quick-and-dirty, hundred-line-long, literate-programming-style
@@ -284,25 +287,21 @@ def generate_html(source, sections, preserve_paths=True, outdir=None):
"stylesheet": csspath,
"sections": sections,
"source": source,
- "path": path,
- "destination": destination
})
return re.sub(r"__DOUBLE_OPEN_STACHE__", "{{", rendered).encode("utf-8")
# === Helpers & Setup ===
-# This module contains all of our static resources.
-import pycco_resources
-
# Import our external dependencies.
import optparse
import os
import pygments
-import pystache
import re
import sys
import time
+import pycco.generate_index as generate_index
+
from markdown import markdown
from os import path
from pygments import lexers, formatters
@@ -320,12 +319,16 @@ languages = {
".c": {"name": "c", "symbol": "//",
"multistart": "/*", "multiend": "*/"},
+ ".h": {"name": "c", "symbol": "//",
+ "multistart": "/*", "multiend": "*/"},
".cpp": {"name": "cpp", "symbol": "//"},
+ ".cl": {"name": "c", "symbol": "//",
+ "multistart": "/*", "multiend": "*/"},
+
".js": {"name": "javascript", "symbol": "//",
"multistart": "/*", "multiend": "*/"},
-
".rb": {"name": "ruby", "symbol": "#",
"multistart": "=begin", "multiend": "=end"},
@@ -447,15 +450,6 @@ def ensure_directory(directory):
return directory
-def template(source):
- return lambda context: pystache.render(source, context)
-
-# Create the template that we will use to generate the Pycco HTML page.
-pycco_template = template(pycco_resources.html)
-
-# The CSS styles we'd like to apply to the documentation.
-pycco_styles = pycco_resources.css
-
# The start of each Pygments highlight block.
highlight_start = "<div class=\"highlight\"><pre>"
@@ -463,11 +457,11 @@ highlight_start = "<div class=\"highlight\"><pre>"
highlight_end = "</pre></div>"
-def process(sources, preserve_paths=True, outdir=None, language=None, encoding="utf8"):
+def process(sources, preserve_paths=True, outdir=None, language=None, encoding="utf8", index=False):
"""For each source file passed as argument, generate the documentation."""
if not outdir:
- raise TypeError("Missing the required 'outdir' keyword argument.")
+ raise TypeError("Missing the required 'directory' keyword argument.")
# Make a copy of sources given on the command line. `main()` needs the
# original list when monitoring for changed files.
@@ -477,9 +471,11 @@ def process(sources, preserve_paths=True, outdir=None, language=None, encoding="
if sources:
outdir = ensure_directory(outdir)
css = open(path.join(outdir, "pycco.css"), "wb")
- css.write(pycco_styles.encode(encoding))
+ css.write(pycco_css.encode(encoding))
css.close()
+ generated_files = []
+
def next_file():
s = sources.pop(0)
dest = destination(s, preserve_paths=preserve_paths, outdir=outdir)
@@ -495,12 +491,17 @@ def process(sources, preserve_paths=True, outdir=None, language=None, encoding="
language=language,
encoding=encoding))
- print("pycco = {} -> {}".format(s, dest))
+ print("pycco: {} -> {}".format(s, dest))
+ generated_files.append(dest)
if sources:
next_file()
next_file()
+ if index:
+ with open(path.join(outdir, "index.html"), "wb") as f:
+ f.write(generate_index.generate_index(generated_files, outdir))
+
__all__ = ("process", "generate_documentation")
@@ -566,10 +567,18 @@ def main():
parser.add_option('-l', '--force-language', action='store', type='string',
dest='language', default=None,
help='Force the language for the given files')
+
+ parser.add_option('-i', '--generate_index', action='store_true',
+ help='Generate an index.html document with sitemap content')
+
opts, sources = parser.parse_args()
+ if opts.outdir == '':
+ outdir = '.'
+ else:
+ outdir = opts.outdir
- process(sources, outdir=opts.outdir, preserve_paths=opts.paths,
- language=opts.language)
+ process(sources, outdir=outdir, preserve_paths=opts.paths,
+ language=opts.language, index=opts.generate_index)
# If the -w / --watch option was present, monitor the source directories
# for changes and re-generate documentation for source files whenever they
diff --git a/pycco_resources/__init__.py b/pycco_resources/__init__.py
index a052967..a0eb757 100644
--- a/pycco_resources/__init__.py
+++ b/pycco_resources/__init__.py
@@ -235,3 +235,11 @@ html = """\
</div>
</body>
"""
+
+import pystache
+
+
+def template(source):
+ return lambda context: pystache.render(source, context)
+# Create the template that we will use to generate the Pycco HTML page.
+pycco_template = template(html)
diff --git a/tests/test_pycco.py b/tests/test_pycco.py
index 85eecc1..d008023 100644
--- a/tests/test_pycco.py
+++ b/tests/test_pycco.py
@@ -2,11 +2,12 @@ import copy
import os
import tempfile
import time
-
+import os.path
import pytest
from hypothesis import given, example, assume
from hypothesis.strategies import lists, text, booleans, choices, none
+import pycco.generate_index as generate_index
import pycco.main as p
@@ -146,7 +147,17 @@ def test_generate_documentation():
p.generate_documentation(PYCCO_SOURCE, outdir=tempfile.gettempdir())
-@given(booleans(), choices())
-def test_process(preserve_paths, choice):
+@given(booleans(), booleans(), choices())
+def test_process(preserve_paths, index, choice):
lang_name = choice([l["name"] for l in p.languages.values()])
- p.process([PYCCO_SOURCE], preserve_paths=preserve_paths, outdir=tempfile.gettempdir(), language=lang_name)
+ p.process([PYCCO_SOURCE], preserve_paths=preserve_paths,
+ index=index,
+ outdir=tempfile.gettempdir(),
+ language=lang_name)
+
+
+@given(lists(lists(text(min_size=1), min_size=1), min_size=1), lists(text(min_size=1), min_size=1))
+def test_generate_index(path_lists, outdir_list):
+ file_paths = [os.path.join(*path_list) for path_list in path_lists]
+ outdir = os.path.join(*outdir_list)
+ generate_index.generate_index(file_paths, outdir=outdir)