psycopg2/scripts/ext2html.py

170 lines
5.0 KiB
Python
Raw Normal View History

#!/usr/bin/env python
# Author: Daniele Varrazzo
# Contact: daniele dot varrazzo at gmail dot com
# Revision: $Revision$
# Date: $Date$
# Copyright: This module has been placed in the public domain.
"""
A minimal front end to the Docutils Publisher, producing HTML.
Output can refer to Epydoc-generated APIs through the iterpreted text role
"api".
"""
import types
import sys
# The url fragment where the api "index.html" resides w.r.t. the generated docs
api_root = "api/"
try:
import locale
locale.setlocale(locale.LC_ALL, '')
except:
pass
from docutils.core import publish_cmdline, default_description
from docutils.parsers.rst.roles import register_canonical_role
from docutils import nodes, utils
# api references are searched for in these modules
api_modules = [
'psycopg2',
'psycopg2._psycopg',
'psycopg2.extensions',
]
# name starting with a dot are looking as those objects attributes.
searched_objects = [
# module_name, object_name
('psycopg2.extensions', 'connection'),
('psycopg2.extensions', 'cursor'),
]
# import all the referenced modules
for modname in api_modules:
__import__(modname)
class EpydocTarget:
"""Representation of an element language."""
def __init__(self, name, element):
self.name = name
# The python object described
self.element = element
# The base name of the page
self.page = None
# The url fragment
self.fragment = None
def get_url(self):
# is it a private element?
components = self.page.split('.')
if self.fragment: components.append(self.fragment)
for component in components:
if component.startswith('_'):
private = True
break
else:
private = False
ref = api_root + (private and "private/" or "public/") \
+ self.page + "-" + self.get_type() + ".html"
if self.fragment:
ref = ref + "#" + self.fragment
return ref
def get_type(self):
# detect the element type
if isinstance(self.element, types.TypeType):
return 'class'
elif isinstance(self.element, types.ModuleType):
return 'module'
else:
raise ValueError("Can't choose a type for '%s'." % self.name)
def filter_par(name):
"""Filter parenthesis away from a name."""
if name.endswith(")"):
return name.split("(")[0]
else:
return name
def get_element_target(name):
"""Return the life, the death, the miracles about a package element."""
name = filter_par(name)
if name.startswith('.'):
for modname, objname in searched_objects:
if hasattr(getattr(sys.modules[modname], objname), name[1:]):
name = objname + name
break
# is the element a module?
if name in api_modules:
out = EpydocTarget(name, sys.modules[name])
out.page = name
return out
# look for the element in some module
for modname in api_modules:
element = getattr(sys.modules[modname], name, None)
if element is not None:
# Check if it is a function defined in a module
if isinstance(element,
(int, types.FunctionType, types.BuiltinFunctionType)):
out = EpydocTarget(name, sys.modules[modname])
out.page = modname
out.fragment = name
else:
out = EpydocTarget(name, element)
out.page = modname + '.' + name
return out
# maybe a qualified name?
if '.' in name:
out = get_element_target('.'.join(name.split('.')[:-1]))
if out is not None:
out.fragment = filter_par(name.split('.')[-1])
return out
raise ValueError("Can't find '%s' in any provided module." % name)
def api_role(role, rawtext, text, lineno, inliner,
options={}, content=[]):
try:
target = get_element_target(text)
except Exception, exc:
msg = inliner.reporter.error(str(exc), line=lineno)
prb = inliner.problematic(rawtext, rawtext, msg)
return [prb], [msg]
ref = target.get_url()
node2 = nodes.literal(rawtext, utils.unescape(text))
node = nodes.reference(rawtext, '', node2, refuri=ref,
**options)
return [node], []
register_canonical_role('api', api_role)
# Register the 'api' role as canonical role
from docutils.parsers.rst import roles
roles.DEFAULT_INTERPRETED_ROLE = 'api'
description = ('Generates (X)HTML documents from standalone reStructuredText '
'sources with links to Epydoc API. ' + default_description)
publish_cmdline(writer_name='html', description=description)