Этого можно достичь, запустив небольшой скрипт:
, который импортирует подлежащие документированию модули,
записывает документацию вhtml файлы, а затем
записывает выходные данные внутренней функции, которая динамически генерирует index.html, в файл index.html.
Itэто не очень хорошее решение, потому что оно опирается на внутренние компоненты модуля pydoc
, но достаточно компактно:
import pydoc
import importlib
module_list = ['sys']
for m in module_list:
importlib.import_module(m)
pydoc.writedoc(m)
#the monkey patching optionally goes here
with open('index.html','w') as out_file:
out_file.write(pydoc._url_handler('index.html'))
Есть еще один недостаток в том, что он также создает ссылки на все встроенныемодули и т. д., для которых мы не (и, я думаю, не хотели) создавать документацию для.
Можем ли мы скопировать функцию из pydoc.py
, которая создает файл index.html, и изменить ее только длядобавить ссылки на наши нужные модули? К сожалению, это не так просто, потому что функция использует некоторую нелокальную область видимости для достижения некоторой своей логики.
Следующим лучшим решением будет обезьяна-исправление метода index_html()
, который генерирует эту страницу дляперечислите только наши модули.
К сожалению pydoc._url_handler
использует локальную функцию для реализации этого, а не метод класса. Таким образом, это становится немного сложнее.
Существует решение для обезьяньего патча, но это немного хак:
перед вызовом _url_handler
нам нужно:
определяет исправленную версию, которая генерирует ссылки только для элементов в нашем module_list (обходной путь через __placeholder__
используется, потому что наш module_list не определен в области, в которой выполняется функция, поэтому нам нужносделать что-то, что соответствует жесткому кодированию в функции, вроде того.)
исправьте источник модуля pydoc
, чтобы использовать эту локальную функцию вместо первоначально определенного
Это достигается следующим образом:
import inspect, ast
__placeholder__ = None
#our patched version, needs to have same name and signature as original
def html_index():
"""Module Index page."""
names= __placeholder__
def bltinlink(name):
return '<a href="%s.html">%s</a>' % (name, name)
heading = html.heading(
'<big><big><strong>Index of Modules</strong></big></big>',
'#ffffff', '#7799ee')
contents = html.multicolumn(names, bltinlink)
contents = [heading, '<p>' + html.bigsection(
'Module List', '#ffffff', '#ee77aa', contents)]
contents.append(
'<p align=right><font color="#909090" face="helvetica,'
'arial"><strong>pydoc</strong> by Ka-Ping Yee'
'<ping@lfw.org></font>')
return 'Index of Modules', ''.join(contents)
#get source and replace __placeholder__ with our module_list
s=inspect.getsource(html_index).replace('__placeholder__', str(module_list))
#create abstract syntax tree, and store the actual function definition in l_index
l_index=ast.parse(s).body[0]
#ast.dump(l_index) #check if you want
#now obtain source from unpatched pydoc, generate ast patch it and recompile:
s= inspect.getsource(pydoc)
m = ast.parse(s)
def find_named_el_ind(body, name):
'''find named element in ast body'''
found=False
for i,e in enumerate(body):
if hasattr(e,'name') and e.name == name:
found=True
break
if not found: raise ValueError('not found!')
return i
#find and replace html_index with our patched html_index
i_url_handler = find_named_el_ind(m.body, '_url_handler')
i_html_index = find_named_el_ind(m.body[i_url_handler].body, 'html_index')
m.body[i_url_handler].body[i_html_index] = l_index
#compile and replace module in memory
co = compile(m, '<string>', 'exec')
exec(co, pydoc.__dict__)
#ast.dump(m.body[i_url_handler]) #check ast if you will