mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-14 13:06:34 +03:00
170 lines
5.0 KiB
Python
170 lines
5.0 KiB
Python
|
#!/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)
|