# Tracpydoc plugin
from trac.core import *
from trac.web.chrome import INavigationContributor, ITemplateProvider, \
add_stylesheet
from trac.web.main import IRequestHandler
from trac.util import escape, shorten_line
from trac.wiki.api import IWikiSyntaxProvider, IWikiMacroProvider
from trac.Search import ISearchSource
import inspect, os
from pydoc import ispackage
try:
from trac.util import Markup
except ImportError:
def Markup(markup): return markup
import urllib
import pydoc
import re
import time
import sys
import os
import imp
from fnmatch import fnmatch
try:
import threading
except ImportError:
import dummy_threading as threading
def any(gen):
for p in gen:
if p: return True
return False
class TracDoc(pydoc.HTMLDoc):
_cleanup_re = re.compile(r'(?:bg)?color="[^"]+"')
_cleanup_heading_re = re.compile(r'href="([^"]+).html"')
_cleanup_html_re = re.compile(r'\.html($|#)')
_cleanup_inline_re = re.compile(r'index(?:
)?|'
r'%s' % \
(self.env.href.pydoc(obj.__name__), obj.__name__)
def modpkglink(self, (name, path, ispackage, shadowed)):
fpath = '%s%s' % (path and path + '.' or '', name)
return '%s' % (self.env.href.pydoc(fpath), name)
def namelink(self, name, *dicts):
for dict in dicts:
if name in dict:
return '%s' % \
(re.sub(self._cleanup_html_re, r'\1', dict[name]), name)
return name
def _link_components(self, path):
if not path: return ''
links = []
sofar = []
for mod in path.split('.'):
sofar.append(mod)
links.append('%s' % \
(self.env.href.pydoc('.'.join(sofar)), mod))
return links
def classlink(self, object, modname):
module = object.__module__
path = '%s.%s' % (module, object.__name__)
return '.'.join(self._link_components(path))
def heading(self, *args):
return re.sub(self._cleanup_heading_re, r'href="\1"',
self._cleanup('heading', *args))
def section(self, *args):
return self._cleanup('section', *args)
def grey(self, *args):
return self._cleanup('grey', *args)
def _cleanup(self, kind, *args):
return re.sub(self._cleanup_inline_re, '',
re.sub(self._cleanup_re, 'class="pydoc%s"'% kind,
getattr(pydoc.HTMLDoc, kind)(self, *args)))
class PyDoc(Component):
""" Allow browsing of Python documentation through Trac. """
implements(INavigationContributor, ITemplateProvider, IRequestHandler)
def __init__(self):
self.doc = TracDoc(self.env)
syspath = self.config.get('pydoc', 'sys.path')
if syspath:
self.syspath = [os.path.normpath(p) for p in
syspath.split(os.pathsep)]
else:
self.syspath = sys.path
self.includes, self.excludes = self.get_filters()
show_private = self.config.get('pydoc', 'show_private', '')
self.show_private = [p.rstrip('.*') for p in show_private.split()]
self.makedoc_lock = threading.Lock()
def filter_match(self, file):
includes, excludes = self.get_filters()
for match in excludes:
if fnmatch(file, match):
return 0
for match in includes:
if fnmatch(file, match):
return 1
return not includes
def get_filters(self):
return ([p for p in self.config.get('pydoc',
'include', '').split() if p],
[p for p in self.config.get('pydoc',
'exclude', '').split() if p])
def load_object(self, fullobject):
""" Load an arbitrary object from a full dotted path. """
fullspec = fullobject.split('.')
i = 0
module = mfile = mdescr = None
mpath = self.syspath
# Find module
if fullspec[0] in sys.builtin_module_names:
module = __import__(fullspec[0], None, None)
i += 1
else:
while i < len(fullspec):
try:
f, p, mdescr = imp.find_module(fullspec[i], mpath)
if mfile:
mfile.close()
mfile, mpath = f, [p]
i += 1
except ImportError:
break
try:
mname = ".".join(fullspec[0:i])
if sys.modules.has_key(mname):
module = sys.modules[mname]
elif mname and mdescr:
module = imp.load_module(mname, mfile, mpath[0], mdescr)
finally:
if mfile:
mfile.close()
# Find object
object = module
while i < len(fullspec):
try:
object = getattr(object, fullspec[i])
i += 1
except AttributeError:
raise ImportError, fullobject
return (module, object)
def generate_help(self, target, inline=False, visibility=''):
"""Show documentation for named `target`.
If `inline` is set, no header will be generated.
For the `visibility` argument, see `PyDocMacro`.
"""
try:
if not target or target == 'index':
if inline:
doc = ''
else:
doc = '