You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sphinx-autoapi/autoapi/extension.py

267 lines
7.8 KiB
Python

10 years ago
# -*- coding: utf-8 -*-
"""
Sphinx Auto-API
"""
import os
import sys
10 years ago
import yaml
import fnmatch
10 years ago
from collections import defaultdict
import traceback
10 years ago
from sphinx.util.osutil import ensuredir
from jinja2 import Environment, FileSystemLoader
from .utils import TEMPLATE_DIR
from epyparse import parsed
10 years ago
env = Environment(loader=FileSystemLoader(TEMPLATE_DIR))
class DotNetMember(object):
def __init__(self, obj):
self.obj = obj
def render(self):
print "Unknown Type: %s (%s)" % (self.obj['type'], self.obj['name'])
self.obj['underline'] = len(self.obj['qualifiedName']['CSharp']) * "~"
10 years ago
template = env.get_template('member.rst')
return template.render(**self.obj)
class PythonMember(object):
def __init__(self, obj):
self.obj = obj
def render(self):
print "Unknown Type: %s (%s)" % (self.obj['type'], self.obj['fullname'])
self.obj['underline'] = len(self.obj['fullname']) * "~"
template = env.get_template('python/member.rst')
try:
return template.render(**self.obj)
except Exception, e:
print "Exception, Keeping going"
print sys.exc_info()
return ''
class PythonFunction(object):
def __init__(self, obj):
self.obj = obj
def render(self):
# print "Rendering function %s" % self.obj['fullname']
self.obj['underline'] = len(self.obj['fullname']) * "~"
template = env.get_template('python/function.rst')
try:
return template.render(**self.obj)
except Exception, e:
print "Exception, Keeping going"
print sys.exc_info()
return ''
class PythonModule(object):
def __init__(self, obj):
self.obj = obj
self.item_map = defaultdict(list)
self.sort()
def sort(self):
for item in self.obj.get('children', []):
if 'type' not in item:
print "Missing Type: %s" % item
continue
self.item_map[item['type']].append(classify(item, 'python'))
def render(self):
# print "Rendering module %s" % self.obj['fullname']
self.obj['underline'] = len(self.obj['fullname']) * "#"
template = env.get_template('python/module.rst')
ctx = self.obj
ctx.update(dict(
methods=self.item_map['function'],
classes=self.item_map['class'],
imports=self.obj['imports'],
))
return template.render(**ctx)
class PythonClass(object):
def __init__(self, obj):
self.obj = obj
self.item_map = defaultdict(list)
self.sort()
def sort(self):
for item in self.obj.get('children', []):
if 'type' not in item:
print "Missing Type: %s" % item
continue
self.item_map[item['type']].append(classify(item, 'python'))
def render(self, indent=4):
# print "Rendering class %s" % self.obj['fullname']
template = env.get_template('python/class.rst')
ctx = self.obj
ctx.update(dict(
underline=len(self.obj['fullname']) * "-",
methods=self.item_map['function'],
classes=self.item_map['class'],
indent=indent,
))
return template.render(**ctx)
10 years ago
class DotNetClass(object):
def __init__(self, obj):
self.obj = obj
self.item_map = defaultdict(list)
self.sort()
def sort(self):
for item in self.obj['items']:
if 'type' not in item:
print "Missing Type: %s" % item
continue
self.item_map[item['type']].append(item)
def render(self, indent=4):
# print "Rendering class %s" % self.obj['name']
10 years ago
self.obj['underline'] = len(self.obj['qualifiedName']['CSharp']) * "#"
template = env.get_template('class.rst')
ctx = self.obj
ctx.update(dict(
ctors=self.item_map['Constructor'],
methods=self.item_map['Method'],
attributes=self.item_map['Property'],
))
return template.render(**ctx)
def classify(obj, obj_type):
10 years ago
if 'type' not in obj:
return ''
if obj_type == 'python':
if obj['type'] == 'module':
if not obj.get('children'):
return ''
return PythonModule(obj)
if obj['type'] == 'class':
return PythonClass(obj)
if obj['type'] == 'function':
return PythonFunction(obj)
else:
return PythonMember(obj)
if obj_type == 'dotnet':
if obj['type'] == 'Class':
return DotNetClass(obj)
if obj['type'] == 'Namespace':
return '' # for now
else:
return DotNetMember(obj)
def parse(obj, obj_type):
cls = classify(obj, obj_type)
if cls:
return cls.render()
def ignore_file(app, filename):
for pat in app.config.autoapi_ignore:
if fnmatch.fnmatch(filename, pat):
return True
return False
10 years ago
def load_yaml(app):
if not app.config.autoapi_dir:
return
app.env.autoapi_data = []
if app.config.autoapi_type == 'dotnet':
for _file in os.listdir(app.config.autoapi_dir):
# print "Loading Yaml from %s" % _file
10 years ago
to_open = os.path.join(app.env.config.autoapi_dir, _file)
app.env.autoapi_data.append(yaml.safe_load(open(to_open, 'r')))
# Generate RST
for obj in app.env.autoapi_data:
# print "Parsing %s" % obj['name']
rst = parse(obj, 'dotnet')
if rst:
path = os.path.join(app.config.autoapi_root, '%s%s' % (obj['name']['CSharp'], app.config.source_suffix[0]))
ensuredir(app.config.autoapi_root)
with open(path, 'w+') as fp:
fp.write(rst)
elif app.config.autoapi_type == 'python':
for root, dirnames, filenames in os.walk(app.config.autoapi_dir):
for filename in fnmatch.filter(filenames, u'*.py'):
to_open = os.path.join(root, filename)
if ignore_file(app, to_open):
continue
# print "Parsing Python File from %s" % to_open
try:
parsed_data = parsed(to_open)
app.env.autoapi_data.append(parsed_data)
except Exception, e:
print "Exception, Keeping going: %s" % to_open
print sys.exc_info()
import traceback; traceback.print_exc();
app.env.autoapi_enabled = True
# Generate RST
for obj in app.env.autoapi_data:
# print "Parsing %s" % obj['fullname']
rst = parse(obj, 'python')
if rst:
path = os.path.join(app.config.autoapi_root, '%s%s' % (obj['fullname'], app.config.source_suffix[0]))
ensuredir(app.config.autoapi_root)
with open(path, 'w+') as fp:
fp.write(rst.encode('utf8'))
10 years ago
def doctree_read(app, doctree):
pass
# para = nodes.paragraph('Test Para', 'Test Para')
# new_doc = utils.new_document(para)
def env_updated(app, env):
# env.found_docs.add(os.path.join(app.config.autoapi_root, 'test'))
pass
def collect_pages(app):
pass
context = {
'title': 'Test Title',
'body': 'Fak',
}
yield (os.path.join(app.config.autoapi_root, 'test_insert'), context, 'page.html')
def setup(app):
app.connect('doctree-read', doctree_read)
app.connect('builder-inited', load_yaml)
app.connect('env-updated', env_updated)
app.connect('html-collect-pages', collect_pages)
app.add_config_value('autoapi_type', 'dotnet', 'html')
10 years ago
app.add_config_value('autoapi_root', 'autoapi', 'html')
app.add_config_value('autoapi_ignore', ['*migrations*'], 'html')
app.add_config_value('autoapi_dir', '', 'html')